|
@@ -79,13 +79,15 @@ public:
|
|
|
|
|
|
enum Token {
|
|
|
TOK_EOF = -1,
|
|
|
+ TOK_EOL = -2,
|
|
|
|
|
|
// commands
|
|
|
- TOK_MACRO = -2, TOK_ENDMACRO = -3,
|
|
|
- TOK_FUNCTION = -4, TOK_ENDFUNCTION = -5,
|
|
|
- TOK_DOXYGEN_COMMENT = -6,
|
|
|
-
|
|
|
+ TOK_MACRO = -3, TOK_ENDMACRO = -4,
|
|
|
+ TOK_FUNCTION = -5, TOK_ENDFUNCTION = -6,
|
|
|
+ TOK_DOXYGEN_COMMENT = -7,
|
|
|
+ TOK_SET = -8,
|
|
|
TOK_STRING_LITERAL = -100,
|
|
|
+ TOK_NUMBER_LITERAL = -102,
|
|
|
|
|
|
// primary
|
|
|
TOK_IDENTIFIER = -200
|
|
@@ -98,7 +100,7 @@ public:
|
|
|
int getToken()
|
|
|
{
|
|
|
// skip whitespace
|
|
|
- while (isspace(_lastChar))
|
|
|
+ while (isspace(_lastChar) && _lastChar != '\r' && _lastChar != '\n')
|
|
|
{
|
|
|
_lastChar = getChar();
|
|
|
}
|
|
@@ -111,6 +113,8 @@ public:
|
|
|
_identifier += _lastChar;
|
|
|
}
|
|
|
|
|
|
+ if (_identifier == "set")
|
|
|
+ return TOK_SET;
|
|
|
if (_identifier == "function")
|
|
|
return TOK_FUNCTION;
|
|
|
if (_identifier == "macro")
|
|
@@ -122,6 +126,17 @@ public:
|
|
|
return TOK_IDENTIFIER;
|
|
|
}
|
|
|
|
|
|
+ if (isdigit(_lastChar))
|
|
|
+ {
|
|
|
+ // very lax!! number detection
|
|
|
+ _identifier = _lastChar;
|
|
|
+ while (isalnum(_lastChar = getChar()) || _lastChar == '.' || _lastChar == ',')
|
|
|
+ {
|
|
|
+ _identifier += _lastChar;
|
|
|
+ }
|
|
|
+ return TOK_NUMBER_LITERAL;
|
|
|
+ }
|
|
|
+
|
|
|
if (_lastChar == '#')
|
|
|
{
|
|
|
_lastChar = getChar();
|
|
@@ -164,6 +179,14 @@ public:
|
|
|
// don't eat the EOF
|
|
|
if (_lastChar == EOF) return TOK_EOF;
|
|
|
|
|
|
+ // don't eat the EOL
|
|
|
+ if (_lastChar == '\r' || _lastChar == '\n')
|
|
|
+ {
|
|
|
+ if (_lastChar == '\r') _lastChar = getChar();
|
|
|
+ if (_lastChar == '\n') _lastChar = getChar();
|
|
|
+ return TOK_EOL;
|
|
|
+ }
|
|
|
+
|
|
|
// return the character as its ascii value
|
|
|
int thisChar = _lastChar;
|
|
|
_lastChar = getChar();
|
|
@@ -221,7 +244,7 @@ class CMakeParser
|
|
|
public:
|
|
|
|
|
|
CMakeParser(std::istream& is, std::ostream& os)
|
|
|
- : _is(is), _os(os), _lexer(is), _curToken(CMakeLexer::TOK_EOF)
|
|
|
+ : _is(is), _os(os), _lexer(is), _curToken(CMakeLexer::TOK_EOF), _lastToken(CMakeLexer::TOK_EOF)
|
|
|
{ }
|
|
|
|
|
|
int curToken()
|
|
@@ -231,7 +254,15 @@ public:
|
|
|
|
|
|
int nextToken()
|
|
|
{
|
|
|
- return _curToken = _lexer.getToken();
|
|
|
+ _lastToken = _curToken;
|
|
|
+ _curToken = _lexer.getToken();
|
|
|
+ while (_curToken == CMakeLexer::TOK_EOL)
|
|
|
+ {
|
|
|
+ // Try to preserve lines in output to allow correct line number referencing by doxygen.
|
|
|
+ _os << std::endl;
|
|
|
+ _curToken = _lexer.getToken();
|
|
|
+ }
|
|
|
+ return _curToken;
|
|
|
}
|
|
|
|
|
|
void handleMacro()
|
|
@@ -252,9 +283,23 @@ public:
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ void handleSet()
|
|
|
+ {
|
|
|
+ // SET(var ...) following a documentation block is assumed to be a variable declaration.
|
|
|
+ if (_lastToken != CMakeLexer::TOK_DOXYGEN_COMMENT)
|
|
|
+ {
|
|
|
+ // No comment block before
|
|
|
+ nextToken();
|
|
|
+ } else if(!parseSet())
|
|
|
+ {
|
|
|
+ // skip token for error recovery
|
|
|
+ nextToken();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
void handleDoxygenComment()
|
|
|
{
|
|
|
- _os << "///" << _lexer.getIdentifier() << std::endl;
|
|
|
+ _os << "///" << _lexer.getIdentifier();
|
|
|
nextToken();
|
|
|
}
|
|
|
|
|
@@ -268,7 +313,7 @@ private:
|
|
|
|
|
|
void printError(const char* str)
|
|
|
{
|
|
|
- std::cerr << "Error: " << str << " (at line " << _lexer.curLine() << ", col " << _lexer.curCol() << ")\n";
|
|
|
+ std::cerr << "Error: " << str << " (at line " << _lexer.curLine() << ", col " << _lexer.curCol() << ")";
|
|
|
}
|
|
|
|
|
|
bool parseMacro()
|
|
@@ -303,7 +348,47 @@ private:
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- _os << ");" << std::endl;
|
|
|
+ _os << ");";
|
|
|
+ }
|
|
|
+
|
|
|
+ // eat the ')'
|
|
|
+ nextToken();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool parseSet()
|
|
|
+ {
|
|
|
+ if (nextToken() != '(')
|
|
|
+ {
|
|
|
+ printError("Expected '(' after SET");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ nextToken();
|
|
|
+ std::string variableName = _lexer.getIdentifier();
|
|
|
+ if (curToken() != CMakeLexer::TOK_IDENTIFIER || variableName.empty())
|
|
|
+ {
|
|
|
+ printError("Expected variable name");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ _os << "CMAKE_VARIABLE " << variableName;
|
|
|
+
|
|
|
+ nextToken();
|
|
|
+ while ((curToken() == CMakeLexer::TOK_IDENTIFIER)
|
|
|
+ || (curToken() == CMakeLexer::TOK_STRING_LITERAL)
|
|
|
+ || (curToken() == CMakeLexer::TOK_NUMBER_LITERAL))
|
|
|
+ {
|
|
|
+ nextToken();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (curToken() != ')')
|
|
|
+ {
|
|
|
+ printError("Missing expected ')'");
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ _os << ";";
|
|
|
}
|
|
|
|
|
|
// eat the ')'
|
|
@@ -343,7 +428,7 @@ private:
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- _os << ");" << std::endl;
|
|
|
+ _os << ");";
|
|
|
}
|
|
|
|
|
|
// eat the ')'
|
|
@@ -356,6 +441,7 @@ private:
|
|
|
std::ostream& _os;
|
|
|
CMakeLexer _lexer;
|
|
|
int _curToken;
|
|
|
+ int _lastToken;
|
|
|
};
|
|
|
|
|
|
|
|
@@ -367,14 +453,14 @@ int main(int argc, char** argv)
|
|
|
assert(argc > 1);
|
|
|
|
|
|
for (int i = 1; i < argc; ++i)
|
|
|
- {
|
|
|
+ {
|
|
|
std::ifstream ifs(argv[i]);
|
|
|
std::ostream& os = std::cout;
|
|
|
-
|
|
|
+
|
|
|
#ifdef USE_NAMESPACE
|
|
|
os << "namespace " << DOUBLESTRINGIFY(USE_NAMESPACE) << " {\n";
|
|
|
#endif
|
|
|
-
|
|
|
+
|
|
|
CMakeParser parser(ifs, os);
|
|
|
parser.nextToken();
|
|
|
while (ifs.good())
|
|
@@ -389,6 +475,9 @@ int main(int argc, char** argv)
|
|
|
case CMakeLexer::TOK_FUNCTION:
|
|
|
parser.handleFunction();
|
|
|
break;
|
|
|
+ case CMakeLexer::TOK_SET:
|
|
|
+ parser.handleSet();
|
|
|
+ break;
|
|
|
case CMakeLexer::TOK_DOXYGEN_COMMENT:
|
|
|
parser.handleDoxygenComment();
|
|
|
break;
|
|
@@ -397,7 +486,7 @@ int main(int argc, char** argv)
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
#ifdef USE_NAMESPACE
|
|
|
os << "}\n";
|
|
|
#endif
|
|
@@ -405,3 +494,4 @@ int main(int argc, char** argv)
|
|
|
|
|
|
return EXIT_SUCCESS;
|
|
|
}
|
|
|
+
|