33 struct ci_char_traits :
public std::char_traits<char>
37 static bool eq(
char c1,
char c2)
38 {
return toupper(c1) == toupper(c2); }
40 static bool ne(
char c1,
char c2)
41 {
return toupper(c1) != toupper(c2); }
43 static bool lt(
char c1,
char c2)
44 {
return toupper(c1) < toupper(c2); }
46 static bool gt(
char c1,
char c2)
47 {
return toupper(c1) > toupper(c2); }
49 static int compare(
const char* s1,
const char* s2, std::size_t n)
53 if (lt(*s1, *s2))
return -1;
54 if (gt(*s1, *s2))
return 1;
60 static const char* find(
const char* s,
int n,
char a)
62 while (n-- > 0 && toupper(*s) != toupper(a))
70 typedef std::basic_string<char, ci_char_traits>
ci_string;
85 TOK_MACRO = -3, TOK_ENDMACRO = -4,
86 TOK_FUNCTION = -5, TOK_ENDFUNCTION = -6,
87 TOK_DOXYGEN_COMMENT = -7,
89 TOK_STRING_LITERAL = -100,
90 TOK_NUMBER_LITERAL = -102,
96 CMakeLexer(std::istream& is)
97 : _lastChar(
' '), _is(is), _line(1), _col(1)
103 while (isspace(_lastChar) && _lastChar !=
'\r' && _lastChar !=
'\n')
105 _lastChar = getChar();
108 if (isalpha(_lastChar) || _lastChar ==
'_')
110 _identifier = _lastChar;
111 while (isalnum(_lastChar = getChar()) || _lastChar ==
'-' || _lastChar ==
'_')
113 _identifier += _lastChar;
116 if (_identifier ==
"set")
118 if (_identifier ==
"function")
120 if (_identifier ==
"macro")
122 if (_identifier ==
"endfunction")
123 return TOK_ENDFUNCTION;
124 if (_identifier ==
"endmacro")
126 return TOK_IDENTIFIER;
129 if (isdigit(_lastChar))
132 _identifier = _lastChar;
133 while (isalnum(_lastChar = getChar()) || _lastChar ==
'.' || _lastChar ==
',')
135 _identifier += _lastChar;
137 return TOK_NUMBER_LITERAL;
140 if (_lastChar ==
'#')
142 _lastChar = getChar();
143 if (_lastChar ==
'!')
148 _lastChar = getChar();
149 while (_lastChar != EOF && _lastChar !=
'\n' && _lastChar !=
'\r')
151 _identifier += _lastChar;
152 _lastChar = getChar();
154 return TOK_DOXYGEN_COMMENT;
158 while (_lastChar != EOF && _lastChar !=
'\n' && _lastChar !=
'\r')
160 _lastChar = getChar();
164 if (_lastChar ==
'"')
166 _lastChar = getChar();
168 while (_lastChar != EOF && _lastChar !=
'"')
170 _identifier += _lastChar;
171 _lastChar = getChar();
175 _lastChar = getChar();
176 return TOK_STRING_LITERAL;
180 if (_lastChar == EOF)
return TOK_EOF;
183 if (_lastChar ==
'\r' || _lastChar ==
'\n')
185 if (_lastChar ==
'\r') _lastChar = getChar();
186 if (_lastChar ==
'\n') _lastChar = getChar();
191 int thisChar = _lastChar;
192 _lastChar = getChar();
196 std::string getIdentifier()
const 198 return std::string(_identifier.c_str());
216 void updateLoc(
int c)
218 if (c ==
'\n' || c ==
'\r')
229 ci_string _identifier;
246 CMakeParser(std::istream& is, std::ostream& os)
247 : _os(os), _lexer(is), _curToken(CMakeLexer::TOK_EOF), _lastToken(CMakeLexer::TOK_EOF)
257 _lastToken = _curToken;
258 _curToken = _lexer.getToken();
259 while (_curToken == CMakeLexer::TOK_EOL)
263 _curToken = _lexer.getToken();
277 void handleFunction()
289 if (_lastToken != CMakeLexer::TOK_DOXYGEN_COMMENT)
293 }
else if(!parseSet())
300 void handleDoxygenComment()
302 _os <<
"///" << _lexer.getIdentifier();
306 void handleTopLevelExpression()
314 void printError(
const char* str)
316 std::cerr <<
"Error: " << str <<
" (at line " << _lexer.curLine() <<
", col " << _lexer.curCol() <<
")";
321 if (nextToken() !=
'(')
323 printError(
"Expected '(' after MACRO");
328 std::string macroName = _lexer.getIdentifier();
329 if (curToken() != CMakeLexer::TOK_IDENTIFIER || macroName.empty())
331 printError(
"Expected macro name");
335 _os << macroName <<
'(';
336 if (nextToken() == CMakeLexer::TOK_IDENTIFIER)
338 _os << _lexer.getIdentifier();
339 while (nextToken() == CMakeLexer::TOK_IDENTIFIER)
341 _os <<
", " << _lexer.getIdentifier();
345 if (curToken() !=
')')
347 printError(
"Missing expected ')'");
361 if (nextToken() !=
'(')
363 printError(
"Expected '(' after SET");
368 std::string variableName = _lexer.getIdentifier();
369 if (curToken() != CMakeLexer::TOK_IDENTIFIER || variableName.empty())
371 printError(
"Expected variable name");
375 _os <<
"CMAKE_VARIABLE " << variableName;
378 while ((curToken() == CMakeLexer::TOK_IDENTIFIER)
379 || (curToken() == CMakeLexer::TOK_STRING_LITERAL)
380 || (curToken() == CMakeLexer::TOK_NUMBER_LITERAL))
385 if (curToken() !=
')')
387 printError(
"Missing expected ')'");
401 if (nextToken() !=
'(')
403 printError(
"Expected '(' after FUNCTION");
408 std::string funcName = _lexer.getIdentifier();
409 if (curToken() != CMakeLexer::TOK_IDENTIFIER || funcName.empty())
411 printError(
"Expected function name");
415 _os << funcName <<
'(';
416 if (nextToken() == CMakeLexer::TOK_IDENTIFIER)
418 _os << _lexer.getIdentifier();
419 while (nextToken() == CMakeLexer::TOK_IDENTIFIER)
421 _os <<
", " << _lexer.getIdentifier();
425 if (curToken() !=
')')
427 printError(
"Missing expected ')'");
447 #define STRINGIFY(a) #a 448 #define DOUBLESTRINGIFY(a) STRINGIFY(a) 450 int main(
int argc,
char** argv)
454 for (
int i = 1; i < argc; ++i)
456 std::ifstream ifs(argv[i]);
457 std::ostream& os = std::cout;
463 CMakeParser parser(ifs, os);
467 switch (parser.curToken())
469 case CMakeLexer::TOK_EOF:
471 case CMakeLexer::TOK_MACRO:
472 parser.handleMacro();
474 case CMakeLexer::TOK_FUNCTION:
475 parser.handleFunction();
477 case CMakeLexer::TOK_SET:
480 case CMakeLexer::TOK_DOXYGEN_COMMENT:
481 parser.handleDoxygenComment();
484 parser.handleTopLevelExpression();
std::basic_string< char, ci_char_traits > ci_string
#define DOUBLESTRINGIFY(a)
int main(int argc, char **argv)
bool compare(std::pair< double, int > i, std::pair< double, int > j)