forked from qt-creator/qt-creator
		
	
		
			
				
	
	
		
			3265 lines
		
	
	
		
			96 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			3265 lines
		
	
	
		
			96 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /***************************************************************************
 | |
| **
 | |
| ** 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.3, included in the file GPL_EXCEPTION.txt in this package.
 | |
| **
 | |
| ***************************************************************************/
 | |
| // Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
 | |
| //
 | |
| // 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 <cstdlib>
 | |
| #include <cassert>
 | |
| 
 | |
| 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);
 | |
| 
 | |
|     bool parsed = false;
 | |
| 
 | |
|     const bool previousInFunctionBody = _inFunctionBody;
 | |
|     _inFunctionBody = false;
 | |
| 
 | |
|     unsigned colon_token = 0;
 | |
| 
 | |
|     if (LA() == T_COLON || LA() == T_LBRACE) {
 | |
|         BaseSpecifierAST *base_clause = 0;
 | |
|         if (LA() == T_COLON) {
 | |
|             colon_token = cursor();
 | |
|             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->colon_token = colon_token;
 | |
|         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;
 | |
|         parsed = true;
 | |
|     }
 | |
| 
 | |
|     _inFunctionBody = previousInFunctionBody;
 | |
| 
 | |
|     return parsed;
 | |
| }
 | |
| 
 | |
| 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<StringLiteralAST **> (&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) const
 | |
| {
 | |
|     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::maybeSimpleExpression(SimpleDeclarationAST *simpleDecl) const
 | |
| {
 | |
|     if (! simpleDecl->declarators)  {
 | |
|         SpecifierAST *spec = simpleDecl->decl_specifier_seq;
 | |
|         if (spec && ! spec->next && spec->asNamedTypeSpecifier()) {
 | |
|             return true;
 | |
|         }
 | |
|     }
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| 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<DeclarationStatementAST *>(node);
 | |
|         SimpleDeclarationAST *simpleDecl = 0;
 | |
|         if (stmt->declaration)
 | |
|             simpleDecl = stmt->declaration->asSimpleDeclaration();
 | |
| 
 | |
|         if (simpleDecl && simpleDecl->decl_specifier_seq &&
 | |
|                 ! maybeFunctionCall(simpleDecl) && ! maybeSimpleExpression(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 <unop> ?
 | |
|             // identifier <binop>
 | |
|             // identifier <access>
 | |
|             // 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
 |