Improved parsing of ambiguous statements.

Done with Erik Verbruggen
This commit is contained in:
Roberto Raggi
2009-10-19 17:47:49 +02:00
parent aa89317731
commit fe2c9cc16d
3 changed files with 165 additions and 19 deletions

View File

@@ -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()) {