summaryrefslogtreecommitdiff
path: root/src/shared/cplusplus/Parser.cpp
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@nokia.com>2010-01-28 15:21:57 +0100
committerErik Verbruggen <erik.verbruggen@nokia.com>2010-01-28 15:22:50 +0100
commit3dd011fcb6d6beaab0a9ed715ecb014d86c7c9ce (patch)
tree7f637c47b99d659efe8ca15103c71a84529a5983 /src/shared/cplusplus/Parser.cpp
parenta72230feee03f9dde6ff3dfd7c042160611ec257 (diff)
downloadqt-creator-3dd011fcb6d6beaab0a9ed715ecb014d86c7c9ce.tar.gz
Changed binary expression parsing to use precedence parsing.
Diffstat (limited to 'src/shared/cplusplus/Parser.cpp')
-rw-r--r--src/shared/cplusplus/Parser.cpp360
1 files changed, 120 insertions, 240 deletions
diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp
index 9ab40ce6f7..cc7f0da211 100644
--- a/src/shared/cplusplus/Parser.cpp
+++ b/src/shared/cplusplus/Parser.cpp
@@ -59,6 +59,7 @@
#endif
#define CPLUSPLUS_NO_DEBUG_RULE
+#define MAX_EXPRESSION_DEPTH 100
using namespace CPlusPlus;
@@ -85,6 +86,73 @@ public:
int DebugRule::depth = 0;
+inline int precedence(int tokenKind, bool templateArguments)
+{
+ if (templateArguments && tokenKind == T_GREATER)
+ return -1;
+
+ 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;
+ case T_ARROW_STAR:
+ case T_DOT_STAR: return 10;
+
+ default:
+ return -1;
+ }
+}
+
+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:
+ case T_ARROW_STAR:
+ case T_DOT_STAR:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+inline bool isRightAssoc(int /*tokenKind*/)
+{
+ return false;
+}
+
} // end of anonymous namespace
#ifndef CPLUSPLUS_NO_DEBUG_RULE
@@ -93,6 +161,14 @@ int DebugRule::depth = 0;
# define DEBUG_THIS_RULE() do {} while (0)
#endif
+#define PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, minPrecedence) { \
+ if (!parseCastExpression(node)) \
+ return false; \
+ \
+ parseExpressionWithOperatorPrecedence(node, minPrecedence); \
+ return true; \
+}
+
class Parser::Rewind
{
Parser *_parser;
@@ -127,7 +203,7 @@ Parser::Parser(TranslationUnit *unit)
_objCEnabled(false),
_inFunctionBody(false),
_inObjCImplementationContext(false),
- depth(0)
+ _expressionDepth(0)
{ }
Parser::~Parser()
@@ -4145,280 +4221,57 @@ bool Parser::parseCastExpression(ExpressionAST *&node)
bool Parser::parsePmExpression(ExpressionAST *&node)
{
- DEBUG_THIS_RULE();
- if (! parseCastExpression(node))
- return false;
-
- while (LA() == T_ARROW_STAR || LA() == T_DOT_STAR) {
- unsigned op = consumeToken();
-
- ExpressionAST *rightExpr = 0;
- if (! parseCastExpression(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;
+ PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, precedence(T_ARROW_STAR, _templateArguments))
}
bool Parser::parseMultiplicativeExpression(ExpressionAST *&node)
{
- DEBUG_THIS_RULE();
- if (! parsePmExpression(node))
- return false;
-
- while (LA() == T_STAR || LA() == T_SLASH || LA() == T_PERCENT) {
- unsigned op = consumeToken();
-
- ExpressionAST *rightExpr = 0;
- if (! parsePmExpression(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;
+ PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, precedence(T_STAR, _templateArguments))
}
bool Parser::parseAdditiveExpression(ExpressionAST *&node)
{
- DEBUG_THIS_RULE();
- if (! parseMultiplicativeExpression(node))
- return false;
-
- while (LA() == T_PLUS || LA() == T_MINUS) {
- unsigned op = consumeToken();
-
- ExpressionAST *rightExpr = 0;
- if (! parseMultiplicativeExpression(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;
+ PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, precedence(T_PLUS, _templateArguments))
}
bool Parser::parseShiftExpression(ExpressionAST *&node)
{
- DEBUG_THIS_RULE();
- if (! parseAdditiveExpression(node))
- return false;
-
- while (LA() == T_LESS_LESS || LA() == T_GREATER_GREATER) {
- unsigned op = consumeToken();
-
- ExpressionAST *rightExpr = 0;
- if (! parseAdditiveExpression(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;
+ PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, precedence(T_LESS_LESS, _templateArguments))
}
bool Parser::parseRelationalExpression(ExpressionAST *&node)
{
- DEBUG_THIS_RULE();
- if (! parseShiftExpression(node))
- return false;
-
- while (LA() == T_LESS || (LA() == T_GREATER && ! _templateArguments) ||
- LA() == T_LESS_EQUAL || LA() == T_GREATER_EQUAL) {
- unsigned op = consumeToken();
-
- ExpressionAST *rightExpr = 0;
- if (! parseShiftExpression(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;
+ PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, precedence(T_LESS, _templateArguments))
}
bool Parser::parseEqualityExpression(ExpressionAST *&node)
{
- DEBUG_THIS_RULE();
- if (! parseRelationalExpression(node))
- return false;
-
- while (LA() == T_EQUAL_EQUAL || LA() == T_EXCLAIM_EQUAL) {
- unsigned op = consumeToken();
-
- ExpressionAST *rightExpr = 0;
- if (! parseRelationalExpression(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;
+ PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, precedence(T_EQUAL_EQUAL, _templateArguments))
}
bool Parser::parseAndExpression(ExpressionAST *&node)
{
- DEBUG_THIS_RULE();
- if (! parseEqualityExpression(node))
- return false;
-
- while (LA() == T_AMPER) {
- unsigned op = consumeToken();
-
- ExpressionAST *rightExpr = 0;
- if (! parseEqualityExpression(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;
+ PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, precedence(T_AMPER, _templateArguments))
}
bool Parser::parseExclusiveOrExpression(ExpressionAST *&node)
{
- DEBUG_THIS_RULE();
- if (! parseAndExpression(node))
- return false;
-
- while (LA() == T_CARET) {
- unsigned op = consumeToken();
-
- ExpressionAST *rightExpr = 0;
- if (! parseAndExpression(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;
+ PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, precedence(T_CARET, _templateArguments))
}
bool Parser::parseInclusiveOrExpression(ExpressionAST *&node)
{
- DEBUG_THIS_RULE();
- if (! parseExclusiveOrExpression(node))
- return false;
-
- while (LA() == T_PIPE) {
- unsigned op = consumeToken();
-
- ExpressionAST *rightExpr = 0;
- if (! parseExclusiveOrExpression(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;
+ PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, precedence(T_PIPE, _templateArguments))
}
bool Parser::parseLogicalAndExpression(ExpressionAST *&node)
{
- DEBUG_THIS_RULE();
- if (! parseInclusiveOrExpression(node))
- return false;
-
- while (LA() == T_AMPER_AMPER) {
- unsigned op = consumeToken();
-
- ExpressionAST *rightExpr = 0;
- if (! parseInclusiveOrExpression(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;
+ PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, precedence(T_AMPER_AMPER, _templateArguments))
}
bool Parser::parseLogicalOrExpression(ExpressionAST *&node)
{
- DEBUG_THIS_RULE();
- if (! parseLogicalAndExpression(node))
- return false;
-
- while (LA() == T_PIPE_PIPE) {
- unsigned op = consumeToken();
-
- ExpressionAST *rightExpr = 0;
- if (! parseLogicalAndExpression(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;
+ PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, precedence(T_PIPE_PIPE, _templateArguments))
}
bool Parser::parseConditionalExpression(ExpressionAST *&node)
@@ -4515,13 +4368,40 @@ bool Parser::parseConstantExpression(ExpressionAST *&node)
bool Parser::parseExpression(ExpressionAST *&node)
{
DEBUG_THIS_RULE();
- if (depth > 100)
+
+ if (_expressionDepth > MAX_EXPRESSION_DEPTH)
return false;
- ++depth;
- bool result = parseCommaExpression(node);
- --depth;
- return result;
+ ++_expressionDepth;
+ bool success = parseCommaExpression(node);
+ --_expressionDepth;
+ return success;
+}
+
+void Parser::parseExpressionWithOperatorPrecedence(ExpressionAST *&lhs, int minPrecedence)
+{
+ DEBUG_THIS_RULE();
+
+ 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 = precedence(tokenKindAhead, _templateArguments);
+ precedenceAhead > operPrecedence && isBinaryOperator(tokenKindAhead)
+ || precedenceAhead == operPrecedence && isRightAssoc(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;
+ }
}
bool Parser::parseCommaExpression(ExpressionAST *&node)