hrev48115 adds 1 changeset to branch 'master' old head: 076135838d3ab9e0710f5807bfae689d55091f55 new head: 310f631263c46b099f5e50d1f18ddb1293e6a0ae overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=310f631+%5E0761358 ---------------------------------------------------------------------------- 310f631: Debugger: Rework expression tokenizer. - Separate operator parsing out into its own function, and refactor it to handle multi-character operators. These aren't yet handled by the parser itself though. [ Rene Gollent <rene@xxxxxxxxxxx> ] ---------------------------------------------------------------------------- Revision: hrev48115 Commit: 310f631263c46b099f5e50d1f18ddb1293e6a0ae URL: http://cgit.haiku-os.org/haiku/commit/?id=310f631 Author: Rene Gollent <rene@xxxxxxxxxxx> Date: Mon Oct 27 03:18:53 2014 UTC ---------------------------------------------------------------------------- 1 file changed, 271 insertions(+), 54 deletions(-) .../CLanguageExpressionEvaluator.cpp | 325 ++++++++++++++++--- ---------------------------------------------------------------------------- diff --git a/src/apps/debugger/source_language/expression_evaluators/CLanguageExpressionEvaluator.cpp b/src/apps/debugger/source_language/expression_evaluators/CLanguageExpressionEvaluator.cpp index 3632652..34721fb 100644 --- a/src/apps/debugger/source_language/expression_evaluators/CLanguageExpressionEvaluator.cpp +++ b/src/apps/debugger/source_language/expression_evaluators/CLanguageExpressionEvaluator.cpp @@ -27,28 +27,126 @@ enum { TOKEN_NONE = 0, TOKEN_IDENTIFIER, TOKEN_CONSTANT, + TOKEN_END_OF_LINE, + + TOKEN_PLUS, + TOKEN_MINUS, + + TOKEN_STAR, + TOKEN_SLASH, + TOKEN_MODULO, + + TOKEN_POWER, + + TOKEN_OPENING_BRACKET, + TOKEN_CLOSING_BRACKET, + + TOKEN_LOGICAL_AND, + TOKEN_LOGICAL_OR, + TOKEN_LOGICAL_NOT, + TOKEN_BITWISE_AND, + TOKEN_BITWISE_OR, + TOKEN_BITWISE_NOT, + TOKEN_EQ, + TOKEN_NE, + TOKEN_GT, + TOKEN_GE, + TOKEN_LT, + TOKEN_LE +}; - TOKEN_END_OF_LINE = '\n', +static BString TokenTypeToString(int32 type) +{ + BString token; - TOKEN_PLUS = '+', - TOKEN_MINUS = '-', + switch (type) { + case TOKEN_PLUS: + token = "+"; + break; - TOKEN_STAR = '*', - TOKEN_SLASH = '/', - TOKEN_MODULO = '%', + case TOKEN_MINUS: + token = "-"; + break; - TOKEN_POWER = '^', + case TOKEN_STAR: + token = "*"; + break; - TOKEN_OPENING_BRACKET = '(', - TOKEN_CLOSING_BRACKET = ')', + case TOKEN_SLASH: + token = "/"; + break; - TOKEN_AND = '&', - TOKEN_OR = '|', - TOKEN_NOT = '~', - TOKEN_EQ = '=', - TOKEN_GE = '>', - TOKEN_LE = '<' -}; + case TOKEN_MODULO: + token = "%"; + break; + + case TOKEN_POWER: + token = "^"; + break; + + case TOKEN_OPENING_BRACKET: + token = "("; + break; + + case TOKEN_CLOSING_BRACKET: + token = ")"; + break; + + case TOKEN_LOGICAL_AND: + token = "&&"; + break; + + case TOKEN_LOGICAL_OR: + token = "||"; + break; + + case TOKEN_LOGICAL_NOT: + token = "!"; + break; + + case TOKEN_BITWISE_AND: + token = "&"; + break; + + case TOKEN_BITWISE_OR: + token = "|"; + break; + + case TOKEN_BITWISE_NOT: + token = "~"; + break; + + case TOKEN_EQ: + token = "=="; + break; + + case TOKEN_NE: + token = "!="; + break; + + case TOKEN_GT: + token = ">"; + break; + + case TOKEN_GE: + token = ">="; + break; + + case TOKEN_LT: + token = "<"; + break; + + case TOKEN_LE: + token = "<="; + break; + + default: + token.SetToFormat("Unknown token type %" B_PRId32, type); + break; + } + + return token; +} struct CLanguageExpressionEvaluator::Token { @@ -214,56 +312,169 @@ class CLanguageExpressionEvaluator::Tokenizer { TOKEN_IDENTIFIER); fCurrentChar += 2; } else { - int32 type = TOKEN_NONE; - - switch (*fCurrentChar) { - case TOKEN_PLUS: - case TOKEN_MINUS: - case TOKEN_STAR: - case TOKEN_SLASH: - case TOKEN_MODULO: - case TOKEN_POWER: - case TOKEN_OPENING_BRACKET: - case TOKEN_CLOSING_BRACKET: - case TOKEN_AND: - case TOKEN_OR: - case TOKEN_NOT: - case TOKEN_EQ: - case TOKEN_GE: - case TOKEN_LE: - case TOKEN_END_OF_LINE: - type = *fCurrentChar; - break; - - case '\\': - case ':': - type = TOKEN_SLASH; - break; + if (!_ParseOperator()) { + int32 type = TOKEN_NONE; + switch (*fCurrentChar) { + case '\n': + type = TOKEN_END_OF_LINE; + break; + + case '(': + type = TOKEN_OPENING_BRACKET; + break; + case ')': + type = TOKEN_CLOSING_BRACKET; + break; - case 'x': - if (!fHexSupport) { - type = TOKEN_STAR; + case '\\': + case ':': + type = TOKEN_SLASH; break; - } - // fall through - default: - throw ParseException("unexpected character", _CurrentPos()); + case 'x': + if (!fHexSupport) { + type = TOKEN_STAR; + break; + } + // fall through + + default: + throw ParseException("unexpected character", + _CurrentPos()); + } + fCurrentToken = Token(fCurrentChar, 1, _CurrentPos(), type); + fCurrentChar++; } - fCurrentToken = Token(fCurrentChar, 1, _CurrentPos(), type); - fCurrentChar++; } //printf("next token: '%s'\n", fCurrentToken.string.String()); return fCurrentToken; } + bool _ParseOperator() + { + int32 type = TOKEN_NONE; + int32 length = 0; + switch (*fCurrentChar) { + case '+': + type = TOKEN_PLUS; + length = 1; + break; + + case '-': + type = TOKEN_MINUS; + length = 1; + break; + + case '*': + type = TOKEN_STAR; + length = 1; + break; + + case '/': + type = TOKEN_SLASH; + length = 1; + break; + + case '%': + type = TOKEN_MODULO; + length = 1; + break; + + case '^': + type = TOKEN_POWER; + length = 1; + break; + + case '&': + if (Peek() == '&') { + type = TOKEN_LOGICAL_AND; + length = 2; + } else { + type = TOKEN_BITWISE_AND; + length = 1; + } + break; + + case '|': + if (Peek() == '|') { + type = TOKEN_LOGICAL_OR; + length = 2; + } else { + type = TOKEN_BITWISE_OR; + length = 1; + } + break; + + case '!': + if (Peek() == '=') { + type = TOKEN_NE; + length = 2; + } else { + type = TOKEN_LOGICAL_NOT; + length = 1; + } + break; + + case '=': + if (Peek() == '=') { + type = TOKEN_EQ; + length = 2; + } + break; + + case '>': + if (Peek() == '=') { + type = TOKEN_GE; + length = 2; + } else { + type = TOKEN_GT; + length = 1; + } + break; + + case '<': + if (Peek() == '=') { + type = TOKEN_LE; + length = 2; + } else { + type = TOKEN_LT; + length = 1; + } + break; + + case '~': + type = TOKEN_BITWISE_NOT; + length = 1; + break; + + default: + break; + } + + if (length == 0) + return false; + + fCurrentToken = Token(fCurrentChar, length, _CurrentPos(), type); + fCurrentChar += length; + + return true; + } + void RewindToken() { fReuseToken = true; } private: + char Peek() const + { + if (_CurrentPos() < fString.Length()) + return *(fCurrentChar + 1); + + return '\0'; + } + static bool _IsHexDigit(char c) { return isdigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); @@ -602,13 +813,19 @@ CLanguageExpressionEvaluator::_EatToken(int32 type) case TOKEN_POWER: case TOKEN_OPENING_BRACKET: case TOKEN_CLOSING_BRACKET: - case TOKEN_AND: - case TOKEN_OR: - case TOKEN_NOT: + case TOKEN_LOGICAL_AND: + case TOKEN_BITWISE_AND: + case TOKEN_LOGICAL_OR: + case TOKEN_BITWISE_OR: + case TOKEN_LOGICAL_NOT: + case TOKEN_BITWISE_NOT: case TOKEN_EQ: + case TOKEN_NE: + case TOKEN_GT: case TOKEN_GE: + case TOKEN_LT: case TOKEN_LE: - expected << "'" << (char)type << "'"; + expected << "'" << TokenTypeToString(type) << "'"; break; case TOKEN_SLASH: