Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Tobias Hunger
qt-creator
Commits
3dd011fc
Commit
3dd011fc
authored
Jan 28, 2010
by
Erik Verbruggen
Browse files
Changed binary expression parsing to use precedence parsing.
parent
a72230fe
Changes
3
Hide whitespace changes
Inline
Side-by-side
src/shared/cplusplus/Parser.cpp
View file @
3dd011fc
...
...
@@ -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
),
d
epth
(
0
)
_expressionD
epth
(
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
)
...
...
src/shared/cplusplus/Parser.h
View file @
3dd011fc
...
...
@@ -214,6 +214,8 @@ public:
bool
parseUsingDirective
(
DeclarationAST
*&
node
);
bool
parseWhileStatement
(
StatementAST
*&
node
);
void
parseExpressionWithOperatorPrecedence
(
ExpressionAST
*&
lhs
,
int
minPrecedence
);
// Qt MOC run
bool
parseQtMethod
(
ExpressionAST
*&
node
);
...
...
@@ -313,8 +315,7 @@ private:
bool
_objCEnabled
:
1
;
bool
_inFunctionBody
:
1
;
bool
_inObjCImplementationContext
:
1
;
int
depth
;
int
_expressionDepth
;
std
::
map
<
unsigned
,
TemplateArgumentListEntry
>
_templateArgumentList
;
...
...
tests/auto/cplusplus/ast/tst_ast.cpp
View file @
3dd011fc
...
...
@@ -185,11 +185,56 @@ void tst_AST::new_expression_2()
void
tst_AST
::
condition_1
()
{
QSharedPointer
<
TranslationUnit
>
unit
(
parseExpression
(
"
\n
"
"(x < 0 && y > (int) a)"
"(x < 0 && y > (int) a)"
));
AST
*
ast
=
unit
->
ast
();
QVERIFY
(
ast
!=
0
);
NestedExpressionAST
*
nestedExpr
=
ast
->
asNestedExpression
();
QVERIFY
(
nestedExpr
);
QVERIFY
(
nestedExpr
->
expression
);
BinaryExpressionAST
*
andExpr
=
nestedExpr
->
expression
->
asBinaryExpression
();
QVERIFY
(
andExpr
);
QCOMPARE
(
unit
->
tokenKind
(
andExpr
->
binary_op_token
),
(
int
)
T_AMPER_AMPER
);
QVERIFY
(
andExpr
->
left_expression
);
QVERIFY
(
andExpr
->
right_expression
);
BinaryExpressionAST
*
ltExpr
=
andExpr
->
left_expression
->
asBinaryExpression
();
QVERIFY
(
ltExpr
);
QCOMPARE
(
unit
->
tokenKind
(
ltExpr
->
binary_op_token
),
(
int
)
T_LESS
);
QVERIFY
(
ltExpr
->
left_expression
);
QVERIFY
(
ltExpr
->
right_expression
);
SimpleNameAST
*
x
=
ltExpr
->
left_expression
->
asSimpleName
();
QVERIFY
(
x
);
QCOMPARE
(
unit
->
spell
(
x
->
identifier_token
),
"x"
);
NumericLiteralAST
*
zero
=
ltExpr
->
right_expression
->
asNumericLiteral
();
QVERIFY
(
zero
);
QCOMPARE
(
unit
->
spell
(
zero
->
literal_token
),
"0"
);
BinaryExpressionAST
*
gtExpr
=
andExpr
->
right_expression
->
asBinaryExpression
();
QVERIFY
(
gtExpr
);
QCOMPARE
(
unit
->
tokenKind
(
gtExpr
->
binary_op_token
),
(
int
)
T_GREATER
);
QVERIFY
(
gtExpr
->
left_expression
);
QVERIFY
(
gtExpr
->
right_expression
);
SimpleNameAST
*
y
=
gtExpr
->
left_expression
->
asSimpleName
();
QVERIFY
(
y
);
QCOMPARE
(
unit
->
spell
(
y
->
identifier_token
),
"y"
);
CastExpressionAST
*
cast
=
gtExpr
->
right_expression
->
asCastExpression
();
QVERIFY
(
cast
);
QVERIFY
(
cast
->
type_id
);
QVERIFY
(
cast
->
expression
);
TypeIdAST
*
intType
=
cast
->
type_id
->
asTypeId
();
QVERIFY
(
intType
);
// ### here we could check if the type is an actual int
SimpleNameAST
*
a
=
cast
->
expression
->
asSimpleName
();
QVERIFY
(
a
);
QCOMPARE
(
unit
->
spell
(
a
->
identifier_token
),
"a"
);
}
void
tst_AST
::
init_1
()
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment