Extended operator precedence parsing.

It now includes comma expressions, conditionals and assignment
expressions.
This commit is contained in:
Erik Verbruggen
2010-02-02 12:08:01 +01:00
parent 5878a89569
commit c33b55537d
2 changed files with 178 additions and 98 deletions

View File

@@ -107,8 +107,7 @@ inline bool lookAtAssignmentOperator(int tokenKind)
} // switch
}
namespace Prec { // operator-precedence
namespace Prec {
enum {
Unknown = 0,
Comma = 1,
@@ -126,46 +125,53 @@ enum {
Multiplicative = 13,
PointerToMember = 14
};
} // end of namespace Precedece
inline int precedence(int tokenKind, bool templateArguments)
{
// ### this will/might need some tuning for C++0x
// (see: [temp.names]p3)
if (templateArguments && tokenKind == T_GREATER)
return -1;
if (lookAtAssignmentOperator(tokenKind))
return Assignment;
return Prec::Assignment;
switch (tokenKind) {
case T_COMMA: return Comma;
case T_QUESTION: return Conditional;
case T_PIPE_PIPE: return LogicalOr;
case T_AMPER_AMPER: return LogicalAnd;
case T_PIPE: return InclusiveOr;
case T_CARET: return ExclusiveOr;
case T_AMPER: return And;
case T_COMMA: return Prec::Comma;
case T_QUESTION: return Prec::Conditional;
case T_PIPE_PIPE: return Prec::LogicalOr;
case T_AMPER_AMPER: return Prec::LogicalAnd;
case T_PIPE: return Prec::InclusiveOr;
case T_CARET: return Prec::ExclusiveOr;
case T_AMPER: return Prec::And;
case T_EQUAL_EQUAL:
case T_EXCLAIM_EQUAL: return Equality;
case T_EXCLAIM_EQUAL: return Prec::Equality;
case T_GREATER:
case T_LESS:
case T_LESS_EQUAL:
case T_GREATER_EQUAL: return Relational;
case T_GREATER_EQUAL: return Prec::Relational;
case T_LESS_LESS:
case T_GREATER_GREATER: return ExclusiveOr;
case T_GREATER_GREATER: return Prec::ExclusiveOr;
case T_PLUS:
case T_MINUS: return Additive;
case T_MINUS: return Prec::Additive;
case T_STAR:
case T_SLASH:
case T_PERCENT: return Multiplicative;
case T_PERCENT: return Prec::Multiplicative;
case T_ARROW_STAR:
case T_DOT_STAR: return PointerToMember;
default: return Unknown;
case T_DOT_STAR: return Prec::PointerToMember;
default: return Prec::Unknown;
}
}
} // end of namespace Precedece
inline bool isBinaryOperator(int tokenKind)
{ return Prec::precedence(tokenKind, false) != Prec::Unknown; }
{ return precedence(tokenKind, false) != Prec::Unknown; }
inline bool isRightAssociative(int tokenKind)
{
const int prec = precedence(tokenKind, false);
return prec == Prec::Conditional || prec == Prec::Assignment;
}
} // end of anonymous namespace
@@ -4250,76 +4256,62 @@ bool Parser::parseCastExpression(ExpressionAST *&node)
bool Parser::parsePmExpression(ExpressionAST *&node)
{
PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::precedence(T_ARROW_STAR, _templateArguments))
PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::PointerToMember)
}
bool Parser::parseMultiplicativeExpression(ExpressionAST *&node)
{
PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::precedence(T_STAR, _templateArguments))
PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::Multiplicative)
}
bool Parser::parseAdditiveExpression(ExpressionAST *&node)
{
PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::precedence(T_PLUS, _templateArguments))
PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::Additive)
}
bool Parser::parseShiftExpression(ExpressionAST *&node)
{
PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::precedence(T_LESS_LESS, _templateArguments))
PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::Shift)
}
bool Parser::parseRelationalExpression(ExpressionAST *&node)
{
PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::precedence(T_LESS, _templateArguments))
PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::Relational)
}
bool Parser::parseEqualityExpression(ExpressionAST *&node)
{
PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::precedence(T_EQUAL_EQUAL, _templateArguments))
PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::Equality)
}
bool Parser::parseAndExpression(ExpressionAST *&node)
{
PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::precedence(T_AMPER, _templateArguments))
PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::And)
}
bool Parser::parseExclusiveOrExpression(ExpressionAST *&node)
{
PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::precedence(T_CARET, _templateArguments))
PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::ExclusiveOr)
}
bool Parser::parseInclusiveOrExpression(ExpressionAST *&node)
{
PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::precedence(T_PIPE, _templateArguments))
PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::InclusiveOr)
}
bool Parser::parseLogicalAndExpression(ExpressionAST *&node)
{
PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::precedence(T_AMPER_AMPER, _templateArguments))
PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::LogicalAnd)
}
bool Parser::parseLogicalOrExpression(ExpressionAST *&node)
{
PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::precedence(T_PIPE_PIPE, _templateArguments))
PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::LogicalOr)
}
bool Parser::parseConditionalExpression(ExpressionAST *&node)
{
DEBUG_THIS_RULE();
if (! parseLogicalOrExpression(node))
return false;
if (LA() != T_QUESTION)
return true;
ConditionalExpressionAST *ast = new (_pool) ConditionalExpressionAST;
ast->condition = node;
ast->question_token = consumeToken();
parseAssignmentExpression(ast->left_expression);
match(T_COLON, &ast->colon_token);
parseAssignmentExpression(ast->right_expression);
node = ast;
return true;
PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::Conditional)
}
bool Parser::parseAssignmentExpression(ExpressionAST *&node)
@@ -4327,27 +4319,8 @@ bool Parser::parseAssignmentExpression(ExpressionAST *&node)
DEBUG_THIS_RULE();
if (LA() == T_THROW)
return parseThrowExpression(node);
else if (! parseConditionalExpression(node))
return false;
if (lookAtAssignmentOperator(LA())) {
unsigned op = consumeToken();
ExpressionAST *rightExpr = 0;
if (! parseAssignmentExpression(rightExpr)) {
_translationUnit->error(op, "expected expression after token `%s'",
_translationUnit->spell(op));
return false;
}
BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST;
ast->binary_op_token = op;
ast->left_expression = node;
ast->right_expression = rightExpr;
node = ast;
}
return true;
else
PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::Assignment)
}
bool Parser::parseQtMethod(ExpressionAST *&node)
@@ -4390,47 +4363,61 @@ void Parser::parseExpressionWithOperatorPrecedence(ExpressionAST *&lhs, int minP
{
DEBUG_THIS_RULE();
while (Prec::precedence(tok().kind(), _templateArguments) >= minPrecedence) {
const int operPrecedence = Prec::precedence(tok().kind(), _templateArguments);
while (precedence(tok().kind(), _templateArguments) >= minPrecedence) {
const int operPrecedence = precedence(tok().kind(), _templateArguments);
const int oper = consumeToken();
ExpressionAST *rhs = 0;
if (!parseCastExpression(rhs))
return;
for (int tokenKindAhead = tok().kind(), precedenceAhead = Prec::precedence(tokenKindAhead, _templateArguments);
precedenceAhead > operPrecedence && isBinaryOperator(tokenKindAhead);
tokenKindAhead = tok().kind(), precedenceAhead = Prec::precedence(tokenKindAhead, _templateArguments)) {
ConditionalExpressionAST *condExpr = 0;
if (operPrecedence == Prec::Conditional) {
condExpr = new (_pool) ConditionalExpressionAST;
condExpr->question_token = oper;
if (oper == T_COLON) {
// GNU extension:
// logical-or-expression '?' ':' conditional-expression
condExpr->left_expression = 0;
} else {
parseExpression(condExpr->left_expression);
}
match(T_COLON, &condExpr->colon_token);
}
ExpressionAST *rhs = 0;
const bool isCPlusPlus = true;
if (operPrecedence <= Prec::Conditional && isCPlusPlus) {
// in C++ you can put a throw in the right-most expression of a conditional expression,
// or an assignment, so some special handling:
if (!parseAssignmentExpression(rhs))
return;
} else {
// for C & all other expressions:
if (!parseCastExpression(rhs))
return;
}
for (int tokenKindAhead = tok().kind(), precedenceAhead = precedence(tokenKindAhead, _templateArguments);
precedenceAhead > operPrecedence && isBinaryOperator(tokenKindAhead)
|| precedenceAhead == operPrecedence && isRightAssociative(tokenKindAhead);
tokenKindAhead = tok().kind(), precedenceAhead = precedence(tokenKindAhead, _templateArguments)) {
parseExpressionWithOperatorPrecedence(rhs, precedenceAhead);
}
BinaryExpressionAST *expr = new (_pool) BinaryExpressionAST;
expr->left_expression = lhs;
expr->binary_op_token = oper;
expr->right_expression = rhs;
lhs = expr;
if (condExpr) { // we were parsing a ternairy conditional expression
condExpr->condition = lhs;
condExpr->right_expression = rhs;
lhs = condExpr;
} else {
BinaryExpressionAST *expr = new (_pool) BinaryExpressionAST;
expr->left_expression = lhs;
expr->binary_op_token = oper;
expr->right_expression = rhs;
lhs = expr;
}
}
}
bool Parser::parseCommaExpression(ExpressionAST *&node)
{
DEBUG_THIS_RULE();
if (! parseAssignmentExpression(node))
return false;
while (LA() == T_COMMA) {
unsigned op = consumeToken();
ExpressionAST *rightExpr = 0;
if (! parseAssignmentExpression(rightExpr))
return false;
BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST;
ast->binary_op_token = op;
ast->left_expression = node;
ast->right_expression = rightExpr;
node = ast;
}
return true;
PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::Comma)
}
bool Parser::parseThrowExpression(ExpressionAST *&node)