31 struct ci_char_traits :
public std::char_traits<char>
35 static bool eq(
char c1,
char c2)
36 {
return toupper(c1) == toupper(c2); }
38 static bool ne(
char c1,
char c2)
39 {
return toupper(c1) != toupper(c2); }
41 static bool lt(
char c1,
char c2)
42 {
return toupper(c1) < toupper(c2); }
44 static bool gt(
char c1,
char c2)
45 {
return toupper(c1) > toupper(c2); }
47 static int compare(
const char* s1,
const char* s2, std::size_t n)
51 if (lt(*s1, *s2))
return -1;
52 if (gt(*s1, *s2))
return 1;
58 static const char* find(
const char* s,
int n,
char a)
60 while (n-- > 0 && toupper(*s) != toupper(a))
68 typedef std::basic_string<char, ci_char_traits>
ci_string;
83 TOK_MACRO = -3, TOK_ENDMACRO = -4,
84 TOK_FUNCTION = -5, TOK_ENDFUNCTION = -6,
85 TOK_DOXYGEN_COMMENT = -7,
87 TOK_STRING_LITERAL = -100,
88 TOK_NUMBER_LITERAL = -102,
94 CMakeLexer(std::istream& is)
95 : _lastChar(
' '), _is(is), _line(1), _col(1)
101 while (isspace(_lastChar) && _lastChar !=
'\r' && _lastChar !=
'\n')
103 _lastChar = getChar();
106 if (isalpha(_lastChar) || _lastChar ==
'_')
108 _identifier = _lastChar;
109 while (isalnum(_lastChar = getChar()) || _lastChar ==
'-' || _lastChar ==
'_')
111 _identifier += _lastChar;
114 if (_identifier ==
"set")
116 if (_identifier ==
"function")
118 if (_identifier ==
"macro")
120 if (_identifier ==
"endfunction")
121 return TOK_ENDFUNCTION;
122 if (_identifier ==
"endmacro")
124 return TOK_IDENTIFIER;
127 if (isdigit(_lastChar))
130 _identifier = _lastChar;
131 while (isalnum(_lastChar = getChar()) || _lastChar ==
'.' || _lastChar ==
',')
133 _identifier += _lastChar;
135 return TOK_NUMBER_LITERAL;
138 if (_lastChar ==
'#')
140 _lastChar = getChar();
141 if (_lastChar ==
'!')
146 _lastChar = getChar();
147 while (_lastChar != EOF && _lastChar !=
'\n' && _lastChar !=
'\r')
149 _identifier += _lastChar;
150 _lastChar = getChar();
152 return TOK_DOXYGEN_COMMENT;
156 while (_lastChar != EOF && _lastChar !=
'\n' && _lastChar !=
'\r')
158 _lastChar = getChar();
162 if (_lastChar ==
'"')
164 _lastChar = getChar();
166 while (_lastChar != EOF && _lastChar !=
'"')
168 _identifier += _lastChar;
169 _lastChar = getChar();
173 _lastChar = getChar();
174 return TOK_STRING_LITERAL;
178 if (_lastChar == EOF)
return TOK_EOF;
181 if (_lastChar ==
'\r' || _lastChar ==
'\n')
183 if (_lastChar ==
'\r') _lastChar = getChar();
184 if (_lastChar ==
'\n') _lastChar = getChar();
189 int thisChar = _lastChar;
190 _lastChar = getChar();
194 std::string getIdentifier()
const
196 return std::string(_identifier.c_str());
214 void updateLoc(
int c)
216 if (c ==
'\n' || c ==
'\r')
227 ci_string _identifier;
244 CMakeParser(std::istream& is, std::ostream& os)
245 : _os(os), _lexer(is), _curToken(CMakeLexer::TOK_EOF), _lastToken(CMakeLexer::TOK_EOF)
255 _lastToken = _curToken;
256 _curToken = _lexer.getToken();
257 while (_curToken == CMakeLexer::TOK_EOL)
261 _curToken = _lexer.getToken();
275 void handleFunction()
287 if (_lastToken != CMakeLexer::TOK_DOXYGEN_COMMENT)
291 }
else if(!parseSet())
298 void handleDoxygenComment()
300 _os <<
"///" << _lexer.getIdentifier();
304 void handleTopLevelExpression()
312 void printError(
const char* str)
314 std::cerr <<
"Error: " << str <<
" (at line " << _lexer.curLine() <<
", col " << _lexer.curCol() <<
")";
319 if (nextToken() !=
'(')
321 printError(
"Expected '(' after MACRO");
326 std::string macroName = _lexer.getIdentifier();
327 if (curToken() != CMakeLexer::TOK_IDENTIFIER || macroName.empty())
329 printError(
"Expected macro name");
333 _os << macroName <<
'(';
334 if (nextToken() == CMakeLexer::TOK_IDENTIFIER)
336 _os << _lexer.getIdentifier();
337 while (nextToken() == CMakeLexer::TOK_IDENTIFIER)
339 _os <<
", " << _lexer.getIdentifier();
343 if (curToken() !=
')')
345 printError(
"Missing expected ')'");
359 if (nextToken() !=
'(')
361 printError(
"Expected '(' after SET");
366 std::string variableName = _lexer.getIdentifier();
367 if (curToken() != CMakeLexer::TOK_IDENTIFIER || variableName.empty())
369 printError(
"Expected variable name");
373 _os <<
"CMAKE_VARIABLE " << variableName;
376 while ((curToken() == CMakeLexer::TOK_IDENTIFIER)
377 || (curToken() == CMakeLexer::TOK_STRING_LITERAL)
378 || (curToken() == CMakeLexer::TOK_NUMBER_LITERAL))
383 if (curToken() !=
')')
385 printError(
"Missing expected ')'");
399 if (nextToken() !=
'(')
401 printError(
"Expected '(' after FUNCTION");
406 std::string funcName = _lexer.getIdentifier();
407 if (curToken() != CMakeLexer::TOK_IDENTIFIER || funcName.empty())
409 printError(
"Expected function name");
413 _os << funcName <<
'(';
414 if (nextToken() == CMakeLexer::TOK_IDENTIFIER)
416 _os << _lexer.getIdentifier();
417 while (nextToken() == CMakeLexer::TOK_IDENTIFIER)
419 _os <<
", " << _lexer.getIdentifier();
423 if (curToken() !=
')')
425 printError(
"Missing expected ')'");
445 #define STRINGIFY(a) #a
446 #define DOUBLESTRINGIFY(a) STRINGIFY(a)
448 int main(
int argc,
char** argv)
452 for (
int i = 1; i < argc; ++i)
454 std::ifstream ifs(argv[i]);
455 std::ostream& os = std::cout;
461 CMakeParser parser(ifs, os);
465 switch (parser.curToken())
467 case CMakeLexer::TOK_EOF:
469 case CMakeLexer::TOK_MACRO:
470 parser.handleMacro();
472 case CMakeLexer::TOK_FUNCTION:
473 parser.handleFunction();
475 case CMakeLexer::TOK_SET:
478 case CMakeLexer::TOK_DOXYGEN_COMMENT:
479 parser.handleDoxygenComment();
482 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)