/*************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Qt Software Information (qt-info@nokia.com) ** ** ** Non-Open Source Usage ** ** Licensees may use this file in accordance with the Qt Beta Version ** License Agreement, Agreement version 2.2 provided with the Software or, ** alternatively, in accordance with the terms contained in a written ** agreement between you and Nokia. ** ** GNU General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU General ** Public License versions 2.0 or 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the packaging ** of this file. Please review the following information to ensure GNU ** General Public Licensing requirements will be met: ** ** http://www.fsf.org/licensing/licenses/info/GPLv2.html and ** http://www.gnu.org/copyleft/gpl.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt GPL Exception ** version 1.2, included in the file GPL_EXCEPTION.txt in this package. ** ***************************************************************************/ // Copyright (c) 2008 Roberto Raggi // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "Parser.h" #include "Token.h" #include "Lexer.h" #include "Control.h" #include "AST.h" #include "Literals.h" #include #include CPLUSPLUS_BEGIN_NAMESPACE Parser::Parser(TranslationUnit *unit) : _translationUnit(unit), _control(_translationUnit->control()), _pool(_translationUnit->memoryPool()), _tokenIndex(1), _templateArguments(0), _qtMocRunEnabled(false), _inFunctionBody(false) { } Parser::~Parser() { } bool Parser::qtMocRunEnabled() const { return _qtMocRunEnabled; } void Parser::setQtMocRunEnabled(bool onoff) { _qtMocRunEnabled = onoff; } bool Parser::switchTemplateArguments(bool templateArguments) { bool previousTemplateArguments = _templateArguments; _templateArguments = templateArguments; return previousTemplateArguments; } bool Parser::blockErrors(bool block) { return _translationUnit->blockErrors(block); } bool Parser::skipUntil(int token) { while (int tk = LA()) { if (tk == token) return true; consumeToken(); } return false; } bool Parser::skipUntilDeclaration() { while (int tk = LA()) { switch (tk) { case T_SEMICOLON: case T_TILDE: case T_COLON_COLON: case T_IDENTIFIER: case T_OPERATOR: case T_CHAR: case T_WCHAR_T: case T_BOOL: case T_SHORT: case T_INT: case T_LONG: case T_SIGNED: case T_UNSIGNED: case T_FLOAT: case T_DOUBLE: case T_VOID: case T_EXTERN: case T_NAMESPACE: case T_USING: case T_TYPEDEF: case T_ASM: case T_TEMPLATE: case T_EXPORT: case T_CONST: case T_VOLATILE: case T_PUBLIC: case T_PROTECTED: case T_PRIVATE: return true; default: consumeToken(); } } return false; } bool Parser::skipUntilStatement() { while (int tk = LA()) { switch (tk) { case T_SEMICOLON: case T_LBRACE: case T_RBRACE: case T_CONST: case T_VOLATILE: case T_IDENTIFIER: case T_CASE: case T_DEFAULT: case T_IF: case T_SWITCH: case T_WHILE: case T_DO: case T_FOR: case T_BREAK: case T_CONTINUE: case T_RETURN: case T_GOTO: case T_TRY: case T_CATCH: case T_THROW: case T_CHAR: case T_WCHAR_T: case T_BOOL: case T_SHORT: case T_INT: case T_LONG: case T_SIGNED: case T_UNSIGNED: case T_FLOAT: case T_DOUBLE: case T_VOID: case T_CLASS: case T_STRUCT: case T_UNION: case T_ENUM: case T_COLON_COLON: case T_TEMPLATE: case T_USING: return true; default: consumeToken(); } } return false; } bool Parser::skip(int l, int r) { int count = 0; while (int tk = LA()) { if (tk == l) ++count; else if (tk == r) --count; else if (l != T_LBRACE && (tk == T_LBRACE || tk == T_RBRACE || tk == T_SEMICOLON)) return false; if (count == 0) return true; consumeToken(); } return false; } void Parser::match(int kind, unsigned *token) { if (LA() == kind) *token = consumeToken(); else { *token = 0; _translationUnit->error(_tokenIndex, "expected token `%s' got `%s'", Token::name(kind), tok().spell()); } } bool Parser::parseClassOrNamespaceName(NameAST *&node) { if (LA() == T_IDENTIFIER) { unsigned identifier_token = cursor(); if (LA(2) == T_LESS && parseTemplateId(node) && LA() == T_COLON_COLON) return true; rewind(identifier_token); if (LA(2) == T_COLON_COLON) { SimpleNameAST *ast = new (_pool) SimpleNameAST; ast->identifier_token = consumeToken(); node = ast; return true; } } else if (LA() == T_TEMPLATE) { unsigned template_token = consumeToken(); if (parseTemplateId(node)) return true; rewind(template_token); } return false; } bool Parser::parseTemplateId(NameAST *&node) { if (LA() == T_IDENTIFIER && LA(2) == T_LESS) { TemplateIdAST *ast = new (_pool) TemplateIdAST; ast->identifier_token = consumeToken(); ast->less_token = consumeToken(); if (LA() == T_GREATER || parseTemplateArgumentList( ast->template_arguments)) { if (LA() == T_GREATER) { ast->greater_token = consumeToken(); node = ast; return true; } } } return false; } bool Parser::parseNestedNameSpecifier(NestedNameSpecifierAST *&node, bool /*acceptTemplateId*/) { NestedNameSpecifierAST **nested_name_specifier = &node; NameAST *class_or_namespace_name = 0; if (parseClassOrNamespaceName(class_or_namespace_name) && LA() == T_COLON_COLON) { unsigned scope_token = consumeToken(); *nested_name_specifier = new (_pool) NestedNameSpecifierAST; (*nested_name_specifier)->class_or_namespace_name = class_or_namespace_name; (*nested_name_specifier)->scope_token = scope_token; nested_name_specifier = &(*nested_name_specifier)->next; while (parseClassOrNamespaceName(class_or_namespace_name) && LA() == T_COLON_COLON) { scope_token = consumeToken(); *nested_name_specifier = new (_pool) NestedNameSpecifierAST; (*nested_name_specifier)->class_or_namespace_name = class_or_namespace_name; (*nested_name_specifier)->scope_token = scope_token; nested_name_specifier = &(*nested_name_specifier)->next; } // ### ugly hack rewind(scope_token); consumeToken(); return true; } return false; } bool Parser::parseNestedNameSpecifierOpt(NestedNameSpecifierAST *&name, bool acceptTemplateId) { unsigned start = cursor(); if (! parseNestedNameSpecifier(name, acceptTemplateId)) rewind(start); return true; } bool Parser::parseName(NameAST *&node, bool acceptTemplateId) { unsigned global_scope_token = 0; if (LA() == T_COLON_COLON) global_scope_token = consumeToken(); NestedNameSpecifierAST *nested_name_specifier = 0; parseNestedNameSpecifierOpt(nested_name_specifier, /*acceptTemplateId=*/ true); NameAST *unqualified_name = 0; if (parseUnqualifiedName(unqualified_name, /*acceptTemplateId=*/ acceptTemplateId || nested_name_specifier != 0)) { if (! global_scope_token && ! nested_name_specifier) { node = unqualified_name; return true; } QualifiedNameAST *ast = new (_pool) QualifiedNameAST; ast->global_scope_token = global_scope_token; ast->nested_name_specifier = nested_name_specifier; ast->unqualified_name = unqualified_name; node = ast; return true; } return false; } bool Parser::parseTranslationUnit(TranslationUnitAST *&node) { TranslationUnitAST *ast = new (_pool) TranslationUnitAST; DeclarationAST **decl = &ast->declarations; while (LA()) { unsigned start_declaration = cursor(); if (parseDeclaration(*decl)) { if (*decl) decl = &(*decl)->next; } else { rewind(start_declaration + 1); skipUntilDeclaration(); } } node = ast; return true; } bool Parser::parseEmptyDeclaration(DeclarationAST *&node) { if (LA() == T_SEMICOLON) { EmptyDeclarationAST *ast = new (_pool) EmptyDeclarationAST; ast->semicolon_token = consumeToken(); node = ast; return true; } return false; } bool Parser::parseDeclaration(DeclarationAST *&node) { switch (LA()) { case T_SEMICOLON: return parseEmptyDeclaration(node); case T_NAMESPACE: return parseNamespace(node); case T_USING: return parseUsing(node); case T_ASM: return parseAsmDefinition(node); case T_TEMPLATE: case T_EXPORT: return parseTemplateDeclaration(node); default: if (LA() == T_EXTERN && LA(2) == T_TEMPLATE) return parseTemplateDeclaration(node); else if (LA() == T_EXTERN && LA(2) == T_STRING_LITERAL) return parseLinkageSpecification(node); else return parseSimpleDeclaration(node); } // end switch } bool Parser::parseLinkageSpecification(DeclarationAST *&node) { if (LA() == T_EXTERN && LA(2) == T_STRING_LITERAL) { LinkageSpecificationAST *ast = new (_pool) LinkageSpecificationAST; ast->extern_token = consumeToken(); ast->extern_type = consumeToken(); if (LA() == T_LBRACE) parseLinkageBody(ast->declaration); else parseDeclaration(ast->declaration); node = ast; return true; } return false; } bool Parser::parseLinkageBody(DeclarationAST *&node) { if (LA() == T_LBRACE) { LinkageBodyAST *ast = new (_pool) LinkageBodyAST; ast->lbrace_token = consumeToken(); DeclarationAST **declaration_ptr = &ast->declarations; while (int tk = LA()) { if (tk == T_RBRACE) break; unsigned start_declaration = cursor(); if (parseDeclaration(*declaration_ptr)) { if (*declaration_ptr) // ### remove me declaration_ptr = &(*declaration_ptr)->next; } else { rewind(start_declaration + 1); skipUntilDeclaration(); } } match(T_RBRACE, &ast->rbrace_token); node = ast; return true; } return false; } // ### rename parseNamespaceAliarOrDeclaration? bool Parser::parseNamespace(DeclarationAST *&node) { if (LA() != T_NAMESPACE) return false; unsigned namespace_token = consumeToken(); if (LA() == T_IDENTIFIER && LA(2) == T_EQUAL) { NamespaceAliasDefinitionAST *ast = new (_pool) NamespaceAliasDefinitionAST; ast->namespace_token = namespace_token; ast->namespace_name = consumeToken(); ast->equal_token = consumeToken(); parseName(ast->name); match(T_SEMICOLON, &ast->semicolon_token); node = ast; return true; } NamespaceAST *ast = new (_pool) NamespaceAST; ast->namespace_token = namespace_token; if (LA() == T_IDENTIFIER) ast->identifier_token = consumeToken(); SpecifierAST **attr_ptr = &ast->attributes; while (LA() == T___ATTRIBUTE__) { parseAttributeSpecifier(*attr_ptr); attr_ptr = &(*attr_ptr)->next; } if (LA() == T_LBRACE) parseLinkageBody(ast->linkage_body); node = ast; return true; } bool Parser::parseUsing(DeclarationAST *&node) { if (LA() != T_USING) return false; if (LA(2) == T_NAMESPACE) return parseUsingDirective(node); UsingAST *ast = new (_pool) UsingAST; ast->using_token = consumeToken(); if (LA() == T_TYPENAME) ast->typename_token = consumeToken(); parseName(ast->name); match(T_SEMICOLON, &ast->semicolon_token); node = ast; return true; } bool Parser::parseUsingDirective(DeclarationAST *&node) { if (LA() == T_USING && LA(2) == T_NAMESPACE) { UsingDirectiveAST *ast = new (_pool) UsingDirectiveAST; ast->using_token = consumeToken(); ast->namespace_token = consumeToken(); if (! parseName(ast->name)) _translationUnit->warning(cursor(), "expected `namespace name' before `%s'", tok().spell()); match(T_SEMICOLON, &ast->semicolon_token); node = ast; return true; } return false; } bool Parser::parseConversionFunctionId(NameAST *&node) { if (LA() != T_OPERATOR) return false; unsigned operator_token = consumeToken(); SpecifierAST *type_specifier = 0; if (! parseTypeSpecifier(type_specifier)) { return false; } PtrOperatorAST *ptr_operators = 0, **ptr_operators_tail = &ptr_operators; while (parsePtrOperator(*ptr_operators_tail)) ptr_operators_tail = &(*ptr_operators_tail)->next; ConversionFunctionIdAST *ast = new (_pool) ConversionFunctionIdAST; ast->operator_token = operator_token; ast->type_specifier = type_specifier; ast->ptr_operators = ptr_operators; node = ast; return true; } bool Parser::parseOperatorFunctionId(NameAST *&node) { if (LA() != T_OPERATOR) return false; unsigned operator_token = consumeToken(); OperatorAST *op = 0; if (! parseOperator(op)) return false; OperatorFunctionIdAST *ast = new (_pool) OperatorFunctionIdAST; ast->operator_token = operator_token; ast->op = op; node = ast; return true; } bool Parser::parseTemplateArgumentList(TemplateArgumentListAST *&node) { TemplateArgumentListAST **template_argument_ptr = &node; ExpressionAST *template_argument = 0; if (parseTemplateArgument(template_argument)) { *template_argument_ptr = new (_pool) TemplateArgumentListAST; (*template_argument_ptr)->template_argument = template_argument; template_argument_ptr = &(*template_argument_ptr)->next; while (LA() == T_COMMA) { consumeToken(); if (parseTemplateArgument(template_argument)) { *template_argument_ptr = new (_pool) TemplateArgumentListAST; (*template_argument_ptr)->template_argument = template_argument; template_argument_ptr = &(*template_argument_ptr)->next; } } return true; } return false; } bool Parser::parseAsmDefinition(DeclarationAST *&node) { if (LA() == T_ASM) { AsmDefinitionAST *ast = new (_pool) AsmDefinitionAST; ast->asm_token = consumeToken(); parseCvQualifiers(ast->cv_qualifier_seq); if (LA() == T_LPAREN) { ast->lparen_token = cursor(); if (skip(T_LPAREN, T_RPAREN)) ast->rparen_token = consumeToken(); } match(T_SEMICOLON, &ast->semicolon_token); node = ast; return true; } return false; } bool Parser::parseTemplateDeclaration(DeclarationAST *&node) { if (! (LA(1) == T_TEMPLATE || ((LA(1) == T_EXPORT || LA(1) == T_EXTERN) && LA(2) == T_TEMPLATE))) return false; TemplateDeclarationAST *ast = new (_pool) TemplateDeclarationAST; if (LA() == T_EXPORT || LA() == T_EXPORT) ast->export_token = consumeToken(); ast->template_token = consumeToken(); if (LA() == T_LESS) { ast->less_token = consumeToken(); if (LA() == T_GREATER || parseTemplateParameterList(ast->template_parameters)) match(T_GREATER, &ast->greater_token); } parseDeclaration(ast->declaration); node = ast; return true; } bool Parser::parseOperator(OperatorAST *&node) // ### FIXME { OperatorAST *ast = new (_pool) OperatorAST; switch (LA()) { case T_NEW: case T_DELETE: { ast->op_token = consumeToken(); if (LA() == T_LBRACKET) { ast->open_token = consumeToken(); match(T_RBRACKET, &ast->close_token); } } break; case T_PLUS: case T_MINUS: case T_STAR: case T_SLASH: case T_PERCENT: case T_CARET: case T_AMPER: case T_PIPE: case T_TILDE: case T_EXCLAIM: case T_LESS: case T_GREATER: case T_COMMA: case T_AMPER_EQUAL: case T_CARET_EQUAL: case T_SLASH_EQUAL: case T_EQUAL: case T_EQUAL_EQUAL: case T_EXCLAIM_EQUAL: case T_GREATER_EQUAL: case T_GREATER_GREATER_EQUAL: case T_LESS_EQUAL: case T_LESS_LESS_EQUAL: case T_MINUS_EQUAL: case T_PERCENT_EQUAL: case T_PIPE_EQUAL: case T_PLUS_EQUAL: case T_STAR_EQUAL: case T_TILDE_EQUAL: case T_LESS_LESS: case T_GREATER_GREATER: case T_AMPER_AMPER: case T_PIPE_PIPE: case T_PLUS_PLUS: case T_MINUS_MINUS: case T_ARROW_STAR: case T_DOT_STAR: case T_ARROW: ast->op_token = consumeToken(); break; default: if (LA() == T_LPAREN && LA(2) == T_RPAREN) { ast->op_token = ast->open_token = consumeToken(); ast->close_token = consumeToken(); } else if (LA() == T_LBRACKET && LA(2) == T_RBRACKET) { ast->op_token = ast->open_token = consumeToken(); ast->close_token = consumeToken(); } else { return false; } } node = ast; return true; } bool Parser::parseCvQualifiers(SpecifierAST *&node) { unsigned start = cursor(); SpecifierAST **ast = &node; while (*ast) ast = &(*ast)->next; while (int tk = LA()) { if (tk == T_CONST || tk == T_VOLATILE) { SimpleSpecifierAST *spec = new (_pool) SimpleSpecifierAST; spec->specifier_token = consumeToken(); *ast = spec; ast = &(*ast)->next; } else { break; } } return start != cursor(); } bool Parser::parsePtrOperator(PtrOperatorAST *&node) { if (LA() == T_AMPER) { ReferenceAST *ast = new (_pool) ReferenceAST; ast->amp_token = consumeToken(); node = ast; return true; } else if (LA() == T_STAR) { PointerAST *ast = new (_pool) PointerAST; ast->star_token = consumeToken(); parseCvQualifiers(ast->cv_qualifier_seq); node = ast; return true; } else if (LA() == T_COLON_COLON || LA() == T_IDENTIFIER) { unsigned scope_or_identifier_token = cursor(); unsigned global_scope_token = 0; if (LA() == T_COLON_COLON) global_scope_token = consumeToken(); NestedNameSpecifierAST *nested_name_specifier = 0; bool has_nested_name_specifier = parseNestedNameSpecifier( nested_name_specifier, true); if (has_nested_name_specifier && LA() == T_STAR) { PointerToMemberAST *ast = new (_pool) PointerToMemberAST; ast->global_scope_token = global_scope_token; ast->nested_name_specifier = nested_name_specifier; ast->star_token = consumeToken(); parseCvQualifiers(ast->cv_qualifier_seq); node = ast; return true; } rewind(scope_or_identifier_token); } return false; } bool Parser::parseTemplateArgument(ExpressionAST *&node) { unsigned start = cursor(); if (parseTypeId(node) && (LA() == T_COMMA || LA() == T_GREATER)) return true; rewind(start); bool previousTemplateArguments = switchTemplateArguments(true); bool parsed = parseLogicalOrExpression(node); (void) switchTemplateArguments(previousTemplateArguments); return parsed; } bool Parser::parseDeclSpecifierSeq(SpecifierAST *&decl_specifier_seq, bool onlyTypeSpecifiers, bool simplified) { bool has_type_specifier = false; NameAST *named_type_specifier = 0; SpecifierAST **decl_specifier_seq_ptr = &decl_specifier_seq; for (;;) { if (lookAtCVQualifier()) { SimpleSpecifierAST *spec = new (_pool) SimpleSpecifierAST; spec->specifier_token = consumeToken(); *decl_specifier_seq_ptr = spec; decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next; } else if (! onlyTypeSpecifiers && lookAtStorageClassSpecifier()) { SimpleSpecifierAST *spec = new (_pool) SimpleSpecifierAST; spec->specifier_token = consumeToken(); *decl_specifier_seq_ptr = spec; decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next; } else if (! named_type_specifier && lookAtBuiltinTypeSpecifier()) { parseBuiltinTypeSpecifier(*decl_specifier_seq_ptr); decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next; has_type_specifier = true; } else if (! has_type_specifier && (LA() == T_COLON_COLON || LA() == T_IDENTIFIER)) { if (! parseName(named_type_specifier)) return false; NamedTypeSpecifierAST *spec = new (_pool) NamedTypeSpecifierAST; spec->name = named_type_specifier; *decl_specifier_seq_ptr = spec; decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next; has_type_specifier = true; } else if (! simplified && ! has_type_specifier && (LA() == T_TYPENAME || LA() == T_ENUM || lookAtClassKey())) { unsigned startOfElaboratedTypeSpecifier = cursor(); if (! parseElaboratedTypeSpecifier(*decl_specifier_seq_ptr)) { _translationUnit->error(startOfElaboratedTypeSpecifier, "expected an elaborated type specifier"); break; } decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next; has_type_specifier = true; } else break; } return decl_specifier_seq != 0; } bool Parser::parseDeclaratorOrAbstractDeclarator(DeclaratorAST *&node) { unsigned start = cursor(); bool blocked = blockErrors(true); if (parseDeclarator(node)) { blockErrors(blocked); return true; } blockErrors(blocked); rewind(start); return parseAbstractDeclarator(node); } bool Parser::parseCoreDeclarator(DeclaratorAST *&node) { PtrOperatorAST *ptr_operators = 0, **ptr_operators_tail = &ptr_operators; while (parsePtrOperator(*ptr_operators_tail)) ptr_operators_tail = &(*ptr_operators_tail)->next; if (LA() == T_COLON_COLON || LA() == T_IDENTIFIER || LA() == T_TILDE || LA() == T_OPERATOR) { NameAST *name = 0; if (parseName(name)) { DeclaratorIdAST *declarator_id = new (_pool) DeclaratorIdAST; declarator_id->name = name; DeclaratorAST *ast = new (_pool) DeclaratorAST; ast->ptr_operators = ptr_operators; ast->core_declarator = declarator_id; node = ast; return true; } } else if (LA() == T_LPAREN) { unsigned lparen_token = consumeToken(); DeclaratorAST *declarator = 0; if (parseDeclarator(declarator) && LA() == T_RPAREN) { NestedDeclaratorAST *nested_declarator = new (_pool) NestedDeclaratorAST; nested_declarator->lparen_token = lparen_token; nested_declarator->declarator = declarator; nested_declarator->rparen_token = consumeToken(); DeclaratorAST *ast = new (_pool) DeclaratorAST; ast->ptr_operators = ptr_operators; ast->core_declarator = nested_declarator; node = ast; return true; } } return false; } bool Parser::parseDeclarator(DeclaratorAST *&node) { if (! parseCoreDeclarator(node)) return false; PostfixDeclaratorAST **postfix_ptr = &node->postfix_declarators; for (;;) { unsigned startOfPostDeclarator = cursor(); if (LA() == T_LPAREN) { FunctionDeclaratorAST *ast = new (_pool) FunctionDeclaratorAST; ast->lparen_token = consumeToken(); parseParameterDeclarationClause(ast->parameters); if (LA() != T_RPAREN) { rewind(startOfPostDeclarator); break; } ast->rparen_token = consumeToken(); parseCvQualifiers(ast->cv_qualifier_seq); parseExceptionSpecification(ast->exception_specification); *postfix_ptr = ast; postfix_ptr = &(*postfix_ptr)->next; } else if (LA() == T_LBRACKET) { ArrayDeclaratorAST *ast = new (_pool) ArrayDeclaratorAST; ast->lbracket_token = consumeToken(); if (LA() == T_RBRACKET || parseConstantExpression(ast->expression)) { match(T_RBRACKET, &ast->rbracket_token); } *postfix_ptr = ast; postfix_ptr = &(*postfix_ptr)->next; } else break; } SpecifierAST **spec_ptr = &node->attributes; while (LA() == T___ATTRIBUTE__) { parseAttributeSpecifier(*spec_ptr); spec_ptr = &(*spec_ptr)->next; } return true; } bool Parser::parseAbstractCoreDeclarator(DeclaratorAST *&node) { PtrOperatorAST *ptr_operators = 0, **ptr_operators_tail = &ptr_operators; while (parsePtrOperator(*ptr_operators_tail)) ptr_operators_tail = &(*ptr_operators_tail)->next; unsigned after_ptr_operators = cursor(); if (LA() == T_LPAREN) { unsigned lparen_token = consumeToken(); DeclaratorAST *declarator = 0; if (parseAbstractDeclarator(declarator) && LA() == T_RPAREN) { NestedDeclaratorAST *nested_declarator = new (_pool) NestedDeclaratorAST; nested_declarator->lparen_token = lparen_token; nested_declarator->declarator = declarator; nested_declarator->rparen_token = consumeToken(); DeclaratorAST *ast = new (_pool) DeclaratorAST; ast->ptr_operators = ptr_operators; ast->core_declarator = nested_declarator; node = ast; return true; } } rewind(after_ptr_operators); if (ptr_operators) { DeclaratorAST *ast = new (_pool) DeclaratorAST; ast->ptr_operators = ptr_operators; node = ast; } return true; } bool Parser::parseAbstractDeclarator(DeclaratorAST *&node) { if (! parseAbstractCoreDeclarator(node)) return false; PostfixDeclaratorAST *postfix_declarators = 0, **postfix_ptr = &postfix_declarators; for (;;) { if (LA() == T_LPAREN) { FunctionDeclaratorAST *ast = new (_pool) FunctionDeclaratorAST; ast->lparen_token = consumeToken(); if (LA() == T_RPAREN || parseParameterDeclarationClause(ast->parameters)) { if (LA() == T_RPAREN) ast->rparen_token = consumeToken(); } parseCvQualifiers(ast->cv_qualifier_seq); parseExceptionSpecification(ast->exception_specification); *postfix_ptr = ast; postfix_ptr = &(*postfix_ptr)->next; } else if (LA() == T_LBRACKET) { ArrayDeclaratorAST *ast = new (_pool) ArrayDeclaratorAST; ast->lbracket_token = consumeToken(); if (LA() == T_RBRACKET || parseConstantExpression(ast->expression)) { if (LA() == T_RBRACKET) ast->rbracket_token = consumeToken(); } *postfix_ptr = ast; postfix_ptr = &(*postfix_ptr)->next; } else break; } if (postfix_declarators) { if (! node) node = new (_pool) DeclaratorAST; node->postfix_declarators = postfix_declarators; } return true; } bool Parser::parseEnumSpecifier(SpecifierAST *&node) { if (LA() == T_ENUM) { unsigned enum_token = consumeToken(); NameAST *name = 0; parseName(name); if (LA() == T_LBRACE) { EnumSpecifierAST *ast = new (_pool) EnumSpecifierAST; ast->enum_token = enum_token; ast->name = name; ast->lbrace_token = consumeToken(); EnumeratorAST **enumerator_ptr = &ast->enumerators; while (int tk = LA()) { if (tk == T_RBRACE) break; if (LA() != T_IDENTIFIER) { _translationUnit->error(cursor(), "expected identifier before '%s'", tok().spell()); skipUntil(T_IDENTIFIER); } if (parseEnumerator(*enumerator_ptr)) enumerator_ptr = &(*enumerator_ptr)->next; if (LA() != T_RBRACE) { unsigned comma_token = 0; match(T_COMMA, &comma_token); } } match(T_RBRACE, &ast->rbrace_token); node = ast; return true; } } return false; } bool Parser::parseTemplateParameterList(DeclarationAST *&node) { DeclarationAST **template_parameter_ptr = &node; if (parseTemplateParameter(*template_parameter_ptr)) { template_parameter_ptr = &(*template_parameter_ptr)->next; while (LA() == T_COMMA) { consumeToken(); if (parseTemplateParameter(*template_parameter_ptr)) template_parameter_ptr = &(*template_parameter_ptr)->next; } return true; } return false; } bool Parser::parseTemplateParameter(DeclarationAST *&node) { if (parseTypeParameter(node)) return true; bool previousTemplateArguments = switchTemplateArguments(true); bool parsed = parseParameterDeclaration(node); (void) switchTemplateArguments(previousTemplateArguments); return parsed; } bool Parser::parseTypenameTypeParameter(DeclarationAST *&node) { if (LA() == T_CLASS || LA() == T_TYPENAME) { TypenameTypeParameterAST *ast = new (_pool) TypenameTypeParameterAST; ast->classkey_token = consumeToken(); parseName(ast->name); if (LA() == T_EQUAL) { ast->equal_token = consumeToken(); parseTypeId(ast->type_id); } node = ast; return true; } return false; } bool Parser::parseTemplateTypeParameter(DeclarationAST *&node) { if (LA() == T_TEMPLATE) { TemplateTypeParameterAST *ast = new (_pool) TemplateTypeParameterAST; ast->template_token = consumeToken(); if (LA() == T_LESS) ast->less_token = consumeToken(); parseTemplateParameterList(ast->template_parameters); if (LA() == T_GREATER) ast->greater_token = consumeToken(); if (LA() == T_CLASS) ast->class_token = consumeToken(); // parse optional name parseName(ast->name); if (LA() == T_EQUAL) { ast->equal_token = consumeToken(); parseTypeId(ast->type_id); } node = ast; return true; } return false; } bool Parser::parseTypeParameter(DeclarationAST *&node) { if (LA() == T_CLASS || LA() == T_TYPENAME) return parseTypenameTypeParameter(node); else if (LA() == T_TEMPLATE) return parseTemplateTypeParameter(node); else return false; } bool Parser::parseTypeId(ExpressionAST *&node) { SpecifierAST *type_specifier = 0; if (parseTypeSpecifier(type_specifier)) { TypeIdAST *ast = new (_pool) TypeIdAST; ast->type_specifier = type_specifier; parseAbstractDeclarator(ast->declarator); node = ast; return true; } return false; } bool Parser::parseParameterDeclarationClause(ParameterDeclarationClauseAST *&node) { DeclarationAST *parameter_declarations = 0; if (LA() != T_DOT_DOT_DOT) parseParameterDeclarationList(parameter_declarations); unsigned dot_dot_dot_token = 0; if (LA() == T_DOT_DOT_DOT || (LA() == T_COMMA && LA(2) == T_DOT_DOT_DOT)) { if (LA() == T_COMMA) consumeToken(); dot_dot_dot_token = consumeToken(); } ParameterDeclarationClauseAST *ast = new (_pool) ParameterDeclarationClauseAST; ast->parameter_declarations = parameter_declarations; ast->dot_dot_dot_token = dot_dot_dot_token; node = ast; return true; } bool Parser::parseParameterDeclarationList(DeclarationAST *&node) { DeclarationAST **parameter_declaration_ptr = &node; if (parseParameterDeclaration(*parameter_declaration_ptr)) { parameter_declaration_ptr = &(*parameter_declaration_ptr)->next; while (LA() == T_COMMA) { consumeToken(); if (LA() == T_DOT_DOT_DOT) break; if (parseParameterDeclaration(*parameter_declaration_ptr)) parameter_declaration_ptr = &(*parameter_declaration_ptr)->next; } return true; } return false; } bool Parser::parseParameterDeclaration(DeclarationAST *&node) { SpecifierAST *decl_specifier_seq = 0; if (parseDeclSpecifierSeq(decl_specifier_seq)) { ParameterDeclarationAST *ast = new (_pool) ParameterDeclarationAST; ast->type_specifier = decl_specifier_seq; parseDeclaratorOrAbstractDeclarator(ast->declarator); if (LA() == T_EQUAL) { ast->equal_token = consumeToken(); parseLogicalOrExpression(ast->expression); } node = ast; return true; } return false; } bool Parser::parseClassSpecifier(SpecifierAST *&node) { if (! lookAtClassKey()) return false; unsigned classkey_token = consumeToken(); SpecifierAST *attributes = 0, **attr_ptr = &attributes; while (LA() == T___ATTRIBUTE__) { parseAttributeSpecifier(*attr_ptr); attr_ptr = &(*attr_ptr)->next; } if (LA(1) == T_IDENTIFIER && LA(2) == T_IDENTIFIER) { _translationUnit->warning(cursor(), "skip identifier `%s'", tok().spell()); consumeToken(); } NameAST *name = 0; parseName(name); if (LA() == T_COLON || LA() == T_LBRACE) { BaseSpecifierAST *base_clause = 0; if (LA() == T_COLON) { parseBaseClause(base_clause); if (LA() != T_LBRACE) { _translationUnit->error(cursor(), "expected `{' before `%s'", tok().spell()); unsigned saved = cursor(); for (int n = 0; n < 3 && LA() != T_EOF_SYMBOL; ++n, consumeToken()) { if (LA() == T_LBRACE) break; } if (LA() != T_LBRACE) rewind(saved); } } ClassSpecifierAST *ast = new (_pool) ClassSpecifierAST; ast->classkey_token = classkey_token; ast->attributes = attributes; ast->name = name; ast->base_clause = base_clause; if (LA() == T_LBRACE) ast->lbrace_token = consumeToken(); DeclarationAST **declaration_ptr = &ast->member_specifiers; while (int tk = LA()) { if (tk == T_RBRACE) { ast->rbrace_token = consumeToken(); break; } unsigned start_declaration = cursor(); if (parseMemberSpecification(*declaration_ptr)) { if (*declaration_ptr) declaration_ptr = &(*declaration_ptr)->next; } else { rewind(start_declaration + 1); skipUntilDeclaration(); } } node = ast; return true; } return false; } bool Parser::parseAccessSpecifier(SpecifierAST *&node) { switch (LA()) { case T_PUBLIC: case T_PROTECTED: case T_PRIVATE: { SimpleSpecifierAST *ast = new (_pool) SimpleSpecifierAST; ast->specifier_token = consumeToken(); node = ast; return true; } default: return false; } // switch } bool Parser::parseAccessDeclaration(DeclarationAST *&node) { if (LA() == T_PUBLIC || LA() == T_PROTECTED || LA() == T_PRIVATE || LA() == T_SIGNALS) { bool isSignals = LA() == T_SIGNALS; AccessDeclarationAST *ast = new (_pool) AccessDeclarationAST; ast->access_specifier_token = consumeToken(); if (! isSignals && LA() == T_SLOTS) ast->slots_token = consumeToken(); match(T_COLON, &ast->colon_token); node = ast; return true; } return false; } bool Parser::parseMemberSpecification(DeclarationAST *&node) { switch (LA()) { case T_SEMICOLON: return parseEmptyDeclaration(node); case T_USING: return parseUsing(node); case T_TEMPLATE: return parseTemplateDeclaration(node); case T_SIGNALS: case T_PUBLIC: case T_PROTECTED: case T_PRIVATE: return parseAccessDeclaration(node); default: return parseSimpleDeclaration(node, /*acceptStructDeclarator=*/true); } // switch } bool Parser::parseCtorInitializer(CtorInitializerAST *&node) { if (LA() == T_COLON) { unsigned colon_token = consumeToken(); CtorInitializerAST *ast = new (_pool) CtorInitializerAST; ast->colon_token = colon_token; parseMemInitializerList(ast->member_initializers); node = ast; return true; } return false; } bool Parser::parseElaboratedTypeSpecifier(SpecifierAST *&node) { if (lookAtClassKey() || LA() == T_ENUM || LA() == T_TYPENAME) { unsigned classkey_token = consumeToken(); NameAST *name = 0; if (parseName(name)) { ElaboratedTypeSpecifierAST *ast = new (_pool) ElaboratedTypeSpecifierAST; ast->classkey_token = classkey_token; ast->name = name; node = ast; return true; } } return false; } bool Parser::parseExceptionSpecification(ExceptionSpecificationAST *&node) { if (LA() == T_THROW) { ExceptionSpecificationAST *ast = new (_pool) ExceptionSpecificationAST; ast->throw_token = consumeToken(); if (LA() == T_LPAREN) ast->lparen_token = consumeToken(); if (LA() == T_DOT_DOT_DOT) ast->dot_dot_dot_token = consumeToken(); else parseTypeIdList(ast->type_ids); if (LA() == T_RPAREN) ast->rparen_token = consumeToken(); node = ast; return true; } return false; } bool Parser::parseEnumerator(EnumeratorAST *&node) { if (LA() == T_IDENTIFIER) { EnumeratorAST *ast = new (_pool) EnumeratorAST; ast->identifier_token = consumeToken(); if (LA() == T_EQUAL) { ast->equal_token = consumeToken(); parseConstantExpression(ast->expression); } node = ast; return true; } return false; } bool Parser::parseInitDeclarator(DeclaratorAST *&node, bool acceptStructDeclarator) { unsigned start = cursor(); if (acceptStructDeclarator && LA() == T_COLON) { // anonymous bit-field declaration. // ### TODO create the AST } else if (! parseDeclarator(node)) { return false; } if (LA() == T_ASM && LA(2) == T_LPAREN) { // ### FIXME consumeToken(); if (skip(T_LPAREN, T_RPAREN)) consumeToken(); } if (acceptStructDeclarator && node && ! node->postfix_declarators && node->core_declarator && node->core_declarator->asNestedDeclarator()) { rewind(start); return false; } if (acceptStructDeclarator && LA() == T_COLON && (! node || ! node->postfix_declarators)) { unsigned colon_token = consumeToken(); ExpressionAST *expression = 0; if (parseConstantExpression(expression) && (LA() == T_COMMA || LA() == T_SEMICOLON)) { // recognized a bitfielddeclarator. // ### TODO create the AST return true; } rewind(colon_token); } else if (LA() == T_EQUAL || (! acceptStructDeclarator && LA() == T_LPAREN)) { parseInitializer(node->initializer); } return true; } bool Parser::parseBaseClause(BaseSpecifierAST *&node) { if (LA() == T_COLON) { consumeToken(); BaseSpecifierAST **ast = &node; if (parseBaseSpecifier(*ast)) { ast = &(*ast)->next; while (LA() == T_COMMA) { consumeToken(); if (parseBaseSpecifier(*ast)) ast = &(*ast)->next; } } return true; } return false; } bool Parser::parseInitializer(ExpressionAST *&node) { if (LA() == T_LPAREN) { return parsePrimaryExpression(node); } else if (LA() == T_EQUAL) { consumeToken(); return parseInitializerClause(node); } return false; } bool Parser::parseMemInitializerList(MemInitializerAST *&node) { MemInitializerAST **initializer = &node; if (parseMemInitializer(*initializer)) { initializer = &(*initializer)->next; while (LA() == T_COMMA) { consumeToken(); if (parseMemInitializer(*initializer)) initializer = &(*initializer)->next; } return true; } return false; } bool Parser::parseMemInitializer(MemInitializerAST *&node) { NameAST *name = 0; if (parseName(name) && LA() == T_LPAREN) { MemInitializerAST *ast = new (_pool) MemInitializerAST; ast->name = name; ast->lparen_token = consumeToken(); parseExpression(ast->expression); if (LA() == T_RPAREN) ast->rparen_token = consumeToken(); node = ast; return true; } return false; } bool Parser::parseTypeIdList(ExpressionListAST *&node) { ExpressionListAST **expression_list_ptr = &node; ExpressionAST *typeId = 0; if (parseTypeId(typeId)) { *expression_list_ptr = new (_pool) ExpressionListAST; (*expression_list_ptr)->expression = typeId; expression_list_ptr = &(*expression_list_ptr)->next; while (LA() == T_COMMA) { consumeToken(); if (parseTypeId(typeId)) { *expression_list_ptr = new (_pool) ExpressionListAST; (*expression_list_ptr)->expression = typeId; expression_list_ptr = &(*expression_list_ptr)->next; } } return true; } return false; } bool Parser::parseExpressionList(ExpressionListAST *&node) { ExpressionListAST **expression_list_ptr = &node; ExpressionAST *expression = 0; if (parseAssignmentExpression(expression)) { *expression_list_ptr = new (_pool) ExpressionListAST; (*expression_list_ptr)->expression = expression; expression_list_ptr = &(*expression_list_ptr)->next; while (LA() == T_COMMA) { consumeToken(); if (parseExpression(expression)) { *expression_list_ptr = new (_pool) ExpressionListAST; (*expression_list_ptr)->expression = expression; expression_list_ptr = &(*expression_list_ptr)->next; } } return true; } return false; } bool Parser::parseBaseSpecifier(BaseSpecifierAST *&node) { BaseSpecifierAST *ast = new (_pool) BaseSpecifierAST; if (LA() == T_VIRTUAL) { ast->token_virtual = consumeToken(); int tk = LA(); if (tk == T_PUBLIC || tk == T_PROTECTED || tk == T_PRIVATE) ast->token_access_specifier = consumeToken(); } else { int tk = LA(); if (tk == T_PUBLIC || tk == T_PROTECTED || tk == T_PRIVATE) ast->token_access_specifier = consumeToken(); if (LA() == T_VIRTUAL) ast->token_virtual = consumeToken(); } parseName(ast->name); if (! ast->name) _translationUnit->error(cursor(), "expected class-name"); node = ast; return true; } bool Parser::parseInitializerList(ExpressionListAST *&node) { ExpressionListAST **initializer_ptr = &node; ExpressionAST *initializer = 0; if (parseInitializerClause(initializer)) { *initializer_ptr = new (_pool) ExpressionListAST; (*initializer_ptr)->expression = initializer; initializer_ptr = &(*initializer_ptr)->next; while (LA() == T_COMMA) { consumeToken(); initializer = 0; parseInitializerClause(initializer); *initializer_ptr = new (_pool) ExpressionListAST; (*initializer_ptr)->expression = initializer; initializer_ptr = &(*initializer_ptr)->next; } } return true; } bool Parser::parseInitializerClause(ExpressionAST *&node) { if (LA() == T_LBRACE) { ArrayInitializerAST *ast = new (_pool) ArrayInitializerAST; ast->lbrace_token = consumeToken(); parseInitializerList(ast->expression_list); if (LA() == T_RBRACE) ast->rbrace_token = consumeToken(); node = ast; return true; } return parseAssignmentExpression(node); } bool Parser::parseUnqualifiedName(NameAST *&node, bool acceptTemplateId) { if (LA() == T_TILDE && LA(2) == T_IDENTIFIER) { DestructorNameAST *ast = new (_pool) DestructorNameAST; ast->tilde_token = consumeToken(); ast->identifier_token = consumeToken(); node = ast; return true; } else if (LA() == T_OPERATOR) { unsigned operator_token = cursor(); if (parseOperatorFunctionId(node)) return true; rewind(operator_token); return parseConversionFunctionId(node); } else if (LA() == T_IDENTIFIER) { unsigned identifier_token = cursor(); if (acceptTemplateId && LA(2) == T_LESS && parseTemplateId(node)) { if (! _templateArguments || (LA() == T_COMMA || LA() == T_GREATER || LA() == T_LPAREN || LA() == T_RPAREN || LA() == T_COLON_COLON)) return true; } rewind(identifier_token); SimpleNameAST *ast = new (_pool) SimpleNameAST; ast->identifier_token = consumeToken(); node = ast; return true; } else if (LA() == T_TEMPLATE) { unsigned template_token = consumeToken(); if (parseTemplateId(node)) return true; rewind(template_token); } return false; } bool Parser::parseStringLiteral(ExpressionAST *&node) { if (! (LA() == T_STRING_LITERAL || LA() == T_WIDE_STRING_LITERAL)) return false; StringLiteralAST **ast = reinterpret_cast (&node); while (LA() == T_STRING_LITERAL || LA() == T_WIDE_STRING_LITERAL) { *ast = new (_pool) StringLiteralAST; (*ast)->token = consumeToken(); ast = &(*ast)->next; } return true; } bool Parser::parseExpressionStatement(StatementAST *&node) { ExpressionAST *expression = 0; if (LA() == T_SEMICOLON || parseExpression(expression)) { ExpressionStatementAST *ast = new (_pool) ExpressionStatementAST; ast->expression = expression; match(T_SEMICOLON, &ast->semicolon_token); node = ast; return true; } return false; } bool Parser::parseStatement(StatementAST *&node) { switch (LA()) { case T_WHILE: return parseWhileStatement(node); case T_DO: return parseDoStatement(node); case T_FOR: return parseForStatement(node); case T_IF: return parseIfStatement(node); case T_SWITCH: return parseSwitchStatement(node); case T_TRY: return parseTryBlockStatement(node); case T_CASE: case T_DEFAULT: return parseLabeledStatement(node); case T_BREAK: return parseBreakStatement(node); case T_CONTINUE: return parseContinueStatement(node); case T_GOTO: return parseGotoStatement(node); case T_RETURN: return parseReturnStatement(node); case T_LBRACE: return parseCompoundStatement(node); case T_ASM: case T_NAMESPACE: case T_USING: case T_TEMPLATE: case T_CLASS: case T_STRUCT: case T_UNION: return parseDeclarationStatement(node); case T_SEMICOLON: { ExpressionStatementAST *ast = new (_pool) ExpressionStatementAST; ast->semicolon_token = consumeToken(); node = ast; return true; } default: if (LA() == T_IDENTIFIER && LA(2) == T_COLON) return parseLabeledStatement(node); return parseExpressionOrDeclarationStatement(node); } // switch return false; } bool Parser::parseBreakStatement(StatementAST *&node) { if (LA() == T_BREAK) { BreakStatementAST *ast = new (_pool) BreakStatementAST; ast->break_token = consumeToken(); match(T_SEMICOLON, &ast->semicolon_token); node = ast; return true; } return false; } bool Parser::parseContinueStatement(StatementAST *&node) { if (LA() == T_CONTINUE) { ContinueStatementAST *ast = new (_pool) ContinueStatementAST; ast->continue_token = consumeToken(); match(T_SEMICOLON, &ast->semicolon_token); node = ast; return true; } return false; } bool Parser::parseGotoStatement(StatementAST *&node) { if (LA() == T_GOTO) { GotoStatementAST *ast = new (_pool) GotoStatementAST; ast->goto_token = consumeToken(); match(T_IDENTIFIER, &ast->identifier_token); match(T_SEMICOLON, &ast->semicolon_token); node = ast; return true; } return false; } bool Parser::parseReturnStatement(StatementAST *&node) { if (LA() == T_RETURN) { ReturnStatementAST *ast = new (_pool) ReturnStatementAST; ast->return_token = consumeToken(); parseExpression(ast->expression); match(T_SEMICOLON, &ast->semicolon_token); node = ast; return true; } return false; } bool Parser::maybeFunctionCall(SimpleDeclarationAST *simpleDecl) { if (! simpleDecl) return false; else if (! simpleDecl->decl_specifier_seq) return false; else if (simpleDecl->decl_specifier_seq->next) return false; NamedTypeSpecifierAST *type_spec = simpleDecl->decl_specifier_seq->asNamedTypeSpecifier(); if (! type_spec) return false; DeclaratorListAST *first_declarator = simpleDecl->declarators; if (! first_declarator) return false; else if (first_declarator->next) return false; DeclaratorAST *declarator = first_declarator->declarator; if (! declarator) return false; else if (declarator->ptr_operators) return false; else if (declarator->postfix_declarators) return false; else if (declarator->initializer) return false; else if (! declarator->core_declarator) return false; NestedDeclaratorAST *nested_declarator = declarator->core_declarator->asNestedDeclarator(); if (! nested_declarator) return false; return true; } bool Parser::parseExpressionOrDeclarationStatement(StatementAST *&node) { if (LA() == T_SEMICOLON) return parseExpressionStatement(node); unsigned start = cursor(); bool blocked = blockErrors(true); if (parseDeclarationStatement(node)) { DeclarationStatementAST *stmt = static_cast(node); SimpleDeclarationAST *simpleDecl = 0; if (stmt->declaration) simpleDecl = stmt->declaration->asSimpleDeclaration(); if (simpleDecl && simpleDecl->decl_specifier_seq && ! maybeFunctionCall(simpleDecl)) { 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; ast->declaration = node; ast->expression = expression; node = ast; } blockErrors(blocked); return true; } } blockErrors(blocked); rewind(start); return parseExpressionStatement(node); } bool Parser::parseCondition(ExpressionAST *&node) { unsigned start = cursor(); bool blocked = blockErrors(true); SpecifierAST *type_specifier = 0; if (parseTypeSpecifier(type_specifier)) { DeclaratorAST *declarator = 0; if (parseInitDeclarator(declarator, /*acceptStructDeclarator=*/false)) { if (declarator->initializer) { ConditionAST *ast = new (_pool) ConditionAST; ast->type_specifier = type_specifier; ast->declarator = declarator; node = ast; blockErrors(blocked); return true; } } } blockErrors(blocked); rewind(start); return parseExpression(node); } bool Parser::parseWhileStatement(StatementAST *&node) { if (LA() == T_WHILE) { WhileStatementAST *ast = new (_pool) WhileStatementAST; ast->while_token = consumeToken(); match(T_LPAREN, &ast->lparen_token); parseCondition(ast->condition); match(T_RPAREN, &ast->rparen_token); parseStatement(ast->statement); node = ast; return true; } return true; } bool Parser::parseDoStatement(StatementAST *&node) { if (LA() == T_DO) { DoStatementAST *ast = new (_pool) DoStatementAST; ast->do_token = consumeToken(); parseStatement(ast->statement); match(T_WHILE, &ast->while_token); match(T_LPAREN, &ast->lparen_token); parseExpression(ast->expression); match(T_RPAREN, &ast->rparen_token); match(T_SEMICOLON, &ast->semicolon_token); node = ast; return true; } return false; } bool Parser::parseForStatement(StatementAST *&node) { if (LA() == T_FOR) { ForStatementAST *ast = new (_pool) ForStatementAST; ast->for_token = consumeToken(); match(T_LPAREN, &ast->lparen_token); parseForInitStatement(ast->initializer); parseExpression(ast->condition); match(T_SEMICOLON, &ast->semicolon_token); parseExpression(ast->expression); match(T_RPAREN, &ast->rparen_token); parseStatement(ast->statement); node = ast; return true; } return false; } bool Parser::parseForInitStatement(StatementAST *&node) { return parseExpressionOrDeclarationStatement(node); } bool Parser::parseCompoundStatement(StatementAST *&node) { if (LA() == T_LBRACE) { CompoundStatementAST *ast = new (_pool) CompoundStatementAST; ast->lbrace_token = consumeToken(); StatementAST **statement_ptr = &ast->statements; while (int tk = LA()) { if (tk == T_RBRACE) break; unsigned start_statement = cursor(); if (! parseStatement(*statement_ptr)) { rewind(start_statement + 1); skipUntilStatement(); } else { statement_ptr = &(*statement_ptr)->next; } } match(T_RBRACE, &ast->rbrace_token); node = ast; return true; } return false; } bool Parser::parseIfStatement(StatementAST *&node) { if (LA() == T_IF) { IfStatementAST *ast = new (_pool) IfStatementAST; ast->if_token = consumeToken(); match(T_LPAREN, &ast->lparen_token); parseCondition(ast->condition); match(T_RPAREN, &ast->rparen_token); if (! parseStatement(ast->statement)) _translationUnit->error(cursor(), "expected statement"); if (LA() == T_ELSE) { ast->else_token = consumeToken(); if (! parseStatement(ast->else_statement)) _translationUnit->error(cursor(), "expected statement"); } node = ast; return true; } return false; } bool Parser::parseSwitchStatement(StatementAST *&node) { if (LA() == T_SWITCH) { SwitchStatementAST *ast = new (_pool) SwitchStatementAST; ast->switch_token = consumeToken(); match(T_LPAREN, &ast->lparen_token); parseCondition(ast->condition); match(T_RPAREN, &ast->rparen_token); parseStatement(ast->statement); node = ast; return true; } return false; } bool Parser::parseLabeledStatement(StatementAST *&node) { switch (LA()) { case T_IDENTIFIER: if (LA(2) == T_COLON) { LabeledStatementAST *ast = new (_pool) LabeledStatementAST; ast->label_token = consumeToken(); ast->colon_token = consumeToken(); parseStatement(ast->statement); node = ast; return true; } break; case T_DEFAULT: { LabeledStatementAST *ast = new (_pool) LabeledStatementAST; ast->label_token = consumeToken(); match(T_COLON, &ast->colon_token); parseStatement(ast->statement); node = ast; return true; } case T_CASE: { CaseStatementAST *ast = new (_pool) CaseStatementAST; ast->case_token = consumeToken(); parseConstantExpression(ast->expression); match(T_COLON, &ast->colon_token); parseStatement(ast->statement); node = ast; return true; } default: break; } // switch return false; } bool Parser::parseBlockDeclaration(DeclarationAST *&node) { switch (LA()) { case T_USING: return parseUsing(node); case T_ASM: return parseAsmDefinition(node); case T_NAMESPACE: return parseNamespaceAliasDefinition(node); default: return parseSimpleDeclaration(node); } // switch } bool Parser::parseNamespaceAliasDefinition(DeclarationAST *&node) { if (LA() == T_NAMESPACE && LA(2) == T_IDENTIFIER && LA(3) == T_EQUAL) { NamespaceAliasDefinitionAST *ast = new (_pool) NamespaceAliasDefinitionAST; ast->namespace_token = consumeToken(); ast->namespace_name = consumeToken(); ast->equal_token = consumeToken(); parseName(ast->name); match(T_SEMICOLON, &ast->semicolon_token); node = ast; return true; } return false; } bool Parser::parseDeclarationStatement(StatementAST *&node) { DeclarationAST *declaration = 0; if (! parseBlockDeclaration(declaration)) return false; DeclarationStatementAST *ast = new (_pool) DeclarationStatementAST; ast->declaration = declaration; node = ast; return true; } bool Parser::lookAtCVQualifier() const { switch (LA()) { case T_CONST: case T_VOLATILE: return true; default: return false; } } bool Parser::lookAtFunctionSpecifier() const { switch (LA()) { case T_INLINE: case T_VIRTUAL: case T_EXPLICIT: return true; default: return false; } } bool Parser::lookAtStorageClassSpecifier() const { switch (LA()) { case T_FRIEND: case T_AUTO: case T_REGISTER: case T_STATIC: case T_EXTERN: case T_MUTABLE: case T_TYPEDEF: return true; default: return false; } } bool Parser::lookAtBuiltinTypeSpecifier() const { switch (LA()) { case T_CHAR: case T_WCHAR_T: case T_BOOL: case T_SHORT: case T_INT: case T_LONG: case T_SIGNED: case T_UNSIGNED: case T_FLOAT: case T_DOUBLE: case T_VOID: return true; // [gcc] extensions case T___TYPEOF__: case T___ATTRIBUTE__: return true; default: return false; } } bool Parser::lookAtClassKey() const { switch (LA()) { case T_CLASS: case T_STRUCT: case T_UNION: return true; default: return false; } } bool Parser::parseAttributeSpecifier(SpecifierAST *&node) { if (LA() != T___ATTRIBUTE__) return false; AttributeSpecifierAST *ast = new (_pool) AttributeSpecifierAST; ast->attribute_token = consumeToken(); match(T_LPAREN, &ast->first_lparen_token); match(T_LPAREN, &ast->second_lparen_token); parseAttributeList(ast->attributes); match(T_RPAREN, &ast->first_rparen_token); match(T_RPAREN, &ast->second_rparen_token); node = ast; return true; } bool Parser::parseAttributeList(AttributeAST *&node) { AttributeAST **attribute_ptr = &node; while (LA() == T_IDENTIFIER || LA() == T_CONST) { AttributeAST *ast = new (_pool) AttributeAST; ast->identifier_token = consumeToken(); if (LA() == T_LPAREN) { consumeToken(); if (LA() == T_IDENTIFIER && (LA(2) == T_COMMA || LA(2) == T_RPAREN)) { ast->tag_token = consumeToken(); if (LA() == T_COMMA) { consumeToken(); parseExpressionList(ast->expression_list); } } else { parseExpressionList(ast->expression_list); } unsigned rparen_token = 0; match(T_RPAREN, &rparen_token); } *attribute_ptr = ast; if (LA() != T_COMMA) break; consumeToken(); attribute_ptr = &(*attribute_ptr)->next; } return true; } bool Parser::parseBuiltinTypeSpecifier(SpecifierAST *&node) { if (LA() == T___ATTRIBUTE__) { return parseAttributeSpecifier(node); } else if (LA() == T___TYPEOF__) { TypeofSpecifierAST *ast = new (_pool) TypeofSpecifierAST; ast->typeof_token = consumeToken(); if (LA() == T_LPAREN) { unsigned lparen_token = consumeToken(); if (parseTypeId(ast->expression) && LA() == T_RPAREN) { consumeToken(); node = ast; return true; } rewind(lparen_token); } parseUnaryExpression(ast->expression); node = ast; return true; } else if (lookAtBuiltinTypeSpecifier()) { SimpleSpecifierAST *ast = new (_pool) SimpleSpecifierAST; ast->specifier_token = consumeToken(); node = ast; return true; } return false; } bool Parser::parseSimpleDeclaration(DeclarationAST *&node, bool acceptStructDeclarator) { // parse a simple declaration, a function definition, // or a contructor declaration. cursor(); bool has_type_specifier = false; bool has_complex_type_specifier = false; unsigned startOfNamedTypeSpecifier = 0; NameAST *named_type_specifier = 0; SpecifierAST *decl_specifier_seq = 0, **decl_specifier_seq_ptr = &decl_specifier_seq; for (;;) { if (lookAtCVQualifier() || lookAtFunctionSpecifier() || lookAtStorageClassSpecifier()) { SimpleSpecifierAST *spec = new (_pool) SimpleSpecifierAST; spec->specifier_token = consumeToken(); *decl_specifier_seq_ptr = spec; decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next; } else if (LA() == T___ATTRIBUTE__) { parseAttributeSpecifier(*decl_specifier_seq_ptr); decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next; } else if (! named_type_specifier && ! has_complex_type_specifier && lookAtBuiltinTypeSpecifier()) { parseBuiltinTypeSpecifier(*decl_specifier_seq_ptr); decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next; has_type_specifier = true; } else if (! has_type_specifier && (LA() == T_COLON_COLON || LA() == T_IDENTIFIER)) { startOfNamedTypeSpecifier = cursor(); if (parseName(named_type_specifier)) { NamedTypeSpecifierAST *spec = new (_pool) NamedTypeSpecifierAST; spec->name = named_type_specifier; *decl_specifier_seq_ptr = spec; decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next; has_type_specifier = true; } else { rewind(startOfNamedTypeSpecifier); break; } } else if (! has_type_specifier && LA() == T_ENUM) { unsigned startOfTypeSpecifier = cursor(); if (! parseElaboratedTypeSpecifier(*decl_specifier_seq_ptr) || LA() == T_LBRACE) { rewind(startOfTypeSpecifier); if (! parseEnumSpecifier(*decl_specifier_seq_ptr)) { _translationUnit->error(startOfTypeSpecifier, "expected an enum specifier"); break; } has_complex_type_specifier = true; } decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next; has_type_specifier = true; } else if (! has_type_specifier && LA() == T_TYPENAME) { unsigned startOfElaboratedTypeSpecifier = cursor(); if (! parseElaboratedTypeSpecifier(*decl_specifier_seq_ptr)) { _translationUnit->error(startOfElaboratedTypeSpecifier, "expected an elaborated type specifier"); break; } decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next; has_type_specifier = true; } else if (! has_type_specifier && lookAtClassKey()) { unsigned startOfTypeSpecifier = cursor(); if (! parseElaboratedTypeSpecifier(*decl_specifier_seq_ptr) || (LA() == T_COLON || LA() == T_LBRACE || (LA(0) == T_IDENTIFIER && LA(1) == T_IDENTIFIER && (LA(2) == T_COLON || LA(2) == T_LBRACE)))) { rewind(startOfTypeSpecifier); if (! parseClassSpecifier(*decl_specifier_seq_ptr)) { _translationUnit->error(startOfTypeSpecifier, "wrong type specifier"); break; } has_complex_type_specifier = true; } decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next; has_type_specifier = true; } else break; } DeclaratorListAST *declarator_list = 0, **declarator_ptr = &declarator_list; const bool maybeCtor = (LA() == T_LPAREN && named_type_specifier); DeclaratorAST *declarator = 0; if (! parseInitDeclarator(declarator, acceptStructDeclarator) && maybeCtor) { rewind(startOfNamedTypeSpecifier); named_type_specifier = 0; // pop the named type specifier from the decl-specifier-seq SpecifierAST **spec_ptr = &decl_specifier_seq; for (; *spec_ptr; spec_ptr = &(*spec_ptr)->next) { if (! (*spec_ptr)->next) { *spec_ptr = 0; break; } } if (! parseInitDeclarator(declarator, acceptStructDeclarator)) return false; } DeclaratorAST *firstDeclarator = declarator; if (declarator) { *declarator_ptr = new (_pool) DeclaratorListAST; (*declarator_ptr)->declarator = declarator; declarator_ptr = &(*declarator_ptr)->next; } if (LA() == T_COMMA || LA() == T_SEMICOLON || has_complex_type_specifier) { while (LA() == T_COMMA) { consumeToken(); declarator = 0; if (parseInitDeclarator(declarator, acceptStructDeclarator)) { *declarator_ptr = new (_pool) DeclaratorListAST; (*declarator_ptr)->declarator = declarator; declarator_ptr = &(*declarator_ptr)->next; } } SimpleDeclarationAST *ast = new (_pool) SimpleDeclarationAST; ast->decl_specifier_seq = decl_specifier_seq; ast->declarators = declarator_list; match(T_SEMICOLON, &ast->semicolon_token); node = ast; return true; } else if (! _inFunctionBody && declarator && (LA() == T_COLON || LA() == T_LBRACE || LA() == T_TRY)) { CtorInitializerAST *ctor_initializer = 0; if (LA() == T_COLON) parseCtorInitializer(ctor_initializer); if (LA() == T_LBRACE) { FunctionDefinitionAST *ast = new (_pool) FunctionDefinitionAST; ast->decl_specifier_seq = decl_specifier_seq; ast->declarator = firstDeclarator; ast->ctor_initializer = ctor_initializer; parseFunctionBody(ast->function_body); node = ast; return true; // recognized a function definition. } else if (LA() == T_TRY) { FunctionDefinitionAST *ast = new (_pool) FunctionDefinitionAST; ast->decl_specifier_seq = decl_specifier_seq; ast->declarator = firstDeclarator; ast->ctor_initializer = ctor_initializer; parseTryBlockStatement(ast->function_body); node = ast; return true; // recognized a function definition. } } _translationUnit->error(cursor(), "unexpected token `%s'", tok().spell()); return false; } bool Parser::parseFunctionBody(StatementAST *&node) { if (_translationUnit->skipFunctionBody()) { unsigned token_lbrace = 0; match(T_LBRACE, &token_lbrace); if (! token_lbrace) return false; const Token &tk = _translationUnit->tokenAt(token_lbrace); if (tk.close_brace) rewind(tk.close_brace); unsigned token_rbrace = 0; match(T_RBRACE, &token_rbrace); return true; } _inFunctionBody = true; const bool parsed = parseCompoundStatement(node); _inFunctionBody = false; return parsed; } bool Parser::parseTryBlockStatement(StatementAST *&node) { if (LA() == T_TRY) { TryBlockStatementAST *ast = new (_pool) TryBlockStatementAST; ast->try_token = consumeToken(); parseCompoundStatement(ast->statement); CatchClauseAST **catch_clause_ptr = &ast->catch_clause_seq; while (parseCatchClause(*catch_clause_ptr)) catch_clause_ptr = &(*catch_clause_ptr)->next; node = ast; return true; } return false; } bool Parser::parseCatchClause(CatchClauseAST *&node) { if (LA() == T_CATCH) { CatchClauseAST *ast = new (_pool) CatchClauseAST; ast->catch_token = consumeToken(); match(T_LPAREN, &ast->lparen_token); parseExceptionDeclaration(ast->exception_declaration); match(T_RPAREN, &ast->rparen_token); parseCompoundStatement(ast->statement); node = ast; return true; } return false; } bool Parser::parseExceptionDeclaration(ExceptionDeclarationAST *&node) { if (LA() == T_DOT_DOT_DOT) { ExceptionDeclarationAST *ast = new (_pool) ExceptionDeclarationAST; ast->dot_dot_dot_token = consumeToken(); node = ast; return true; } SpecifierAST *type_specifier = 0; if (parseTypeSpecifier(type_specifier)) { ExceptionDeclarationAST *ast = new (_pool) ExceptionDeclarationAST; ast->type_specifier = type_specifier; parseDeclaratorOrAbstractDeclarator(ast->declarator); node = ast; return true; } return false; } bool Parser::parseBoolLiteral(ExpressionAST *&node) { if (LA() == T_TRUE || LA() == T_FALSE) { BoolLiteralAST *ast = new (_pool) BoolLiteralAST; ast->token = consumeToken(); node = ast; return true; } return false; } bool Parser::parseNumericLiteral(ExpressionAST *&node) { if (LA() == T_INT_LITERAL || LA() == T_FLOAT_LITERAL || LA() == T_CHAR_LITERAL) { NumericLiteralAST *ast = new (_pool) NumericLiteralAST; ast->token = consumeToken(); node = ast; return true; } return false; } bool Parser::parseThisExpression(ExpressionAST *&node) { if (LA() == T_THIS) { ThisExpressionAST *ast = new (_pool) ThisExpressionAST; ast->this_token = consumeToken(); node = ast; return true; } return false; } bool Parser::parsePrimaryExpression(ExpressionAST *&node) { switch (LA()) { case T_STRING_LITERAL: case T_WIDE_STRING_LITERAL: return parseStringLiteral(node); case T_INT_LITERAL: case T_FLOAT_LITERAL: case T_CHAR_LITERAL: case T_WIDE_CHAR_LITERAL: return parseNumericLiteral(node); case T_TRUE: case T_FALSE: return parseBoolLiteral(node); case T_THIS: return parseThisExpression(node); case T_LPAREN: return parseNestedExpression(node); case T_SIGNAL: case T_SLOT: return parseQtMethod(node); default: { unsigned startOfName = cursor(); NameAST *name = 0; if (parseName(name)) { if (LA() == T_IDENTIFIER || tok().isLiteral() || (tok().isOperator() && LA() != T_LPAREN && LA() != T_LBRACKET)) { rewind(startOfName); parseName(name, false); } // literal // identifier ? // identifier // identifier // identifier rparen // lparen type rparen identifier [[cast-expression]] node = name; return true; } } // default } // switch return false; } bool Parser::parseNestedExpression(ExpressionAST *&node) { if (LA() == T_LPAREN) { unsigned lparen_token = consumeToken(); if (LA() == T_LBRACE) { NestedExpressionAST *ast = new (_pool) NestedExpressionAST; ast->lparen_token = lparen_token; // ### ast StatementAST *statement = 0; parseCompoundStatement(statement); match(T_RPAREN, &ast->rparen_token); node = ast; return true; } bool previousTemplateArguments = switchTemplateArguments(false); ExpressionAST *expression = 0; if (parseExpression(expression) && LA() == T_RPAREN) { NestedExpressionAST *ast = new (_pool) NestedExpressionAST; ast->lparen_token = lparen_token; ast->expression = expression; ast->rparen_token = consumeToken(); node = ast; (void) switchTemplateArguments(previousTemplateArguments); return true; } (void) switchTemplateArguments(previousTemplateArguments); } return false; } bool Parser::parseCppCastExpression(ExpressionAST *&node) { if (LA() == T_DYNAMIC_CAST || LA() == T_STATIC_CAST || LA() == T_REINTERPRET_CAST || LA() == T_CONST_CAST) { CppCastExpressionAST *ast = new (_pool) CppCastExpressionAST; ast->cast_token = consumeToken(); match(T_LESS, &ast->less_token); parseTypeId(ast->type_id); match(T_GREATER, &ast->greater_token); match(T_LPAREN, &ast->lparen_token); parseExpression(ast->expression); match(T_RPAREN, &ast->rparen_token); node = ast; return true; } return false; } // typename ::opt nested-name-specifier identifier ( expression-listopt ) // typename ::opt nested-name-specifier templateopt template-id ( expression-listopt ) bool Parser::parseTypenameCallExpression(ExpressionAST *&node) { if (LA() == T_TYPENAME) { unsigned typename_token = consumeToken(); NameAST *name = 0; if (parseName(name) && LA() == T_LPAREN) { TypenameCallExpressionAST *ast = new (_pool) TypenameCallExpressionAST; ast->typename_token = typename_token; ast->name = name; ast->lparen_token = consumeToken(); parseExpressionList(ast->expression_list); match(T_RPAREN, &ast->rparen_token); node = ast; return true; } } return false; } // typeid ( expression ) // typeid ( type-id ) bool Parser::parseTypeidExpression(ExpressionAST *&node) { if (LA() == T_TYPEID) { TypeidExpressionAST *ast = new (_pool) TypeidExpressionAST; ast->typeid_token = consumeToken(); if (LA() == T_LPAREN) ast->lparen_token = consumeToken(); unsigned saved = cursor(); if (! (parseTypeId(ast->expression) && LA() == T_RPAREN)) { rewind(saved); parseExpression(ast->expression); } match(T_RPAREN, &ast->rparen_token); node = ast; return true; } return false; } bool Parser::parseCorePostfixExpression(ExpressionAST *&node) { if (parseCppCastExpression(node)) return true; else if (parseTypenameCallExpression(node)) return true; else if (parseTypeidExpression(node)) return true; else { unsigned start = cursor(); SpecifierAST *type_specifier = 0; bool blocked = blockErrors(true); if (lookAtBuiltinTypeSpecifier() && parseSimpleTypeSpecifier(type_specifier) && LA() == T_LPAREN) { unsigned lparen_token = consumeToken(); ExpressionListAST *expression_list = 0; parseExpressionList(expression_list); if (LA() == T_RPAREN) { unsigned rparen_token = consumeToken(); TypeConstructorCallAST *ast = new (_pool) TypeConstructorCallAST; ast->type_specifier = type_specifier; ast->lparen_token = lparen_token; ast->expression_list = expression_list; ast->rparen_token = rparen_token; node = ast; blockErrors(blocked); return true; } } blockErrors(blocked); rewind(start); return parsePrimaryExpression(node); } } bool Parser::parsePostfixExpression(ExpressionAST *&node) { if (parseCorePostfixExpression(node)) { PostfixAST *postfix_expressions = 0, **postfix_ptr = &postfix_expressions; while (LA()) { if (LA() == T_LPAREN) { CallAST *ast = new (_pool) CallAST; ast->lparen_token = consumeToken(); parseExpressionList(ast->expression_list); match(T_RPAREN, &ast->rparen_token); *postfix_ptr = ast; postfix_ptr = &(*postfix_ptr)->next; } else if (LA() == T_LBRACKET) { ArrayAccessAST *ast = new (_pool) ArrayAccessAST; ast->lbracket_token = consumeToken(); parseExpression(ast->expression); match(T_RBRACKET, &ast->rbracket_token); *postfix_ptr = ast; postfix_ptr = &(*postfix_ptr)->next; } else if (LA() == T_PLUS_PLUS || LA() == T_MINUS_MINUS) { PostIncrDecrAST *ast = new (_pool) PostIncrDecrAST; ast->incr_decr_token = consumeToken(); *postfix_ptr = ast; postfix_ptr = &(*postfix_ptr)->next; } else if (LA() == T_DOT || LA() == T_ARROW) { MemberAccessAST *ast = new (_pool) MemberAccessAST; ast->access_token = consumeToken(); if (LA() == T_TEMPLATE) ast->template_token = consumeToken(); if (! parseName(ast->member_name)) _translationUnit->error(cursor(), "expected unqualified-id before token `%s'", tok().spell()); *postfix_ptr = ast; postfix_ptr = &(*postfix_ptr)->next; } else break; } // while if (postfix_expressions) { PostfixExpressionAST *ast = new (_pool) PostfixExpressionAST; ast->base_expression = node; ast->postfix_expressions = postfix_expressions; node = ast; } return true; } return false; } bool Parser::parseUnaryExpression(ExpressionAST *&node) { switch (LA()) { case T_PLUS_PLUS: case T_MINUS_MINUS: case T_STAR: case T_AMPER: case T_PLUS: case T_MINUS: case T_EXCLAIM: { UnaryExpressionAST *ast = new (_pool) UnaryExpressionAST; ast->unary_op_token = consumeToken(); parseCastExpression(ast->expression); node = ast; return true; } case T_TILDE: { if (LA(2) == T_IDENTIFIER && LA(3) == T_LPAREN) break; // prefer destructor names UnaryExpressionAST *ast = new (_pool) UnaryExpressionAST; ast->unary_op_token = consumeToken(); parseCastExpression(ast->expression); node = ast; return true; } case T_SIZEOF: { SizeofExpressionAST *ast = new (_pool) SizeofExpressionAST; ast->sizeof_token = consumeToken(); if (LA() == T_LPAREN) { unsigned lparen_token = consumeToken(); if (parseTypeId(ast->expression) && LA() == T_RPAREN) { consumeToken(); node = ast; return true; } else { rewind(lparen_token); } } parseUnaryExpression(ast->expression); node = ast; return true; } default: break; } // switch if (LA() == T_NEW || (LA(1) == T_COLON_COLON && LA(2) == T_NEW)) return parseNewExpression(node); else if (LA() == T_DELETE || (LA(1) == T_COLON_COLON && LA(2) == T_DELETE)) return parseDeleteExpression(node); else return parsePostfixExpression(node); } bool Parser::parseNewExpression(ExpressionAST *&node) { if (LA() == T_NEW || (LA() == T_COLON_COLON && LA(2) == T_NEW)) { NewExpressionAST *ast = new (_pool) NewExpressionAST; if (LA() == T_COLON_COLON) ast->scope_token = consumeToken(); ast->new_token = consumeToken(); if (LA() == T_LPAREN) { consumeToken(); parseExpression(ast->expression); if (LA() == T_RPAREN) consumeToken(); } if (LA() == T_LPAREN) { consumeToken(); parseTypeId(ast->type_id); if (LA() == T_RPAREN) consumeToken(); } else { parseNewTypeId(ast->new_type_id); } parseNewInitializer(ast->new_initializer); node = ast; return true; } return false; } bool Parser::parseNewTypeId(NewTypeIdAST *&node) { SpecifierAST *typeSpec = 0; if (! parseTypeSpecifier(typeSpec)) return false; NewTypeIdAST *ast = new (_pool) NewTypeIdAST; ast->type_specifier = typeSpec; parseNewDeclarator(ast->new_declarator); node = ast; return true; } bool Parser::parseNewDeclarator(NewDeclaratorAST *&node) { NewDeclaratorAST *ast = new (_pool) NewDeclaratorAST; PtrOperatorAST **ptr_operators_tail = &ast->ptr_operators; while (parsePtrOperator(*ptr_operators_tail)) ptr_operators_tail = &(*ptr_operators_tail)->next; while (LA() == T_LBRACKET) { // ### create the AST consumeToken(); ExpressionAST *expression = 0; parseExpression(expression); unsigned rbracket_token = 0; match(T_RBRACKET, &rbracket_token); } node = ast; return true; } bool Parser::parseNewInitializer(NewInitializerAST *&node) { if (LA() == T_LPAREN) { unsigned lparen_token = consumeToken(); ExpressionAST *expression = 0; if (LA() == T_RPAREN || parseExpression(expression)) { NewInitializerAST *ast = new (_pool) NewInitializerAST; ast->lparen_token = lparen_token; ast->expression = expression; match(T_RPAREN, &ast->rparen_token); node = ast; return true; } } return false; } bool Parser::parseDeleteExpression(ExpressionAST *&node) { if (LA() == T_DELETE || (LA() == T_COLON_COLON && LA(2) == T_DELETE)) { DeleteExpressionAST *ast = new (_pool) DeleteExpressionAST; if (LA() == T_COLON_COLON) ast->scope_token = consumeToken(); ast->delete_token = consumeToken(); if (LA() == T_LBRACKET) { ast->lbracket_token = consumeToken(); match(T_RBRACKET, &ast->rbracket_token); } parseCastExpression(ast->expression); node = ast; return true; } return false; } bool Parser::parseCastExpression(ExpressionAST *&node) { if (LA() == T_LPAREN) { unsigned lparen_token = consumeToken(); ExpressionAST *type_id = 0; if (parseTypeId(type_id) && LA() == T_RPAREN) { unsigned rparen_token = consumeToken(); ExpressionAST *expression = 0; if (parseCastExpression(expression)) { CastExpressionAST *ast = new (_pool) CastExpressionAST; ast->lparen_token = lparen_token; ast->type_id = type_id; ast->rparen_token = rparen_token; ast->expression = expression; node = ast; return true; } } rewind(lparen_token); } return parseUnaryExpression(node); } bool Parser::parsePmExpression(ExpressionAST *&node) { if (! parseCastExpression(node)) return false; while (LA() == T_ARROW_STAR || LA() == T_DOT_STAR) { unsigned op = consumeToken(); ExpressionAST *rightExpr = 0; if (! parseCastExpression(rightExpr)) return false; BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST; ast->binary_op_token = op; ast->left_expression = node; ast->right_expression = rightExpr; node = ast; } return true; } bool Parser::parseMultiplicativeExpression(ExpressionAST *&node) { if (! parsePmExpression(node)) return false; while (LA() == T_STAR || LA() == T_SLASH || LA() == T_PERCENT) { unsigned op = consumeToken(); ExpressionAST *rightExpr = 0; if (! parsePmExpression(rightExpr)) return false; BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST; ast->binary_op_token = op; ast->left_expression = node; ast->right_expression = rightExpr; node = ast; } return true; } bool Parser::parseAdditiveExpression(ExpressionAST *&node) { if (! parseMultiplicativeExpression(node)) return false; while (LA() == T_PLUS || LA() == T_MINUS) { unsigned op = consumeToken(); ExpressionAST *rightExpr = 0; if (! parseMultiplicativeExpression(rightExpr)) return false; BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST; ast->binary_op_token = op; ast->left_expression = node; ast->right_expression = rightExpr; node = ast; } return true; } bool Parser::parseShiftExpression(ExpressionAST *&node) { if (! parseAdditiveExpression(node)) return false; while (LA() == T_LESS_LESS || LA() == T_GREATER_GREATER) { unsigned op = consumeToken(); ExpressionAST *rightExpr = 0; if (! parseAdditiveExpression(rightExpr)) return false; BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST; ast->binary_op_token = op; ast->left_expression = node; ast->right_expression = rightExpr; node = ast; } return true; } bool Parser::parseRelationalExpression(ExpressionAST *&node) { 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)) return false; BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST; ast->binary_op_token = op; ast->left_expression = node; ast->right_expression = rightExpr; node = ast; } return true; } bool Parser::parseEqualityExpression(ExpressionAST *&node) { if (! parseRelationalExpression(node)) return false; while (LA() == T_EQUAL_EQUAL || LA() == T_EXCLAIM_EQUAL) { unsigned op = consumeToken(); ExpressionAST *rightExpr = 0; if (! parseRelationalExpression(rightExpr)) return false; BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST; ast->binary_op_token = op; ast->left_expression = node; ast->right_expression = rightExpr; node = ast; } return true; } bool Parser::parseAndExpression(ExpressionAST *&node) { if (! parseEqualityExpression(node)) return false; while (LA() == T_AMPER) { unsigned op = consumeToken(); ExpressionAST *rightExpr = 0; if (! parseEqualityExpression(rightExpr)) return false; BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST; ast->binary_op_token = op; ast->left_expression = node; ast->right_expression = rightExpr; node = ast; } return true; } bool Parser::parseExclusiveOrExpression(ExpressionAST *&node) { if (! parseAndExpression(node)) return false; while (LA() == T_CARET) { unsigned op = consumeToken(); ExpressionAST *rightExpr = 0; if (! parseAndExpression(rightExpr)) return false; BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST; ast->binary_op_token = op; ast->left_expression = node; ast->right_expression = rightExpr; node = ast; } return true; } bool Parser::parseInclusiveOrExpression(ExpressionAST *&node) { if (! parseExclusiveOrExpression(node)) return false; while (LA() == T_PIPE) { unsigned op = consumeToken(); ExpressionAST *rightExpr = 0; if (! parseExclusiveOrExpression(rightExpr)) return false; BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST; ast->binary_op_token = op; ast->left_expression = node; ast->right_expression = rightExpr; node = ast; } return true; } bool Parser::parseLogicalAndExpression(ExpressionAST *&node) { if (! parseInclusiveOrExpression(node)) return false; while (LA() == T_AMPER_AMPER) { unsigned op = consumeToken(); ExpressionAST *rightExpr = 0; if (! parseInclusiveOrExpression(rightExpr)) return false; BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST; ast->binary_op_token = op; ast->left_expression = node; ast->right_expression = rightExpr; node = ast; } return true; } bool Parser::parseLogicalOrExpression(ExpressionAST *&node) { if (! parseLogicalAndExpression(node)) return false; while (LA() == T_PIPE_PIPE) { unsigned op = consumeToken(); ExpressionAST *rightExpr = 0; if (! parseLogicalAndExpression(rightExpr)) return false; BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST; ast->binary_op_token = op; ast->left_expression = node; ast->right_expression = rightExpr; node = ast; } return true; } bool Parser::parseConditionalExpression(ExpressionAST *&node) { if (! parseLogicalOrExpression(node)) return false; if (LA() != T_QUESTION) return true; ConditionalExpressionAST *ast = new (_pool) ConditionalExpressionAST; ast->condition = node; ast->question_token = consumeToken(); parseAssignmentExpression(ast->left_expression); match(T_COLON, &ast->colon_token); parseAssignmentExpression(ast->right_expression); node = ast; return true; } bool Parser::lookAtAssignmentOperator() const { switch (LA()) { case T_EQUAL: case T_AMPER_EQUAL: case T_CARET_EQUAL: case T_SLASH_EQUAL: case T_GREATER_GREATER_EQUAL: case T_LESS_LESS_EQUAL: case T_MINUS_EQUAL: case T_PERCENT_EQUAL: case T_PIPE_EQUAL: case T_PLUS_EQUAL: case T_STAR_EQUAL: case T_TILDE_EQUAL: return true; default: return false; } // switch } bool Parser::parseAssignmentExpression(ExpressionAST *&node) { if (LA() == T_THROW) return parseThrowExpression(node); else if (! parseConditionalExpression(node)) return false; if (lookAtAssignmentOperator()) { unsigned op = consumeToken(); ExpressionAST *rightExpr = 0; if (! parseAssignmentExpression(rightExpr)) return false; BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST; ast->binary_op_token = op; ast->left_expression = node; ast->right_expression = rightExpr; node = ast; } return true; } bool Parser::parseQtMethod(ExpressionAST *&node) { if (LA() == T_SIGNAL || LA() == T_SLOT) { QtMethodAST *ast = new (_pool) QtMethodAST; ast->method_token = consumeToken(); match(T_LPAREN, &ast->lparen_token); if (! parseDeclarator(ast->declarator)) _translationUnit->error(cursor(), "expected a function declarator before token `%s'", tok().spell()); match(T_RPAREN, &ast->rparen_token); node = ast; return true; } return false; } bool Parser::parseConstantExpression(ExpressionAST *&node) { return parseConditionalExpression(node); } bool Parser::parseExpression(ExpressionAST *&node) { return parseCommaExpression(node); } bool Parser::parseCommaExpression(ExpressionAST *&node) { if (! parseAssignmentExpression(node)) return false; while (LA() == T_COMMA) { unsigned op = consumeToken(); ExpressionAST *rightExpr = 0; if (! parseAssignmentExpression(rightExpr)) return false; BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST; ast->binary_op_token = op; ast->left_expression = node; ast->right_expression = rightExpr; node = ast; } return true; } bool Parser::parseThrowExpression(ExpressionAST *&node) { if (LA() == T_THROW) { ThrowExpressionAST *ast = new (_pool) ThrowExpressionAST; ast->throw_token = consumeToken(); parseAssignmentExpression(ast->expression); node = ast; return true; } return false; } CPLUSPLUS_END_NAMESPACE