summaryrefslogtreecommitdiff
path: root/src/shared/cplusplus/Parser.cpp
diff options
context:
space:
mode:
authorRoberto Raggi <roberto.raggi@nokia.com>2009-10-19 17:47:49 +0200
committerRoberto Raggi <roberto.raggi@nokia.com>2009-10-19 17:48:57 +0200
commitfe2c9cc16dc35c0f55bea45046d64d0170a0bbc0 (patch)
treecbd910817e7091e3e4f875f31b887511d6bd78da /src/shared/cplusplus/Parser.cpp
parentaa89317731a861e8d156d407ddc1f3d411c1af1f (diff)
downloadqt-creator-fe2c9cc16dc35c0f55bea45046d64d0170a0bbc0.tar.gz
Improved parsing of ambiguous statements.
Done with Erik Verbruggen
Diffstat (limited to 'src/shared/cplusplus/Parser.cpp')
-rw-r--r--src/shared/cplusplus/Parser.cpp105
1 files changed, 93 insertions, 12 deletions
diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp
index d754b234f4..e60751305a 100644
--- a/src/shared/cplusplus/Parser.cpp
+++ b/src/shared/cplusplus/Parser.cpp
@@ -56,7 +56,7 @@
#include <cstdlib>
#include <cstring>
#include <cassert>
-#include <QDebug>
+
CPLUSPLUS_BEGIN_NAMESPACE
Parser::Parser(TranslationUnit *unit)
@@ -2041,10 +2041,68 @@ bool Parser::maybeSimpleExpression(SimpleDeclarationAST *simpleDecl) const
{
if (! simpleDecl->declarators) {
SpecifierAST *spec = simpleDecl->decl_specifier_seq;
- if (spec && ! spec->next && spec->asNamedTypeSpecifier()) {
+
+ if (spec && ! spec->next && spec->asNamedTypeSpecifier())
return true;
+ }
+
+ return false;
+}
+
+bool Parser::isPointerDeclaration(DeclarationStatementAST *ast) const
+{
+ if (! ast)
+ return false;
+
+ if (SimpleDeclarationAST *declaration = ast->declaration->asSimpleDeclaration()) {
+ if (SpecifierAST *spec = declaration->decl_specifier_seq) {
+ if (spec->asNamedTypeSpecifier() && ! spec->next) {
+ if (DeclaratorListAST *declarators = declaration->declarators) {
+ if (DeclaratorAST *declarator = declarators->declarator) {
+ if (declarator->ptr_operators && declarator->equals_token && declarator->initializer) {
+ return true;
+ }
+ }
+ }
+ }
}
}
+
+ return false;
+}
+
+bool Parser::maybeAmbiguousStatement(DeclarationStatementAST *ast) const
+{
+ if (! ast)
+ return false;
+
+ if (SimpleDeclarationAST *declaration = ast->declaration->asSimpleDeclaration()) {
+ if (SpecifierAST *spec = declaration->decl_specifier_seq) {
+ if (spec->asNamedTypeSpecifier() && ! spec->next) {
+ if (DeclaratorListAST *declarators = declaration->declarators) {
+ if (DeclaratorAST *declarator = declarators->declarator) {
+ if (declarator->core_declarator &&
+ declarator->core_declarator->asNestedDeclarator()) {
+ // recognized name(id-expression)
+ return true;
+ }
+ }
+ }
+ }
+
+ } else if (DeclaratorListAST *declarators = declaration->declarators) {
+ // no decl_specifiers...
+ if (DeclaratorAST *declarator = declarators->declarator) {
+ if (declarator->postfix_declarators && declarator->postfix_declarators->asFunctionDeclarator()
+ && ! declarator->initializer) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+
return false;
}
@@ -2055,31 +2113,35 @@ bool Parser::parseExpressionOrDeclarationStatement(StatementAST *&node)
unsigned start = cursor();
bool blocked = blockErrors(true);
+
if (parseDeclarationStatement(node)) {
DeclarationStatementAST *stmt = static_cast<DeclarationStatementAST *>(node);
- SimpleDeclarationAST *simpleDecl = 0;
- if (stmt->declaration)
- simpleDecl = stmt->declaration->asSimpleDeclaration();
- if (simpleDecl && simpleDecl->decl_specifier_seq &&
- ! maybeFunctionCall(simpleDecl) && ! maybeSimpleExpression(simpleDecl)) {
+ if (isPointerDeclaration(stmt)) {
+ blockErrors(blocked);
+ return true;
+ }
+
+ if (! maybeAmbiguousStatement(stmt)) {
unsigned end_of_declaration_statement = cursor();
rewind(start);
+
StatementAST *expression = 0;
- if (! parseExpressionStatement(expression) || cursor() != end_of_declaration_statement) {
- rewind(end_of_declaration_statement);
- } else {
- ExpressionOrDeclarationStatementAST *ast =
- new (_pool) ExpressionOrDeclarationStatementAST;
+ if (parseExpressionStatement(expression) && cursor() == end_of_declaration_statement) {
+ // it's an ambiguous expression-or-declaration statement.
+ ExpressionOrDeclarationStatementAST *ast = new (_pool) ExpressionOrDeclarationStatementAST;
ast->declaration = node;
ast->expression = expression;
node = ast;
}
+
+ rewind(end_of_declaration_statement);
blockErrors(blocked);
return true;
}
}
+ // it's not a declaration statement.
blockErrors(blocked);
rewind(start);
return parseExpressionStatement(node);
@@ -2653,6 +2715,12 @@ bool Parser::parseSimpleDeclaration(DeclarationAST *&node,
return false;
}
+ // if there is no valid declarator
+ // and it doesn't look like a fwd or a class declaration
+ // then it's not a declarations
+ if (! declarator && ! maybeForwardOrClassDeclaration(decl_specifier_seq))
+ return false;
+
DeclaratorAST *firstDeclarator = declarator;
if (declarator) {
@@ -2709,6 +2777,19 @@ bool Parser::parseSimpleDeclaration(DeclarationAST *&node,
return false;
}
+bool Parser::maybeForwardOrClassDeclaration(SpecifierAST *decl_specifier_seq) const
+{
+ // look at the decl_specifier for possible fwd or class declarations.
+ if (SpecifierAST *spec = decl_specifier_seq) {
+ if (! spec->next && (spec->asElaboratedTypeSpecifier() ||
+ spec->asEnumSpecifier() ||
+ spec->asClassSpecifier()))
+ return true;
+ }
+
+ return false;
+}
+
bool Parser::parseFunctionBody(StatementAST *&node)
{
if (_translationUnit->skipFunctionBody()) {