forked from qt-creator/qt-creator
Changed binary expression parsing to use precedence parsing.
This commit is contained in:
@@ -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,245 +274,62 @@ 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)
|
||||
{
|
||||
Value result = lhs;
|
||||
|
||||
while (precedence((*_lex)->kind()) >= minPrecedence) {
|
||||
const int oper = (*_lex)->kind();
|
||||
const int operPrecedence = precedence(oper);
|
||||
++(*_lex);
|
||||
process_primary();
|
||||
Value rhs = _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);
|
||||
}
|
||||
|
||||
result = evaluate_expression(oper, result, rhs);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void process_constant_expression()
|
||||
{
|
||||
process_primary();
|
||||
_value = process_expression_with_operator_precedence(_value, precedence(T_PIPE_PIPE));
|
||||
|
||||
while ((*_lex)->is(T_STAR) || (*_lex)->is(T_SLASH) || (*_lex)->is(T_PERCENT)) {
|
||||
const Token op = *(*_lex);
|
||||
++(*_lex);
|
||||
|
||||
const Value left = _value;
|
||||
process_primary();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool process_and()
|
||||
{
|
||||
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();
|
||||
|
||||
while ((*_lex)->is(T_CARET)) {
|
||||
const Token op = *(*_lex);
|
||||
++(*_lex);
|
||||
|
||||
const Value left = _value;
|
||||
process_and();
|
||||
|
||||
_value = left ^ _value;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool process_or()
|
||||
{
|
||||
process_xor();
|
||||
|
||||
while ((*_lex)->is(T_PIPE)) {
|
||||
const Token op = *(*_lex);
|
||||
++(*_lex);
|
||||
|
||||
const Value left = _value;
|
||||
process_xor();
|
||||
|
||||
_value = left | _value;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool process_logical_and()
|
||||
{
|
||||
process_or();
|
||||
|
||||
while ((*_lex)->is(T_AMPER_AMPER)) {
|
||||
const Token op = *(*_lex);
|
||||
++(*_lex);
|
||||
|
||||
const Value left = _value;
|
||||
process_or();
|
||||
|
||||
_value = left && _value;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool process_logical_or()
|
||||
{
|
||||
process_logical_and();
|
||||
|
||||
while ((*_lex)->is(T_PIPE_PIPE)) {
|
||||
const Token op = *(*_lex);
|
||||
++(*_lex);
|
||||
|
||||
const Value left = _value;
|
||||
process_logical_and();
|
||||
|
||||
_value = left || _value;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool process_constant_expression()
|
||||
{
|
||||
process_logical_or();
|
||||
const Value cond = _value;
|
||||
if ((*_lex)->is(T_QUESTION)) {
|
||||
const Value cond = _value;
|
||||
++(*_lex);
|
||||
process_constant_expression();
|
||||
Value left = _value, right;
|
||||
@@ -525,10 +340,94 @@ protected:
|
||||
}
|
||||
_value = ! cond.is_zero() ? left : right;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
inline int precedence(int tokenKind) const
|
||||
{
|
||||
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;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool isBinaryOperator(int tokenKind)
|
||||
{
|
||||
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;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static inline Value evaluate_expression(int tokenKind, const Value &lhs, const Value &rhs)
|
||||
{
|
||||
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;
|
||||
|
||||
default:
|
||||
return Value();
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool isRightAssoc(int /*tokenKind*/)
|
||||
{ return false; }
|
||||
|
||||
private:
|
||||
Client *client;
|
||||
Environment *env;
|
||||
|
||||
Reference in New Issue
Block a user