summaryrefslogtreecommitdiff
path: root/src/libs/cplusplus
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@nokia.com>2010-01-28 15:22:36 +0100
committerErik Verbruggen <erik.verbruggen@nokia.com>2010-01-28 15:22:50 +0100
commit0fdf02ab4d97d8ee24f5b0cd4703f0a45c355349 (patch)
treeef823692a99888e0dd0312185861dcfbdbaa6931 /src/libs/cplusplus
parent3dd011fcb6d6beaab0a9ed715ecb014d86c7c9ce (diff)
downloadqt-creator-0fdf02ab4d97d8ee24f5b0cd4703f0a45c355349.tar.gz
Changed binary expression parsing to use precedence parsing.
Diffstat (limited to 'src/libs/cplusplus')
-rw-r--r--src/libs/cplusplus/pp-engine.cpp299
1 files changed, 99 insertions, 200 deletions
diff --git a/src/libs/cplusplus/pp-engine.cpp b/src/libs/cplusplus/pp-engine.cpp
index 7b9ad5ec41..b0557baeaa 100644
--- a/src/libs/cplusplus/pp-engine.cpp
+++ b/src/libs/cplusplus/pp-engine.cpp
@@ -246,10 +246,10 @@ protected:
return text;
}
- bool process_expression()
- { return process_constant_expression(); }
+ inline void process_expression()
+ { process_constant_expression(); }
- bool process_primary()
+ void process_primary()
{
if ((*_lex)->is(T_NUMERIC_LITERAL)) {
int base = 10;
@@ -262,13 +262,11 @@ protected:
}
_value.set_long(tokenSpell().toLong(0, base));
++(*_lex);
- return true;
} else if (isTokenDefined()) {
++(*_lex);
if ((*_lex)->is(T_IDENTIFIER)) {
_value.set_long(isMacroDefined(tokenSpell(), (*_lex)->offset, env, client));
++(*_lex);
- return true;
} else if ((*_lex)->is(T_LPAREN)) {
++(*_lex);
if ((*_lex)->is(T_IDENTIFIER)) {
@@ -276,258 +274,159 @@ protected:
++(*_lex);
if ((*_lex)->is(T_RPAREN)) {
++(*_lex);
- return true;
}
}
- return false;
}
- return true;
} else if ((*_lex)->is(T_IDENTIFIER)) {
_value.set_long(0);
++(*_lex);
- return true;
} else if ((*_lex)->is(T_MINUS)) {
++(*_lex);
process_primary();
_value.set_long(- _value.l);
- return true;
} else if ((*_lex)->is(T_PLUS)) {
++(*_lex);
process_primary();
- return true;
} else if ((*_lex)->is(T_EXCLAIM)) {
++(*_lex);
process_primary();
_value.set_long(_value.is_zero());
- return true;
} else if ((*_lex)->is(T_LPAREN)) {
++(*_lex);
process_expression();
if ((*_lex)->is(T_RPAREN))
++(*_lex);
- return true;
}
-
- return false;
}
- bool process_multiplicative()
+ Value process_expression_with_operator_precedence(const Value &lhs, int minPrecedence)
{
- process_primary();
+ Value result = lhs;
- while ((*_lex)->is(T_STAR) || (*_lex)->is(T_SLASH) || (*_lex)->is(T_PERCENT)) {
- const Token op = *(*_lex);
+ while (precedence((*_lex)->kind()) >= minPrecedence) {
+ const int oper = (*_lex)->kind();
+ const int operPrecedence = precedence(oper);
++(*_lex);
-
- const Value left = _value;
process_primary();
+ Value rhs = _value;
- if (op.is(T_STAR)) {
- _value = left * _value;
- } else if (op.is(T_SLASH)) {
- if (_value.is_zero())
- _value.set_long(0);
- else
- _value = left / _value;
- } else if (op.is(T_PERCENT)) {
- if (_value.is_zero())
- _value.set_long(0);
- else
- _value = left % _value;
+ for (int LA_token_kind = (*_lex)->kind(), LA_precedence = precedence(LA_token_kind);
+ LA_precedence > operPrecedence && isBinaryOperator(LA_token_kind)
+ || LA_precedence == operPrecedence && isRightAssoc(LA_token_kind);
+ LA_token_kind = (*_lex)->kind(), LA_precedence = precedence(LA_token_kind)) {
+ rhs = process_expression_with_operator_precedence(rhs, LA_precedence);
}
- }
-
- return true;
- }
-
- bool process_additive()
- {
- process_multiplicative();
-
- while ((*_lex)->is(T_PLUS) || (*_lex)->is(T_MINUS)) {
- const Token op = *(*_lex);
- ++(*_lex);
-
- const Value left = _value;
- process_multiplicative();
-
- if (op.is(T_PLUS))
- _value = left + _value;
- else if (op.is(T_MINUS))
- _value = left - _value;
- }
-
- return true;
- }
-
- bool process_shift()
- {
- process_additive();
- while ((*_lex)->is(T_MINUS_MINUS) || (*_lex)->is(T_GREATER_GREATER)) {
- const Token op = *(*_lex);
- ++(*_lex);
-
- const Value left = _value;
- process_additive();
-
- if (op.is(T_MINUS_MINUS))
- _value = left << _value;
- else if (op.is(T_GREATER_GREATER))
- _value = left >> _value;
- }
-
- return true;
- }
-
- bool process_relational()
- {
- process_shift();
-
- while ((*_lex)->is(T_LESS) || (*_lex)->is(T_LESS_EQUAL) ||
- (*_lex)->is(T_GREATER) || (*_lex)->is(T_GREATER_EQUAL)) {
- const Token op = *(*_lex);
- ++(*_lex);
-
- const Value left = _value;
- process_shift();
-
- if (op.is(T_LESS))
- _value = left < _value;
- else if (op.is(T_LESS_EQUAL))
- _value = left <= _value;
- else if (op.is(T_GREATER))
- _value = left > _value;
- else if (op.is(T_GREATER_EQUAL))
- _value = left >= _value;
- }
-
- return true;
- }
-
- bool process_equality()
- {
- process_relational();
-
- while ((*_lex)->is(T_EXCLAIM_EQUAL) || (*_lex)->is(T_EQUAL_EQUAL)) {
- const Token op = *(*_lex);
- ++(*_lex);
-
- const Value left = _value;
- process_relational();
-
- if (op.is(T_EXCLAIM_EQUAL))
- _value = left != _value;
- else if (op.is(T_EQUAL_EQUAL))
- _value = left == _value;
+ result = evaluate_expression(oper, result, rhs);
}
- return true;
+ return result;
}
- bool process_and()
+ void process_constant_expression()
{
- process_equality();
-
- while ((*_lex)->is(T_AMPER)) {
- const Token op = *(*_lex);
- ++(*_lex);
-
- const Value left = _value;
- process_equality();
-
- _value = left & _value;
- }
-
- return true;
- }
-
- bool process_xor()
- {
- process_and();
+ process_primary();
+ _value = process_expression_with_operator_precedence(_value, precedence(T_PIPE_PIPE));
- while ((*_lex)->is(T_CARET)) {
- const Token op = *(*_lex);
+ if ((*_lex)->is(T_QUESTION)) {
+ const Value cond = _value;
++(*_lex);
-
- const Value left = _value;
- process_and();
-
- _value = left ^ _value;
+ process_constant_expression();
+ Value left = _value, right;
+ if ((*_lex)->is(T_COLON)) {
+ ++(*_lex);
+ process_constant_expression();
+ right = _value;
+ }
+ _value = ! cond.is_zero() ? left : right;
}
-
- return true;
}
- bool process_or()
+private:
+ inline int precedence(int tokenKind) const
{
- process_xor();
-
- while ((*_lex)->is(T_PIPE)) {
- const Token op = *(*_lex);
- ++(*_lex);
-
- const Value left = _value;
- process_xor();
+ switch (tokenKind) {
+ case T_PIPE_PIPE: return 0;
+ case T_AMPER_AMPER: return 1;
+ case T_PIPE: return 2;
+ case T_CARET: return 3;
+ case T_AMPER: return 4;
+ case T_EQUAL_EQUAL:
+ case T_EXCLAIM_EQUAL: return 5;
+ case T_GREATER:
+ case T_LESS:
+ case T_LESS_EQUAL:
+ case T_GREATER_EQUAL: return 6;
+ case T_LESS_LESS:
+ case T_GREATER_GREATER: return 7;
+ case T_PLUS:
+ case T_MINUS: return 8;
+ case T_STAR:
+ case T_SLASH:
+ case T_PERCENT: return 9;
- _value = left | _value;
+ default:
+ return -1;
}
-
- return true;
}
- bool process_logical_and()
+ static inline bool isBinaryOperator(int tokenKind)
{
- process_or();
-
- while ((*_lex)->is(T_AMPER_AMPER)) {
- const Token op = *(*_lex);
- ++(*_lex);
-
- const Value left = _value;
- process_or();
+ switch (tokenKind) {
+ case T_PIPE_PIPE:
+ case T_AMPER_AMPER:
+ case T_PIPE:
+ case T_CARET:
+ case T_AMPER:
+ case T_EQUAL_EQUAL:
+ case T_EXCLAIM_EQUAL:
+ case T_GREATER:
+ case T_LESS:
+ case T_LESS_EQUAL:
+ case T_GREATER_EQUAL:
+ case T_LESS_LESS:
+ case T_GREATER_GREATER:
+ case T_PLUS:
+ case T_MINUS:
+ case T_STAR:
+ case T_SLASH:
+ case T_PERCENT:
+ return true;
- _value = left && _value;
+ default:
+ return false;
}
-
- return true;
}
- bool process_logical_or()
+ static inline Value evaluate_expression(int tokenKind, const Value &lhs, const Value &rhs)
{
- process_logical_and();
-
- while ((*_lex)->is(T_PIPE_PIPE)) {
- const Token op = *(*_lex);
- ++(*_lex);
-
- const Value left = _value;
- process_logical_and();
+ switch (tokenKind) {
+ case T_PIPE_PIPE: return lhs || rhs;
+ case T_AMPER_AMPER: return lhs && rhs;
+ case T_PIPE: return lhs | rhs;
+ case T_CARET: return lhs ^ rhs;
+ case T_AMPER: return lhs & rhs;
+ case T_EQUAL_EQUAL: return lhs == rhs;
+ case T_EXCLAIM_EQUAL: return lhs != rhs;
+ case T_GREATER: return lhs > rhs;
+ case T_LESS: return lhs < rhs;
+ case T_LESS_EQUAL: return lhs <= rhs;
+ case T_GREATER_EQUAL: return lhs >= rhs;
+ case T_LESS_LESS: return lhs << rhs;
+ case T_GREATER_GREATER: return lhs >> rhs;
+ case T_PLUS: return lhs + rhs;
+ case T_MINUS: return lhs - rhs;
+ case T_STAR: return lhs * rhs;
+ case T_SLASH: return rhs.is_zero() ? Value() : lhs / rhs;
+ case T_PERCENT: return rhs.is_zero() ? Value() : lhs % rhs;
- _value = left || _value;
+ default:
+ return Value();
}
-
- return true;
}
- bool process_constant_expression()
- {
- process_logical_or();
- const Value cond = _value;
- if ((*_lex)->is(T_QUESTION)) {
- ++(*_lex);
- process_constant_expression();
- Value left = _value, right;
- if ((*_lex)->is(T_COLON)) {
- ++(*_lex);
- process_constant_expression();
- right = _value;
- }
- _value = ! cond.is_zero() ? left : right;
- }
-
- return true;
- }
+ static inline bool isRightAssoc(int /*tokenKind*/)
+ { return false; }
private:
Client *client;