diff options
author | Roberto Raggi <roberto.raggi@nokia.com> | 2009-10-19 17:47:49 +0200 |
---|---|---|
committer | Roberto Raggi <roberto.raggi@nokia.com> | 2009-10-19 17:48:57 +0200 |
commit | fe2c9cc16dc35c0f55bea45046d64d0170a0bbc0 (patch) | |
tree | cbd910817e7091e3e4f875f31b887511d6bd78da /src/shared/cplusplus/Parser.cpp | |
parent | aa89317731a861e8d156d407ddc1f3d411c1af1f (diff) | |
download | qt-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.cpp | 105 |
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()) { |