diff options
Diffstat (limited to 'src/shared/cplusplus')
70 files changed, 25410 insertions, 0 deletions
diff --git a/src/shared/cplusplus/AST.cpp b/src/shared/cplusplus/AST.cpp new file mode 100644 index 0000000000..3d710db366 --- /dev/null +++ b/src/shared/cplusplus/AST.cpp @@ -0,0 +1,3985 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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 "AST.h" +#include "ASTVisitor.h" +#include "MemoryPool.h" + +#include <cassert> +#include <cstddef> +#include <algorithm> + +CPLUSPLUS_BEGIN_NAMESPACE + +AST::AST() +{ } + +AST::~AST() +{ assert(0); } + +AccessDeclarationAST *AST::asAccessDeclaration() +{ return dynamic_cast<AccessDeclarationAST *>(this); } + +ArrayAccessAST *AST::asArrayAccess() +{ return dynamic_cast<ArrayAccessAST *>(this); } + +ArrayDeclaratorAST *AST::asArrayDeclarator() +{ return dynamic_cast<ArrayDeclaratorAST *>(this); } + +ArrayInitializerAST *AST::asArrayInitializer() +{ return dynamic_cast<ArrayInitializerAST *>(this); } + +AsmDefinitionAST *AST::asAsmDefinition() +{ return dynamic_cast<AsmDefinitionAST *>(this); } + +AttributeAST *AST::asAttribute() +{ return dynamic_cast<AttributeAST *>(this); } + +AttributeSpecifierAST *AST::asAttributeSpecifier() +{ return dynamic_cast<AttributeSpecifierAST *>(this); } + +BaseSpecifierAST *AST::asBaseSpecifier() +{ return dynamic_cast<BaseSpecifierAST *>(this); } + +QtMethodAST *AST::asQtMethod() +{ return dynamic_cast<QtMethodAST *>(this); } + +BinaryExpressionAST *AST::asBinaryExpression() +{ return dynamic_cast<BinaryExpressionAST *>(this); } + +BoolLiteralAST *AST::asBoolLiteral() +{ return dynamic_cast<BoolLiteralAST *>(this); } + +BreakStatementAST *AST::asBreakStatement() +{ return dynamic_cast<BreakStatementAST *>(this); } + +CallAST *AST::asCall() +{ return dynamic_cast<CallAST *>(this); } + +CaseStatementAST *AST::asCaseStatement() +{ return dynamic_cast<CaseStatementAST *>(this); } + +CastExpressionAST *AST::asCastExpression() +{ return dynamic_cast<CastExpressionAST *>(this); } + +CatchClauseAST *AST::asCatchClause() +{ return dynamic_cast<CatchClauseAST *>(this); } + +ClassSpecifierAST *AST::asClassSpecifier() +{ return dynamic_cast<ClassSpecifierAST *>(this); } + +CompoundLiteralAST *AST::asCompoundLiteral() +{ return dynamic_cast<CompoundLiteralAST *>(this); } + +CompoundStatementAST *AST::asCompoundStatement() +{ return dynamic_cast<CompoundStatementAST *>(this); } + +ConditionAST *AST::asCondition() +{ return dynamic_cast<ConditionAST *>(this); } + +ConditionalExpressionAST *AST::asConditionalExpression() +{ return dynamic_cast<ConditionalExpressionAST *>(this); } + +ContinueStatementAST *AST::asContinueStatement() +{ return dynamic_cast<ContinueStatementAST *>(this); } + +ConversionFunctionIdAST *AST::asConversionFunctionId() +{ return dynamic_cast<ConversionFunctionIdAST *>(this); } + +CoreDeclaratorAST *AST::asCoreDeclarator() +{ return dynamic_cast<CoreDeclaratorAST *>(this); } + +CppCastExpressionAST *AST::asCppCastExpression() +{ return dynamic_cast<CppCastExpressionAST *>(this); } + +CtorInitializerAST *AST::asCtorInitializer() +{ return dynamic_cast<CtorInitializerAST *>(this); } + +DeclarationAST *AST::asDeclaration() +{ return dynamic_cast<DeclarationAST *>(this); } + +DeclarationStatementAST *AST::asDeclarationStatement() +{ return dynamic_cast<DeclarationStatementAST *>(this); } + +DeclaratorAST *AST::asDeclarator() +{ return dynamic_cast<DeclaratorAST *>(this); } + +DeclaratorIdAST *AST::asDeclaratorId() +{ return dynamic_cast<DeclaratorIdAST *>(this); } + +DeclaratorListAST *AST::asDeclaratorList() +{ return dynamic_cast<DeclaratorListAST *>(this); } + +DeleteExpressionAST *AST::asDeleteExpression() +{ return dynamic_cast<DeleteExpressionAST *>(this); } + +DestructorNameAST *AST::asDestructorName() +{ return dynamic_cast<DestructorNameAST *>(this); } + +DoStatementAST *AST::asDoStatement() +{ return dynamic_cast<DoStatementAST *>(this); } + +ElaboratedTypeSpecifierAST *AST::asElaboratedTypeSpecifier() +{ return dynamic_cast<ElaboratedTypeSpecifierAST *>(this); } + +EmptyDeclarationAST *AST::asEmptyDeclaration() +{ return dynamic_cast<EmptyDeclarationAST *>(this); } + +EnumSpecifierAST *AST::asEnumSpecifier() +{ return dynamic_cast<EnumSpecifierAST *>(this); } + +EnumeratorAST *AST::asEnumerator() +{ return dynamic_cast<EnumeratorAST *>(this); } + +ExceptionDeclarationAST *AST::asExceptionDeclaration() +{ return dynamic_cast<ExceptionDeclarationAST *>(this); } + +ExceptionSpecificationAST *AST::asExceptionSpecification() +{ return dynamic_cast<ExceptionSpecificationAST *>(this); } + +ExpressionAST *AST::asExpression() +{ return dynamic_cast<ExpressionAST *>(this); } + +ExpressionListAST *AST::asExpressionList() +{ return dynamic_cast<ExpressionListAST *>(this); } + +ExpressionOrDeclarationStatementAST *AST::asExpressionOrDeclarationStatement() +{ return dynamic_cast<ExpressionOrDeclarationStatementAST *>(this); } + +ExpressionStatementAST *AST::asExpressionStatement() +{ return dynamic_cast<ExpressionStatementAST *>(this); } + +ForStatementAST *AST::asForStatement() +{ return dynamic_cast<ForStatementAST *>(this); } + +FunctionDeclaratorAST *AST::asFunctionDeclarator() +{ return dynamic_cast<FunctionDeclaratorAST *>(this); } + +FunctionDefinitionAST *AST::asFunctionDefinition() +{ return dynamic_cast<FunctionDefinitionAST *>(this); } + +GotoStatementAST *AST::asGotoStatement() +{ return dynamic_cast<GotoStatementAST *>(this); } + +IfStatementAST *AST::asIfStatement() +{ return dynamic_cast<IfStatementAST *>(this); } + +LabeledStatementAST *AST::asLabeledStatement() +{ return dynamic_cast<LabeledStatementAST *>(this); } + +LinkageBodyAST *AST::asLinkageBody() +{ return dynamic_cast<LinkageBodyAST *>(this); } + +LinkageSpecificationAST *AST::asLinkageSpecification() +{ return dynamic_cast<LinkageSpecificationAST *>(this); } + +MemInitializerAST *AST::asMemInitializer() +{ return dynamic_cast<MemInitializerAST *>(this); } + +MemberAccessAST *AST::asMemberAccess() +{ return dynamic_cast<MemberAccessAST *>(this); } + +NameAST *AST::asName() +{ return dynamic_cast<NameAST *>(this); } + +NamedTypeSpecifierAST *AST::asNamedTypeSpecifier() +{ return dynamic_cast<NamedTypeSpecifierAST *>(this); } + +NamespaceAST *AST::asNamespace() +{ return dynamic_cast<NamespaceAST *>(this); } + +NamespaceAliasDefinitionAST *AST::asNamespaceAliasDefinition() +{ return dynamic_cast<NamespaceAliasDefinitionAST *>(this); } + +NestedDeclaratorAST *AST::asNestedDeclarator() +{ return dynamic_cast<NestedDeclaratorAST *>(this); } + +NestedExpressionAST *AST::asNestedExpression() +{ return dynamic_cast<NestedExpressionAST *>(this); } + +NestedNameSpecifierAST *AST::asNestedNameSpecifier() +{ return dynamic_cast<NestedNameSpecifierAST *>(this); } + +NewDeclaratorAST *AST::asNewDeclarator() +{ return dynamic_cast<NewDeclaratorAST *>(this); } + +NewExpressionAST *AST::asNewExpression() +{ return dynamic_cast<NewExpressionAST *>(this); } + +NewInitializerAST *AST::asNewInitializer() +{ return dynamic_cast<NewInitializerAST *>(this); } + +NewTypeIdAST *AST::asNewTypeId() +{ return dynamic_cast<NewTypeIdAST *>(this); } + +NumericLiteralAST *AST::asNumericLiteral() +{ return dynamic_cast<NumericLiteralAST *>(this); } + +OperatorAST *AST::asOperator() +{ return dynamic_cast<OperatorAST *>(this); } + +OperatorFunctionIdAST *AST::asOperatorFunctionId() +{ return dynamic_cast<OperatorFunctionIdAST *>(this); } + +ParameterDeclarationAST *AST::asParameterDeclaration() +{ return dynamic_cast<ParameterDeclarationAST *>(this); } + +ParameterDeclarationClauseAST *AST::asParameterDeclarationClause() +{ return dynamic_cast<ParameterDeclarationClauseAST *>(this); } + +PointerAST *AST::asPointer() +{ return dynamic_cast<PointerAST *>(this); } + +PointerToMemberAST *AST::asPointerToMember() +{ return dynamic_cast<PointerToMemberAST *>(this); } + +PostIncrDecrAST *AST::asPostIncrDecr() +{ return dynamic_cast<PostIncrDecrAST *>(this); } + +PostfixAST *AST::asPostfix() +{ return dynamic_cast<PostfixAST *>(this); } + +PostfixDeclaratorAST *AST::asPostfixDeclarator() +{ return dynamic_cast<PostfixDeclaratorAST *>(this); } + +PostfixExpressionAST *AST::asPostfixExpression() +{ return dynamic_cast<PostfixExpressionAST *>(this); } + +PtrOperatorAST *AST::asPtrOperator() +{ return dynamic_cast<PtrOperatorAST *>(this); } + +QualifiedNameAST *AST::asQualifiedName() +{ return dynamic_cast<QualifiedNameAST *>(this); } + +ReferenceAST *AST::asReference() +{ return dynamic_cast<ReferenceAST *>(this); } + +ReturnStatementAST *AST::asReturnStatement() +{ return dynamic_cast<ReturnStatementAST *>(this); } + +SimpleDeclarationAST *AST::asSimpleDeclaration() +{ return dynamic_cast<SimpleDeclarationAST *>(this); } + +SimpleNameAST *AST::asSimpleName() +{ return dynamic_cast<SimpleNameAST *>(this); } + +SimpleSpecifierAST *AST::asSimpleSpecifier() +{ return dynamic_cast<SimpleSpecifierAST *>(this); } + +SizeofExpressionAST *AST::asSizeofExpression() +{ return dynamic_cast<SizeofExpressionAST *>(this); } + +SpecifierAST *AST::asSpecifier() +{ return dynamic_cast<SpecifierAST *>(this); } + +StatementAST *AST::asStatement() +{ return dynamic_cast<StatementAST *>(this); } + +StringLiteralAST *AST::asStringLiteral() +{ return dynamic_cast<StringLiteralAST *>(this); } + +SwitchStatementAST *AST::asSwitchStatement() +{ return dynamic_cast<SwitchStatementAST *>(this); } + +TemplateArgumentListAST *AST::asTemplateArgumentList() +{ return dynamic_cast<TemplateArgumentListAST *>(this); } + +TemplateDeclarationAST *AST::asTemplateDeclaration() +{ return dynamic_cast<TemplateDeclarationAST *>(this); } + +TemplateIdAST *AST::asTemplateId() +{ return dynamic_cast<TemplateIdAST *>(this); } + +TemplateTypeParameterAST *AST::asTemplateTypeParameter() +{ return dynamic_cast<TemplateTypeParameterAST *>(this); } + +ThisExpressionAST *AST::asThisExpression() +{ return dynamic_cast<ThisExpressionAST *>(this); } + +ThrowExpressionAST *AST::asThrowExpression() +{ return dynamic_cast<ThrowExpressionAST *>(this); } + +TranslationUnitAST *AST::asTranslationUnit() +{ return dynamic_cast<TranslationUnitAST *>(this); } + +TryBlockStatementAST *AST::asTryBlockStatement() +{ return dynamic_cast<TryBlockStatementAST *>(this); } + +TypeConstructorCallAST *AST::asTypeConstructorCall() +{ return dynamic_cast<TypeConstructorCallAST *>(this); } + +TypeIdAST *AST::asTypeId() +{ return dynamic_cast<TypeIdAST *>(this); } + +TypeidExpressionAST *AST::asTypeidExpression() +{ return dynamic_cast<TypeidExpressionAST *>(this); } + +TypenameCallExpressionAST *AST::asTypenameCallExpression() +{ return dynamic_cast<TypenameCallExpressionAST *>(this); } + +TypenameTypeParameterAST *AST::asTypenameTypeParameter() +{ return dynamic_cast<TypenameTypeParameterAST *>(this); } + +TypeofSpecifierAST *AST::asTypeofSpecifier() +{ return dynamic_cast<TypeofSpecifierAST *>(this); } + +UnaryExpressionAST *AST::asUnaryExpression() +{ return dynamic_cast<UnaryExpressionAST *>(this); } + +UsingAST *AST::asUsing() +{ return dynamic_cast<UsingAST *>(this); } + +UsingDirectiveAST *AST::asUsingDirective() +{ return dynamic_cast<UsingDirectiveAST *>(this); } + +WhileStatementAST *AST::asWhileStatement() +{ return dynamic_cast<WhileStatementAST *>(this); } + +void AST::accept(ASTVisitor *visitor) +{ + if (visitor->preVisit(this)) + accept0(visitor); + visitor->postVisit(this); +} + +unsigned AttributeSpecifierAST::firstToken() const +{ + return attribute_token; +} + +unsigned AttributeSpecifierAST::lastToken() const +{ + if (second_rparen_token) + return second_rparen_token + 1; + else if (first_rparen_token) + return first_rparen_token + 1; + else if (attributes) + return attributes->lastToken(); + else if (second_lparen_token) + return second_lparen_token + 1; + else if (first_lparen_token) + return first_lparen_token + 1; + return attribute_token + 1; +} + +AttributeSpecifierAST *AttributeSpecifierAST::clone(MemoryPool *pool) const +{ + AttributeSpecifierAST *ast = new (pool) AttributeSpecifierAST; + ast->attribute_token = attribute_token; + ast->first_lparen_token = first_lparen_token; + ast->second_lparen_token = second_lparen_token; + if (attributes) + ast->attributes = attributes->clone(pool); + ast->first_rparen_token = first_rparen_token; + ast->second_rparen_token = second_rparen_token; + return ast; +} + +void AttributeSpecifierAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + for (AttributeAST *attr = attributes; attr; attr = attr->next) + accept(attr, visitor); + } +} + +unsigned AttributeAST::firstToken() const +{ + return identifier_token; +} + +unsigned AttributeAST::lastToken() const +{ + if (rparen_token) + return rparen_token + 1; + + for (ExpressionListAST *it = expression_list; + it->expression && it->next; it = it->next) { + if (! it->next && it->expression) { + return it->expression->lastToken(); + } + } + + if (tag_token) + return tag_token + 1; + + if (lparen_token) + return lparen_token + 1; + + return identifier_token + 1; +} + +AttributeAST *AttributeAST::clone(MemoryPool *pool) const +{ + AttributeAST *ast = new (pool) AttributeAST; + ast->identifier_token = identifier_token; + ast->lparen_token = lparen_token; + ast->tag_token = tag_token; + if (expression_list) + ast->expression_list = expression_list->clone(pool); + ast->rparen_token = rparen_token; + if (next) + ast->next = next->clone(pool); + return ast; +} + +void AttributeAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + for (ExpressionListAST *it = expression_list; it; it = it->next) + accept(it->expression, visitor); + } +} + +AccessDeclarationAST *AccessDeclarationAST::clone(MemoryPool *pool) const +{ + AccessDeclarationAST *ast = new (pool) AccessDeclarationAST; + ast->access_specifier_token = access_specifier_token; + ast->slots_token = slots_token; + ast->colon_token = colon_token; + return ast; +} + +void AccessDeclarationAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + } +} + +unsigned AccessDeclarationAST::firstToken() const +{ + return access_specifier_token; +} + +unsigned AccessDeclarationAST::lastToken() const +{ + if (colon_token) + return colon_token + 1; + else if (slots_token) + return slots_token + 1; + return access_specifier_token + 1; +} + +ArrayAccessAST *ArrayAccessAST::clone(MemoryPool *pool) const +{ + ArrayAccessAST *ast = new (pool) ArrayAccessAST; + ast->lbracket_token = lbracket_token; + if (expression) + ast->expression = expression->clone(pool); + ast->rbracket_token = rbracket_token; + return ast; +} + +void ArrayAccessAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + } +} + +unsigned ArrayAccessAST::firstToken() const +{ + return lbracket_token; +} + +unsigned ArrayAccessAST::lastToken() const +{ + if (rbracket_token) + return rbracket_token + 1; + else if (expression) + return expression->lastToken(); + return lbracket_token + 1; +} + +ArrayDeclaratorAST *ArrayDeclaratorAST::clone(MemoryPool *pool) const +{ + ArrayDeclaratorAST *ast = new (pool) ArrayDeclaratorAST; + ast->lbracket_token = lbracket_token; + if (expression) + ast->expression = expression->clone(pool); + ast->rbracket_token = rbracket_token; + return ast; +} + +void ArrayDeclaratorAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(this->expression, visitor); + } +} + +unsigned ArrayDeclaratorAST::firstToken() const +{ + return lbracket_token; +} + +unsigned ArrayDeclaratorAST::lastToken() const +{ + if (rbracket_token) + return rbracket_token + 1; + else if (expression) + return expression->lastToken(); + return lbracket_token + 1; +} + +ArrayInitializerAST *ArrayInitializerAST::clone(MemoryPool *pool) const +{ + ArrayInitializerAST *ast = new (pool) ArrayInitializerAST; + ast->lbrace_token = lbrace_token; + if (expression_list) + ast->expression_list = expression_list->clone(pool); + ast->rbrace_token = rbrace_token; + return ast; +} + +void ArrayInitializerAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + for (ExpressionListAST *expr = expression_list; expr; expr = expr->next) + accept(expr->expression, visitor); + } +} + +unsigned ArrayInitializerAST::firstToken() const +{ + return lbrace_token; +} + +unsigned ArrayInitializerAST::lastToken() const +{ + if (rbrace_token) + return rbrace_token + 1; + + for (ExpressionListAST *it = expression_list; it; it = it->next) { + if (! it->next && it->expression) + return it->expression->lastToken(); + } + + return lbrace_token + 1; +} + +AsmDefinitionAST *AsmDefinitionAST::clone(MemoryPool *pool) const +{ + AsmDefinitionAST *ast = new (pool) AsmDefinitionAST; + ast->asm_token = asm_token; + if (cv_qualifier_seq) + ast->cv_qualifier_seq = cv_qualifier_seq->clone(pool); + ast->lparen_token = lparen_token; + ast->rparen_token = rparen_token; + ast->semicolon_token = semicolon_token; + return ast; +} + +void AsmDefinitionAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + for (SpecifierAST *spec = cv_qualifier_seq; spec; + spec = spec->next) + accept(spec, visitor); + } +} + +unsigned AsmDefinitionAST::firstToken() const +{ + return asm_token; +} + +unsigned AsmDefinitionAST::lastToken() const +{ + if (semicolon_token) + return semicolon_token + 1; + else if (rparen_token) + return rparen_token + 1; + else if (lparen_token) + return lparen_token + 1; + for (SpecifierAST *it = cv_qualifier_seq; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + return asm_token + 1; +} + +BaseSpecifierAST *BaseSpecifierAST::clone(MemoryPool *pool) const +{ + BaseSpecifierAST *ast = new (pool) BaseSpecifierAST; + ast->token_virtual = token_virtual; + ast->token_access_specifier = token_access_specifier; + if (name) + ast->name = name->clone(pool); + if (next) + ast->next = next->clone(pool); + return ast; +} + +void BaseSpecifierAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(name, visitor); + } +} + +unsigned BaseSpecifierAST::firstToken() const +{ + if (token_virtual && token_access_specifier) + return std::min(token_virtual, token_access_specifier); + return name->firstToken(); +} + +unsigned BaseSpecifierAST::lastToken() const +{ + if (name) + return name->lastToken(); + else if (token_virtual && token_access_specifier) + return std::min(token_virtual, token_access_specifier) + 1; + else if (token_virtual) + return token_virtual + 1; + else if (token_access_specifier) + return token_access_specifier + 1; + // assert? + return 0; +} + +unsigned QtMethodAST::firstToken() const +{ return method_token; } + +unsigned QtMethodAST::lastToken() const +{ + if (rparen_token) + return rparen_token + 1; + else if (declarator) + return declarator->lastToken(); + else if (lparen_token) + return lparen_token + 1; + return method_token + 1; +} + +QtMethodAST *QtMethodAST::clone(MemoryPool *pool) const +{ + QtMethodAST *ast = new (pool) QtMethodAST; + ast->method_token = method_token; + ast->lparen_token = lparen_token; + if (declarator) + ast->declarator = declarator->clone(pool); + ast->rparen_token = rparen_token; + return ast; +} + +void QtMethodAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(declarator, visitor); + } +} + +BinaryExpressionAST *BinaryExpressionAST::clone(MemoryPool *pool) const +{ + BinaryExpressionAST *ast = new (pool) BinaryExpressionAST; + if (left_expression) + ast->left_expression = left_expression->clone(pool); + ast->binary_op_token = binary_op_token; + if (right_expression) + ast->right_expression = right_expression->clone(pool); + return ast; +} + +void BinaryExpressionAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(left_expression, visitor); + accept(right_expression, visitor); + } +} + +unsigned BinaryExpressionAST::firstToken() const +{ + return left_expression->firstToken(); +} + +unsigned BinaryExpressionAST::lastToken() const +{ + if (right_expression) + return right_expression->lastToken(); + else if (binary_op_token) + return binary_op_token + 1; + return left_expression->lastToken(); +} + +BoolLiteralAST *BoolLiteralAST::clone(MemoryPool *pool) const +{ + BoolLiteralAST *ast = new (pool) BoolLiteralAST; + ast->token = token; + return ast; +} + +void BoolLiteralAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + } +} + +unsigned BoolLiteralAST::firstToken() const +{ + return token; +} + +unsigned BoolLiteralAST::lastToken() const +{ + return token + 1; +} + +CompoundLiteralAST *CompoundLiteralAST::clone(MemoryPool *pool) const +{ + CompoundLiteralAST *ast = new (pool) CompoundLiteralAST; + ast->lparen_token = lparen_token; + if (type_id) + ast->type_id = type_id->clone(pool); + ast->rparen_token = rparen_token; + if (initializer) + ast->initializer = initializer->clone(pool); + return ast; +} + +void CompoundLiteralAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(type_id, visitor); + accept(initializer, visitor); + } +} + +unsigned CompoundLiteralAST::firstToken() const +{ + return lparen_token; +} + +unsigned CompoundLiteralAST::lastToken() const +{ + if (initializer) + return initializer->lastToken(); + else if (rparen_token) + return rparen_token + 1; + else if (type_id) + return type_id->lastToken(); + return lparen_token + 1; +} + +BreakStatementAST *BreakStatementAST::clone(MemoryPool *pool) const +{ + BreakStatementAST *ast = new (pool) BreakStatementAST; + ast->break_token = break_token; + ast->semicolon_token = semicolon_token; + return ast; +} + +void BreakStatementAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + } +} + +unsigned BreakStatementAST::firstToken() const +{ + return break_token; +} + +unsigned BreakStatementAST::lastToken() const +{ + if (semicolon_token) + return semicolon_token + 1; + return break_token + 1; +} + +CallAST *CallAST::clone(MemoryPool *pool) const +{ + CallAST *ast = new (pool) CallAST; + ast->lparen_token = lparen_token; + if (expression_list) + ast->expression_list = expression_list; + ast->rparen_token = rparen_token; + return ast; +} + +void CallAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + for (ExpressionListAST *expr = expression_list; + expr; expr = expr->next) + accept(expr->expression, visitor); + } +} + +unsigned CallAST::firstToken() const +{ + return lparen_token; +} + +unsigned CallAST::lastToken() const +{ + if (rparen_token) + return rparen_token + 1; + for (ExpressionListAST *it = expression_list; it; it = it->next) { + if (! it->next && it->expression) + return it->expression->lastToken(); + } + return lparen_token + 1; +} + +CaseStatementAST *CaseStatementAST::clone(MemoryPool *pool) const +{ + CaseStatementAST *ast = new (pool) CaseStatementAST; + ast->case_token = case_token; + if (expression) + ast->expression = expression->clone(pool); + ast->colon_token = colon_token; + if (statement) + ast->statement = statement->clone(pool); + return ast; +} + +void CaseStatementAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + } +} + +unsigned CaseStatementAST::firstToken() const +{ + return case_token; +} + +unsigned CaseStatementAST::lastToken() const +{ + if (statement) + return statement->lastToken(); + else if (colon_token) + return colon_token + 1; + else if (expression) + return expression->lastToken(); + return case_token + 1; +} + +CastExpressionAST *CastExpressionAST::clone(MemoryPool *pool) const +{ + CastExpressionAST *ast = new (pool) CastExpressionAST; + ast->lparen_token = lparen_token; + if (type_id) + ast->type_id = type_id->clone(pool); + ast->rparen_token = rparen_token; + if (expression) + ast->expression = expression->clone(pool); + return ast; +} + +void CastExpressionAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + } +} + +unsigned CastExpressionAST::firstToken() const +{ + return lparen_token; +} + +unsigned CastExpressionAST::lastToken() const +{ + if (expression) + return expression->lastToken(); + else if (rparen_token) + return rparen_token + 1; + else if (type_id) + return type_id->lastToken(); + return lparen_token + 1; +} + +CatchClauseAST *CatchClauseAST::clone(MemoryPool *pool) const +{ + CatchClauseAST *ast = new (pool) CatchClauseAST; + ast->catch_token = catch_token; + ast->lparen_token = lparen_token; + if (exception_declaration) + ast->exception_declaration = exception_declaration->clone(pool); + ast->rparen_token = rparen_token; + if (statement) + ast->statement = statement->clone(pool); + if (next) + ast->next = next->clone(pool); + return ast; +} + +void CatchClauseAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(exception_declaration, visitor); + accept(statement, visitor); + } +} + +unsigned CatchClauseAST::firstToken() const +{ + return catch_token; +} + +unsigned CatchClauseAST::lastToken() const +{ + if (statement) + return statement->lastToken(); + else if (rparen_token) + return rparen_token + 1; + for (DeclarationAST *it = exception_declaration; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + if (lparen_token) + return lparen_token + 1; + + return catch_token + 1; +} + +ClassSpecifierAST *ClassSpecifierAST::clone(MemoryPool *pool) const +{ + ClassSpecifierAST *ast = new (pool) ClassSpecifierAST; + ast->classkey_token = classkey_token; + if (attributes) + ast->attributes = attributes->clone(pool); + if (name) + ast->name = name->clone(pool); + ast->colon_token = colon_token; + if (base_clause) + ast->base_clause = base_clause->clone(pool); + ast->lbrace_token = lbrace_token; + if (member_specifiers) + ast->member_specifiers = member_specifiers->clone(pool); + ast->rbrace_token = rbrace_token; + return ast; +} + +void ClassSpecifierAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + for (SpecifierAST *spec = attributes; spec; spec = spec->next) + accept(spec, visitor); + accept(name, visitor); + for (BaseSpecifierAST *spec = base_clause; spec; spec = spec->next) + accept(spec, visitor); + for (DeclarationAST *decl = member_specifiers; decl; decl = decl->next) + accept(decl, visitor); + } +} + +unsigned ClassSpecifierAST::firstToken() const +{ + return classkey_token; +} + +unsigned ClassSpecifierAST::lastToken() const +{ + if (rbrace_token) + return rbrace_token + 1; + + for (DeclarationAST *it = member_specifiers; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + if (lbrace_token) + return lbrace_token + 1; + + for (BaseSpecifierAST *it = base_clause; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + if (colon_token) + return colon_token + 1; + + if (name) + return name->lastToken(); + + for (SpecifierAST *it = attributes; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + return classkey_token + 1; +} + +CompoundStatementAST *CompoundStatementAST::clone(MemoryPool *pool) const +{ + CompoundStatementAST *ast = new (pool) CompoundStatementAST; + ast->lbrace_token = lbrace_token; + if (statements) + ast->statements = statements->clone(pool); + ast->rbrace_token = rbrace_token; + return ast; +} + +void CompoundStatementAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + for (StatementAST *stmt = statements; stmt; stmt = stmt->next) + accept(stmt, visitor); + } +} + +unsigned CompoundStatementAST::firstToken() const +{ + return lbrace_token; +} + +unsigned CompoundStatementAST::lastToken() const +{ + if (rbrace_token) + return rbrace_token + 1; + + for (StatementAST *it = statements; it ; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + return lbrace_token + 1; +} + +ConditionAST *ConditionAST::clone(MemoryPool *pool) const +{ + ConditionAST *ast = new (pool) ConditionAST; + if (type_specifier) + ast->type_specifier = type_specifier->clone(pool); + if (declarator) + ast->declarator = declarator->clone(pool); + return ast; +} + +void ConditionAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + for (SpecifierAST *spec = type_specifier; spec; spec = spec->next) + accept(spec, visitor); + accept(declarator, visitor); + } +} + +unsigned ConditionAST::firstToken() const +{ + if (type_specifier) + return type_specifier->firstToken(); + + return declarator->firstToken(); +} + +unsigned ConditionAST::lastToken() const +{ + if (declarator) + return declarator->lastToken(); + + for (SpecifierAST *it = type_specifier; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + // ### assert? + return 0; +} + +ConditionalExpressionAST *ConditionalExpressionAST::clone(MemoryPool *pool) const +{ + ConditionalExpressionAST *ast = new (pool) ConditionalExpressionAST; + if (condition) + ast->condition = condition->clone(pool); + ast->question_token = question_token; + if (left_expression) + ast->left_expression = left_expression->clone(pool); + ast->colon_token = colon_token; + if (right_expression) + ast->right_expression = right_expression->clone(pool); + return ast; +} + +void ConditionalExpressionAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(condition, visitor); + accept(left_expression, visitor); + accept(right_expression, visitor); + } +} + +unsigned ConditionalExpressionAST::firstToken() const +{ + return condition->firstToken(); +} + +unsigned ConditionalExpressionAST::lastToken() const +{ + if (right_expression) + return right_expression->lastToken(); + else if (colon_token) + return colon_token + 1; + else if (left_expression) + return left_expression->lastToken(); + else if (question_token) + return question_token + 1; + else if (condition) + return condition->lastToken(); + // ### assert? + return 0; +} + +ContinueStatementAST *ContinueStatementAST::clone(MemoryPool *pool) const +{ + ContinueStatementAST *ast = new (pool) ContinueStatementAST; + ast->continue_token = continue_token; + ast->semicolon_token = semicolon_token; + return ast; +} + +void ContinueStatementAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + } +} + +unsigned ContinueStatementAST::firstToken() const +{ + return continue_token; +} + +unsigned ContinueStatementAST::lastToken() const +{ + if (semicolon_token) + return semicolon_token + 1; + return continue_token + 1; +} + +ConversionFunctionIdAST *ConversionFunctionIdAST::clone(MemoryPool *pool) const +{ + ConversionFunctionIdAST *ast = new (pool) ConversionFunctionIdAST; + ast->operator_token = operator_token; + if (type_specifier) + ast->type_specifier = type_specifier->clone(pool); + if (ptr_operators) + ast->ptr_operators = ptr_operators->clone(pool); + return ast; +} + +void ConversionFunctionIdAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + for (SpecifierAST *spec = type_specifier; spec; spec = spec->next) + accept(spec, visitor); + for (PtrOperatorAST *ptr_op = ptr_operators; ptr_op; + ptr_op = static_cast<PtrOperatorAST *>(ptr_op->next)) + accept(ptr_op, visitor); + } +} + +unsigned ConversionFunctionIdAST::firstToken() const +{ + return operator_token; +} + +unsigned ConversionFunctionIdAST::lastToken() const +{ + for (PtrOperatorAST *it = ptr_operators; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + for (SpecifierAST *it = type_specifier; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + return operator_token + 1; +} + +CppCastExpressionAST *CppCastExpressionAST::clone(MemoryPool *pool) const +{ + CppCastExpressionAST *ast = new (pool) CppCastExpressionAST; + ast->cast_token = cast_token; + ast->less_token = less_token; + if (type_id) + ast->type_id = type_id->clone(pool); + ast->greater_token = greater_token; + ast->lparen_token = lparen_token; + if (expression) + ast->expression = expression->clone(pool); + ast->rparen_token = rparen_token; + return ast; +} + +void CppCastExpressionAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(type_id, visitor); + accept(expression, visitor); + } +} + +unsigned CppCastExpressionAST::firstToken() const +{ + return cast_token; +} + +unsigned CppCastExpressionAST::lastToken() const +{ + if (rparen_token) + return rparen_token + 1; + else if (expression) + return expression->lastToken(); + else if (lparen_token) + return lparen_token + 1; + else if (greater_token) + return greater_token + 1; + else if (type_id) + return type_id->lastToken(); + else if (less_token) + return less_token + 1; + return cast_token + 1; +} + +CtorInitializerAST *CtorInitializerAST::clone(MemoryPool *pool) const +{ + CtorInitializerAST *ast = new (pool) CtorInitializerAST; + ast->colon_token = colon_token; + if (member_initializers) + ast->member_initializers = member_initializers->clone(pool); + return ast; +} + +void CtorInitializerAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + for (MemInitializerAST *mem_init = member_initializers; + mem_init; mem_init = mem_init->next) + accept(mem_init, visitor); + } +} + +unsigned CtorInitializerAST::firstToken() const +{ + return colon_token; +} + +unsigned CtorInitializerAST::lastToken() const +{ + for (MemInitializerAST *it = member_initializers; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + return colon_token + 1; +} + +DeclaratorAST *DeclaratorAST::clone(MemoryPool *pool) const +{ + DeclaratorAST *ast = new (pool) DeclaratorAST; + if (ptr_operators) + ast->ptr_operators = ptr_operators->clone(pool); + if (core_declarator) + ast->core_declarator = core_declarator->clone(pool); + if (postfix_declarators) + ast->postfix_declarators = postfix_declarators->clone(pool); + if (attributes) + ast->attributes = attributes->clone(pool); + if (initializer) + ast->initializer = initializer->clone(pool); + return ast; +} + +void DeclaratorAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + for (PtrOperatorAST *ptr_op = ptr_operators; ptr_op; ptr_op = ptr_op->next) { + accept(ptr_op, visitor); + } + accept(core_declarator, visitor); + for (PostfixDeclaratorAST *fx = postfix_declarators; fx; fx = fx->next) { + accept(fx, visitor); + } + accept(attributes, visitor); + accept(initializer, visitor); + } +} + +unsigned DeclaratorAST::firstToken() const +{ + if (ptr_operators) + return ptr_operators->firstToken(); + else if (core_declarator) + return core_declarator->firstToken(); + else if (postfix_declarators) + return postfix_declarators->firstToken(); + else if (attributes) + return attributes->firstToken(); + else if (initializer) + return initializer->firstToken(); + // ### assert? + return 0; +} + +unsigned DeclaratorAST::lastToken() const +{ + if (initializer) + return initializer->lastToken(); + + for (SpecifierAST *it = attributes; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + for (PostfixDeclaratorAST *it = postfix_declarators; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + if (core_declarator) + return core_declarator->lastToken(); + + for (PtrOperatorAST *it = ptr_operators; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + // ### assert? + return 0; +} + +DeclarationStatementAST *DeclarationStatementAST::clone(MemoryPool *pool) const +{ + DeclarationStatementAST *ast = new (pool) DeclarationStatementAST; + if (declaration) + ast->declaration = declaration->clone(pool); + return ast; +} + +void DeclarationStatementAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(declaration, visitor); + } +} + +unsigned DeclarationStatementAST::firstToken() const +{ + return declaration->firstToken(); +} + +unsigned DeclarationStatementAST::lastToken() const +{ + return declaration->lastToken(); +} + +DeclaratorIdAST *DeclaratorIdAST::clone(MemoryPool *pool) const +{ + DeclaratorIdAST *ast = new (pool) DeclaratorIdAST; + if (name) + ast->name = name->clone(pool); + return ast; +} + +void DeclaratorIdAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(name, visitor); + } +} + +unsigned DeclaratorIdAST::firstToken() const +{ + return name->firstToken(); +} + +unsigned DeclaratorIdAST::lastToken() const +{ + return name->lastToken(); +} + +DeclaratorListAST *DeclaratorListAST::clone(MemoryPool *pool) const +{ + DeclaratorListAST *ast = new (pool) DeclaratorListAST; + if (declarator) + ast->declarator = declarator->clone(pool); + if (next) + ast->next = next->clone(pool); + return ast; +} + +void DeclaratorListAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + for (DeclaratorListAST *it = this; it; it = it->next) + accept(it->declarator, visitor); + } +} + +unsigned DeclaratorListAST::firstToken() const +{ + return declarator->firstToken(); +} + +unsigned DeclaratorListAST::lastToken() const +{ + for (const DeclaratorListAST *it = this; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + return 0; +} + +DeleteExpressionAST *DeleteExpressionAST::clone(MemoryPool *pool) const +{ + DeleteExpressionAST *ast = new (pool) DeleteExpressionAST; + ast->scope_token = scope_token; + ast->delete_token = delete_token; + ast->lbracket_token = lbracket_token; + ast->rbracket_token = rbracket_token; + if (expression) + ast->expression = expression->clone(pool); + return ast; +} + +void DeleteExpressionAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + } +} + +unsigned DeleteExpressionAST::firstToken() const +{ + if (scope_token) + return scope_token; + return delete_token; +} + +unsigned DeleteExpressionAST::lastToken() const +{ + if (expression) + return expression->lastToken(); + else if (rbracket_token) + return rbracket_token + 1; + else if (lbracket_token) + return lbracket_token + 1; + else if (delete_token) + return delete_token + 1; + return scope_token + 1; +} + +DestructorNameAST *DestructorNameAST::clone(MemoryPool *pool) const +{ + DestructorNameAST *ast = new (pool) DestructorNameAST; + ast->tilde_token = tilde_token; + ast->identifier_token = identifier_token; + return ast; +} + +void DestructorNameAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + } +} + +unsigned DestructorNameAST::firstToken() const +{ + return tilde_token; +} + +unsigned DestructorNameAST::lastToken() const +{ + if (identifier_token) + return identifier_token + 1; + return tilde_token + 1; +} + +DoStatementAST *DoStatementAST::clone(MemoryPool *pool) const +{ + DoStatementAST *ast = new (pool) DoStatementAST; + ast->do_token = do_token; + if (statement) + ast->statement = statement->clone(pool); + ast->while_token = while_token; + ast->lparen_token = lparen_token; + if (expression) + ast->expression = expression->clone(pool); + ast->rparen_token = rparen_token; + ast->semicolon_token = semicolon_token; + return ast; +} + +void DoStatementAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(statement, visitor); + accept(expression, visitor); + } +} + +unsigned DoStatementAST::firstToken() const +{ + return do_token; +} + +unsigned DoStatementAST::lastToken() const +{ + if (semicolon_token) + return semicolon_token + 1; + else if (rparen_token) + return rparen_token + 1; + else if (expression) + return expression->lastToken(); + else if (lparen_token) + return lparen_token + 1; + else if (while_token) + return while_token + 1; + else if (statement) + return statement->lastToken(); + return do_token + 1; +} + +ElaboratedTypeSpecifierAST *ElaboratedTypeSpecifierAST::clone(MemoryPool *pool) const +{ + ElaboratedTypeSpecifierAST *ast = new (pool) ElaboratedTypeSpecifierAST; + ast->classkey_token = classkey_token; + if (name) + ast->name = name->clone(pool); + return ast; +} + +void ElaboratedTypeSpecifierAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(name, visitor); + } +} + +unsigned ElaboratedTypeSpecifierAST::firstToken() const +{ + return classkey_token; +} + +unsigned ElaboratedTypeSpecifierAST::lastToken() const +{ + if (name) + return name->lastToken(); + return classkey_token + 1; +} + +EmptyDeclarationAST *EmptyDeclarationAST::clone(MemoryPool *pool) const +{ + EmptyDeclarationAST *ast = new (pool) EmptyDeclarationAST; + ast->semicolon_token = semicolon_token; + return ast; +} + +void EmptyDeclarationAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + } +} + +unsigned EmptyDeclarationAST::firstToken() const +{ + return semicolon_token; +} + +unsigned EmptyDeclarationAST::lastToken() const +{ + return semicolon_token + 1; +} + +EnumSpecifierAST *EnumSpecifierAST::clone(MemoryPool *pool) const +{ + EnumSpecifierAST *ast = new (pool) EnumSpecifierAST; + ast->enum_token = enum_token; + if (name) + ast->name = name->clone(pool); + ast->lbrace_token = lbrace_token; + if (enumerators) + ast->enumerators = enumerators->clone(pool); + ast->rbrace_token = rbrace_token; + return ast; +} + +void EnumSpecifierAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(name, visitor); + for (EnumeratorAST *enumerator = enumerators; enumerator; + enumerator = enumerator->next) + accept(enumerator, visitor); + } +} + +unsigned EnumSpecifierAST::firstToken() const +{ + return enum_token; +} + +unsigned EnumSpecifierAST::lastToken() const +{ + if (rbrace_token) + return rbrace_token + 1; + + for (EnumeratorAST *it = enumerators; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + if (lbrace_token) + return lbrace_token + 1; + if (name) + return name->lastToken(); + + return enum_token + 1; +} + +EnumeratorAST *EnumeratorAST::clone(MemoryPool *pool) const +{ + EnumeratorAST *ast = new (pool) EnumeratorAST; + ast->identifier_token = identifier_token; + ast->equal_token = equal_token; + if (expression) + ast->expression = expression->clone(pool); + if (next) + ast->next = next->clone(pool); + return ast; +} + +void EnumeratorAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + } +} + +unsigned EnumeratorAST::firstToken() const +{ + return identifier_token; +} + +unsigned EnumeratorAST::lastToken() const +{ + if (expression) + return expression->lastToken(); + else if (equal_token) + return equal_token + 1; + return identifier_token + 1; +} + +ExceptionDeclarationAST *ExceptionDeclarationAST::clone(MemoryPool *pool) const +{ + ExceptionDeclarationAST *ast = new (pool) ExceptionDeclarationAST; + if (type_specifier) + ast->type_specifier = type_specifier->clone(pool); + if (declarator) + ast->declarator = declarator->clone(pool); + ast->dot_dot_dot_token = dot_dot_dot_token; + return ast; +} + +void ExceptionDeclarationAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + for (SpecifierAST *spec = type_specifier; spec; spec = spec->next) + accept(spec, visitor); + accept(declarator, visitor); + } +} + +unsigned ExceptionDeclarationAST::firstToken() const +{ + if (type_specifier) + return type_specifier->firstToken(); + if (declarator) + return declarator->firstToken(); + return dot_dot_dot_token; +} + +unsigned ExceptionDeclarationAST::lastToken() const +{ + if (dot_dot_dot_token) + return dot_dot_dot_token + 1; + else if (declarator) + return declarator->lastToken(); + for (SpecifierAST *it = type_specifier; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + return 0; +} + +ExceptionSpecificationAST *ExceptionSpecificationAST::clone(MemoryPool *pool) const +{ + ExceptionSpecificationAST *ast = new (pool) ExceptionSpecificationAST; + ast->throw_token = throw_token; + ast->lparen_token = lparen_token; + ast->dot_dot_dot_token = dot_dot_dot_token; + if (type_ids) + ast->type_ids = type_ids->clone(pool); + ast->rparen_token = rparen_token; + return ast; +} + +void ExceptionSpecificationAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + for (ExpressionListAST *type_id = type_ids; type_id; + type_id = type_id->next) + accept(type_id->expression, visitor); + } +} + +unsigned ExceptionSpecificationAST::firstToken() const +{ + return throw_token; +} + +unsigned ExceptionSpecificationAST::lastToken() const +{ + if (rparen_token) + return rparen_token + 1; + + for (ExpressionListAST *it = type_ids; it; it = it->next) { + if (! it->next && it->expression) + return it->expression->lastToken(); + } + + if (dot_dot_dot_token) + return dot_dot_dot_token + 1; + else if (lparen_token) + return lparen_token + 1; + + return throw_token + 1; +} + +ExpressionListAST *ExpressionListAST::clone(MemoryPool *pool) const +{ + ExpressionListAST *ast = new (pool) ExpressionListAST; + if (expression) + ast->expression = expression->clone(pool); + if (next) + ast->next = next->clone(pool); + return ast; +} + +void ExpressionListAST::accept0(ASTVisitor *visitor) +{ + for (const ExpressionListAST *it = this; it; it = it->next) { + accept(it->expression, visitor); + } +} + +unsigned ExpressionListAST::firstToken() const +{ + return expression->firstToken(); +} + +unsigned ExpressionListAST::lastToken() const +{ + for (const ExpressionListAST *it = this; it; it = it->next) { + if (! it->next) + return it->expression->lastToken(); + } + return 0; +} + +ExpressionOrDeclarationStatementAST *ExpressionOrDeclarationStatementAST::clone(MemoryPool *pool) const +{ + ExpressionOrDeclarationStatementAST *ast = new (pool) ExpressionOrDeclarationStatementAST; + if (expression) + ast->expression = expression->clone(pool); + if (declaration) + ast->declaration = declaration->clone(pool); + return ast; +} + +void ExpressionOrDeclarationStatementAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(declaration, visitor); + accept(expression, visitor); + } +} + +unsigned ExpressionOrDeclarationStatementAST::firstToken() const +{ + return declaration->firstToken(); +} + +unsigned ExpressionOrDeclarationStatementAST::lastToken() const +{ + return declaration->lastToken(); +} + +ExpressionStatementAST *ExpressionStatementAST::clone(MemoryPool *pool) const +{ + ExpressionStatementAST *ast = new (pool) ExpressionStatementAST; + if (expression) + ast->expression = expression->clone(pool); + ast->semicolon_token = semicolon_token; + return ast; +} + +void ExpressionStatementAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + } +} + +unsigned ExpressionStatementAST::firstToken() const +{ + if (expression) + return expression->firstToken(); + return semicolon_token; +} + +unsigned ExpressionStatementAST::lastToken() const +{ + if (semicolon_token) + return semicolon_token + 1; + else if (expression) + return expression->lastToken(); + // ### assert? + return 0; +} + +ForStatementAST *ForStatementAST::clone(MemoryPool *pool) const +{ + ForStatementAST *ast = new (pool) ForStatementAST; + ast->for_token = for_token; + ast->lparen_token = lparen_token; + if (initializer) + ast->initializer = initializer->clone(pool); + if (condition) + ast->condition = condition->clone(pool); + ast->semicolon_token = semicolon_token; + if (expression) + ast->expression = expression->clone(pool); + ast->rparen_token = rparen_token; + if (statement) + ast->statement = statement->clone(pool); + return ast; +} + +void ForStatementAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(initializer, visitor); + accept(condition, visitor); + accept(expression, visitor); + accept(statement, visitor); + } +} + +unsigned ForStatementAST::firstToken() const +{ + return for_token; +} + +unsigned ForStatementAST::lastToken() const +{ + if (statement) + return statement->lastToken(); + else if (rparen_token) + return rparen_token + 1; + else if (expression) + return expression->lastToken(); + else if (semicolon_token) + return semicolon_token + 1; + else if (condition) + return condition->lastToken(); + else if (initializer) + return initializer->lastToken(); + else if (lparen_token) + return lparen_token + 1; + + return for_token + 1; +} + +FunctionDeclaratorAST *FunctionDeclaratorAST::clone(MemoryPool *pool) const +{ + FunctionDeclaratorAST *ast = new (pool) FunctionDeclaratorAST; + ast->lparen_token = lparen_token; + if (parameters) + ast->parameters = parameters->clone(pool); + ast->rparen_token = rparen_token; + if (cv_qualifier_seq) + ast->cv_qualifier_seq = cv_qualifier_seq->clone(pool); + if (exception_specification) + ast->exception_specification = exception_specification->clone(pool); + return ast; +} + +void FunctionDeclaratorAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + } +} + +unsigned FunctionDeclaratorAST::firstToken() const +{ + return lparen_token; +} + +unsigned FunctionDeclaratorAST::lastToken() const +{ + if (exception_specification) + return exception_specification->lastToken(); + + for (SpecifierAST *it = cv_qualifier_seq; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + if (rparen_token) + return rparen_token + 1; + else if (parameters) + return parameters->lastToken(); + + return lparen_token + 1; +} + +FunctionDefinitionAST *FunctionDefinitionAST::clone(MemoryPool *pool) const +{ + FunctionDefinitionAST *ast = new (pool) FunctionDefinitionAST; + if (decl_specifier_seq) + ast->decl_specifier_seq = decl_specifier_seq->clone(pool); + if (declarator) + ast->declarator = declarator->clone(pool); + if (ctor_initializer) + ast->ctor_initializer = ctor_initializer->clone(pool); + if (function_body) + ast->function_body = function_body->clone(pool); + return ast; +} + +void FunctionDefinitionAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + for (SpecifierAST *spec = decl_specifier_seq; spec; + spec = spec->next) + accept(spec, visitor); + accept(declarator, visitor); + accept(ctor_initializer, visitor); + accept(function_body, visitor); + } +} + +unsigned FunctionDefinitionAST::firstToken() const +{ + if (decl_specifier_seq) + return decl_specifier_seq->firstToken(); + else if (declarator) + return declarator->firstToken(); + else if (ctor_initializer) + return ctor_initializer->firstToken(); + return function_body->firstToken(); +} + +unsigned FunctionDefinitionAST::lastToken() const +{ + if (function_body) + return function_body->lastToken(); + else if (ctor_initializer) + return ctor_initializer->lastToken(); + if (declarator) + return declarator->lastToken(); + + for (SpecifierAST *it = decl_specifier_seq; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + // ### assert + return 0; +} + +GotoStatementAST *GotoStatementAST::clone(MemoryPool *pool) const +{ + GotoStatementAST *ast = new (pool) GotoStatementAST; + ast->goto_token = goto_token; + ast->identifier_token = identifier_token; + ast->semicolon_token = semicolon_token; + return ast; +} + +void GotoStatementAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + } +} + +unsigned GotoStatementAST::firstToken() const +{ + return goto_token; +} + +unsigned GotoStatementAST::lastToken() const +{ + if (semicolon_token) + return semicolon_token + 1; + else if (identifier_token) + return identifier_token + 1; + else if (goto_token) + return goto_token + 1; + return 0; +} + +IfStatementAST *IfStatementAST::clone(MemoryPool *pool) const +{ + IfStatementAST *ast = new (pool) IfStatementAST; + ast->if_token = if_token; + ast->lparen_token = lparen_token; + if (condition) + ast->condition = condition->clone(pool); + ast->rparen_token = rparen_token; + if (statement) + ast->statement = statement->clone(pool); + ast->else_token = else_token; + if (else_statement) + ast->else_statement = else_statement->clone(pool); + return ast; +} + +void IfStatementAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(condition, visitor); + accept(statement, visitor); + accept(else_statement, visitor); + } +} + +unsigned IfStatementAST::firstToken() const +{ + return if_token; +} + +unsigned IfStatementAST::lastToken() const +{ + if (else_statement) + return else_statement->lastToken(); + else if (else_token) + return else_token + 1; + else if (statement) + return statement->lastToken(); + else if (rparen_token) + return rparen_token + 1; + else if (condition) + return condition->lastToken(); + else if (lparen_token) + return lparen_token + 1; + return if_token + 1; +} + +LabeledStatementAST *LabeledStatementAST::clone(MemoryPool *pool) const +{ + LabeledStatementAST *ast = new (pool) LabeledStatementAST; + ast->label_token = label_token; + ast->colon_token = colon_token; + if (statement) + ast->statement = statement->clone(pool); + return ast; +} + +void LabeledStatementAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(statement, visitor); + } +} + +unsigned LabeledStatementAST::firstToken() const +{ + return label_token; +} + +unsigned LabeledStatementAST::lastToken() const +{ + if (statement) + return statement->lastToken(); + else if (colon_token) + return colon_token + 1; + return label_token + 1; +} + +LinkageBodyAST *LinkageBodyAST::clone(MemoryPool *pool) const +{ + LinkageBodyAST *ast = new (pool) LinkageBodyAST; + ast->lbrace_token = lbrace_token; + if (declarations) + ast->declarations = declarations->clone(pool); + ast->rbrace_token = rbrace_token; + return ast; +} + +void LinkageBodyAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + for (DeclarationAST *decl = declarations; decl; + decl = decl->next) + accept(decl, visitor); + } +} + +unsigned LinkageBodyAST::firstToken() const +{ + return lbrace_token; +} + +unsigned LinkageBodyAST::lastToken() const +{ + if (rbrace_token) + return rbrace_token + 1; + + for (DeclarationAST *it = declarations; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + return lbrace_token + 1; +} + +LinkageSpecificationAST *LinkageSpecificationAST::clone(MemoryPool *pool) const +{ + LinkageSpecificationAST *ast = new (pool) LinkageSpecificationAST; + ast->extern_token = extern_token; + ast->extern_type = extern_type; + if (declaration) + ast->declaration = declaration->clone(pool); + return ast; +} + +void LinkageSpecificationAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(declaration, visitor); + } +} + +unsigned LinkageSpecificationAST::firstToken() const +{ + return extern_token; +} + +unsigned LinkageSpecificationAST::lastToken() const +{ + if (declaration) + return declaration->lastToken(); + else if (extern_type) + return extern_type + 1; + return extern_token + 1; +} + +MemInitializerAST *MemInitializerAST::clone(MemoryPool *pool) const +{ + MemInitializerAST *ast = new (pool) MemInitializerAST; + if (name) + ast->name = name->clone(pool); + ast->lparen_token = lparen_token; + if (expression) + ast->expression = expression->clone(pool); + ast->rparen_token = rparen_token; + if (next) + ast->next = next->clone(pool); + return ast; +} + +void MemInitializerAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + } +} + +unsigned MemInitializerAST::firstToken() const +{ + return name->firstToken(); +} + +unsigned MemInitializerAST::lastToken() const +{ + if (rparen_token) + return rparen_token + 1; + else if (expression) + return expression->lastToken(); + else if (lparen_token) + return lparen_token + 1; + return name->lastToken(); +} + +MemberAccessAST *MemberAccessAST::clone(MemoryPool *pool) const +{ + MemberAccessAST *ast = new (pool) MemberAccessAST; + ast->access_token = access_token; + ast->template_token = template_token; + if (member_name) + ast->member_name = member_name->clone(pool); + return ast; +} + +void MemberAccessAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(member_name, visitor); + } +} + +unsigned MemberAccessAST::firstToken() const +{ + return access_token; +} + +unsigned MemberAccessAST::lastToken() const +{ + if (member_name) + return member_name->lastToken(); + else if (template_token) + return template_token + 1; + return access_token + 1; +} + +NamedTypeSpecifierAST *NamedTypeSpecifierAST::clone(MemoryPool *pool) const +{ + NamedTypeSpecifierAST *ast = new (pool) NamedTypeSpecifierAST; + if (name) + ast->name = name->clone(pool); + return ast; +} + +void NamedTypeSpecifierAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(name, visitor); + } +} + +unsigned NamedTypeSpecifierAST::firstToken() const +{ + return name->firstToken(); +} + +unsigned NamedTypeSpecifierAST::lastToken() const +{ + return name->lastToken(); +} + +NamespaceAST *NamespaceAST::clone(MemoryPool *pool) const +{ + NamespaceAST *ast = new (pool) NamespaceAST; + ast->namespace_token = namespace_token; + ast->identifier_token = identifier_token; + if (attributes) + ast->attributes = attributes->clone(pool); + if (linkage_body) + ast->linkage_body = linkage_body->clone(pool); + return ast; +} + +void NamespaceAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + for (SpecifierAST *attr = attributes; attr; attr = attr->next) { + accept(attr, visitor); + } + accept(linkage_body, visitor); + } +} + +unsigned NamespaceAST::firstToken() const +{ + return namespace_token; +} + +unsigned NamespaceAST::lastToken() const +{ + if (linkage_body) + return linkage_body->lastToken(); + + for (SpecifierAST *it = attributes; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + if (identifier_token) + return identifier_token + 1; + + return namespace_token + 1; +} + +NamespaceAliasDefinitionAST *NamespaceAliasDefinitionAST::clone(MemoryPool *pool) const +{ + NamespaceAliasDefinitionAST *ast = new (pool) NamespaceAliasDefinitionAST; + ast->namespace_token = namespace_token; + ast->namespace_name = namespace_name; + ast->equal_token = equal_token; + if (name) + ast->name = name->clone(pool); + ast->semicolon_token = semicolon_token; + return ast; +} + +void NamespaceAliasDefinitionAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(name, visitor); + } +} + +unsigned NamespaceAliasDefinitionAST::firstToken() const +{ + return namespace_token; +} + +unsigned NamespaceAliasDefinitionAST::lastToken() const +{ + if (semicolon_token) + return semicolon_token + 1; + else if (name) + return name->lastToken(); + else if (equal_token) + return equal_token + 1; + else if (namespace_name) + return namespace_name + 1; + return namespace_token + 1; +} + +NestedDeclaratorAST *NestedDeclaratorAST::clone(MemoryPool *pool) const +{ + NestedDeclaratorAST *ast = new (pool) NestedDeclaratorAST; + ast->lparen_token = lparen_token; + if (declarator) + ast->declarator = declarator->clone(pool); + ast->rparen_token = rparen_token; + return ast; +} + +void NestedDeclaratorAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(declarator, visitor); + } +} + +unsigned NestedDeclaratorAST::firstToken() const +{ + return lparen_token; +} + +unsigned NestedDeclaratorAST::lastToken() const +{ + if (rparen_token) + return rparen_token + 1; + else if (declarator) + return declarator->lastToken(); + return lparen_token + 1; +} + +NestedExpressionAST *NestedExpressionAST::clone(MemoryPool *pool) const +{ + NestedExpressionAST *ast = new (pool) NestedExpressionAST; + ast->lparen_token = lparen_token; + if (expression) + ast->expression = expression->clone(pool); + ast->rparen_token = rparen_token; + return ast; +} + +void NestedExpressionAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + } +} + +unsigned NestedExpressionAST::firstToken() const +{ + return lparen_token; +} + +unsigned NestedExpressionAST::lastToken() const +{ + if (rparen_token) + return rparen_token + 1; + else if (expression) + return expression->lastToken(); + return lparen_token + 1; +} + +NestedNameSpecifierAST *NestedNameSpecifierAST::clone(MemoryPool *pool) const +{ + NestedNameSpecifierAST *ast = new (pool) NestedNameSpecifierAST; + if (class_or_namespace_name) + ast->class_or_namespace_name = class_or_namespace_name->clone(pool); + ast->scope_token = scope_token; + if (next) + ast->next = next->clone(pool); + return ast; +} + +void NestedNameSpecifierAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(class_or_namespace_name, visitor); + accept(next, visitor); // ### I'm not 100% sure about this. + } +} + +unsigned NestedNameSpecifierAST::firstToken() const +{ + return class_or_namespace_name->firstToken(); +} + +unsigned NestedNameSpecifierAST::lastToken() const +{ + if (scope_token) + return scope_token + 1; + return class_or_namespace_name->lastToken(); +} + +NewDeclaratorAST *NewDeclaratorAST::clone(MemoryPool *pool) const +{ + NewDeclaratorAST *ast = new (pool) NewDeclaratorAST; + if (ptr_operators) + ast->ptr_operators = ptr_operators->clone(pool); + if (declarator) + ast->declarator = declarator->clone(pool); + return ast; +} + +void NewDeclaratorAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + for (PtrOperatorAST *ptr_op = ptr_operators; ptr_op; + ptr_op = static_cast<PtrOperatorAST *>(ptr_op->next)) { + accept(ptr_op, visitor); + } + + accept(declarator, visitor); + } +} + +unsigned NewDeclaratorAST::firstToken() const +{ + return ptr_operators->firstToken(); +} + +unsigned NewDeclaratorAST::lastToken() const +{ + if (declarator) + return declarator->lastToken(); + + for (PtrOperatorAST *it = ptr_operators; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + return 0; +} + +NewExpressionAST *NewExpressionAST::clone(MemoryPool *pool) const +{ + NewExpressionAST *ast = new (pool) NewExpressionAST; + ast->scope_token = scope_token; + ast->new_token = new_token; + if (expression) + ast->expression = expression->clone(pool); + if (type_id) + ast->type_id = type_id->clone(pool); + if (new_type_id) + ast->new_type_id = new_type_id->clone(pool); + if (new_initializer) + ast->new_initializer = new_initializer->clone(pool); + return ast; +} + +void NewExpressionAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + accept(type_id, visitor); + accept(new_type_id, visitor); + accept(new_initializer, visitor); + } +} + +unsigned NewExpressionAST::firstToken() const +{ + if (scope_token) + return scope_token; + return new_token; +} + +unsigned NewExpressionAST::lastToken() const +{ + if (new_initializer) + return new_initializer->lastToken(); + else if (new_type_id) + return new_type_id->lastToken(); + else if (type_id) + return type_id->lastToken(); + else if (expression) + return expression->lastToken(); + else if (new_token) + return new_token + 1; + else if (scope_token) + return scope_token + 1; + // ### assert? + return 0; +} + +NewInitializerAST *NewInitializerAST::clone(MemoryPool *pool) const +{ + NewInitializerAST *ast = new (pool) NewInitializerAST; + ast->lparen_token = lparen_token; + if (expression) + ast->expression = expression->clone(pool); + ast->rparen_token = rparen_token; + return ast; +} + +void NewInitializerAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + } +} + +unsigned NewInitializerAST::firstToken() const +{ + return lparen_token; +} + +unsigned NewInitializerAST::lastToken() const +{ + if (rparen_token) + return rparen_token + 1; + else if (expression) + return expression->lastToken(); + return lparen_token + 1; +} + +TypeIdAST *TypeIdAST::clone(MemoryPool *pool) const +{ + TypeIdAST *ast = new (pool) TypeIdAST; + if (type_specifier) + ast->type_specifier = type_specifier->clone(pool); + if (declarator) + ast->declarator = declarator->clone(pool); + return ast; +} + +NewTypeIdAST *NewTypeIdAST::clone(MemoryPool *pool) const +{ + NewTypeIdAST *ast = new (pool) NewTypeIdAST; + if (type_specifier) + ast->type_specifier = type_specifier->clone(pool); + if (new_initializer) + ast->new_initializer = new_initializer->clone(pool); + if (new_declarator) + ast->new_declarator = new_declarator->clone(pool); + return ast; +} + +void NewTypeIdAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + for (SpecifierAST *spec = type_specifier; spec; spec = spec->next) + accept(spec, visitor); + accept(new_initializer, visitor); + accept(new_declarator, visitor); + } +} + +unsigned NewTypeIdAST::firstToken() const +{ + return type_specifier->firstToken(); +} + +unsigned NewTypeIdAST::lastToken() const +{ + if (new_declarator) + return new_declarator->lastToken(); + else if (new_initializer) + return new_initializer->lastToken(); + for (SpecifierAST *it = type_specifier; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + // ### assert? + return 0; +} + +NumericLiteralAST *NumericLiteralAST::clone(MemoryPool *pool) const +{ + NumericLiteralAST *ast = new (pool) NumericLiteralAST; + ast->token = token; + return ast; +} + +void NumericLiteralAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + } +} + +unsigned NumericLiteralAST::firstToken() const +{ + return token; +} + +unsigned NumericLiteralAST::lastToken() const +{ + return token + 1; +} + +OperatorAST *OperatorAST::clone(MemoryPool *pool) const +{ + OperatorAST *ast = new (pool) OperatorAST; + ast->op_token = op_token; + ast->open_token = open_token; + ast->close_token = close_token; + return ast; +} + +void OperatorAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + } +} + +unsigned OperatorAST::firstToken() const +{ + return op_token; +} + +unsigned OperatorAST::lastToken() const +{ + if (close_token) + return close_token + 1; + else if (open_token) + return open_token + 1; + return op_token + 1; +} + +OperatorFunctionIdAST *OperatorFunctionIdAST::clone(MemoryPool *pool) const +{ + OperatorFunctionIdAST *ast = new (pool) OperatorFunctionIdAST; + ast->operator_token = operator_token; + if (op) + ast->op = op->clone(pool); + return ast; +} + +void OperatorFunctionIdAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(op, visitor); + } +} + +unsigned OperatorFunctionIdAST::firstToken() const +{ + return operator_token; +} + +unsigned OperatorFunctionIdAST::lastToken() const +{ + if (op) + return op->lastToken(); + return operator_token + 1; +} + +ParameterDeclarationAST *ParameterDeclarationAST::clone(MemoryPool *pool) const +{ + ParameterDeclarationAST *ast = new (pool) ParameterDeclarationAST; + if (type_specifier) + ast->type_specifier = type_specifier->clone(pool); + if (declarator) + ast->declarator = declarator->clone(pool); + ast->equal_token = equal_token; + if (expression) + ast->expression = expression->clone(pool); + return ast; +} + +void ParameterDeclarationAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + for (SpecifierAST *spec = type_specifier; spec; spec = spec->next) + accept(spec, visitor); + accept(declarator, visitor); + accept(expression, visitor); + } +} + +unsigned ParameterDeclarationAST::firstToken() const +{ + return type_specifier->firstToken(); +} + +unsigned ParameterDeclarationAST::lastToken() const +{ + if (expression) + return expression->lastToken(); + else if (equal_token) + return equal_token + 1; + else if (declarator) + return declarator->lastToken(); + for (SpecifierAST *it = type_specifier; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + // ### assert? + return 0; +} + +ParameterDeclarationClauseAST *ParameterDeclarationClauseAST::clone(MemoryPool *pool) const +{ + ParameterDeclarationClauseAST *ast = new (pool) ParameterDeclarationClauseAST; + if (parameter_declarations) + ast->parameter_declarations = parameter_declarations; + ast->dot_dot_dot_token = dot_dot_dot_token; + return ast; +} + +void ParameterDeclarationClauseAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + for (DeclarationAST *param = parameter_declarations; param; + param = param->next) + accept(param, visitor); + } +} + +unsigned ParameterDeclarationClauseAST::firstToken() const +{ + if (parameter_declarations) + return parameter_declarations->firstToken(); + return dot_dot_dot_token; +} + +unsigned ParameterDeclarationClauseAST::lastToken() const +{ + if (dot_dot_dot_token) + return dot_dot_dot_token + 1; + return parameter_declarations->lastToken(); +} + +PointerAST *PointerAST::clone(MemoryPool *pool) const +{ + PointerAST *ast = new (pool) PointerAST; + ast->star_token = star_token; + if (cv_qualifier_seq) + ast->cv_qualifier_seq = cv_qualifier_seq->clone(pool); + return ast; +} + +void PointerAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + for (SpecifierAST *spec = cv_qualifier_seq; spec; + spec = spec->next) + accept(spec, visitor); + } +} + +unsigned PointerAST::firstToken() const +{ + return star_token; +} + +unsigned PointerAST::lastToken() const +{ + for (SpecifierAST *it = cv_qualifier_seq; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + return star_token + 1; +} + +PointerToMemberAST *PointerToMemberAST::clone(MemoryPool *pool) const +{ + PointerToMemberAST *ast = new (pool) PointerToMemberAST; + ast->global_scope_token = global_scope_token; + if (nested_name_specifier) + ast->nested_name_specifier = nested_name_specifier->clone(pool); + ast->star_token = star_token; + if (cv_qualifier_seq) + ast->cv_qualifier_seq = cv_qualifier_seq->clone(pool); + return ast; +} + +void PointerToMemberAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(nested_name_specifier, visitor); + for (SpecifierAST *spec = cv_qualifier_seq; spec; + spec = spec->next) + accept(spec, visitor); + } +} + +unsigned PointerToMemberAST::firstToken() const +{ + if (global_scope_token) + return global_scope_token; + else if (nested_name_specifier) + return nested_name_specifier->firstToken(); + return star_token; +} + +unsigned PointerToMemberAST::lastToken() const +{ + for (SpecifierAST *it = cv_qualifier_seq; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + if (star_token) + return star_token + 1; + + for (NestedNameSpecifierAST *it = nested_name_specifier; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + if (global_scope_token) + return global_scope_token + 1; + + return 0; +} + +PostIncrDecrAST *PostIncrDecrAST::clone(MemoryPool *pool) const +{ + PostIncrDecrAST *ast = new (pool) PostIncrDecrAST; + ast->incr_decr_token = incr_decr_token; + return ast; +} + +void PostIncrDecrAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + } +} + +unsigned PostIncrDecrAST::firstToken() const +{ + return incr_decr_token; +} + +unsigned PostIncrDecrAST::lastToken() const +{ + return incr_decr_token + 1; +} + +PostfixExpressionAST *PostfixExpressionAST::clone(MemoryPool *pool) const +{ + PostfixExpressionAST *ast = new (pool) PostfixExpressionAST; + if (base_expression) + ast->base_expression = base_expression->clone(pool); + if (postfix_expressions) + ast->postfix_expressions = postfix_expressions->clone(pool); + return ast; +} + +void PostfixExpressionAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(base_expression, visitor); + for (PostfixAST *fx = postfix_expressions; fx; fx = fx->next) + accept(fx, visitor); + } +} + +unsigned PostfixExpressionAST::firstToken() const +{ + return base_expression->firstToken(); +} + +unsigned PostfixExpressionAST::lastToken() const +{ + for (PostfixAST *it = postfix_expressions; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + return base_expression->lastToken(); +} + +QualifiedNameAST *QualifiedNameAST::clone(MemoryPool *pool) const +{ + QualifiedNameAST *ast = new (pool) QualifiedNameAST; + ast->global_scope_token = global_scope_token; + if (nested_name_specifier) + ast->nested_name_specifier = nested_name_specifier->clone(pool); + if (unqualified_name) + ast->unqualified_name = unqualified_name->clone(pool); + return ast; +} + +void QualifiedNameAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(nested_name_specifier, visitor); + accept(unqualified_name, visitor); + } +} + +unsigned QualifiedNameAST::firstToken() const +{ + if (global_scope_token) + return global_scope_token; + else if (nested_name_specifier) + return nested_name_specifier->firstToken(); + return unqualified_name->firstToken(); +} + +unsigned QualifiedNameAST::lastToken() const +{ + if (unqualified_name) + return unqualified_name->lastToken(); + + for (NestedNameSpecifierAST *it = nested_name_specifier; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + if (global_scope_token) + return global_scope_token + 1; + + return 0; +} + +ReferenceAST *ReferenceAST::clone(MemoryPool *pool) const +{ + ReferenceAST *ast = new (pool) ReferenceAST; + ast->amp_token = amp_token; + return ast; +} + +void ReferenceAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + } +} + +unsigned ReferenceAST::firstToken() const +{ + return amp_token; +} + +unsigned ReferenceAST::lastToken() const +{ + return amp_token + 1; +} + +ReturnStatementAST *ReturnStatementAST::clone(MemoryPool *pool) const +{ + ReturnStatementAST *ast = new (pool) ReturnStatementAST; + ast->return_token = return_token; + if (expression) + ast->expression = expression->clone(pool); + ast->semicolon_token = semicolon_token; + return ast; +} + +void ReturnStatementAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + } +} + +unsigned ReturnStatementAST::firstToken() const +{ + return return_token; +} + +unsigned ReturnStatementAST::lastToken() const +{ + if (semicolon_token) + return semicolon_token + 1; + else if (expression) + return expression->lastToken(); + return return_token + 1; +} + +SimpleDeclarationAST *SimpleDeclarationAST::clone(MemoryPool *pool) const +{ + SimpleDeclarationAST *ast = new (pool) SimpleDeclarationAST; + if (decl_specifier_seq) + ast->decl_specifier_seq = decl_specifier_seq->clone(pool); + if (declarators) + ast->declarators = declarators->clone(pool); + ast->semicolon_token = semicolon_token; + return ast; +} + +void SimpleDeclarationAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + for (SpecifierAST *spec = decl_specifier_seq; spec; + spec = spec->next) + accept(spec, visitor); + accept(declarators, visitor); + } +} + +unsigned SimpleDeclarationAST::firstToken() const +{ + if (decl_specifier_seq) + return decl_specifier_seq->firstToken(); + else if (declarators) + return declarators->firstToken(); + return semicolon_token; +} + +unsigned SimpleDeclarationAST::lastToken() const +{ + if (semicolon_token) + return semicolon_token + 1; + + for (DeclaratorListAST *it = declarators; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + for (SpecifierAST *it = decl_specifier_seq; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + return 0; +} + +SimpleNameAST *SimpleNameAST::clone(MemoryPool *pool) const +{ + SimpleNameAST *ast = new (pool) SimpleNameAST; + ast->identifier_token = identifier_token; + return ast; +} + +void SimpleNameAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + } +} + +unsigned SimpleNameAST::firstToken() const +{ + return identifier_token; +} + +unsigned SimpleNameAST::lastToken() const +{ + return identifier_token + 1; +} + +void SimpleSpecifierAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + } +} + +SimpleSpecifierAST *SimpleSpecifierAST::clone(MemoryPool *pool) const +{ + SimpleSpecifierAST *ast = new (pool) SimpleSpecifierAST; + ast->specifier_token = specifier_token; + if (next) + ast->next = next->clone(pool); + return ast; +} + +unsigned SimpleSpecifierAST::firstToken() const +{ + return specifier_token; +} + +unsigned SimpleSpecifierAST::lastToken() const +{ + return specifier_token + 1; +} + +TypeofSpecifierAST *TypeofSpecifierAST::clone(MemoryPool *pool) const +{ + TypeofSpecifierAST *ast = new (pool) TypeofSpecifierAST; + ast->typeof_token = typeof_token; + if (expression) + ast->expression = expression->clone(pool); + if (next) + ast->next = next->clone(pool); + return ast; +} + +void TypeofSpecifierAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + } +} + +unsigned TypeofSpecifierAST::firstToken() const +{ + return typeof_token; +} + +unsigned TypeofSpecifierAST::lastToken() const +{ + if (expression) + return expression->lastToken(); + return typeof_token + 1; +} + +SizeofExpressionAST *SizeofExpressionAST::clone(MemoryPool *pool) const +{ + SizeofExpressionAST *ast = new (pool) SizeofExpressionAST; + ast->sizeof_token = sizeof_token; + if (expression) + ast->expression = expression->clone(pool); + return ast; +} + +void SizeofExpressionAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + } +} + +unsigned SizeofExpressionAST::firstToken() const +{ + return sizeof_token; +} + +unsigned SizeofExpressionAST::lastToken() const +{ + if (expression) + return expression->lastToken(); + return sizeof_token + 1; +} + +StringLiteralAST *StringLiteralAST::clone(MemoryPool *pool) const +{ + StringLiteralAST *ast = new (pool) StringLiteralAST; + ast->token = token; + if (next) + ast->next = next->clone(pool); + return ast; +} + +void StringLiteralAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(next, visitor); + } +} + +unsigned StringLiteralAST::firstToken() const +{ + return token; +} + +unsigned StringLiteralAST::lastToken() const +{ + if (next) + return next->lastToken(); + return token + 1; +} + +SwitchStatementAST *SwitchStatementAST::clone(MemoryPool *pool) const +{ + SwitchStatementAST *ast = new (pool) SwitchStatementAST; + ast->switch_token = switch_token; + ast->lparen_token = lparen_token; + if (condition) + ast->condition = condition->clone(pool); + ast->rparen_token = rparen_token; + if (statement) + ast->statement = statement->clone(pool); + return ast; +} + +void SwitchStatementAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(condition, visitor); + accept(statement, visitor); + } +} + +unsigned SwitchStatementAST::firstToken() const +{ + return switch_token; +} + +unsigned SwitchStatementAST::lastToken() const +{ + if (statement) + return statement->lastToken(); + else if (rparen_token) + return rparen_token + 1; + else if (condition) + return condition->lastToken(); + else if (lparen_token) + return lparen_token + 1; + return switch_token + 1; +} + +TemplateArgumentListAST *TemplateArgumentListAST::clone(MemoryPool *pool) const +{ + TemplateArgumentListAST *ast = new (pool) TemplateArgumentListAST; + if (template_argument) + ast->template_argument = template_argument->clone(pool); + if (next) + ast->next = next->clone(pool); + return ast; +} + +void TemplateArgumentListAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(template_argument, visitor); + accept(next, visitor); + } +} + +unsigned TemplateArgumentListAST::firstToken() const +{ + return template_argument->firstToken(); +} + +unsigned TemplateArgumentListAST::lastToken() const +{ + for (const TemplateArgumentListAST *it = this; it; it = it->next) { + if (! it->next && it->template_argument) + return it->template_argument->lastToken(); + } + return 0; +} + +TemplateDeclarationAST *TemplateDeclarationAST::clone(MemoryPool *pool) const +{ + TemplateDeclarationAST *ast = new (pool) TemplateDeclarationAST; + ast->export_token = export_token; + ast->template_token = template_token; + ast->less_token = less_token; + if (template_parameters) + ast->template_parameters = template_parameters->clone(pool); + ast->greater_token = greater_token; + if (declaration) + ast->declaration = declaration->clone(pool); + return ast; +} + +void TemplateDeclarationAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + for (DeclarationAST *param = template_parameters; param; + param = param->next) + accept(param, visitor); + accept(declaration, visitor); + } +} + +unsigned TemplateDeclarationAST::firstToken() const +{ + if (export_token) + return export_token; + return template_token; +} + +unsigned TemplateDeclarationAST::lastToken() const +{ + if (declaration) + return declaration->lastToken(); + else if (greater_token) + return greater_token + 1; + + for (DeclarationAST *it = template_parameters; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + if (less_token) + return less_token + 1; + else if (template_token) + return template_token + 1; + else if (export_token) + return export_token + 1; + + return 0; +} + +TemplateIdAST *TemplateIdAST::clone(MemoryPool *pool) const +{ + TemplateIdAST *ast = new (pool) TemplateIdAST; + ast->identifier_token = identifier_token; + ast->less_token = less_token; + if (template_arguments) + ast->template_arguments = template_arguments->clone(pool); + ast->greater_token = greater_token; + return ast; +} + +void TemplateIdAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + for (TemplateArgumentListAST *it = template_arguments; it; it = it->next) { + accept(it, visitor); + } + } +} + +unsigned TemplateIdAST::firstToken() const +{ + return identifier_token; +} + +unsigned TemplateIdAST::lastToken() const +{ + if (greater_token) + return greater_token + 1; + + for (TemplateArgumentListAST *it = template_arguments; it; it = it->next) { + if (! it->next && it->template_argument) + return it->template_argument->lastToken(); + } + + if (less_token) + return less_token + 1; + + return identifier_token + 1; +} + +TemplateTypeParameterAST *TemplateTypeParameterAST::clone(MemoryPool *pool) const +{ + TemplateTypeParameterAST *ast = new (pool) TemplateTypeParameterAST; + ast->template_token = template_token; + ast->less_token = less_token; + if (template_parameters) + ast->template_parameters = template_parameters->clone(pool); + ast->greater_token = greater_token; + ast->class_token = class_token; + if (name) + ast->name = name->clone(pool); + ast->equal_token = equal_token; + if (type_id) + ast->type_id = type_id->clone(pool); + return ast; +} + +void TemplateTypeParameterAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + } +} + +unsigned TemplateTypeParameterAST::firstToken() const +{ + return template_token; +} + +unsigned TemplateTypeParameterAST::lastToken() const +{ + if (type_id) + return type_id->lastToken(); + else if (equal_token) + return equal_token + 1; + else if (name) + return name->lastToken(); + else if (class_token) + return class_token + 1; + else if (greater_token) + return greater_token + 1; + + for (DeclarationAST *it = template_parameters; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + if (less_token) + return less_token + 1; + + return template_token + 1; +} + +ThisExpressionAST *ThisExpressionAST::clone(MemoryPool *pool) const +{ + ThisExpressionAST *ast = new (pool) ThisExpressionAST; + ast->this_token = this_token; + return ast; +} + +void ThisExpressionAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + } +} + +unsigned ThisExpressionAST::firstToken() const +{ + return this_token; +} + +unsigned ThisExpressionAST::lastToken() const +{ + return this_token + 1; +} + +ThrowExpressionAST *ThrowExpressionAST::clone(MemoryPool *pool) const +{ + ThrowExpressionAST *ast = new (pool) ThrowExpressionAST; + ast->throw_token = throw_token; + if (expression) + ast->expression = expression->clone(pool); + return ast; +} + +void ThrowExpressionAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + } +} + +unsigned ThrowExpressionAST::firstToken() const +{ + return throw_token; +} + +unsigned ThrowExpressionAST::lastToken() const +{ + if (expression) + return expression->lastToken(); + return throw_token + 1; +} + +TranslationUnitAST *TranslationUnitAST::clone(MemoryPool *pool) const +{ + TranslationUnitAST *ast = new (pool) TranslationUnitAST; + if (declarations) + ast->declarations = declarations->clone(pool); + return ast; +} + +void TranslationUnitAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + for (DeclarationAST *decl = declarations; decl; + decl = decl->next) + accept(decl, visitor); + } +} + +unsigned TranslationUnitAST::firstToken() const +{ + return declarations->firstToken(); +} + +unsigned TranslationUnitAST::lastToken() const +{ + for (DeclarationAST *it = declarations; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + return 0; +} + +TryBlockStatementAST *TryBlockStatementAST::clone(MemoryPool *pool) const +{ + TryBlockStatementAST *ast = new (pool) TryBlockStatementAST; + ast->try_token = try_token; + if (statement) + ast->statement = statement->clone(pool); + if (catch_clause_seq) + ast->catch_clause_seq = catch_clause_seq->clone(pool); + return ast; +} + +void TryBlockStatementAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(statement, visitor); + accept(catch_clause_seq, visitor); + } +} + +unsigned TryBlockStatementAST::firstToken() const +{ + return try_token; +} + +unsigned TryBlockStatementAST::lastToken() const +{ + for (CatchClauseAST *it = catch_clause_seq; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + if (statement) + return statement->lastToken(); + + return try_token + 1; +} + +TypeConstructorCallAST *TypeConstructorCallAST::clone(MemoryPool *pool) const +{ + TypeConstructorCallAST *ast = new (pool) TypeConstructorCallAST; + if (type_specifier) + ast->type_specifier = type_specifier->clone(pool); + ast->lparen_token = lparen_token; + if (expression_list) + ast->expression_list = expression_list; + ast->rparen_token = rparen_token; + return ast; +} + +void TypeConstructorCallAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + for (SpecifierAST *spec = type_specifier; spec; spec = spec->next) + accept(spec, visitor); + for (ExpressionListAST *expr = expression_list;expr; + expr = expr->next) + accept(expr->expression, visitor); + } +} + +unsigned TypeConstructorCallAST::firstToken() const +{ + return type_specifier->firstToken(); +} + +unsigned TypeConstructorCallAST::lastToken() const +{ + if (rparen_token) + return rparen_token + 1; + + for (ExpressionListAST *it = expression_list; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + if (lparen_token) + return lparen_token + 1; + + + for (SpecifierAST *it = type_specifier; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + return 0; +} + +void TypeIdAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + for (SpecifierAST *spec = type_specifier; spec; spec = spec->next) + accept(spec, visitor); + accept(declarator, visitor); + } +} + +unsigned TypeIdAST::firstToken() const +{ + return type_specifier->firstToken(); +} + +unsigned TypeIdAST::lastToken() const +{ + if (declarator) + return declarator->lastToken(); + + for (SpecifierAST *it = type_specifier; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + return 0; +} + +TypeidExpressionAST *TypeidExpressionAST::clone(MemoryPool *pool) const +{ + TypeidExpressionAST *ast = new (pool) TypeidExpressionAST; + ast->typeid_token = typeid_token; + ast->lparen_token = lparen_token; + if (expression) + ast->expression = expression->clone(pool); + ast->rparen_token = rparen_token; + return ast; +} + +void TypeidExpressionAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + } +} + +unsigned TypeidExpressionAST::firstToken() const +{ + return typeid_token; +} + +unsigned TypeidExpressionAST::lastToken() const +{ + if (rparen_token) + return rparen_token + 1; + else if (expression) + return expression->lastToken(); + else if (lparen_token) + return lparen_token + 1; + + return typeid_token + 1; +} + +TypenameCallExpressionAST *TypenameCallExpressionAST::clone(MemoryPool *pool) const +{ + TypenameCallExpressionAST *ast = new (pool) TypenameCallExpressionAST; + ast->typename_token = typename_token; + if (name) + ast->name = name->clone(pool); + ast->lparen_token = lparen_token; + if (expression_list) + ast->expression_list = expression_list; + ast->rparen_token = rparen_token; + return ast; +} + +void TypenameCallExpressionAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(name, visitor); + for (ExpressionListAST *expr = expression_list;expr; + expr = expr->next) + accept(expr->expression, visitor); + } +} + +unsigned TypenameCallExpressionAST::firstToken() const +{ + return typename_token; +} + +unsigned TypenameCallExpressionAST::lastToken() const +{ + if (rparen_token) + return rparen_token + 1; + + for (ExpressionListAST *it = expression_list; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + if (lparen_token) + return lparen_token + 1; + else if (name) + return name->lastToken(); + + return typename_token + 1; +} + +TypenameTypeParameterAST *TypenameTypeParameterAST::clone(MemoryPool *pool) const +{ + TypenameTypeParameterAST *ast = new (pool) TypenameTypeParameterAST; + ast->classkey_token = classkey_token; + if (name) + ast->name = name->clone(pool); + ast->equal_token = equal_token; + if (type_id) + ast->type_id = type_id->clone(pool); + return ast; +} + +void TypenameTypeParameterAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(name, visitor); + accept(type_id, visitor); + } +} + +unsigned TypenameTypeParameterAST::firstToken() const +{ + return classkey_token; +} + +unsigned TypenameTypeParameterAST::lastToken() const +{ + if (type_id) + return type_id->lastToken(); + else if (equal_token) + return equal_token + 1; + else if (name) + return name->lastToken(); + return classkey_token + 1; +} + +UnaryExpressionAST *UnaryExpressionAST::clone(MemoryPool *pool) const +{ + UnaryExpressionAST *ast = new (pool) UnaryExpressionAST; + ast->unary_op_token = unary_op_token; + if (expression) + ast->expression = expression->clone(pool); + return ast; +} + +void UnaryExpressionAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + } +} + +unsigned UnaryExpressionAST::firstToken() const +{ + return unary_op_token; +} + +unsigned UnaryExpressionAST::lastToken() const +{ + if (expression) + return expression->lastToken(); + return unary_op_token + 1; +} + +UsingAST *UsingAST::clone(MemoryPool *pool) const +{ + UsingAST *ast = new (pool) UsingAST; + ast->using_token = using_token; + ast->typename_token = typename_token; + if (name) + ast->name = name->clone(pool); + ast->semicolon_token = semicolon_token; + return ast; +} + +void UsingAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(name, visitor); + } +} + +unsigned UsingAST::firstToken() const +{ + return using_token; +} + +unsigned UsingAST::lastToken() const +{ + if (semicolon_token) + return semicolon_token + 1; + else if (name) + return name->lastToken(); + else if (typename_token) + return typename_token + 1; + return using_token + 1; +} + +UsingDirectiveAST *UsingDirectiveAST::clone(MemoryPool *pool) const +{ + UsingDirectiveAST *ast = new (pool) UsingDirectiveAST; + ast->using_token = using_token; + ast->namespace_token = namespace_token; + if (name) + ast->name = name->clone(pool); + ast->semicolon_token = semicolon_token; + return ast; +} + +void UsingDirectiveAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(name, visitor); + } +} + +unsigned UsingDirectiveAST::firstToken() const +{ + return using_token; +} + +unsigned UsingDirectiveAST::lastToken() const +{ + if (semicolon_token) + return semicolon_token + 1; + else if (name) + return name->lastToken(); + else if (namespace_token) + return namespace_token + 1; + return using_token + 1; +} + +WhileStatementAST *WhileStatementAST::clone(MemoryPool *pool) const +{ + WhileStatementAST *ast = new (pool) WhileStatementAST; + ast->while_token = while_token; + ast->lparen_token = lparen_token; + if (condition) + ast->condition = condition->clone(pool); + ast->rparen_token = rparen_token; + if (statement) + ast->statement = statement->clone(pool); + return ast; +} + +void WhileStatementAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(condition, visitor); + accept(statement, visitor); + } +} + +unsigned WhileStatementAST::firstToken() const +{ + return while_token; +} + +unsigned WhileStatementAST::lastToken() const +{ + if (statement) + return statement->lastToken(); + else if (rparen_token) + return rparen_token + 1; + else if (condition) + return condition->lastToken(); + else if (lparen_token) + return lparen_token + 1; + return while_token + 1; +} + +// ObjC++ +unsigned IdentifierListAST::firstToken() const +{ + return identifier_token; +} + +unsigned IdentifierListAST::lastToken() const +{ + for (const IdentifierListAST *it = this; it; it = it->next) { + if (! it->next && it->identifier_token) { + return it->identifier_token + 1; + } + } + // ### assert? + return 0; +} + +IdentifierListAST *IdentifierListAST::clone(MemoryPool *pool) const +{ + IdentifierListAST *ast = new (pool) IdentifierListAST; + ast->identifier_token = identifier_token; + if (next) + ast->next = next->clone(pool); + return ast; +} + +void IdentifierListAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + } +} + +unsigned ObjCClassDeclarationAST::firstToken() const +{ + if (attributes) + return attributes->firstToken(); + return class_token; +} + +unsigned ObjCClassDeclarationAST::lastToken() const +{ + if (semicolon_token) + return semicolon_token + 1; + + for (IdentifierListAST *it = identifier_list; it; it = it->next) { + if (! it->next && it->identifier_token) + return it->identifier_token + 1; + } + + for (SpecifierAST *it = attributes; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + return class_token + 1; +} + +ObjCClassDeclarationAST *ObjCClassDeclarationAST::clone(MemoryPool *pool) const +{ + ObjCClassDeclarationAST *ast = new (pool) ObjCClassDeclarationAST; + if (attributes) + ast->attributes = attributes->clone(pool); + ast->class_token = class_token; + if (identifier_list) + ast->identifier_list = identifier_list->clone(pool); + ast->semicolon_token = semicolon_token; + return ast; +} + +void ObjCClassDeclarationAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + for (SpecifierAST *it = attributes; it; it = it->next) { + accept(it, visitor); + } + } +} + + +CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/AST.h b/src/shared/cplusplus/AST.h new file mode 100644 index 0000000000..d7f346c5b0 --- /dev/null +++ b/src/shared/cplusplus/AST.h @@ -0,0 +1,1989 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. + +#ifndef CPLUSPLUS_AST_H +#define CPLUSPLUS_AST_H + +#include "CPlusPlusForwardDeclarations.h" +#include "ASTfwd.h" +#include "MemoryPool.h" + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +class CPLUSPLUS_EXPORT AST: public Managed +{ + AST(const AST &other); + void operator =(const AST &other); + +public: + AST(); + virtual ~AST(); + + void accept(ASTVisitor *visitor); + + static void accept(AST *ast, ASTVisitor *visitor) + { if (ast) ast->accept(visitor); } + + virtual unsigned firstToken() const = 0; + virtual unsigned lastToken() const = 0; + + AccessDeclarationAST *asAccessDeclaration(); + ArrayAccessAST *asArrayAccess(); + ArrayDeclaratorAST *asArrayDeclarator(); + ArrayInitializerAST *asArrayInitializer(); + AsmDefinitionAST *asAsmDefinition(); + AttributeAST *asAttribute(); + AttributeSpecifierAST *asAttributeSpecifier(); + BaseSpecifierAST *asBaseSpecifier(); + QtMethodAST *asQtMethod(); + BinaryExpressionAST *asBinaryExpression(); + BoolLiteralAST *asBoolLiteral(); + BreakStatementAST *asBreakStatement(); + CallAST *asCall(); + CaseStatementAST *asCaseStatement(); + CastExpressionAST *asCastExpression(); + CatchClauseAST *asCatchClause(); + ClassSpecifierAST *asClassSpecifier(); + CompoundLiteralAST *asCompoundLiteral(); + CompoundStatementAST *asCompoundStatement(); + ConditionAST *asCondition(); + ConditionalExpressionAST *asConditionalExpression(); + ContinueStatementAST *asContinueStatement(); + ConversionFunctionIdAST *asConversionFunctionId(); + CoreDeclaratorAST *asCoreDeclarator(); + CppCastExpressionAST *asCppCastExpression(); + CtorInitializerAST *asCtorInitializer(); + DeclarationAST *asDeclaration(); + DeclarationStatementAST *asDeclarationStatement(); + DeclaratorAST *asDeclarator(); + DeclaratorIdAST *asDeclaratorId(); + DeclaratorListAST *asDeclaratorList(); + DeleteExpressionAST *asDeleteExpression(); + DestructorNameAST *asDestructorName(); + DoStatementAST *asDoStatement(); + ElaboratedTypeSpecifierAST *asElaboratedTypeSpecifier(); + EmptyDeclarationAST *asEmptyDeclaration(); + EnumSpecifierAST *asEnumSpecifier(); + EnumeratorAST *asEnumerator(); + ExceptionDeclarationAST *asExceptionDeclaration(); + ExceptionSpecificationAST *asExceptionSpecification(); + ExpressionAST *asExpression(); + ExpressionListAST *asExpressionList(); + ExpressionOrDeclarationStatementAST *asExpressionOrDeclarationStatement(); + ExpressionStatementAST *asExpressionStatement(); + ForStatementAST *asForStatement(); + FunctionDeclaratorAST *asFunctionDeclarator(); + FunctionDefinitionAST *asFunctionDefinition(); + GotoStatementAST *asGotoStatement(); + IfStatementAST *asIfStatement(); + LabeledStatementAST *asLabeledStatement(); + LinkageBodyAST *asLinkageBody(); + LinkageSpecificationAST *asLinkageSpecification(); + MemInitializerAST *asMemInitializer(); + MemberAccessAST *asMemberAccess(); + NameAST *asName(); + NamedTypeSpecifierAST *asNamedTypeSpecifier(); + NamespaceAST *asNamespace(); + NamespaceAliasDefinitionAST *asNamespaceAliasDefinition(); + NestedDeclaratorAST *asNestedDeclarator(); + NestedExpressionAST *asNestedExpression(); + NestedNameSpecifierAST *asNestedNameSpecifier(); + NewDeclaratorAST *asNewDeclarator(); + NewExpressionAST *asNewExpression(); + NewInitializerAST *asNewInitializer(); + NewTypeIdAST *asNewTypeId(); + NumericLiteralAST *asNumericLiteral(); + OperatorAST *asOperator(); + OperatorFunctionIdAST *asOperatorFunctionId(); + ParameterDeclarationAST *asParameterDeclaration(); + ParameterDeclarationClauseAST *asParameterDeclarationClause(); + PointerAST *asPointer(); + PointerToMemberAST *asPointerToMember(); + PostIncrDecrAST *asPostIncrDecr(); + PostfixAST *asPostfix(); + PostfixDeclaratorAST *asPostfixDeclarator(); + PostfixExpressionAST *asPostfixExpression(); + PtrOperatorAST *asPtrOperator(); + QualifiedNameAST *asQualifiedName(); + ReferenceAST *asReference(); + ReturnStatementAST *asReturnStatement(); + SimpleDeclarationAST *asSimpleDeclaration(); + SimpleNameAST *asSimpleName(); + SimpleSpecifierAST *asSimpleSpecifier(); + SizeofExpressionAST *asSizeofExpression(); + SpecifierAST *asSpecifier(); + StatementAST *asStatement(); + StringLiteralAST *asStringLiteral(); + SwitchStatementAST *asSwitchStatement(); + TemplateArgumentListAST *asTemplateArgumentList(); + TemplateDeclarationAST *asTemplateDeclaration(); + TemplateIdAST *asTemplateId(); + TemplateTypeParameterAST *asTemplateTypeParameter(); + ThisExpressionAST *asThisExpression(); + ThrowExpressionAST *asThrowExpression(); + TranslationUnitAST *asTranslationUnit(); + TryBlockStatementAST *asTryBlockStatement(); + TypeConstructorCallAST *asTypeConstructorCall(); + TypeIdAST *asTypeId(); + TypeidExpressionAST *asTypeidExpression(); + TypenameCallExpressionAST *asTypenameCallExpression(); + TypenameTypeParameterAST *asTypenameTypeParameter(); + TypeofSpecifierAST *asTypeofSpecifier(); + UnaryExpressionAST *asUnaryExpression(); + UsingAST *asUsing(); + UsingDirectiveAST *asUsingDirective(); + WhileStatementAST *asWhileStatement(); + + virtual AST *clone(MemoryPool *pool) const = 0; + +protected: + virtual void accept0(ASTVisitor *visitor) = 0; +}; + +class CPLUSPLUS_EXPORT SpecifierAST: public AST +{ +public: + SpecifierAST *next; + +public: + virtual SpecifierAST *clone(MemoryPool *pool) const = 0; +}; + +class CPLUSPLUS_EXPORT SimpleSpecifierAST: public SpecifierAST +{ +public: + unsigned specifier_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual SimpleSpecifierAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT AttributeSpecifierAST: public SpecifierAST +{ +public: + unsigned attribute_token; + unsigned first_lparen_token; + unsigned second_lparen_token; + AttributeAST *attributes; + unsigned first_rparen_token; + unsigned second_rparen_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual AttributeSpecifierAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT AttributeAST: public AST +{ +public: + unsigned identifier_token; + unsigned lparen_token; + unsigned tag_token; + ExpressionListAST *expression_list; + unsigned rparen_token; + AttributeAST *next; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual AttributeAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT TypeofSpecifierAST: public SpecifierAST +{ +public: + unsigned typeof_token; + ExpressionAST *expression; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual TypeofSpecifierAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT StatementAST: public AST +{ +public: + StatementAST *next; + +public: + virtual StatementAST *clone(MemoryPool *pool) const = 0; +}; + +class CPLUSPLUS_EXPORT ExpressionAST: public AST +{ +public: + virtual ExpressionAST *clone(MemoryPool *pool) const = 0; +}; + +class CPLUSPLUS_EXPORT DeclarationAST: public AST +{ +public: + DeclarationAST *next; + +public: + virtual DeclarationAST *clone(MemoryPool *pool) const = 0; +}; + +class CPLUSPLUS_EXPORT CoreDeclaratorAST: public AST +{ +public: + virtual CoreDeclaratorAST *clone(MemoryPool *pool) const = 0; +}; + +class CPLUSPLUS_EXPORT PostfixDeclaratorAST: public AST +{ +public: + PostfixDeclaratorAST *next; + +public: + virtual PostfixDeclaratorAST *clone(MemoryPool *pool) const = 0; +}; + +class CPLUSPLUS_EXPORT DeclaratorAST: public AST +{ +public: + PtrOperatorAST *ptr_operators; + CoreDeclaratorAST *core_declarator; + PostfixDeclaratorAST *postfix_declarators; + SpecifierAST *attributes; + ExpressionAST *initializer; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual DeclaratorAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT ExpressionListAST: public ExpressionAST +{ +public: + ExpressionAST *expression; + ExpressionListAST *next; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual ExpressionListAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT SimpleDeclarationAST: public DeclarationAST +{ +public: + SpecifierAST *decl_specifier_seq; + DeclaratorListAST *declarators; + unsigned semicolon_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual SimpleDeclarationAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT EmptyDeclarationAST: public DeclarationAST +{ +public: + unsigned semicolon_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual EmptyDeclarationAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT AccessDeclarationAST: public DeclarationAST +{ +public: + unsigned access_specifier_token; + unsigned slots_token; + unsigned colon_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual AccessDeclarationAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT AsmDefinitionAST: public DeclarationAST +{ +public: + unsigned asm_token; + SpecifierAST *cv_qualifier_seq; + unsigned lparen_token; + unsigned rparen_token; + unsigned semicolon_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual AsmDefinitionAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT BaseSpecifierAST: public AST +{ +public: + unsigned token_virtual; + unsigned token_access_specifier; + NameAST *name; + BaseSpecifierAST *next; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual BaseSpecifierAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT CompoundLiteralAST: public ExpressionAST +{ +public: + unsigned lparen_token; + ExpressionAST *type_id; + unsigned rparen_token; + ExpressionAST *initializer; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual CompoundLiteralAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT QtMethodAST: public ExpressionAST +{ +public: + unsigned method_token; + unsigned lparen_token; + DeclaratorAST *declarator; + unsigned rparen_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual QtMethodAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT BinaryExpressionAST: public ExpressionAST +{ +public: + ExpressionAST *left_expression; + unsigned binary_op_token; + ExpressionAST *right_expression; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual BinaryExpressionAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT CastExpressionAST: public ExpressionAST +{ +public: + unsigned lparen_token; + ExpressionAST *type_id; + unsigned rparen_token; + ExpressionAST *expression; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual CastExpressionAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT ClassSpecifierAST: public SpecifierAST +{ +public: + unsigned classkey_token; + SpecifierAST *attributes; + NameAST *name; + unsigned colon_token; + BaseSpecifierAST *base_clause; + unsigned lbrace_token; + DeclarationAST *member_specifiers; + unsigned rbrace_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual ClassSpecifierAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT CaseStatementAST: public StatementAST +{ +public: + unsigned case_token; + ExpressionAST *expression; + unsigned colon_token; + StatementAST *statement; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual CaseStatementAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT CompoundStatementAST: public StatementAST +{ +public: + unsigned lbrace_token; + StatementAST *statements; + unsigned rbrace_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual CompoundStatementAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT ConditionAST: public ExpressionAST +{ +public: + SpecifierAST *type_specifier; + DeclaratorAST *declarator; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual ConditionAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT ConditionalExpressionAST: public ExpressionAST +{ +public: + ExpressionAST *condition; + unsigned question_token; + ExpressionAST *left_expression; + unsigned colon_token; + ExpressionAST *right_expression; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual ConditionalExpressionAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT CppCastExpressionAST: public ExpressionAST +{ +public: + unsigned cast_token; + unsigned less_token; + ExpressionAST *type_id; + unsigned greater_token; + unsigned lparen_token; + ExpressionAST *expression; + unsigned rparen_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual CppCastExpressionAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT CtorInitializerAST: public AST +{ +public: + unsigned colon_token; + MemInitializerAST *member_initializers; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual CtorInitializerAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT DeclarationStatementAST: public StatementAST +{ +public: + DeclarationAST *declaration; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual DeclarationStatementAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT DeclaratorIdAST: public CoreDeclaratorAST +{ +public: + NameAST *name; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual DeclaratorIdAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT NestedDeclaratorAST: public CoreDeclaratorAST +{ +public: + unsigned lparen_token; + DeclaratorAST *declarator; + unsigned rparen_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual NestedDeclaratorAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT FunctionDeclaratorAST: public PostfixDeclaratorAST +{ +public: + unsigned lparen_token; + ParameterDeclarationClauseAST *parameters; + unsigned rparen_token; + SpecifierAST *cv_qualifier_seq; + ExceptionSpecificationAST *exception_specification; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual FunctionDeclaratorAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT ArrayDeclaratorAST: public PostfixDeclaratorAST +{ +public: + unsigned lbracket_token; + ExpressionAST *expression; + unsigned rbracket_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual ArrayDeclaratorAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT DeclaratorListAST: public AST +{ +public: + DeclaratorAST *declarator; + DeclaratorListAST *next; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual DeclaratorListAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT DeleteExpressionAST: public ExpressionAST +{ +public: + unsigned scope_token; + unsigned delete_token; + unsigned lbracket_token; + unsigned rbracket_token; + ExpressionAST *expression; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual DeleteExpressionAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT DoStatementAST: public StatementAST +{ +public: + unsigned do_token; + StatementAST *statement; + unsigned while_token; + unsigned lparen_token; + ExpressionAST *expression; + unsigned rparen_token; + unsigned semicolon_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual DoStatementAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT NamedTypeSpecifierAST: public SpecifierAST +{ +public: + NameAST *name; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual NamedTypeSpecifierAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT ElaboratedTypeSpecifierAST: public SpecifierAST +{ +public: + unsigned classkey_token; + NameAST *name; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual ElaboratedTypeSpecifierAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT EnumSpecifierAST: public SpecifierAST +{ +public: + unsigned enum_token; + NameAST *name; + unsigned lbrace_token; + EnumeratorAST *enumerators; + unsigned rbrace_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual EnumSpecifierAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT EnumeratorAST: public AST +{ +public: + unsigned identifier_token; + unsigned equal_token; + ExpressionAST *expression; + EnumeratorAST *next; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual EnumeratorAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT ExceptionDeclarationAST: public DeclarationAST +{ +public: + SpecifierAST *type_specifier; + DeclaratorAST *declarator; + unsigned dot_dot_dot_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual ExceptionDeclarationAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT ExceptionSpecificationAST: public AST +{ +public: + unsigned throw_token; + unsigned lparen_token; + unsigned dot_dot_dot_token; + ExpressionListAST *type_ids; + unsigned rparen_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual ExceptionSpecificationAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT ExpressionOrDeclarationStatementAST: public StatementAST +{ +public: + StatementAST *expression; + StatementAST *declaration; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual ExpressionOrDeclarationStatementAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT ExpressionStatementAST: public StatementAST +{ +public: + ExpressionAST *expression; + unsigned semicolon_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual ExpressionStatementAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT FunctionDefinitionAST: public DeclarationAST +{ +public: + SpecifierAST *decl_specifier_seq; + DeclaratorAST *declarator; + CtorInitializerAST *ctor_initializer; + StatementAST *function_body; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual FunctionDefinitionAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT ForStatementAST: public StatementAST +{ +public: + unsigned for_token; + unsigned lparen_token; + StatementAST *initializer; + ExpressionAST *condition; + unsigned semicolon_token; + ExpressionAST *expression; + unsigned rparen_token; + StatementAST *statement; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual ForStatementAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT IfStatementAST: public StatementAST +{ +public: + unsigned if_token; + unsigned lparen_token; + ExpressionAST *condition; + unsigned rparen_token; + StatementAST *statement; + unsigned else_token; + StatementAST *else_statement; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual IfStatementAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT ArrayInitializerAST: public ExpressionAST +{ +public: + unsigned lbrace_token; + ExpressionListAST *expression_list; + unsigned rbrace_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual ArrayInitializerAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT LabeledStatementAST: public StatementAST +{ +public: + unsigned label_token; + unsigned colon_token; + StatementAST *statement; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual LabeledStatementAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT LinkageBodyAST: public DeclarationAST +{ +public: + unsigned lbrace_token; + DeclarationAST *declarations; + unsigned rbrace_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual LinkageBodyAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT LinkageSpecificationAST: public DeclarationAST +{ +public: + unsigned extern_token; + unsigned extern_type; + DeclarationAST *declaration; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual LinkageSpecificationAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT MemInitializerAST: public AST +{ +public: + NameAST *name; + unsigned lparen_token; + ExpressionAST *expression; + unsigned rparen_token; + MemInitializerAST *next; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual MemInitializerAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT NameAST: public ExpressionAST +{ +public: + virtual NameAST *clone(MemoryPool *pool) const = 0; +}; + +class CPLUSPLUS_EXPORT NestedNameSpecifierAST: public AST +{ +public: + NameAST *class_or_namespace_name; + unsigned scope_token; + NestedNameSpecifierAST *next; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual NestedNameSpecifierAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT QualifiedNameAST: public NameAST +{ +public: + unsigned global_scope_token; + NestedNameSpecifierAST *nested_name_specifier; + NameAST *unqualified_name; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual QualifiedNameAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT OperatorFunctionIdAST: public NameAST +{ +public: + unsigned operator_token; + OperatorAST *op; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual OperatorFunctionIdAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT ConversionFunctionIdAST: public NameAST +{ +public: + unsigned operator_token; + SpecifierAST *type_specifier; + PtrOperatorAST *ptr_operators; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual ConversionFunctionIdAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT SimpleNameAST: public NameAST +{ +public: + unsigned identifier_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual SimpleNameAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT DestructorNameAST: public NameAST +{ +public: + unsigned tilde_token; + unsigned identifier_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual DestructorNameAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT TemplateIdAST: public NameAST +{ +public: + unsigned identifier_token; + unsigned less_token; + TemplateArgumentListAST *template_arguments; + unsigned greater_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual TemplateIdAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT NamespaceAST: public DeclarationAST +{ +public: + unsigned namespace_token; + unsigned identifier_token; + SpecifierAST *attributes; + DeclarationAST *linkage_body; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual NamespaceAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT NamespaceAliasDefinitionAST: public DeclarationAST +{ +public: + unsigned namespace_token; + unsigned namespace_name; + unsigned equal_token; + NameAST *name; + unsigned semicolon_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual NamespaceAliasDefinitionAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT NewDeclaratorAST: public AST +{ +public: + PtrOperatorAST *ptr_operators; + NewDeclaratorAST *declarator; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual NewDeclaratorAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT NewExpressionAST: public ExpressionAST +{ +public: + unsigned scope_token; + unsigned new_token; + ExpressionAST *expression; + ExpressionAST *type_id; + NewTypeIdAST *new_type_id; + NewInitializerAST *new_initializer; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual NewExpressionAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT NewInitializerAST: public AST +{ +public: + unsigned lparen_token; + ExpressionAST *expression; + unsigned rparen_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual NewInitializerAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT NewTypeIdAST: public AST +{ +public: + SpecifierAST *type_specifier; + NewInitializerAST *new_initializer; + NewDeclaratorAST *new_declarator; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual NewTypeIdAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT OperatorAST: public AST +{ +public: + unsigned op_token; + unsigned open_token; + unsigned close_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual OperatorAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT ParameterDeclarationAST: public DeclarationAST +{ +public: + SpecifierAST *type_specifier; + DeclaratorAST *declarator; + unsigned equal_token; + ExpressionAST *expression; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual ParameterDeclarationAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT ParameterDeclarationClauseAST: public AST +{ +public: + DeclarationAST *parameter_declarations; + unsigned dot_dot_dot_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual ParameterDeclarationClauseAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT PostfixAST: public AST +{ +public: + PostfixAST *next; + +public: + virtual PostfixAST *clone(MemoryPool *pool) const = 0; +}; + +class CPLUSPLUS_EXPORT CallAST: public PostfixAST +{ +public: + unsigned lparen_token; + ExpressionListAST *expression_list; + unsigned rparen_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual CallAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT ArrayAccessAST: public PostfixAST +{ +public: + unsigned lbracket_token; + ExpressionAST *expression; + unsigned rbracket_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual ArrayAccessAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT PostIncrDecrAST: public PostfixAST +{ +public: + unsigned incr_decr_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual PostIncrDecrAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT MemberAccessAST: public PostfixAST +{ +public: + unsigned access_token; + unsigned template_token; + NameAST *member_name; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual MemberAccessAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT TypeidExpressionAST: public ExpressionAST +{ +public: + unsigned typeid_token; + unsigned lparen_token; + ExpressionAST *expression; + unsigned rparen_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual TypeidExpressionAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT TypenameCallExpressionAST: public ExpressionAST +{ +public: + unsigned typename_token; + NameAST *name; + unsigned lparen_token; + ExpressionListAST *expression_list; + unsigned rparen_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual TypenameCallExpressionAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT TypeConstructorCallAST: public ExpressionAST +{ +public: + SpecifierAST *type_specifier; + unsigned lparen_token; + ExpressionListAST *expression_list; + unsigned rparen_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual TypeConstructorCallAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT PostfixExpressionAST: public ExpressionAST +{ +public: + ExpressionAST *base_expression; + PostfixAST *postfix_expressions; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual PostfixExpressionAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT PtrOperatorAST: public AST +{ +public: + PtrOperatorAST *next; + +public: + virtual PtrOperatorAST *clone(MemoryPool *pool) const = 0; +}; + +class CPLUSPLUS_EXPORT PointerToMemberAST: public PtrOperatorAST +{ +public: + unsigned global_scope_token; + NestedNameSpecifierAST *nested_name_specifier; + unsigned star_token; + SpecifierAST *cv_qualifier_seq; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual PointerToMemberAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT PointerAST: public PtrOperatorAST +{ +public: + unsigned star_token; + SpecifierAST *cv_qualifier_seq; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual PointerAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT ReferenceAST: public PtrOperatorAST +{ +public: + unsigned amp_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual ReferenceAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT BreakStatementAST: public StatementAST +{ +public: + unsigned break_token; + unsigned semicolon_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual BreakStatementAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT ContinueStatementAST: public StatementAST +{ +public: + unsigned continue_token; + unsigned semicolon_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual ContinueStatementAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT GotoStatementAST: public StatementAST +{ +public: + unsigned goto_token; + unsigned identifier_token; + unsigned semicolon_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual GotoStatementAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT ReturnStatementAST: public StatementAST +{ +public: + unsigned return_token; + ExpressionAST *expression; + unsigned semicolon_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual ReturnStatementAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT SizeofExpressionAST: public ExpressionAST +{ +public: + unsigned sizeof_token; + ExpressionAST *expression; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual SizeofExpressionAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT NumericLiteralAST: public ExpressionAST +{ +public: + unsigned token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual NumericLiteralAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT BoolLiteralAST: public ExpressionAST +{ +public: + unsigned token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual BoolLiteralAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT ThisExpressionAST: public ExpressionAST +{ +public: + unsigned this_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual ThisExpressionAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT NestedExpressionAST: public ExpressionAST +{ +public: + unsigned lparen_token; + ExpressionAST *expression; + unsigned rparen_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual NestedExpressionAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT StringLiteralAST: public ExpressionAST +{ +public: + unsigned token; + StringLiteralAST *next; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual StringLiteralAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT SwitchStatementAST: public StatementAST +{ +public: + unsigned switch_token; + unsigned lparen_token; + ExpressionAST *condition; + unsigned rparen_token; + StatementAST *statement; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual SwitchStatementAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT TemplateArgumentListAST: public AST +{ +public: + ExpressionAST *template_argument; + TemplateArgumentListAST *next; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual TemplateArgumentListAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT TemplateDeclarationAST: public DeclarationAST +{ +public: + unsigned export_token; + unsigned template_token; + unsigned less_token; + DeclarationAST *template_parameters; + unsigned greater_token; + DeclarationAST *declaration; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual TemplateDeclarationAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT ThrowExpressionAST: public ExpressionAST +{ +public: + unsigned throw_token; + ExpressionAST *expression; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual ThrowExpressionAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT TranslationUnitAST: public AST +{ +public: + DeclarationAST *declarations; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual TranslationUnitAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT TryBlockStatementAST: public StatementAST +{ +public: + unsigned try_token; + StatementAST *statement; + CatchClauseAST *catch_clause_seq; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual TryBlockStatementAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT CatchClauseAST: public StatementAST +{ +public: + unsigned catch_token; + unsigned lparen_token; + ExceptionDeclarationAST *exception_declaration; + unsigned rparen_token; + StatementAST *statement; + CatchClauseAST *next; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual CatchClauseAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT TypeIdAST: public ExpressionAST +{ +public: + SpecifierAST *type_specifier; + DeclaratorAST *declarator; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual TypeIdAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT TypenameTypeParameterAST: public DeclarationAST +{ +public: + unsigned classkey_token; + NameAST *name; + unsigned equal_token; + ExpressionAST *type_id; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual TypenameTypeParameterAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT TemplateTypeParameterAST: public DeclarationAST +{ +public: + unsigned template_token; + unsigned less_token; + DeclarationAST *template_parameters; + unsigned greater_token; + unsigned class_token; + NameAST *name; + unsigned equal_token; + ExpressionAST *type_id; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual TemplateTypeParameterAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT UnaryExpressionAST: public ExpressionAST +{ +public: + unsigned unary_op_token; + ExpressionAST *expression; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual UnaryExpressionAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT UsingAST: public DeclarationAST +{ +public: + unsigned using_token; + unsigned typename_token; + NameAST *name; + unsigned semicolon_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual UsingAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT UsingDirectiveAST: public DeclarationAST +{ +public: + unsigned using_token; + unsigned namespace_token; + NameAST *name; + unsigned semicolon_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual UsingDirectiveAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT WhileStatementAST: public StatementAST +{ +public: + unsigned while_token; + unsigned lparen_token; + ExpressionAST *condition; + unsigned rparen_token; + StatementAST *statement; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual WhileStatementAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + + +// ObjC++ +class CPLUSPLUS_EXPORT IdentifierListAST: public AST +{ +public: + unsigned identifier_token; + IdentifierListAST *next; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual IdentifierListAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT ObjCClassDeclarationAST: public DeclarationAST +{ +public: + SpecifierAST *attributes; + unsigned class_token; + IdentifierListAST *identifier_list; + unsigned semicolon_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual ObjCClassDeclarationAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_AST_H diff --git a/src/shared/cplusplus/ASTVisitor.cpp b/src/shared/cplusplus/ASTVisitor.cpp new file mode 100644 index 0000000000..7b9ca1ed7f --- /dev/null +++ b/src/shared/cplusplus/ASTVisitor.cpp @@ -0,0 +1,105 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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 "ASTVisitor.h" +#include "AST.h" +#include "TranslationUnit.h" +#include "Control.h" + +CPLUSPLUS_BEGIN_NAMESPACE + +ASTVisitor::ASTVisitor(Control *control) + : _control(control) +{ } + +ASTVisitor::~ASTVisitor() +{ } + +void ASTVisitor::accept(AST *ast) +{ AST::accept(ast, this); } + +Control *ASTVisitor::control() const +{ return _control; } + +TranslationUnit *ASTVisitor::translationUnit() const +{ return _control->translationUnit(); } + +int ASTVisitor::tokenKind(unsigned index) const +{ return translationUnit()->tokenKind(index); } + +const char *ASTVisitor::spell(unsigned index) const +{ + if (! index) + return 0; + + return translationUnit()->tokenAt(index).spell(); +} + +Identifier *ASTVisitor::identifier(unsigned index) const +{ return translationUnit()->identifier(index); } + +Literal *ASTVisitor::literal(unsigned index) const +{ return translationUnit()->literal(index); } + +NumericLiteral *ASTVisitor::numericLiteral(unsigned index) const +{ return translationUnit()->numericLiteral(index); } + +StringLiteral *ASTVisitor::stringLiteral(unsigned index) const +{ return translationUnit()->stringLiteral(index); } + +void ASTVisitor::getTokenPosition(unsigned index, + unsigned *line, + unsigned *column, + StringLiteral **fileName) const +{ translationUnit()->getTokenPosition(index, line, column, fileName); } + +CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/ASTVisitor.h b/src/shared/cplusplus/ASTVisitor.h new file mode 100644 index 0000000000..f8d2d6790e --- /dev/null +++ b/src/shared/cplusplus/ASTVisitor.h @@ -0,0 +1,200 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. + +#ifndef CPLUSPLUS_ASTVISITOR_H +#define CPLUSPLUS_ASTVISITOR_H + +#include "CPlusPlusForwardDeclarations.h" +#include "ASTfwd.h" + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +class CPLUSPLUS_EXPORT ASTVisitor +{ + ASTVisitor(const ASTVisitor &other); + void operator =(const ASTVisitor &other); + +public: + ASTVisitor(Control *control); + virtual ~ASTVisitor(); + + Control *control() const; + TranslationUnit *translationUnit() const; + + int tokenKind(unsigned index) const; + const char *spell(unsigned index) const; + Identifier *identifier(unsigned index) const; + Literal *literal(unsigned index) const; + NumericLiteral *numericLiteral(unsigned index) const; + StringLiteral *stringLiteral(unsigned index) const; + + void getTokenPosition(unsigned index, + unsigned *line, + unsigned *column = 0, + StringLiteral **fileName = 0) const; + + void accept(AST *ast); + + virtual bool preVisit(AST *) { return true; } + virtual void postVisit(AST *) {} + + virtual bool visit(AccessDeclarationAST *) { return true; } + virtual bool visit(ArrayAccessAST *) { return true; } + virtual bool visit(ArrayDeclaratorAST *) { return true; } + virtual bool visit(ArrayInitializerAST *) { return true; } + virtual bool visit(AsmDefinitionAST *) { return true; } + virtual bool visit(AttributeSpecifierAST *) { return true; } + virtual bool visit(AttributeAST *) { return true; } + virtual bool visit(BaseSpecifierAST *) { return true; } + virtual bool visit(BinaryExpressionAST *) { return true; } + virtual bool visit(BoolLiteralAST *) { return true; } + virtual bool visit(BreakStatementAST *) { return true; } + virtual bool visit(CallAST *) { return true; } + virtual bool visit(CaseStatementAST *) { return true; } + virtual bool visit(CastExpressionAST *) { return true; } + virtual bool visit(CatchClauseAST *) { return true; } + virtual bool visit(ClassSpecifierAST *) { return true; } + virtual bool visit(CompoundLiteralAST *) { return true; } + virtual bool visit(CompoundStatementAST *) { return true; } + virtual bool visit(ConditionAST *) { return true; } + virtual bool visit(ConditionalExpressionAST *) { return true; } + virtual bool visit(ContinueStatementAST *) { return true; } + virtual bool visit(ConversionFunctionIdAST *) { return true; } + virtual bool visit(CppCastExpressionAST *) { return true; } + virtual bool visit(CtorInitializerAST *) { return true; } + virtual bool visit(DeclaratorAST *) { return true; } + virtual bool visit(DeclarationStatementAST *) { return true; } + virtual bool visit(DeclaratorIdAST *) { return true; } + virtual bool visit(DeclaratorListAST *) { return true; } + virtual bool visit(DeleteExpressionAST *) { return true; } + virtual bool visit(DestructorNameAST *) { return true; } + virtual bool visit(DoStatementAST *) { return true; } + virtual bool visit(ElaboratedTypeSpecifierAST *) { return true; } + virtual bool visit(EmptyDeclarationAST *) { return true; } + virtual bool visit(EnumSpecifierAST *) { return true; } + virtual bool visit(EnumeratorAST *) { return true; } + virtual bool visit(ExceptionDeclarationAST *) { return true; } + virtual bool visit(ExceptionSpecificationAST *) { return true; } + virtual bool visit(ExpressionListAST *) { return true; } + virtual bool visit(ExpressionOrDeclarationStatementAST *) { return true; } + virtual bool visit(ExpressionStatementAST *) { return true; } + virtual bool visit(ForStatementAST *) { return true; } + virtual bool visit(FunctionDeclaratorAST *) { return true; } + virtual bool visit(FunctionDefinitionAST *) { return true; } + virtual bool visit(GotoStatementAST *) { return true; } + virtual bool visit(IfStatementAST *) { return true; } + virtual bool visit(LabeledStatementAST *) { return true; } + virtual bool visit(LinkageBodyAST *) { return true; } + virtual bool visit(LinkageSpecificationAST *) { return true; } + virtual bool visit(MemInitializerAST *) { return true; } + virtual bool visit(MemberAccessAST *) { return true; } + virtual bool visit(NamedTypeSpecifierAST *) { return true; } + virtual bool visit(NamespaceAST *) { return true; } + virtual bool visit(NamespaceAliasDefinitionAST *) { return true; } + virtual bool visit(NestedDeclaratorAST *) { return true; } + virtual bool visit(NestedExpressionAST *) { return true; } + virtual bool visit(NestedNameSpecifierAST *) { return true; } + virtual bool visit(NewDeclaratorAST *) { return true; } + virtual bool visit(NewExpressionAST *) { return true; } + virtual bool visit(NewInitializerAST *) { return true; } + virtual bool visit(NewTypeIdAST *) { return true; } + virtual bool visit(NumericLiteralAST *) { return true; } + virtual bool visit(OperatorAST *) { return true; } + virtual bool visit(OperatorFunctionIdAST *) { return true; } + virtual bool visit(ParameterDeclarationAST *) { return true; } + virtual bool visit(ParameterDeclarationClauseAST *) { return true; } + virtual bool visit(PointerAST *) { return true; } + virtual bool visit(PointerToMemberAST *) { return true; } + virtual bool visit(PostIncrDecrAST *) { return true; } + virtual bool visit(PostfixExpressionAST *) { return true; } + virtual bool visit(QualifiedNameAST *) { return true; } + virtual bool visit(ReferenceAST *) { return true; } + virtual bool visit(ReturnStatementAST *) { return true; } + virtual bool visit(SimpleDeclarationAST *) { return true; } + virtual bool visit(SimpleNameAST *) { return true; } + virtual bool visit(SimpleSpecifierAST *) { return true; } + virtual bool visit(SizeofExpressionAST *) { return true; } + virtual bool visit(StringLiteralAST *) { return true; } + virtual bool visit(SwitchStatementAST *) { return true; } + virtual bool visit(TemplateArgumentListAST *) { return true; } + virtual bool visit(TemplateDeclarationAST *) { return true; } + virtual bool visit(TemplateIdAST *) { return true; } + virtual bool visit(TemplateTypeParameterAST *) { return true; } + virtual bool visit(ThisExpressionAST *) { return true; } + virtual bool visit(ThrowExpressionAST *) { return true; } + virtual bool visit(TranslationUnitAST *) { return true; } + virtual bool visit(TryBlockStatementAST *) { return true; } + virtual bool visit(TypeConstructorCallAST *) { return true; } + virtual bool visit(TypeIdAST *) { return true; } + virtual bool visit(TypeidExpressionAST *) { return true; } + virtual bool visit(TypeofSpecifierAST *) { return true; } + virtual bool visit(TypenameCallExpressionAST *) { return true; } + virtual bool visit(TypenameTypeParameterAST *) { return true; } + virtual bool visit(UnaryExpressionAST *) { return true; } + virtual bool visit(UsingAST *) { return true; } + virtual bool visit(UsingDirectiveAST *) { return true; } + virtual bool visit(WhileStatementAST *) { return true; } + virtual bool visit(QtMethodAST *) { return true; } + + // ObjC++ + virtual bool visit(IdentifierListAST *) { return true; } + virtual bool visit(ObjCClassDeclarationAST *) { return true; } + +private: + Control *_control; +}; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_ASTVISITOR_H diff --git a/src/shared/cplusplus/ASTfwd.h b/src/shared/cplusplus/ASTfwd.h new file mode 100644 index 0000000000..b4f5283a74 --- /dev/null +++ b/src/shared/cplusplus/ASTfwd.h @@ -0,0 +1,178 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. + +#ifndef CPLUSPLUS_ASTFWD_H +#define CPLUSPLUS_ASTFWD_H + +#include <CPlusPlusForwardDeclarations.h> + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +class AST; +class ASTVisitor; + +class AccessDeclarationAST; +class ArrayAccessAST; +class ArrayDeclaratorAST; +class ArrayInitializerAST; +class AsmDefinitionAST; +class AttributeAST; +class AttributeSpecifierAST; +class BaseSpecifierAST; +class BinaryExpressionAST; +class BoolLiteralAST; +class BreakStatementAST; +class CallAST; +class CaseStatementAST; +class CastExpressionAST; +class CatchClauseAST; +class ClassSpecifierAST; +class CompoundLiteralAST; +class CompoundStatementAST; +class ConditionAST; +class ConditionalExpressionAST; +class ContinueStatementAST; +class ConversionFunctionIdAST; +class CoreDeclaratorAST; +class CppCastExpressionAST; +class CtorInitializerAST; +class DeclarationAST; +class DeclarationStatementAST; +class DeclaratorAST; +class DeclaratorIdAST; +class DeclaratorListAST; +class DeleteExpressionAST; +class DestructorNameAST; +class DoStatementAST; +class ElaboratedTypeSpecifierAST; +class EmptyDeclarationAST; +class EnumSpecifierAST; +class EnumeratorAST; +class ExceptionDeclarationAST; +class ExceptionSpecificationAST; +class ExpressionAST; +class ExpressionListAST; +class ExpressionOrDeclarationStatementAST; +class ExpressionStatementAST; +class ForStatementAST; +class FunctionDeclaratorAST; +class FunctionDefinitionAST; +class GotoStatementAST; +class IfStatementAST; +class LabeledStatementAST; +class LinkageBodyAST; +class LinkageSpecificationAST; +class MemInitializerAST; +class MemberAccessAST; +class NameAST; +class NamedTypeSpecifierAST; +class NamespaceAST; +class NamespaceAliasDefinitionAST; +class NestedDeclaratorAST; +class NestedExpressionAST; +class NestedNameSpecifierAST; +class NewDeclaratorAST; +class NewExpressionAST; +class NewInitializerAST; +class NewTypeIdAST; +class NumericLiteralAST; +class OperatorAST; +class OperatorFunctionIdAST; +class ParameterDeclarationAST; +class ParameterDeclarationClauseAST; +class PointerAST; +class PointerToMemberAST; +class PostIncrDecrAST; +class PostfixAST; +class PostfixDeclaratorAST; +class PostfixExpressionAST; +class PtrOperatorAST; +class QualifiedNameAST; +class ReferenceAST; +class ReturnStatementAST; +class SimpleDeclarationAST; +class SimpleNameAST; +class SimpleSpecifierAST; +class SizeofExpressionAST; +class SpecifierAST; +class StatementAST; +class StringLiteralAST; +class SwitchStatementAST; +class TemplateArgumentListAST; +class TemplateDeclarationAST; +class TemplateIdAST; +class TemplateTypeParameterAST; +class ThisExpressionAST; +class ThrowExpressionAST; +class TranslationUnitAST; +class TryBlockStatementAST; +class TypeConstructorCallAST; +class TypeIdAST; +class TypeidExpressionAST; +class TypenameCallExpressionAST; +class TypenameTypeParameterAST; +class TypeofSpecifierAST; +class UnaryExpressionAST; +class UsingAST; +class UsingDirectiveAST; +class WhileStatementAST; +class QtMethodAST; + +// ObjC++ +class IdentifierListAST; +class ObjCClassDeclarationAST; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_ASTFWD_H diff --git a/src/shared/cplusplus/Array.cpp b/src/shared/cplusplus/Array.cpp new file mode 100644 index 0000000000..7159008fd4 --- /dev/null +++ b/src/shared/cplusplus/Array.cpp @@ -0,0 +1,34 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. +** +***************************************************************************/ + +#include "Array.h" diff --git a/src/shared/cplusplus/Array.h b/src/shared/cplusplus/Array.h new file mode 100644 index 0000000000..c639affc89 --- /dev/null +++ b/src/shared/cplusplus/Array.h @@ -0,0 +1,135 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. + +#ifndef CPLUSPLUS_ARRAY_H +#define CPLUSPLUS_ARRAY_H + +#include "CPlusPlusForwardDeclarations.h" +#include <new> +#include <cstdlib> + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +template <typename _Tp, int SEGMENT_SHIFT = 4> +class Array +{ + Array(const Array &other); + void operator =(const Array &other); + +public: + Array() + : _segments(0), + _allocatedSegments(0), + _segmentCount(-1), + _allocatedElements(0), + _count(-1) + { } + + ~Array() + { + if (_segments) { + for (int index = 0; index <= _segmentCount; ++index) { + delete[] (_segments[index] + (index << SEGMENT_SHIFT)); + } + free(_segments); + } + } + + inline unsigned size() const + { return _count + 1; } + + inline unsigned count() const + { return _count + 1; } + + inline const _Tp &at(unsigned index) const + { return _segments[index >> SEGMENT_SHIFT][index]; } + + inline const _Tp &operator[](unsigned index) const + { return _segments[index >> SEGMENT_SHIFT][index]; } + + inline _Tp &operator[](unsigned index) + { return _segments[index >> SEGMENT_SHIFT][index]; } + + void push_back(const _Tp &value) + { + if (++_count == _allocatedElements) { + if (++_segmentCount == _allocatedSegments) { + _allocatedSegments += 4; + _segments = (_Tp **) realloc(_segments, _allocatedSegments * sizeof(_Tp *)); + } + + _Tp *segment = new _Tp[SEGMENT_SIZE]; + _segments[_segmentCount] = segment - (_segmentCount << SEGMENT_SHIFT); + _allocatedElements += SEGMENT_SIZE; + } + + _segments[_count >> SEGMENT_SHIFT][_count] = value; + } + +private: + enum { + SEGMENT_SIZE = 1 << SEGMENT_SHIFT + }; + + _Tp **_segments; + int _allocatedSegments; + int _segmentCount; + + int _allocatedElements; + int _count; +}; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_ARRAY_H diff --git a/src/shared/cplusplus/CPlusPlusForwardDeclarations.h b/src/shared/cplusplus/CPlusPlusForwardDeclarations.h new file mode 100644 index 0000000000..31b01bfd81 --- /dev/null +++ b/src/shared/cplusplus/CPlusPlusForwardDeclarations.h @@ -0,0 +1,140 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. + +#ifndef CPLUSPLUS_CPLUSPLUSFORWARDDECLARATIONS_H +#define CPLUSPLUS_CPLUSPLUSFORWARDDECLARATIONS_H + +#ifdef HAVE_QT +# include <QtCore/qglobal.h> +# define CPLUSPLUS_BEGIN_HEADER +# define CPLUSPLUS_END_HEADER +# if defined(CPLUSPLUS_BUILD_LIB) +# define CPLUSPLUS_EXPORT Q_DECL_EXPORT +# else +# define CPLUSPLUS_EXPORT Q_DECL_IMPORT +# endif +#else +# define CPLUSPLUS_BEGIN_HEADER +# define CPLUSPLUS_END_HEADER +# define CPLUSPLUS_EXPORT +#endif + +#ifdef CPLUSPLUS_WITH_NAMESPACE +# define CPLUSPLUS_BEGIN_NAMESPACE namespace CPlusPlus { +# define CPLUSPLUS_END_NAMESPACE } // end of namespace CPlusPLus +# define CPLUSPLUS_USE_NAMESPACE using namespace CPlusPlus; +#else +# define CPLUSPLUS_BEGIN_NAMESPACE +# define CPLUSPLUS_END_NAMESPACE +# define CPLUSPLUS_USE_NAMESPACE ; +#endif + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +class TranslationUnit; +class Semantic; +class Control; +class MemoryPool; +class DiagnosticClient; + +class Identifier; +class Literal; +class StringLiteral; +class NumericLiteral; + +class Scope; + +// names +class NameVisitor; +class Name; +class NameId; +class TemplateNameId; +class DestructorNameId; +class OperatorNameId; +class ConversionNameId; +class QualifiedNameId; + +// types +class FullySpecifiedType; +class TypeVisitor; +class Type; +class VoidType; +class IntegerType; +class FloatType; +class PointerToMemberType; +class PointerType; +class ReferenceType; +class ArrayType; +class NamedType; + +// symbols +class SymbolVisitor; +class Symbol; +class ScopedSymbol; +class UsingNamespaceDirective; +class UsingDeclaration; +class Declaration; +class Argument; +class Function; +class Namespace; +class BaseClass; +class Block; +class Class; +class Enum; + +class Use; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_CPLUSPLUSFORWARDDECLARATIONS_H diff --git a/src/shared/cplusplus/CheckDeclaration.cpp b/src/shared/cplusplus/CheckDeclaration.cpp new file mode 100644 index 0000000000..610d57626f --- /dev/null +++ b/src/shared/cplusplus/CheckDeclaration.cpp @@ -0,0 +1,374 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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 "CheckDeclaration.h" +#include "Semantic.h" +#include "AST.h" +#include "TranslationUnit.h" +#include "Scope.h" +#include "Names.h" +#include "CoreTypes.h" +#include "Symbols.h" +#include "Control.h" +#include <cassert> + +CPLUSPLUS_BEGIN_NAMESPACE + +CheckDeclaration::CheckDeclaration(Semantic *semantic) + : SemanticCheck(semantic), + _declaration(0), + _scope(0), + _templateParameters(0), + _checkAnonymousArguments(false) +{ } + +CheckDeclaration::~CheckDeclaration() +{ } + +void CheckDeclaration::check(DeclarationAST *declaration, + Scope *scope, Scope *templateParameters) +{ + Scope *previousScope = switchScope(scope); + Scope *previousTemplateParameters = switchTemplateParameters(templateParameters); + DeclarationAST *previousDeclaration = switchDeclaration(declaration); + accept(declaration); + (void) switchDeclaration(previousDeclaration); + (void) switchTemplateParameters(previousTemplateParameters); + (void) switchScope(previousScope); +} + +DeclarationAST *CheckDeclaration::switchDeclaration(DeclarationAST *declaration) +{ + DeclarationAST *previousDeclaration = _declaration; + _declaration = declaration; + return previousDeclaration; +} + +Scope *CheckDeclaration::switchScope(Scope *scope) +{ + Scope *previousScope = _scope; + _scope = scope; + return previousScope; +} + +Scope *CheckDeclaration::switchTemplateParameters(Scope *templateParameters) +{ + Scope *previousTemplateParameters = _templateParameters; + _templateParameters = templateParameters; + return previousTemplateParameters; +} + +void CheckDeclaration::checkFunctionArguments(Function *fun) +{ + if (! _checkAnonymousArguments) + return; + + if (_scope->isClassScope() && fun->isPublic()) { + for (unsigned argc = 0; argc < fun->argumentCount(); ++argc) { + Argument *arg = fun->argumentAt(argc)->asArgument(); + assert(arg != 0); + + if (! arg->name()) { + translationUnit()->warning(arg->sourceLocation(), + "anonymous argument"); + } + } + } +} + +bool CheckDeclaration::visit(SimpleDeclarationAST *ast) +{ + FullySpecifiedType ty = semantic()->check(ast->decl_specifier_seq, _scope); + FullySpecifiedType qualTy = ty.qualifiedType(); + + if (_templateParameters) { + if (Class *klass = ty->asClass()) { + klass->setTemplateParameters(_templateParameters); + } + } + + for (DeclaratorListAST *it = ast->declarators; it; it = it->next) { + Name *name = 0; + FullySpecifiedType declTy = semantic()->check(it->declarator, qualTy, + _scope, &name); + + if (Function *fun = declTy->asFunction()) { + fun->setScope(_scope); + fun->setName(name); + fun->setMethodKey(semantic()->currentMethodKey()); + fun->setVisibility(semantic()->currentVisibility()); + } else if (semantic()->currentMethodKey() != Function::NormalMethod) { + translationUnit()->warning(ast->firstToken(), + "expected a function declaration"); + } + + unsigned location = 0; + if (it->declarator) + location = it->declarator->firstToken(); + else + location = ast->firstToken(); + + Declaration *symbol = control()->newDeclaration(location, name); + symbol->setType(control()->integerType(IntegerType::Int)); + symbol->setType(declTy); + + if (_templateParameters && it == ast->declarators && ! ty->asClass()) + symbol->setTemplateParameters(_templateParameters); + + symbol->setVisibility(semantic()->currentVisibility()); + + if (ty.isFriend()) + symbol->setStorage(Symbol::Friend); + else if (ty.isRegister()) + symbol->setStorage(Symbol::Register); + else if (ty.isStatic()) + symbol->setStorage(Symbol::Static); + else if (ty.isExtern()) + symbol->setStorage(Symbol::Extern); + else if (ty.isMutable()) + symbol->setStorage(Symbol::Mutable); + else if (ty.isTypedef()) + symbol->setStorage(Symbol::Typedef); + + _scope->enterSymbol(symbol); + } + return false; +} + +bool CheckDeclaration::visit(EmptyDeclarationAST *) +{ + return false; +} + +bool CheckDeclaration::visit(AccessDeclarationAST *ast) +{ + int accessSpecifier = tokenKind(ast->access_specifier_token); + int visibility = semantic()->visibilityForAccessSpecifier(accessSpecifier); + semantic()->switchVisibility(visibility); + if (ast->slots_token) + semantic()->switchMethodKey(Function::SlotMethod); + else if (accessSpecifier == T_SIGNALS) + semantic()->switchMethodKey(Function::SignalMethod); + else + semantic()->switchMethodKey(Function::NormalMethod); + return false; +} + +bool CheckDeclaration::visit(AsmDefinitionAST *) +{ + return false; +} + +bool CheckDeclaration::visit(ExceptionDeclarationAST *) +{ + return false; +} + +bool CheckDeclaration::visit(FunctionDefinitionAST *ast) +{ + FullySpecifiedType ty = semantic()->check(ast->decl_specifier_seq, _scope); + FullySpecifiedType qualTy = ty.qualifiedType(); + Name *name = 0; + FullySpecifiedType funTy = semantic()->check(ast->declarator, qualTy, + _scope, &name); + Function *fun = funTy->asFunction(); + if (! fun) { + translationUnit()->error(ast->firstToken(), + "expected a function prototype"); + return false; + } + + fun->setName(name); + fun->setTemplateParameters(_templateParameters); + fun->setVisibility(semantic()->currentVisibility()); + fun->setMethodKey(semantic()->currentMethodKey()); + + checkFunctionArguments(fun); + + _scope->enterSymbol(fun); + + if (ast->ctor_initializer) { + bool looksLikeCtor = false; + if (ty.isValid() || ! fun->identity()) + looksLikeCtor = false; + else if (fun->identity()->isNameId() || fun->identity()->isTemplateNameId()) + looksLikeCtor = true; + + if (! looksLikeCtor) { + translationUnit()->error(ast->ctor_initializer->firstToken(), + "only constructors take base initializers"); + } + } + + const int previousVisibility = semantic()->switchVisibility(Symbol::Public); + const int previousMethodKey = semantic()->switchMethodKey(Function::NormalMethod); + + semantic()->check(ast->function_body, fun->members()); + + semantic()->switchMethodKey(previousMethodKey); + semantic()->switchVisibility(previousVisibility); + + if (ast->next && ast->next->asEmptyDeclaration()) { + translationUnit()->warning(ast->next->firstToken(), + "unnecessary semicolon after function block"); + } + + return false; +} + +bool CheckDeclaration::visit(LinkageBodyAST *ast) +{ + for (DeclarationAST *decl = ast->declarations; decl; decl = decl->next) { + semantic()->check(decl, _scope); + } + return false; +} + +bool CheckDeclaration::visit(LinkageSpecificationAST *ast) +{ + for (DeclarationAST *decl = ast->declaration; decl; decl = decl->next) { + semantic()->check(decl, _scope); + } + return false; +} + +bool CheckDeclaration::visit(NamespaceAST *ast) +{ + Identifier *id = identifier(ast->identifier_token); + Name *namespaceName = control()->nameId(id); + Namespace *ns = control()->newNamespace(ast->firstToken(), namespaceName); + _scope->enterSymbol(ns); + semantic()->check(ast->linkage_body, ns->members()); // ### we'll do the merge later. + + if (ast->next && ast->next->asEmptyDeclaration()) { + translationUnit()->warning(ast->next->firstToken(), + "unnecessary semicolon after namespace"); + } + + return false; +} + +bool CheckDeclaration::visit(NamespaceAliasDefinitionAST *) +{ + return false; +} + +bool CheckDeclaration::visit(ParameterDeclarationAST *ast) +{ + Name *argName = 0; + FullySpecifiedType ty = semantic()->check(ast->type_specifier, _scope); + FullySpecifiedType argTy = semantic()->check(ast->declarator, ty.qualifiedType(), + _scope, &argName); + FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope); + Argument *arg = control()->newArgument(ast->firstToken(), argName); + if (ast->expression) + arg->setInitializer(true); + arg->setType(argTy); + _scope->enterSymbol(arg); + return false; +} + +bool CheckDeclaration::visit(TemplateDeclarationAST *ast) +{ +/* + Template *templ = control()->newTemplate(ast->firstToken()); + + for (DeclarationAST *param = ast->template_parameters; param; + param = param->next) { + semantic()->check(param, templ->members()); + } +*/ + + Scope *previousScope = switchScope(new Scope(_scope->owner())); + for (DeclarationAST *param = ast->template_parameters; param; + param = param->next) { + semantic()->check(param, _scope); + } + + Scope *templateParameters = switchScope(previousScope); + semantic()->check(ast->declaration, _scope, templateParameters); + return false; +} + +bool CheckDeclaration::visit(TypenameTypeParameterAST *ast) +{ + Name *name = semantic()->check(ast->name, _scope); + Argument *arg = control()->newArgument(ast->firstToken(), name); // ### new template type + _scope->enterSymbol(arg); + return false; +} + +bool CheckDeclaration::visit(TemplateTypeParameterAST *ast) +{ + Name *name = semantic()->check(ast->name, _scope); + Argument *arg = control()->newArgument(ast->firstToken(), name); // ### new template type + _scope->enterSymbol(arg); + return false; +} + +bool CheckDeclaration::visit(UsingAST *ast) +{ + Name *name = semantic()->check(ast->name, _scope); + UsingDeclaration *u = control()->newUsingDeclaration(ast->firstToken(), name); + _scope->enterSymbol(u); + return false; +} + +bool CheckDeclaration::visit(UsingDirectiveAST *ast) +{ + Name *name = semantic()->check(ast->name, _scope); + UsingNamespaceDirective *u = control()->newUsingNamespaceDirective(ast->firstToken(), name); + _scope->enterSymbol(u); + return false; +} + +CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/CheckDeclaration.h b/src/shared/cplusplus/CheckDeclaration.h new file mode 100644 index 0000000000..6e82678fa0 --- /dev/null +++ b/src/shared/cplusplus/CheckDeclaration.h @@ -0,0 +1,106 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. + +#ifndef CPLUSPLUS_CHECKDECLARATION_H +#define CPLUSPLUS_CHECKDECLARATION_H + +#include "CPlusPlusForwardDeclarations.h" +#include "SemanticCheck.h" + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +class CPLUSPLUS_EXPORT CheckDeclaration: public SemanticCheck +{ +public: + CheckDeclaration(Semantic *semantic); + virtual ~CheckDeclaration(); + + void check(DeclarationAST *declaration, Scope *scope, Scope *templateParameters); + +protected: + DeclarationAST *switchDeclaration(DeclarationAST *declaration); + Scope *switchScope(Scope *scope); + Scope *switchTemplateParameters(Scope *templateParameters); + + void checkFunctionArguments(Function *fun); + + using ASTVisitor::visit; + + virtual bool visit(SimpleDeclarationAST *ast); + virtual bool visit(EmptyDeclarationAST *ast); + virtual bool visit(AccessDeclarationAST *ast); + virtual bool visit(AsmDefinitionAST *ast); + virtual bool visit(ExceptionDeclarationAST *ast); + virtual bool visit(FunctionDefinitionAST *ast); + virtual bool visit(LinkageBodyAST *ast); + virtual bool visit(LinkageSpecificationAST *ast); + virtual bool visit(NamespaceAST *ast); + virtual bool visit(NamespaceAliasDefinitionAST *ast); + virtual bool visit(ParameterDeclarationAST *ast); + virtual bool visit(TemplateDeclarationAST *ast); + virtual bool visit(TypenameTypeParameterAST *ast); + virtual bool visit(TemplateTypeParameterAST *ast); + virtual bool visit(UsingAST *ast); + virtual bool visit(UsingDirectiveAST *ast); + +private: + DeclarationAST *_declaration; + Scope *_scope; + Scope *_templateParameters; + bool _checkAnonymousArguments: 1; +}; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_CHECKDECLARATION_H diff --git a/src/shared/cplusplus/CheckDeclarator.cpp b/src/shared/cplusplus/CheckDeclarator.cpp new file mode 100644 index 0000000000..13120fec58 --- /dev/null +++ b/src/shared/cplusplus/CheckDeclarator.cpp @@ -0,0 +1,258 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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 "CheckDeclarator.h" +#include "Semantic.h" +#include "AST.h" +#include "Control.h" +#include "TranslationUnit.h" +#include "Literals.h" +#include "CoreTypes.h" +#include "Symbols.h" + +CPLUSPLUS_BEGIN_NAMESPACE + +CheckDeclarator::CheckDeclarator(Semantic *semantic) + : SemanticCheck(semantic), + _declarator(0), + _scope(0), + _name(0) +{ } + +CheckDeclarator::~CheckDeclarator() +{ } + +FullySpecifiedType CheckDeclarator::check(DeclaratorAST *declarator, + FullySpecifiedType type, + Scope *scope, + Name **name) +{ + FullySpecifiedType previousType = switchFullySpecifiedType(type); + Scope *previousScope = switchScope(scope); + DeclaratorAST *previousDeclarator = switchDeclarator(declarator); + Name **previousName = switchName(name); + accept(declarator); + (void) switchName(previousName); + (void) switchDeclarator(previousDeclarator); + (void) switchScope(previousScope); + return switchFullySpecifiedType(previousType); +} + +FullySpecifiedType CheckDeclarator::check(PtrOperatorAST *ptrOperators, + FullySpecifiedType type, + Scope *scope) +{ + FullySpecifiedType previousType = switchFullySpecifiedType(type); + Scope *previousScope = switchScope(scope); + accept(ptrOperators); + (void) switchScope(previousScope); + return switchFullySpecifiedType(previousType); +} + +DeclaratorAST *CheckDeclarator::switchDeclarator(DeclaratorAST *declarator) +{ + DeclaratorAST *previousDeclarator = _declarator; + _declarator = declarator; + return previousDeclarator; +} + +FullySpecifiedType CheckDeclarator::switchFullySpecifiedType(FullySpecifiedType type) +{ + FullySpecifiedType previousType = _fullySpecifiedType; + _fullySpecifiedType = type; + return previousType; +} + +Scope *CheckDeclarator::switchScope(Scope *scope) +{ + Scope *previousScope = _scope; + _scope = scope; + return previousScope; +} + +Name **CheckDeclarator::switchName(Name **name) +{ + Name **previousName = _name; + _name = name; + return previousName; +} + +bool CheckDeclarator::visit(DeclaratorAST *ast) +{ + accept(ast->ptr_operators); + accept(ast->postfix_declarators); + accept(ast->core_declarator); + + // ### check the initializer + // FullySpecifiedType exprTy = semantic()->check(ast->initializer, _scope); + + if (ast->initializer && _fullySpecifiedType->isFunction()) { + _fullySpecifiedType->asFunction()->setPureVirtual(true); + } + return false; +} + +bool CheckDeclarator::visit(DeclaratorIdAST *ast) +{ + Name *name = semantic()->check(ast->name, _scope); + if (_name) + *_name = name; + return false; +} + +bool CheckDeclarator::visit(NestedDeclaratorAST *ast) +{ + accept(ast->declarator); + return false; +} + +bool CheckDeclarator::visit(FunctionDeclaratorAST *ast) +{ + Function *fun = control()->newFunction(ast->firstToken()); + fun->setReturnType(_fullySpecifiedType); + + if (ast->parameters) { + DeclarationAST *parameter_declarations = ast->parameters->parameter_declarations; + for (DeclarationAST *decl = parameter_declarations; decl; decl = decl->next) { + semantic()->check(decl, fun->arguments()); + } + + if (ast->parameters->dot_dot_dot_token) + fun->setVariadic(true); + } + + // check the arguments + bool hasDefaultArguments = false; + for (unsigned i = 0; i < fun->argumentCount(); ++i) { + Argument *arg = fun->argumentAt(i)->asArgument(); + if (hasDefaultArguments && ! arg->hasInitializer()) { + translationUnit()->error(ast->firstToken(), + "default argument missing for parameter at position %d", i + 1); + } else if (! hasDefaultArguments) { + hasDefaultArguments = arg->hasInitializer(); + } + } + + FullySpecifiedType funTy(fun); + _fullySpecifiedType = funTy; + + for (SpecifierAST *it = ast->cv_qualifier_seq; it; it = it->next) { + SimpleSpecifierAST *cv = static_cast<SimpleSpecifierAST *>(it); + int k = tokenKind(cv->specifier_token); + if (k == T_CONST) + fun->setConst(true); + else if (k == T_VOLATILE) + fun->setVolatile(true); + } + + accept(ast->next); + return false; +} + +bool CheckDeclarator::visit(ArrayDeclaratorAST *ast) +{ + ArrayType *ty = control()->arrayType(_fullySpecifiedType); // ### set the dimension + FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope); + FullySpecifiedType arrTy(ty); + _fullySpecifiedType = ty; + accept(ast->next); + return false; +} + +bool CheckDeclarator::visit(PointerToMemberAST *ast) +{ + Name *memberName = semantic()->check(ast->nested_name_specifier, _scope); + PointerToMemberType *ptrTy = control()->pointerToMemberType(memberName, _fullySpecifiedType); + FullySpecifiedType ty(ptrTy); + _fullySpecifiedType = ty; + applyCvQualifiers(ast->cv_qualifier_seq); + accept(ast->next); + return false; +} + +bool CheckDeclarator::visit(PointerAST *ast) +{ + PointerType *ptrTy = control()->pointerType(_fullySpecifiedType); + FullySpecifiedType ty(ptrTy); + _fullySpecifiedType = ty; + applyCvQualifiers(ast->cv_qualifier_seq); + accept(ast->next); + return false; +} + +bool CheckDeclarator::visit(ReferenceAST *ast) +{ + ReferenceType *refTy = control()->referenceType(_fullySpecifiedType); + FullySpecifiedType ty(refTy); + _fullySpecifiedType = ty; + accept(ast->next); + return false; +} + +void CheckDeclarator::applyCvQualifiers(SpecifierAST *cv) +{ + for (; cv; cv = cv->next) { + SimpleSpecifierAST *spec = static_cast<SimpleSpecifierAST *>(cv); + switch (translationUnit()->tokenKind(spec->specifier_token)) { + case T_VOLATILE: + _fullySpecifiedType.setVolatile(true); + break; + case T_CONST: + _fullySpecifiedType.setConst(true); + break; + default: + break; + } // switch + } +} + +CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/CheckDeclarator.h b/src/shared/cplusplus/CheckDeclarator.h new file mode 100644 index 0000000000..b1de623b00 --- /dev/null +++ b/src/shared/cplusplus/CheckDeclarator.h @@ -0,0 +1,110 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. + +#ifndef CPLUSPLUS_CHECKDECLARATOR_H +#define CPLUSPLUS_CHECKDECLARATOR_H + +#include "CPlusPlusForwardDeclarations.h" +#include "SemanticCheck.h" +#include "FullySpecifiedType.h" + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +class CPLUSPLUS_EXPORT CheckDeclarator: public SemanticCheck +{ +public: + CheckDeclarator(Semantic *semantic); + virtual ~CheckDeclarator(); + + FullySpecifiedType check(DeclaratorAST *declarator, + FullySpecifiedType type, + Scope *scope, + Name **name); + + FullySpecifiedType check(PtrOperatorAST *ptrOperators, + FullySpecifiedType type, + Scope *scope); + +protected: + DeclaratorAST *switchDeclarator(DeclaratorAST *declarator); + FullySpecifiedType switchFullySpecifiedType(FullySpecifiedType type); + Scope *switchScope(Scope *scope); + Name **switchName(Name **name); + + using ASTVisitor::visit; + + virtual bool visit(DeclaratorAST *ast); + // ptr operators + virtual bool visit(PointerToMemberAST *ast); + virtual bool visit(PointerAST *ast); + virtual bool visit(ReferenceAST *ast); + // core declarators + virtual bool visit(DeclaratorIdAST *ast); + virtual bool visit(NestedDeclaratorAST *ast); + // postfix declarators + virtual bool visit(FunctionDeclaratorAST *ast); + virtual bool visit(ArrayDeclaratorAST *ast); + + void applyCvQualifiers(SpecifierAST *cv); + +private: + DeclaratorAST *_declarator; + Scope *_scope; + Name **_name; + FullySpecifiedType _fullySpecifiedType; +}; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_CHECKDECLARATOR_H diff --git a/src/shared/cplusplus/CheckExpression.cpp b/src/shared/cplusplus/CheckExpression.cpp new file mode 100644 index 0000000000..e546a99a53 --- /dev/null +++ b/src/shared/cplusplus/CheckExpression.cpp @@ -0,0 +1,369 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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 "CheckExpression.h" +#include "Semantic.h" +#include "TranslationUnit.h" +#include "AST.h" +#include "Scope.h" +#include "Literals.h" +#include "CoreTypes.h" +#include "Symbols.h" +#include "Control.h" + +CPLUSPLUS_BEGIN_NAMESPACE + +CheckExpression::CheckExpression(Semantic *semantic) + : SemanticCheck(semantic), + _expression(0), + _scope(0), + _checkOldStyleCasts(false) +{ } + +CheckExpression::~CheckExpression() +{ } + +FullySpecifiedType CheckExpression::check(ExpressionAST *expression, Scope *scope) +{ + FullySpecifiedType previousType = switchFullySpecifiedType(FullySpecifiedType()); + Scope *previousScope = switchScope(scope); + ExpressionAST *previousExpression = switchExpression(expression); + accept(expression); + (void) switchExpression(previousExpression); + (void) switchScope(previousScope); + return switchFullySpecifiedType(previousType); +} + +ExpressionAST *CheckExpression::switchExpression(ExpressionAST *expression) +{ + ExpressionAST *previousExpression = _expression; + _expression = expression; + return previousExpression; +} + +FullySpecifiedType CheckExpression::switchFullySpecifiedType(FullySpecifiedType type) +{ + FullySpecifiedType previousType = _fullySpecifiedType; + _fullySpecifiedType = type; + return previousType; +} + +Scope *CheckExpression::switchScope(Scope *scope) +{ + Scope *previousScope = _scope; + _scope = scope; + return previousScope; +} + +bool CheckExpression::visit(ExpressionListAST *ast) +{ + for (ExpressionListAST *it = ast; it; it = it->next) { + FullySpecifiedType exprTy = semantic()->check(it->expression, _scope); + } + return false; +} + +bool CheckExpression::visit(BinaryExpressionAST *ast) +{ + FullySpecifiedType leftExprTy = semantic()->check(ast->left_expression, _scope); + FullySpecifiedType rightExprTy = semantic()->check(ast->right_expression, _scope); + return false; +} + +bool CheckExpression::visit(CastExpressionAST *ast) +{ + FullySpecifiedType castTy = semantic()->check(ast->type_id, _scope); + FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope); + if (_checkOldStyleCasts && ! castTy->isVoidType()) + translationUnit()->warning(ast->firstToken(), + "ugly old style cast"); + return false; +} + +bool CheckExpression::visit(ConditionAST *ast) +{ + FullySpecifiedType typeSpecTy = semantic()->check(ast->type_specifier, _scope); + Name *name = 0; + FullySpecifiedType declTy = semantic()->check(ast->declarator, typeSpecTy.qualifiedType(), + _scope, &name); + Declaration *decl = control()->newDeclaration(ast->declarator->firstToken(), name); + decl->setType(declTy); + _scope->enterSymbol(decl); + return false; +} + +bool CheckExpression::visit(ConditionalExpressionAST *ast) +{ + FullySpecifiedType condTy = semantic()->check(ast->condition, _scope); + FullySpecifiedType leftExprTy = semantic()->check(ast->left_expression, _scope); + FullySpecifiedType rightExprTy = semantic()->check(ast->right_expression, _scope); + return false; +} + +bool CheckExpression::visit(CppCastExpressionAST *ast) +{ + FullySpecifiedType typeIdTy = semantic()->check(ast->type_id, _scope); + FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope); + return false; +} + +bool CheckExpression::visit(DeleteExpressionAST *ast) +{ + FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope); + return false; +} + +bool CheckExpression::visit(ArrayInitializerAST *ast) +{ + for (ExpressionListAST *it = ast->expression_list; it; it = it->next) { + FullySpecifiedType exprTy = semantic()->check(it->expression, _scope); + } + return false; +} + +bool CheckExpression::visit(QualifiedNameAST *ast) +{ + Name *name = semantic()->check(ast, _scope); + _scope->addUse(ast->firstToken(), name); + return false; +} + +bool CheckExpression::visit(OperatorFunctionIdAST *ast) +{ + Name *name = semantic()->check(ast, _scope); + _scope->addUse(ast->firstToken(), name); + return false; +} + +bool CheckExpression::visit(ConversionFunctionIdAST *ast) +{ + Name *name = semantic()->check(ast, _scope); + _scope->addUse(ast->firstToken(), name); + return false; +} + +bool CheckExpression::visit(SimpleNameAST *ast) +{ + Name *name = semantic()->check(ast, _scope); + _scope->addUse(ast->firstToken(), name); + return false; +} + +bool CheckExpression::visit(DestructorNameAST *ast) +{ + Name *name = semantic()->check(ast, _scope); + _scope->addUse(ast->firstToken(), name); + return false; +} + +bool CheckExpression::visit(TemplateIdAST *ast) +{ + Name *name = semantic()->check(ast, _scope); + _scope->addUse(ast->firstToken(), name); + return false; +} + +bool CheckExpression::visit(NewExpressionAST *ast) +{ + FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope); + FullySpecifiedType typeIdTy = semantic()->check(ast->type_id, _scope); + // ### process new-typeid + // ### process new-initializer + return false; +} + +bool CheckExpression::visit(TypeidExpressionAST *ast) +{ + FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope); + return false; +} + +bool CheckExpression::visit(TypenameCallExpressionAST *ast) +{ + if (Name *name = semantic()->check(ast->name, _scope)) { + _scope->addUse(ast->name->firstToken(), name); + } + for (ExpressionListAST *it = ast->expression_list; it; it = it->next) { + FullySpecifiedType exprTy = semantic()->check(it->expression, _scope); + } + return false; +} + +bool CheckExpression::visit(TypeConstructorCallAST *ast) +{ + FullySpecifiedType typeSpecTy = semantic()->check(ast->type_specifier, _scope); + for (ExpressionListAST *it = ast->expression_list; it; it = it->next) { + FullySpecifiedType exprTy = semantic()->check(it->expression, _scope); + } + return false; +} + +bool CheckExpression::visit(PostfixExpressionAST *ast) +{ + FullySpecifiedType exprTy = semantic()->check(ast->base_expression, _scope); + for (PostfixAST *fx = ast->postfix_expressions; fx; fx = fx->next) { + accept(fx); // ### not exactly. + } + return false; +} + +bool CheckExpression::visit(SizeofExpressionAST *ast) +{ + FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope); + return false; +} + +bool CheckExpression::visit(NumericLiteralAST *) +{ + _fullySpecifiedType.setType(control()->integerType(IntegerType::Int)); + return false; +} + +bool CheckExpression::visit(BoolLiteralAST *) +{ + _fullySpecifiedType.setType(control()->integerType(IntegerType::Bool)); + return false; +} + +bool CheckExpression::visit(StringLiteralAST *) +{ + IntegerType *charTy = control()->integerType(IntegerType::Char); + _fullySpecifiedType.setType(control()->pointerType(charTy)); + return false; +} + +bool CheckExpression::visit(ThisExpressionAST *) +{ + return false; +} + +bool CheckExpression::visit(NestedExpressionAST *ast) +{ + FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope); + return false; +} + +bool CheckExpression::visit(ThrowExpressionAST *ast) +{ + FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope); + return false; +} + +bool CheckExpression::visit(TypeIdAST *ast) +{ + FullySpecifiedType typeSpecTy = semantic()->check(ast->type_specifier, _scope); + FullySpecifiedType declTy = semantic()->check(ast->declarator, typeSpecTy.qualifiedType(), + _scope); + _fullySpecifiedType = declTy; + return false; +} + +bool CheckExpression::visit(UnaryExpressionAST *ast) +{ + FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope); + return false; +} + +bool CheckExpression::visit(QtMethodAST *ast) +{ + Name *name = 0; + Scope dummy; + FullySpecifiedType methTy = semantic()->check(ast->declarator, FullySpecifiedType(), + &dummy, &name); + Function *fty = methTy->asFunction(); + if (! fty) + translationUnit()->warning(ast->firstToken(), "expected a function declarator"); + else { + for (unsigned i = 0; i < fty->argumentCount(); ++i) { + Symbol *arg = fty->argumentAt(i); + if (arg->name()) + translationUnit()->warning(arg->sourceLocation(), + "argument should be anonymous"); + } + } + return false; +} + +bool CheckExpression::visit(CompoundLiteralAST *ast) +{ + /*FullySpecifiedType exprTy = */ semantic()->check(ast->type_id, _scope); + /*FullySpecifiedType initTy = */ semantic()->check(ast->initializer, _scope); + return false; +} + +bool CheckExpression::visit(CallAST *ast) +{ + for (ExpressionListAST *it = ast->expression_list; it; it = it->next) { + FullySpecifiedType exprTy = semantic()->check(it->expression, _scope); + } + return false; +} + +bool CheckExpression::visit(ArrayAccessAST *ast) +{ + FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope); + return false; +} + +bool CheckExpression::visit(PostIncrDecrAST *) +{ + return false; +} + +bool CheckExpression::visit(MemberAccessAST *ast) +{ + if (Name *name = semantic()->check(ast->member_name, _scope)) + _scope->addUse(ast->member_name->firstToken(), name); + return false; +} + +CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/CheckExpression.h b/src/shared/cplusplus/CheckExpression.h new file mode 100644 index 0000000000..5b5ae884b7 --- /dev/null +++ b/src/shared/cplusplus/CheckExpression.h @@ -0,0 +1,127 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. + +#ifndef CPLUSPLUS_CHECKEXPRESSION_H +#define CPLUSPLUS_CHECKEXPRESSION_H + +#include "CPlusPlusForwardDeclarations.h" +#include "SemanticCheck.h" +#include "FullySpecifiedType.h" + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +class CPLUSPLUS_EXPORT CheckExpression: public SemanticCheck +{ +public: + CheckExpression(Semantic *semantic); + virtual ~CheckExpression(); + + FullySpecifiedType check(ExpressionAST *expression, Scope *scope); + +protected: + ExpressionAST *switchExpression(ExpressionAST *expression); + FullySpecifiedType switchFullySpecifiedType(FullySpecifiedType type); + Scope *switchScope(Scope *scope); + + using ASTVisitor::visit; + + virtual bool visit(ExpressionListAST *ast); + virtual bool visit(BinaryExpressionAST *ast); + virtual bool visit(CastExpressionAST *ast); + virtual bool visit(ConditionAST *ast); + virtual bool visit(ConditionalExpressionAST *ast); + virtual bool visit(CppCastExpressionAST *ast); + virtual bool visit(DeleteExpressionAST *ast); + virtual bool visit(ArrayInitializerAST *ast); + virtual bool visit(NewExpressionAST *ast); + virtual bool visit(TypeidExpressionAST *ast); + virtual bool visit(TypenameCallExpressionAST *ast); + virtual bool visit(TypeConstructorCallAST *ast); + virtual bool visit(PostfixExpressionAST *ast); + virtual bool visit(SizeofExpressionAST *ast); + virtual bool visit(NumericLiteralAST *ast); + virtual bool visit(BoolLiteralAST *ast); + virtual bool visit(ThisExpressionAST *ast); + virtual bool visit(NestedExpressionAST *ast); + virtual bool visit(StringLiteralAST *ast); + virtual bool visit(ThrowExpressionAST *ast); + virtual bool visit(TypeIdAST *ast); + virtual bool visit(UnaryExpressionAST *ast); + virtual bool visit(QtMethodAST *ast); + virtual bool visit(CompoundLiteralAST *ast); + + //names + virtual bool visit(QualifiedNameAST *ast); + virtual bool visit(OperatorFunctionIdAST *ast); + virtual bool visit(ConversionFunctionIdAST *ast); + virtual bool visit(SimpleNameAST *ast); + virtual bool visit(DestructorNameAST *ast); + virtual bool visit(TemplateIdAST *ast); + + // postfix expressions + virtual bool visit(CallAST *ast); + virtual bool visit(ArrayAccessAST *ast); + virtual bool visit(PostIncrDecrAST *ast); + virtual bool visit(MemberAccessAST *ast); + +private: + ExpressionAST *_expression; + FullySpecifiedType _fullySpecifiedType; + Scope *_scope; + bool _checkOldStyleCasts: 1; +}; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_CHECKEXPRESSION_H diff --git a/src/shared/cplusplus/CheckName.cpp b/src/shared/cplusplus/CheckName.cpp new file mode 100644 index 0000000000..09b90f3cb8 --- /dev/null +++ b/src/shared/cplusplus/CheckName.cpp @@ -0,0 +1,348 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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 "CheckName.h" +#include "Semantic.h" +#include "AST.h" +#include "Control.h" +#include "TranslationUnit.h" +#include "Literals.h" +#include "Names.h" +#include "CoreTypes.h" +#include "Symbols.h" +#include <cassert> + +CPLUSPLUS_BEGIN_NAMESPACE + +CheckName::CheckName(Semantic *semantic) + : SemanticCheck(semantic), + _name(0), + _scope(0) +{ } + +CheckName::~CheckName() +{ } + +Name *CheckName::check(NameAST *name, Scope *scope) +{ + Name *previousName = switchName(0); + Scope *previousScope = switchScope(scope); + accept(name); + (void) switchScope(previousScope); + return switchName(previousName); +} + +Name *CheckName::check(NestedNameSpecifierAST *nested_name_specifier, Scope *scope) +{ + Name *previousName = switchName(0); + Scope *previousScope = switchScope(scope); + + std::vector<Name *> names; + for (NestedNameSpecifierAST *it = nested_name_specifier; + it; it = it->next) { + names.push_back(semantic()->check(it->class_or_namespace_name, _scope)); + } + _name = control()->qualifiedNameId(&names[0], names.size()); + + (void) switchScope(previousScope); + return switchName(previousName); +} + +Name *CheckName::switchName(Name *name) +{ + Name *previousName = _name; + _name = name; + return previousName; +} + +Scope *CheckName::switchScope(Scope *scope) +{ + Scope *previousScope = _scope; + _scope = scope; + return previousScope; +} + +bool CheckName::visit(QualifiedNameAST *ast) +{ + std::vector<Name *> names; + for (NestedNameSpecifierAST *it = ast->nested_name_specifier; + it; it = it->next) { + names.push_back(semantic()->check(it->class_or_namespace_name, _scope)); + } + names.push_back(semantic()->check(ast->unqualified_name, _scope)); + _name = control()->qualifiedNameId(&names[0], names.size(), + ast->global_scope_token != 0); + return false; +} + +bool CheckName::visit(OperatorFunctionIdAST *ast) +{ + assert(ast->op != 0); + + OperatorNameId::Kind kind = OperatorNameId::InvalidOp; + + switch (tokenKind(ast->op->op_token)) { + case T_NEW: + if (ast->op->open_token) + kind = OperatorNameId::NewArrayOp; + else + kind = OperatorNameId::NewOp; + break; + + case T_DELETE: + if (ast->op->open_token) + kind = OperatorNameId::DeleteArrayOp; + else + kind = OperatorNameId::DeleteOp; + break; + + case T_PLUS: + kind = OperatorNameId::PlusOp; + break; + + case T_MINUS: + kind = OperatorNameId::MinusOp; + break; + + case T_STAR: + kind = OperatorNameId::StarOp; + break; + + case T_SLASH: + kind = OperatorNameId::SlashOp; + break; + + case T_PERCENT: + kind = OperatorNameId::PercentOp; + break; + + case T_CARET: + kind = OperatorNameId::CaretOp; + break; + + case T_AMPER: + kind = OperatorNameId::AmpOp; + break; + + case T_PIPE: + kind = OperatorNameId::PipeOp; + break; + + case T_TILDE: + kind = OperatorNameId::TildeOp; + break; + + case T_EXCLAIM: + kind = OperatorNameId::ExclaimOp; + break; + + case T_EQUAL: + kind = OperatorNameId::EqualOp; + break; + + case T_LESS: + kind = OperatorNameId::LessOp; + break; + + case T_GREATER: + kind = OperatorNameId::GreaterOp; + break; + + case T_PLUS_EQUAL: + kind = OperatorNameId::PlusEqualOp; + break; + + case T_MINUS_EQUAL: + kind = OperatorNameId::MinusEqualOp; + break; + + case T_STAR_EQUAL: + kind = OperatorNameId::StarEqualOp; + break; + + case T_SLASH_EQUAL: + kind = OperatorNameId::SlashEqualOp; + break; + + case T_PERCENT_EQUAL: + kind = OperatorNameId::PercentEqualOp; + break; + + case T_CARET_EQUAL: + kind = OperatorNameId::CaretEqualOp; + break; + + case T_AMPER_EQUAL: + kind = OperatorNameId::AmpEqualOp; + break; + + case T_PIPE_EQUAL: + kind = OperatorNameId::PipeEqualOp; + break; + + case T_LESS_LESS: + kind = OperatorNameId::LessLessOp; + break; + + case T_GREATER_GREATER: + kind = OperatorNameId::GreaterGreaterOp; + break; + + case T_LESS_LESS_EQUAL: + kind = OperatorNameId::LessLessEqualOp; + break; + + case T_GREATER_GREATER_EQUAL: + kind = OperatorNameId::GreaterGreaterEqualOp; + break; + + case T_EQUAL_EQUAL: + kind = OperatorNameId::EqualEqualOp; + break; + + case T_EXCLAIM_EQUAL: + kind = OperatorNameId::ExclaimEqualOp; + break; + + case T_LESS_EQUAL: + kind = OperatorNameId::LessEqualOp; + break; + + case T_GREATER_EQUAL: + kind = OperatorNameId::GreaterEqualOp; + break; + + case T_AMPER_AMPER: + kind = OperatorNameId::AmpAmpOp; + break; + + case T_PIPE_PIPE: + kind = OperatorNameId::PipePipeOp; + break; + + case T_PLUS_PLUS: + kind = OperatorNameId::PlusPlusOp; + break; + + case T_MINUS_MINUS: + kind = OperatorNameId::MinusMinusOp; + break; + + case T_COMMA: + kind = OperatorNameId::CommaOp; + break; + + case T_ARROW_STAR: + kind = OperatorNameId::ArrowStarOp; + break; + + case T_ARROW: + kind = OperatorNameId::ArrowOp; + break; + + case T_LPAREN: + kind = OperatorNameId::FunctionCallOp; + break; + + case T_LBRACKET: + kind = OperatorNameId::ArrayAccessOp; + break; + + default: + kind = OperatorNameId::InvalidOp; + } // switch + + _name = control()->operatorNameId(kind); + return false; +} + +bool CheckName::visit(ConversionFunctionIdAST *ast) +{ + FullySpecifiedType ty = semantic()->check(ast->type_specifier, _scope); + ty = semantic()->check(ast->ptr_operators, ty, _scope); + _name = control()->conversionNameId(ty); + return false; +} + +bool CheckName::visit(SimpleNameAST *ast) +{ + Identifier *id = identifier(ast->identifier_token); + _name = control()->nameId(id); + return false; +} + +bool CheckName::visit(DestructorNameAST *ast) +{ + Identifier *id = identifier(ast->identifier_token); + _name = control()->destructorNameId(id); + return false; +} + +bool CheckName::visit(TemplateIdAST *ast) +{ + Identifier *id = identifier(ast->identifier_token); + std::vector<FullySpecifiedType> templateArguments; + for (TemplateArgumentListAST *it = ast->template_arguments; it; + it = it->next) { + ExpressionAST *arg = it->template_argument; + FullySpecifiedType exprTy = semantic()->check(arg, _scope); + templateArguments.push_back(exprTy); + } + if (templateArguments.empty()) + _name = control()->templateNameId(id); + else + _name = control()->templateNameId(id, &templateArguments[0], + templateArguments.size()); + return false; +} + +CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/CheckName.h b/src/shared/cplusplus/CheckName.h new file mode 100644 index 0000000000..4b0631b002 --- /dev/null +++ b/src/shared/cplusplus/CheckName.h @@ -0,0 +1,92 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. + +#ifndef CPLUSPLUS_CHECKNAME_H +#define CPLUSPLUS_CHECKNAME_H + +#include "CPlusPlusForwardDeclarations.h" +#include "SemanticCheck.h" + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +class CPLUSPLUS_EXPORT CheckName: public SemanticCheck +{ +public: + CheckName(Semantic *semantic); + virtual ~CheckName(); + + Name *check(NameAST *name, Scope *scope); + Name *check(NestedNameSpecifierAST *name, Scope *scope); + +protected: + Name *switchName(Name *name); + Scope *switchScope(Scope *scope); + + using ASTVisitor::visit; + + virtual bool visit(QualifiedNameAST *ast); + virtual bool visit(OperatorFunctionIdAST *ast); + virtual bool visit(ConversionFunctionIdAST *ast); + virtual bool visit(SimpleNameAST *ast); + virtual bool visit(DestructorNameAST *ast); + virtual bool visit(TemplateIdAST *ast); + +private: + Name *_name; + Scope *_scope; +}; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_CHECKNAME_H diff --git a/src/shared/cplusplus/CheckSpecifier.cpp b/src/shared/cplusplus/CheckSpecifier.cpp new file mode 100644 index 0000000000..eeb59eebcc --- /dev/null +++ b/src/shared/cplusplus/CheckSpecifier.cpp @@ -0,0 +1,392 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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 "CheckSpecifier.h" +#include "Semantic.h" +#include "AST.h" +#include "Token.h" +#include "TranslationUnit.h" +#include "Literals.h" +#include "Names.h" +#include "CoreTypes.h" +#include "Symbols.h" +#include "Control.h" +#include "Scope.h" + +CPLUSPLUS_BEGIN_NAMESPACE + +CheckSpecifier::CheckSpecifier(Semantic *semantic) + : SemanticCheck(semantic), + _specifier(0), + _scope(0) +{ } + +CheckSpecifier::~CheckSpecifier() +{ } + +FullySpecifiedType CheckSpecifier::check(SpecifierAST *specifier, Scope *scope) +{ + FullySpecifiedType previousType = switchFullySpecifiedType(FullySpecifiedType()); + Scope *previousScope = switchScope(scope); + SpecifierAST *previousSpecifier = switchSpecifier(specifier); + accept(specifier); + (void) switchSpecifier(previousSpecifier); + (void) switchScope(previousScope); + return switchFullySpecifiedType(previousType); +} + +SpecifierAST *CheckSpecifier::switchSpecifier(SpecifierAST *specifier) +{ + SpecifierAST *previousSpecifier = _specifier; + _specifier = specifier; + return previousSpecifier; +} + +FullySpecifiedType CheckSpecifier::switchFullySpecifiedType(FullySpecifiedType type) +{ + FullySpecifiedType previousType = _fullySpecifiedType; + _fullySpecifiedType = type; + return previousType; +} + +Scope *CheckSpecifier::switchScope(Scope *scope) +{ + Scope *previousScope = _scope; + _scope = scope; + return previousScope; +} + +bool CheckSpecifier::visit(SimpleSpecifierAST *ast) +{ + switch (tokenKind(ast->specifier_token)) { + case T_CONST: + if (_fullySpecifiedType.isConst()) + translationUnit()->error(ast->specifier_token, + "duplicate `%s'", spell(ast->specifier_token)); + _fullySpecifiedType.setConst(true); + break; + + case T_VOLATILE: + if (_fullySpecifiedType.isVolatile()) + translationUnit()->error(ast->specifier_token, + "duplicate `%s'", spell(ast->specifier_token)); + _fullySpecifiedType.setVolatile(true); + break; + + case T_FRIEND: + if (_fullySpecifiedType.isFriend()) + translationUnit()->error(ast->specifier_token, + "duplicate `%s'", spell(ast->specifier_token)); + _fullySpecifiedType.setFriend(true); + break; + + case T_REGISTER: + if (_fullySpecifiedType.isRegister()) + translationUnit()->error(ast->specifier_token, + "duplicate `%s'", spell(ast->specifier_token)); + _fullySpecifiedType.setRegister(true); + break; + + case T_STATIC: + if (_fullySpecifiedType.isStatic()) + translationUnit()->error(ast->specifier_token, + "duplicate `%s'", spell(ast->specifier_token)); + _fullySpecifiedType.setStatic(true); + break; + + case T_EXTERN: + if (_fullySpecifiedType.isExtern()) + translationUnit()->error(ast->specifier_token, + "duplicate `%s'", spell(ast->specifier_token)); + _fullySpecifiedType.setExtern(true); + break; + + case T_MUTABLE: + if (_fullySpecifiedType.isMutable()) + translationUnit()->error(ast->specifier_token, + "duplicate `%s'", spell(ast->specifier_token)); + _fullySpecifiedType.setMutable(true); + break; + + case T_TYPEDEF: + if (_fullySpecifiedType.isTypedef()) + translationUnit()->error(ast->specifier_token, + "duplicate `%s'", spell(ast->specifier_token)); + _fullySpecifiedType.setTypedef(true); + break; + + case T_INLINE: + if (_fullySpecifiedType.isInline()) + translationUnit()->error(ast->specifier_token, + "duplicate `%s'", spell(ast->specifier_token)); + _fullySpecifiedType.setInline(true); + break; + + case T_VIRTUAL: + if (_fullySpecifiedType.isVirtual()) + translationUnit()->error(ast->specifier_token, + "duplicate `%s'", spell(ast->specifier_token)); + _fullySpecifiedType.setVirtual(true); + break; + + case T_EXPLICIT: + if (_fullySpecifiedType.isExplicit()) + translationUnit()->error(ast->specifier_token, + "duplicate `%s'", spell(ast->specifier_token)); + _fullySpecifiedType.setExplicit(true); + break; + + case T_SIGNED: + if (_fullySpecifiedType.isSigned()) + translationUnit()->error(ast->specifier_token, + "duplicate `%s'", spell(ast->specifier_token)); + _fullySpecifiedType.setSigned(true); + break; + + case T_UNSIGNED: + if (_fullySpecifiedType.isUnsigned()) + translationUnit()->error(ast->specifier_token, + "duplicate `%s'", spell(ast->specifier_token)); + _fullySpecifiedType.setUnsigned(true); + break; + + case T_CHAR: + if (_fullySpecifiedType.type()) + translationUnit()->error(ast->specifier_token, + "duplicate data type in declaration"); + _fullySpecifiedType.setType(control()->integerType(IntegerType::Char)); + break; + + case T_WCHAR_T: + if (_fullySpecifiedType.type()) + translationUnit()->error(ast->specifier_token, + "duplicate data type in declaration"); + _fullySpecifiedType.setType(control()->integerType(IntegerType::WideChar)); + break; + + case T_BOOL: + if (_fullySpecifiedType.type()) + translationUnit()->error(ast->specifier_token, + "duplicate data type in declaration"); + _fullySpecifiedType.setType(control()->integerType(IntegerType::Bool)); + break; + + case T_SHORT: + if (Type *tp = _fullySpecifiedType.type()) { + IntegerType *intType = control()->integerType(IntegerType::Int); + if (tp != intType) + translationUnit()->error(ast->specifier_token, + "duplicate data type in declaration"); + } + _fullySpecifiedType.setType(control()->integerType(IntegerType::Short)); + break; + + case T_INT: + if (Type *tp = _fullySpecifiedType.type()) { + IntegerType *shortType = control()->integerType(IntegerType::Short); + IntegerType *longType = control()->integerType(IntegerType::Long); + IntegerType *longLongType = control()->integerType(IntegerType::LongLong); + if (tp == shortType || tp == longType || tp == longLongType) + break; + translationUnit()->error(ast->specifier_token, + "duplicate data type in declaration"); + } + _fullySpecifiedType.setType(control()->integerType(IntegerType::Int)); + break; + + case T_LONG: + if (Type *tp = _fullySpecifiedType.type()) { + IntegerType *intType = control()->integerType(IntegerType::Int); + IntegerType *longType = control()->integerType(IntegerType::Long); + FloatType *doubleType = control()->floatType(FloatType::Double); + if (tp == longType) { + _fullySpecifiedType.setType(control()->integerType(IntegerType::LongLong)); + break; + } else if (tp == doubleType) { + _fullySpecifiedType.setType(control()->floatType(FloatType::LongDouble)); + break; + } else if (tp != intType) { + translationUnit()->error(ast->specifier_token, + "duplicate data type in declaration"); + } + } + _fullySpecifiedType.setType(control()->integerType(IntegerType::Long)); + break; + + case T_FLOAT: + if (_fullySpecifiedType.type()) + translationUnit()->error(ast->specifier_token, + "duplicate data type in declaration"); + _fullySpecifiedType.setType(control()->floatType(FloatType::Float)); + break; + + case T_DOUBLE: + if (Type *tp = _fullySpecifiedType.type()) { + IntegerType *longType = control()->integerType(IntegerType::Long); + if (tp == longType) { + _fullySpecifiedType.setType(control()->floatType(FloatType::LongDouble)); + break; + } + translationUnit()->error(ast->specifier_token, + "duplicate data type in declaration"); + } + _fullySpecifiedType.setType(control()->floatType(FloatType::Double)); + break; + + case T_VOID: + if (_fullySpecifiedType.type()) + translationUnit()->error(ast->specifier_token, + "duplicate data type in declaration"); + _fullySpecifiedType.setType(control()->voidType()); + break; + + default: + break; + } // switch + accept(ast->next); + return false; +} + +bool CheckSpecifier::visit(ClassSpecifierAST *ast) +{ + Name *className = semantic()->check(ast->name, _scope); + Class *klass = control()->newClass(ast->firstToken(), className); + unsigned classKey = tokenKind(ast->classkey_token); + if (classKey == T_CLASS) + klass->setClassKey(Class::ClassKey); + else if (classKey == T_STRUCT) + klass->setClassKey(Class::StructKey); + else if (classKey == T_UNION) + klass->setClassKey(Class::UnionKey); + klass->setVisibility(semantic()->currentVisibility()); + _scope->enterSymbol(klass); + _fullySpecifiedType.setType(klass); + + for (BaseSpecifierAST *base = ast->base_clause; base; base = base->next) { + Name *baseClassName = semantic()->check(base->name, _scope); + BaseClass *baseClass = control()->newBaseClass(ast->firstToken(), baseClassName); + if (base->token_virtual) + baseClass->setVirtual(true); + if (base->token_access_specifier) { + int accessSpecifier = tokenKind(base->token_access_specifier); + int visibility = semantic()->visibilityForAccessSpecifier(accessSpecifier); + baseClass->setVisibility(visibility); + } + klass->addBaseClass(baseClass); + } + + int visibility = semantic()->visibilityForClassKey(classKey); + int previousVisibility = semantic()->switchVisibility(visibility); + int previousMethodKey = semantic()->switchMethodKey(Function::NormalMethod); + + for (DeclarationAST *member = ast->member_specifiers; + member; member = member->next) { + semantic()->check(member, klass->members()); + } + + (void) semantic()->switchMethodKey(previousMethodKey); + (void) semantic()->switchVisibility(previousVisibility); + + accept(ast->next); + return false; +} + +bool CheckSpecifier::visit(NamedTypeSpecifierAST *ast) +{ + Name *name = semantic()->check(ast->name, _scope); + _fullySpecifiedType.setType(control()->namedType(name)); + accept(ast->next); + return false; +} + +bool CheckSpecifier::visit(ElaboratedTypeSpecifierAST *ast) +{ + Name *name = semantic()->check(ast->name, _scope); + _fullySpecifiedType.setType(control()->namedType(name)); + accept(ast->next); + return false; +} + +bool CheckSpecifier::visit(EnumSpecifierAST *ast) +{ + Name *name = semantic()->check(ast->name, _scope); + Enum *e = control()->newEnum(ast->firstToken(), name); + e->setVisibility(semantic()->currentVisibility()); + _scope->enterSymbol(e); + _fullySpecifiedType.setType(e); + for (EnumeratorAST *enumerator = ast->enumerators; enumerator; + enumerator = enumerator->next) { + Identifier *id = identifier(enumerator->identifier_token); + if (! id) + continue; + NameId *enumeratorName = control()->nameId(id); + Declaration *decl = control()->newDeclaration(enumerator->firstToken(), + enumeratorName); + e->addMember(decl); + } + accept(ast->next); + return false; +} + +bool CheckSpecifier::visit(TypeofSpecifierAST *ast) +{ + semantic()->check(ast->expression, _scope); + accept(ast->next); + return false; +} + +bool CheckSpecifier::visit(AttributeSpecifierAST *) +{ + return false; +} + +CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/CheckSpecifier.h b/src/shared/cplusplus/CheckSpecifier.h new file mode 100644 index 0000000000..3e6ddc57ba --- /dev/null +++ b/src/shared/cplusplus/CheckSpecifier.h @@ -0,0 +1,95 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. + +#ifndef CPLUSPLUS_CHECKSPECIFIER_H +#define CPLUSPLUS_CHECKSPECIFIER_H + +#include "CPlusPlusForwardDeclarations.h" +#include "SemanticCheck.h" +#include "FullySpecifiedType.h" + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +class CPLUSPLUS_EXPORT CheckSpecifier: public SemanticCheck +{ +public: + CheckSpecifier(Semantic *semantic); + virtual ~CheckSpecifier(); + + FullySpecifiedType check(SpecifierAST *specifier, Scope *scope); + +protected: + SpecifierAST *switchSpecifier(SpecifierAST *specifier); + FullySpecifiedType switchFullySpecifiedType(FullySpecifiedType type); + Scope *switchScope(Scope *scope); + + using ASTVisitor::visit; + + virtual bool visit(SimpleSpecifierAST *ast); + virtual bool visit(ClassSpecifierAST *ast); + virtual bool visit(NamedTypeSpecifierAST *ast); + virtual bool visit(ElaboratedTypeSpecifierAST *ast); + virtual bool visit(EnumSpecifierAST *ast); + virtual bool visit(TypeofSpecifierAST *ast); + virtual bool visit(AttributeSpecifierAST *ast); + +private: + SpecifierAST *_specifier; + FullySpecifiedType _fullySpecifiedType; + Scope *_scope; +}; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_CHECKSPECIFIER_H diff --git a/src/shared/cplusplus/CheckStatement.cpp b/src/shared/cplusplus/CheckStatement.cpp new file mode 100644 index 0000000000..67902ff252 --- /dev/null +++ b/src/shared/cplusplus/CheckStatement.cpp @@ -0,0 +1,239 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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 "CheckStatement.h" +#include "Semantic.h" +#include "AST.h" +#include "TranslationUnit.h" +#include "Scope.h" +#include "CoreTypes.h" +#include "Control.h" +#include "Symbols.h" + +CPLUSPLUS_BEGIN_NAMESPACE + +CheckStatement::CheckStatement(Semantic *semantic) + : SemanticCheck(semantic), + _statement(0), + _scope(0) +{ } + +CheckStatement::~CheckStatement() +{ } + +void CheckStatement::check(StatementAST *statement, Scope *scope) +{ + Scope *previousScope = switchScope(scope); + StatementAST *previousStatement = switchStatement(statement); + accept(statement); + (void) switchStatement(previousStatement); + (void) switchScope(previousScope); +} + +StatementAST *CheckStatement::switchStatement(StatementAST *statement) +{ + StatementAST *previousStatement = _statement; + _statement = statement; + return previousStatement; +} + +Scope *CheckStatement::switchScope(Scope *scope) +{ + Scope *previousScope = _scope; + _scope = scope; + return previousScope; +} + +bool CheckStatement::visit(CaseStatementAST *ast) +{ + FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope); + semantic()->check(ast->statement, _scope); + return false; +} + +bool CheckStatement::visit(CompoundStatementAST *ast) +{ + Block *block = control()->newBlock(ast->lbrace_token); + _scope->enterSymbol(block); + Scope *previousScope = switchScope(block->members()); + for (StatementAST *it = ast->statements; it; it = it->next) { + semantic()->check(it, _scope); + } + (void) switchScope(previousScope); + return false; +} + +bool CheckStatement::visit(DeclarationStatementAST *ast) +{ + semantic()->check(ast->declaration, _scope); + return false; +} + +bool CheckStatement::visit(DoStatementAST *ast) +{ + semantic()->check(ast->statement, _scope); + FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope); + return false; +} + +bool CheckStatement::visit(ExpressionOrDeclarationStatementAST *ast) +{ +// translationUnit()->warning(ast->firstToken(), +// "ambiguous expression or declaration statement"); + if (ast->declaration) + semantic()->check(ast->declaration, _scope); + else + semantic()->check(ast->expression, _scope); + return false; +} + +bool CheckStatement::visit(ExpressionStatementAST *ast) +{ + FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope); + return false; +} + +bool CheckStatement::visit(ForStatementAST *ast) +{ + Block *block = control()->newBlock(ast->for_token); + _scope->enterSymbol(block); + Scope *previousScope = switchScope(block->members()); + semantic()->check(ast->initializer, _scope); + FullySpecifiedType condTy = semantic()->check(ast->condition, _scope); + FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope); + semantic()->check(ast->statement, _scope); + (void) switchScope(previousScope); + return false; +} + +bool CheckStatement::visit(IfStatementAST *ast) +{ + Block *block = control()->newBlock(ast->if_token); + _scope->enterSymbol(block); + Scope *previousScope = switchScope(block->members()); + FullySpecifiedType exprTy = semantic()->check(ast->condition, _scope); + semantic()->check(ast->statement, _scope); + semantic()->check(ast->else_statement, _scope); + (void) switchScope(previousScope); + return false; +} + +bool CheckStatement::visit(LabeledStatementAST *ast) +{ + semantic()->check(ast->statement, _scope); + return false; +} + +bool CheckStatement::visit(BreakStatementAST *) +{ + return false; +} + +bool CheckStatement::visit(ContinueStatementAST *) +{ + return false; +} + +bool CheckStatement::visit(GotoStatementAST *) +{ + return false; +} + +bool CheckStatement::visit(ReturnStatementAST *ast) +{ + FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope); + return false; +} + +bool CheckStatement::visit(SwitchStatementAST *ast) +{ + Block *block = control()->newBlock(ast->switch_token); + _scope->enterSymbol(block); + Scope *previousScope = switchScope(block->members()); + FullySpecifiedType condTy = semantic()->check(ast->condition, _scope); + semantic()->check(ast->statement, _scope); + (void) switchScope(previousScope); + return false; +} + +bool CheckStatement::visit(TryBlockStatementAST *ast) +{ + semantic()->check(ast->statement, _scope); + for (CatchClauseAST *c = ast->catch_clause_seq; c; c = c->next) { + semantic()->check(c, _scope); + } + return false; +} + +bool CheckStatement::visit(CatchClauseAST *ast) +{ + Block *block = control()->newBlock(ast->catch_token); + _scope->enterSymbol(block); + Scope *previousScope = switchScope(block->members()); + semantic()->check(ast->exception_declaration, _scope); + semantic()->check(ast->statement, _scope); + (void) switchScope(previousScope); + return false; +} + +bool CheckStatement::visit(WhileStatementAST *ast) +{ + Block *block = control()->newBlock(ast->while_token); + _scope->enterSymbol(block); + Scope *previousScope = switchScope(block->members()); + FullySpecifiedType condTy = semantic()->check(ast->condition, _scope); + semantic()->check(ast->statement, _scope); + (void) switchScope(previousScope); + return false; +} + +CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/CheckStatement.h b/src/shared/cplusplus/CheckStatement.h new file mode 100644 index 0000000000..856f64be8f --- /dev/null +++ b/src/shared/cplusplus/CheckStatement.h @@ -0,0 +1,102 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. + +#ifndef CPLUSPLUS_CHECKSTATEMENT_H +#define CPLUSPLUS_CHECKSTATEMENT_H + +#include "CPlusPlusForwardDeclarations.h" +#include "SemanticCheck.h" + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +class CPLUSPLUS_EXPORT CheckStatement: public SemanticCheck +{ +public: + CheckStatement(Semantic *semantic); + virtual ~CheckStatement(); + + void check(StatementAST *statement, Scope *scope); + +protected: + StatementAST *switchStatement(StatementAST *statement); + Scope *switchScope(Scope *scope); + + using ASTVisitor::visit; + + virtual bool visit(CaseStatementAST *ast); + virtual bool visit(CompoundStatementAST *ast); + virtual bool visit(DeclarationStatementAST *ast); + virtual bool visit(DoStatementAST *ast); + virtual bool visit(ExpressionOrDeclarationStatementAST *ast); + virtual bool visit(ExpressionStatementAST *ast); + virtual bool visit(ForStatementAST *ast); + virtual bool visit(IfStatementAST *ast); + virtual bool visit(LabeledStatementAST *ast); + virtual bool visit(BreakStatementAST *ast); + virtual bool visit(ContinueStatementAST *ast); + virtual bool visit(GotoStatementAST *ast); + virtual bool visit(ReturnStatementAST *ast); + virtual bool visit(SwitchStatementAST *ast); + virtual bool visit(TryBlockStatementAST *ast); + virtual bool visit(CatchClauseAST *ast); + virtual bool visit(WhileStatementAST *ast); + +private: + StatementAST *_statement; + Scope *_scope; +}; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_CHECKSTATEMENT_H diff --git a/src/shared/cplusplus/Control.cpp b/src/shared/cplusplus/Control.cpp new file mode 100644 index 0000000000..e44d84a1ae --- /dev/null +++ b/src/shared/cplusplus/Control.cpp @@ -0,0 +1,636 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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 "Control.h" +#include "MemoryPool.h" +#include "Literals.h" +#include "LiteralTable.h" +#include "TranslationUnit.h" +#include "CoreTypes.h" +#include "Symbols.h" +#include "Names.h" +#include "Array.h" +#include <map> // ### replace me with LiteralTable +#include <string> + +CPLUSPLUS_BEGIN_NAMESPACE + +template <typename _Iterator> +static void delete_map_entries(_Iterator first, _Iterator last) +{ + for (; first != last; ++first) + delete first->second; +} + +template <typename _Map> +static void delete_map_entries(const _Map &m) +{ delete_map_entries(m.begin(), m.end()); } + +template <typename _Iterator> +static void delete_array_entries(_Iterator first, _Iterator last) +{ + for (; first != last; ++first) + delete *first; +} + +template <typename _Array> +static void delete_array_entries(const _Array &a) +{ delete_array_entries(a.begin(), a.end()); } + +class Control::Data +{ +public: + Data(Control *control) + : control(control), + translationUnit(0), + diagnosticClient(0) + { } + + ~Data() + { + // names + delete_map_entries(nameIds); + delete_map_entries(destructorNameIds); + delete_map_entries(operatorNameIds); + delete_map_entries(conversionNameIds); + delete_map_entries(qualifiedNameIds); + delete_map_entries(templateNameIds); + + // types + delete_map_entries(integerTypes); + delete_map_entries(floatTypes); + delete_map_entries(pointerToMemberTypes); + delete_map_entries(pointerTypes); + delete_map_entries(referenceTypes); + delete_map_entries(arrayTypes); + delete_map_entries(namedTypes); + + // symbols + delete_array_entries(declarations); + delete_array_entries(arguments); + delete_array_entries(functions); + delete_array_entries(baseClasses); + delete_array_entries(blocks); + delete_array_entries(classes); + delete_array_entries(namespaces); + delete_array_entries(usingNamespaceDirectives); + delete_array_entries(enums); + delete_array_entries(usingDeclarations); + } + + NameId *findOrInsertNameId(Identifier *id) + { + if (! id) + return 0; + std::map<Identifier *, NameId *>::iterator it = nameIds.lower_bound(id); + if (it == nameIds.end() || it->first != id) + it = nameIds.insert(it, std::make_pair(id, new NameId(id))); + return it->second; + } + + TemplateNameId *findOrInsertTemplateNameId(Identifier *id, + const std::vector<FullySpecifiedType> &templateArguments) + { + if (! id) + return 0; + const TemplateNameIdKey key(id, templateArguments); + std::map<TemplateNameIdKey, TemplateNameId *>::iterator it = + templateNameIds.lower_bound(key); + if (it == templateNameIds.end() || it->first != key) { + const FullySpecifiedType *args = 0; + if (templateArguments.size()) + args = &templateArguments[0]; + TemplateNameId *templ = new TemplateNameId(id, args, + templateArguments.size()); + it = templateNameIds.insert(it, std::make_pair(key, templ)); + } + return it->second; + } + + DestructorNameId *findOrInsertDestructorNameId(Identifier *id) + { + if (! id) + return 0; + std::map<Identifier *, DestructorNameId *>::iterator it = destructorNameIds.lower_bound(id); + if (it == destructorNameIds.end() || it->first != id) + it = destructorNameIds.insert(it, std::make_pair(id, new DestructorNameId(id))); + return it->second; + } + + OperatorNameId *findOrInsertOperatorNameId(int kind) + { + const int key(kind); + std::map<int, OperatorNameId *>::iterator it = operatorNameIds.lower_bound(key); + if (it == operatorNameIds.end() || it->first != key) + it = operatorNameIds.insert(it, std::make_pair(key, new OperatorNameId(kind))); + return it->second; + } + + ConversionNameId *findOrInsertConversionNameId(FullySpecifiedType type) + { + std::map<FullySpecifiedType, ConversionNameId *>::iterator it = + conversionNameIds.lower_bound(type); + if (it == conversionNameIds.end() || it->first != type) + it = conversionNameIds.insert(it, std::make_pair(type, new ConversionNameId(type))); + return it->second; + } + + QualifiedNameId *findOrInsertQualifiedNameId(const std::vector<Name *> &names, bool isGlobal) + { + const QualifiedNameIdKey key(names, isGlobal); + std::map<QualifiedNameIdKey, QualifiedNameId *>::iterator it = + qualifiedNameIds.lower_bound(key); + if (it == qualifiedNameIds.end() || it->first != key) { + QualifiedNameId *name = new QualifiedNameId(&names[0], names.size(), isGlobal); + it = qualifiedNameIds.insert(it, std::make_pair(key, name)); + } + return it->second; + } + + IntegerType *findOrInsertIntegerType(int kind) + { + const int key = int(kind); + std::map<int, IntegerType *>::iterator it = integerTypes.lower_bound(key); + if (it == integerTypes.end() || it->first != key) + it = integerTypes.insert(it, std::make_pair(key, new IntegerType(kind))); + return it->second; + } + + FloatType *findOrInsertFloatType(int kind) + { + const int key = int(kind); + std::map<int, FloatType *>::iterator it = floatTypes.lower_bound(key); + if (it == floatTypes.end() || it->first != key) + it = floatTypes.insert(it, std::make_pair(key, new FloatType(kind))); + return it->second; + } + + PointerToMemberType *findOrInsertPointerToMemberType(Name *memberName, FullySpecifiedType elementType) + { + const PointerToMemberTypeKey key(memberName, elementType); + std::map<PointerToMemberTypeKey, PointerToMemberType *>::iterator it = + pointerToMemberTypes.lower_bound(key); + if (it == pointerToMemberTypes.end() || it->first != key) + it = pointerToMemberTypes.insert(it, std::make_pair(key, new PointerToMemberType(memberName, elementType))); + return it->second; + } + + PointerType *findOrInsertPointerType(FullySpecifiedType elementType) + { + std::map<FullySpecifiedType, PointerType *>::iterator it = + pointerTypes.lower_bound(elementType); + if (it == pointerTypes.end() || it->first != elementType) + it = pointerTypes.insert(it, std::make_pair(elementType, new PointerType(elementType))); + return it->second; + } + + ReferenceType *findOrInsertReferenceType(FullySpecifiedType elementType) + { + std::map<FullySpecifiedType, ReferenceType *>::iterator it = + referenceTypes.lower_bound(elementType); + if (it == referenceTypes.end() || it->first != elementType) + it = referenceTypes.insert(it, std::make_pair(elementType, new ReferenceType(elementType))); + return it->second; + } + + ArrayType *findOrInsertArrayType(FullySpecifiedType elementType, size_t size) + { + const ArrayKey key(elementType, size); + std::map<ArrayKey, ArrayType *>::iterator it = + arrayTypes.lower_bound(key); + if (it == arrayTypes.end() || it->first != key) + it = arrayTypes.insert(it, std::make_pair(key, new ArrayType(elementType, size))); + return it->second; + } + + NamedType *findOrInsertNamedType(Name *name) + { + std::map<Name *, NamedType *>::iterator it = namedTypes.lower_bound(name); + if (it == namedTypes.end() || it->first != name) + it = namedTypes.insert(it, std::make_pair(name, new NamedType(name))); + return it->second; + } + + Declaration *newDeclaration(unsigned sourceLocation, Name *name) + { + Declaration *declaration = new Declaration(translationUnit, + sourceLocation, name); + declarations.push_back(declaration); + return declaration; + } + + Argument *newArgument(unsigned sourceLocation, Name *name) + { + Argument *argument = new Argument(translationUnit, + sourceLocation, name); + arguments.push_back(argument); + return argument; + } + + Function *newFunction(unsigned sourceLocation, Name *name) + { + Function *function = new Function(translationUnit, + sourceLocation, name); + functions.push_back(function); + return function; + } + + BaseClass *newBaseClass(unsigned sourceLocation, Name *name) + { + BaseClass *baseClass = new BaseClass(translationUnit, + sourceLocation, name); + baseClasses.push_back(baseClass); + return baseClass; + } + + Block *newBlock(unsigned sourceLocation) + { + Block *block = new Block(translationUnit, sourceLocation); + blocks.push_back(block); + return block; + } + + Class *newClass(unsigned sourceLocation, Name *name) + { + Class *klass = new Class(translationUnit, + sourceLocation, name); + classes.push_back(klass); + return klass; + } + + Namespace *newNamespace(unsigned sourceLocation, Name *name) + { + Namespace *ns = new Namespace(translationUnit, + sourceLocation, name); + namespaces.push_back(ns); + return ns; + } + + UsingNamespaceDirective *newUsingNamespaceDirective(unsigned sourceLocation, Name *name) + { + UsingNamespaceDirective *u = new UsingNamespaceDirective(translationUnit, + sourceLocation, name); + usingNamespaceDirectives.push_back(u); + return u; + } + + Enum *newEnum(unsigned sourceLocation, Name *name) + { + Enum *e = new Enum(translationUnit, + sourceLocation, name); + enums.push_back(e); + return e; + } + + UsingDeclaration *newUsingDeclaration(unsigned sourceLocation, Name *name) + { + UsingDeclaration *u = new UsingDeclaration(translationUnit, + sourceLocation, name); + usingDeclarations.push_back(u); + return u; + } + + struct TemplateNameIdKey { + Identifier *id; + std::vector<FullySpecifiedType> templateArguments; + + TemplateNameIdKey(Identifier *id, const std::vector<FullySpecifiedType> &templateArguments) + : id(id), templateArguments(templateArguments) + { } + + bool operator == (const TemplateNameIdKey &other) const + { return id == other.id && templateArguments == other.templateArguments; } + + bool operator != (const TemplateNameIdKey &other) const + { return ! operator==(other); } + + bool operator < (const TemplateNameIdKey &other) const + { + if (id == other.id) + return std::lexicographical_compare(templateArguments.begin(), + templateArguments.end(), + other.templateArguments.begin(), + other.templateArguments.end()); + return id < other.id; + } + }; + + struct QualifiedNameIdKey { + std::vector<Name *> names; + bool isGlobal; + + QualifiedNameIdKey(const std::vector<Name *> &names, bool isGlobal) : + names(names), isGlobal(isGlobal) + { } + + bool operator == (const QualifiedNameIdKey &other) const + { return isGlobal == other.isGlobal && names == other.names; } + + bool operator != (const QualifiedNameIdKey &other) const + { return ! operator==(other); } + + bool operator < (const QualifiedNameIdKey &other) const + { + if (isGlobal == other.isGlobal) + return std::lexicographical_compare(names.begin(), names.end(), + other.names.begin(), other.names.end()); + return isGlobal < other.isGlobal; + } + }; + + struct ArrayKey { + FullySpecifiedType type; + size_t size; + + ArrayKey() : + size(0) + { } + + ArrayKey(FullySpecifiedType type, size_t size) : + type(type), size(size) + { } + + bool operator == (const ArrayKey &other) const + { return type == other.type && size == other.size; } + + bool operator != (const ArrayKey &other) const + { return ! operator==(other); } + + bool operator < (const ArrayKey &other) const + { + if (type == other.type) + return size < other.size; + return type < other.type; + } + }; + + struct PointerToMemberTypeKey { + Name *memberName; + FullySpecifiedType type; + + PointerToMemberTypeKey() + : memberName(0) + { } + + PointerToMemberTypeKey(Name *memberName, FullySpecifiedType type) + : memberName(memberName), type(type) + { } + + bool operator == (const PointerToMemberTypeKey &other) const + { return memberName == other.memberName && type == other.type; } + + bool operator != (const PointerToMemberTypeKey &other) const + { return ! operator==(other); } + + bool operator < (const PointerToMemberTypeKey &other) const + { + if (memberName == other.memberName) + return type < other.type; + return memberName < other.memberName; + } + }; + + Control *control; + TranslationUnit *translationUnit; + DiagnosticClient *diagnosticClient; + LiteralTable<Identifier> identifiers; + LiteralTable<StringLiteral> stringLiterals; + LiteralTable<NumericLiteral> numericLiterals; + LiteralTable<StringLiteral> fileNames; + + // ### replace std::map with lookup tables. ASAP! + + // names + std::map<Identifier *, NameId *> nameIds; + std::map<Identifier *, DestructorNameId *> destructorNameIds; + std::map<int, OperatorNameId *> operatorNameIds; + std::map<FullySpecifiedType, ConversionNameId *> conversionNameIds; + std::map<TemplateNameIdKey, TemplateNameId *> templateNameIds; + std::map<QualifiedNameIdKey, QualifiedNameId *> qualifiedNameIds; + + // types + VoidType voidType; + std::map<int, IntegerType *> integerTypes; + std::map<int, FloatType *> floatTypes; + std::map<PointerToMemberTypeKey, PointerToMemberType *> pointerToMemberTypes; + std::map<FullySpecifiedType, PointerType *> pointerTypes; + std::map<FullySpecifiedType, ReferenceType *> referenceTypes; + std::map<ArrayKey, ArrayType *> arrayTypes; + std::map<Name *, NamedType *> namedTypes; + + // symbols + std::vector<Declaration *> declarations; + std::vector<Argument *> arguments; + std::vector<Function *> functions; + std::vector<BaseClass *> baseClasses; + std::vector<Block *> blocks; + std::vector<Class *> classes; + std::vector<Namespace *> namespaces; + std::vector<UsingNamespaceDirective *> usingNamespaceDirectives; + std::vector<Enum *> enums; + std::vector<UsingDeclaration *> usingDeclarations; +}; + +Control::Control() +{ d = new Data(this); } + +Control::~Control() +{ delete d; } + +TranslationUnit *Control::translationUnit() const +{ return d->translationUnit; } + +TranslationUnit *Control::switchTranslationUnit(TranslationUnit *unit) +{ + TranslationUnit *previousTranslationUnit = d->translationUnit; + d->translationUnit = unit; + return previousTranslationUnit; +} + +DiagnosticClient *Control::diagnosticClient() const +{ return d->diagnosticClient; } + +void Control::setDiagnosticClient(DiagnosticClient *diagnosticClient) +{ d->diagnosticClient = diagnosticClient; } + +Identifier *Control::findOrInsertIdentifier(const char *chars, unsigned size) +{ return d->identifiers.findOrInsertLiteral(chars, size); } + +Identifier *Control::findOrInsertIdentifier(const char *chars) +{ + unsigned length = std::char_traits<char>::length(chars); + return findOrInsertIdentifier(chars, length); +} + +Control::IdentifierIterator Control::firstIdentifier() const +{ return d->identifiers.begin(); } + +Control::IdentifierIterator Control::lastIdentifier() const +{ return d->identifiers.end(); } + +StringLiteral *Control::findOrInsertStringLiteral(const char *chars, unsigned size) +{ return d->stringLiterals.findOrInsertLiteral(chars, size); } + +StringLiteral *Control::findOrInsertStringLiteral(const char *chars) +{ + unsigned length = std::char_traits<char>::length(chars); + return findOrInsertStringLiteral(chars, length); +} + +NumericLiteral *Control::findOrInsertNumericLiteral(const char *chars, unsigned size) +{ return d->numericLiterals.findOrInsertLiteral(chars, size); } + +NumericLiteral *Control::findOrInsertNumericLiteral(const char *chars) +{ + unsigned length = std::char_traits<char>::length(chars); + return findOrInsertNumericLiteral(chars, length); +} + +unsigned Control::fileNameCount() const +{ return d->fileNames.size(); } + +StringLiteral *Control::fileNameAt(unsigned index) const +{ return d->fileNames.at(index); } + +StringLiteral *Control::findOrInsertFileName(const char *chars, unsigned size) +{ return d->fileNames.findOrInsertLiteral(chars, size); } + +StringLiteral *Control::findOrInsertFileName(const char *chars) +{ + unsigned length = std::char_traits<char>::length(chars); + return findOrInsertFileName(chars, length); +} + +NameId *Control::nameId(Identifier *id) +{ return d->findOrInsertNameId(id); } + +TemplateNameId *Control::templateNameId(Identifier *id, + FullySpecifiedType *const args, + unsigned argv) +{ + std::vector<FullySpecifiedType> templateArguments(args, args + argv); + return d->findOrInsertTemplateNameId(id, templateArguments); +} + +DestructorNameId *Control::destructorNameId(Identifier *id) +{ return d->findOrInsertDestructorNameId(id); } + +OperatorNameId *Control::operatorNameId(int kind) +{ return d->findOrInsertOperatorNameId(kind); } + +ConversionNameId *Control::conversionNameId(FullySpecifiedType type) +{ return d->findOrInsertConversionNameId(type); } + +QualifiedNameId *Control::qualifiedNameId(Name *const *names, + unsigned nameCount, + bool isGlobal) +{ + std::vector<Name *> classOrNamespaceNames(names, names + nameCount); + return d->findOrInsertQualifiedNameId(classOrNamespaceNames, isGlobal); +} + +VoidType *Control::voidType() +{ return &d->voidType; } + +IntegerType *Control::integerType(int kind) +{ return d->findOrInsertIntegerType(kind); } + +FloatType *Control::floatType(int kind) +{ return d->findOrInsertFloatType(kind); } + +PointerToMemberType *Control::pointerToMemberType(Name *memberName, FullySpecifiedType elementType) +{ return d->findOrInsertPointerToMemberType(memberName, elementType); } + +PointerType *Control::pointerType(FullySpecifiedType elementType) +{ return d->findOrInsertPointerType(elementType); } + +ReferenceType *Control::referenceType(FullySpecifiedType elementType) +{ return d->findOrInsertReferenceType(elementType); } + +ArrayType *Control::arrayType(FullySpecifiedType elementType, size_t size) +{ return d->findOrInsertArrayType(elementType, size); } + +NamedType *Control::namedType(Name *name) +{ return d->findOrInsertNamedType(name); } + +Argument *Control::newArgument(unsigned sourceLocation, Name *name) +{ return d->newArgument(sourceLocation, name); } + +Function *Control::newFunction(unsigned sourceLocation, Name *name) +{ return d->newFunction(sourceLocation, name); } + +Namespace *Control::newNamespace(unsigned sourceLocation, Name *name) +{ return d->newNamespace(sourceLocation, name); } + +BaseClass *Control::newBaseClass(unsigned sourceLocation, Name *name) +{ return d->newBaseClass(sourceLocation, name); } + +Class *Control::newClass(unsigned sourceLocation, Name *name) +{ return d->newClass(sourceLocation, name); } + +Enum *Control::newEnum(unsigned sourceLocation, Name *name) +{ return d->newEnum(sourceLocation, name); } + +Block *Control::newBlock(unsigned sourceLocation) +{ return d->newBlock(sourceLocation); } + +Declaration *Control::newDeclaration(unsigned sourceLocation, Name *name) +{ return d->newDeclaration(sourceLocation, name); } + +UsingNamespaceDirective *Control::newUsingNamespaceDirective(unsigned sourceLocation, + Name *name) +{ return d->newUsingNamespaceDirective(sourceLocation, name); } + +UsingDeclaration *Control::newUsingDeclaration(unsigned sourceLocation, Name *name) +{ return d->newUsingDeclaration(sourceLocation, name); } + +CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/Control.h b/src/shared/cplusplus/Control.h new file mode 100644 index 0000000000..98c1bacdd2 --- /dev/null +++ b/src/shared/cplusplus/Control.h @@ -0,0 +1,180 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. + +#ifndef CPLUSPLUS_CONTROL_H +#define CPLUSPLUS_CONTROL_H + +#include "CPlusPlusForwardDeclarations.h" +#include <cstddef> + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +class CPLUSPLUS_EXPORT Control +{ +public: + Control(); + ~Control(); + + TranslationUnit *translationUnit() const; + TranslationUnit *switchTranslationUnit(TranslationUnit *unit); + + DiagnosticClient *diagnosticClient() const; + void setDiagnosticClient(DiagnosticClient *diagnosticClient); + + /// Returns the canonical name id. + NameId *nameId(Identifier *id); + + /// Returns the canonical template name id. + TemplateNameId *templateNameId(Identifier *id, + FullySpecifiedType *const args = 0, + unsigned argc = 0); + + /// Returns the canonical destructor name id. + DestructorNameId *destructorNameId(Identifier *id); + + /// Returns the canonical operator name id. + OperatorNameId *operatorNameId(int operatorId); + + /// Returns the canonical conversion name id. + ConversionNameId *conversionNameId(FullySpecifiedType type); + + /// Returns the canonical qualified name id. + QualifiedNameId *qualifiedNameId(Name *const *names, + unsigned nameCount, + bool isGlobal = false); + + /// Returns a Type object of type VoidType. + VoidType *voidType(); + + /// Returns a Type object of type IntegerType. + IntegerType *integerType(int integerId); + + /// Returns a Type object of type FloatType. + FloatType *floatType(int floatId); + + /// Returns a Type object of type PointertoMemberType. + PointerToMemberType *pointerToMemberType(Name *memberName, + FullySpecifiedType elementType); + + /// Returns a Type object of type PointerType. + PointerType *pointerType(FullySpecifiedType elementType); + + /// Returns a Type object of type ReferenceType. + ReferenceType *referenceType(FullySpecifiedType elementType); + + /// Retruns a Type object of type ArrayType. + ArrayType *arrayType(FullySpecifiedType elementType, size_t size = 0); + + /// Returns a Type object of type NamedType. + NamedType *namedType(Name *name); + + /// Creates a new Declaration symbol. + Declaration *newDeclaration(unsigned sourceLocation, Name *name = 0); + + /// Creates a new Argument symbol. + Argument *newArgument(unsigned sourceLocation, Name *name = 0); + + /// Creates a new Function symbol. + Function *newFunction(unsigned sourceLocation, Name *name = 0); + + /// Creates a new Namespace symbol. + Namespace *newNamespace(unsigned sourceLocation, Name *name = 0); + + /// Creates a new BaseClass symbol. + BaseClass *newBaseClass(unsigned sourceLocation, Name *name = 0); + + /// Creates a new Class symbol. + Class *newClass(unsigned sourceLocation, Name *name = 0); + + /// Creates a new Enum symbol. + Enum *newEnum(unsigned sourceLocation, Name *name = 0); + + /// Creates a new Block symbol. + Block *newBlock(unsigned sourceLocation); + + /// Creates a new UsingNamespaceDirective symbol. + UsingNamespaceDirective *newUsingNamespaceDirective(unsigned sourceLocation, Name *name = 0); + + /// Creates a new UsingDeclaration symbol. + UsingDeclaration *newUsingDeclaration(unsigned sourceLocation, Name *name = 0); + + Identifier *findOrInsertIdentifier(const char *chars, unsigned size); + Identifier *findOrInsertIdentifier(const char *chars); + + typedef const Identifier *const *IdentifierIterator; + + IdentifierIterator firstIdentifier() const; + IdentifierIterator lastIdentifier() const; + + StringLiteral *findOrInsertStringLiteral(const char *chars, unsigned size); + StringLiteral *findOrInsertStringLiteral(const char *chars); + + NumericLiteral *findOrInsertNumericLiteral(const char *chars, unsigned size); + NumericLiteral *findOrInsertNumericLiteral(const char *chars); + + StringLiteral *findOrInsertFileName(const char *chars, unsigned size); + StringLiteral *findOrInsertFileName(const char *chars); + + unsigned fileNameCount() const; + StringLiteral *fileNameAt(unsigned index) const; + +private: + class Data; + friend class Data; + Data *d; +}; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_CONTROL_H diff --git a/src/shared/cplusplus/CoreTypes.cpp b/src/shared/cplusplus/CoreTypes.cpp new file mode 100644 index 0000000000..cf5a3ca4fb --- /dev/null +++ b/src/shared/cplusplus/CoreTypes.cpp @@ -0,0 +1,237 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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 "CoreTypes.h" +#include "TypeVisitor.h" +#include "Names.h" +#include <algorithm> + +CPLUSPLUS_BEGIN_NAMESPACE + + +bool VoidType::isEqualTo(const Type *other) const +{ + const VoidType *o = other->asVoidType(); + return o != 0; +} + +void VoidType::accept0(TypeVisitor *visitor) +{ visitor->visit(this); } + +PointerToMemberType::PointerToMemberType(Name *memberName, FullySpecifiedType elementType) + : _memberName(memberName), + _elementType(elementType) +{ } + +PointerToMemberType::~PointerToMemberType() +{ } + +Name *PointerToMemberType::memberName() const +{ return _memberName; } + +FullySpecifiedType PointerToMemberType::elementType() const +{ return _elementType; } + +bool PointerToMemberType::isEqualTo(const Type *other) const +{ + const PointerToMemberType *o = other->asPointerToMemberType(); + if (! o) + return false; + else if (! _memberName->isEqualTo(o->_memberName)) + return false; + return _elementType.isEqualTo(o->_elementType); +} + +void PointerToMemberType::accept0(TypeVisitor *visitor) +{ visitor->visit(this); } + +PointerType::PointerType(FullySpecifiedType elementType) + : _elementType(elementType) +{ } + +PointerType::~PointerType() +{ } + +bool PointerType::isEqualTo(const Type *other) const +{ + const PointerType *o = other->asPointerType(); + if (! o) + return false; + return _elementType.isEqualTo(o->_elementType); +} + +void PointerType::accept0(TypeVisitor *visitor) +{ visitor->visit(this); } + +FullySpecifiedType PointerType::elementType() const +{ return _elementType; } + +ReferenceType::ReferenceType(FullySpecifiedType elementType) + : _elementType(elementType) +{ } + +ReferenceType::~ReferenceType() +{ } + +bool ReferenceType::isEqualTo(const Type *other) const +{ + const ReferenceType *o = other->asReferenceType(); + if (! o) + return false; + return _elementType.isEqualTo(o->_elementType); +} + +void ReferenceType::accept0(TypeVisitor *visitor) +{ visitor->visit(this); } + +FullySpecifiedType ReferenceType::elementType() const +{ return _elementType; } + +IntegerType::IntegerType(int kind) + : _kind(kind) +{ } + +IntegerType::~IntegerType() +{ } + +bool IntegerType::isEqualTo(const Type *other) const +{ + const IntegerType *o = other->asIntegerType(); + if (! o) + return false; + return _kind == o->_kind; +} + +void IntegerType::accept0(TypeVisitor *visitor) +{ visitor->visit(this); } + +int IntegerType::kind() const +{ return _kind; } + +FloatType::FloatType(int kind) + : _kind(kind) +{ } + +FloatType::~FloatType() +{ } + +void FloatType::accept0(TypeVisitor *visitor) +{ visitor->visit(this); } + +int FloatType::kind() const +{ return _kind; } + +bool FloatType::isEqualTo(const Type *other) const +{ + const FloatType *o = other->asFloatType(); + if (! o) + return false; + return _kind == o->_kind; +} + +ArrayType::ArrayType(FullySpecifiedType elementType, size_t size) + : _elementType(elementType), _size(size) +{ } + +ArrayType::~ArrayType() +{ } + +bool ArrayType::isEqualTo(const Type *other) const +{ + const ArrayType *o = other->asArrayType(); + if (! o) + return false; + else if (_size != o->_size) + return false; + return _elementType.isEqualTo(o->_elementType); +} + +void ArrayType::accept0(TypeVisitor *visitor) +{ visitor->visit(this); } + +FullySpecifiedType ArrayType::elementType() const +{ return _elementType; } + +size_t ArrayType::size() const +{ return _size; } + +NamedType::NamedType(Name *name) + : _name(name) +{ } + +NamedType::~NamedType() +{ } + +Name *NamedType::name() const +{ return _name; } + +bool NamedType::isEqualTo(const Type *other) const +{ + const NamedType *o = other->asNamedType(); + if (! o) + return false; + + Name *name = _name; + if (QualifiedNameId *q = name->asQualifiedNameId()) + name = q->unqualifiedNameId(); + + Name *otherName = o->name(); + if (QualifiedNameId *q = otherName->asQualifiedNameId()) + otherName = q->unqualifiedNameId(); + + return name->isEqualTo(otherName); +} + +void NamedType::accept0(TypeVisitor *visitor) +{ visitor->visit(this); } + +CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/CoreTypes.h b/src/shared/cplusplus/CoreTypes.h new file mode 100644 index 0000000000..c3c0461838 --- /dev/null +++ b/src/shared/cplusplus/CoreTypes.h @@ -0,0 +1,217 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. + +#ifndef CPLUSPLUS_CORETYPES_H +#define CPLUSPLUS_CORETYPES_H + +#include "CPlusPlusForwardDeclarations.h" +#include "Type.h" +#include "FullySpecifiedType.h" +#include <cstddef> + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +class CPLUSPLUS_EXPORT VoidType: public Type +{ +public: + virtual bool isEqualTo(const Type *other) const; + +protected: + virtual void accept0(TypeVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT IntegerType: public Type +{ +public: + enum Kind { + Char, + WideChar, + Bool, + Short, + Int, + Long, + LongLong + }; + +public: + IntegerType(int kind); + virtual ~IntegerType(); + + int kind() const; + + virtual bool isEqualTo(const Type *other) const; + +protected: + virtual void accept0(TypeVisitor *visitor); + +private: + int _kind; +}; + +class CPLUSPLUS_EXPORT FloatType: public Type +{ +public: + enum Kind { + Float, + Double, + LongDouble + }; + +public: + FloatType(int kind); + virtual ~FloatType(); + + int kind() const; + + virtual bool isEqualTo(const Type *other) const; + +protected: + virtual void accept0(TypeVisitor *visitor); + +private: + int _kind; +}; + +class CPLUSPLUS_EXPORT PointerType: public Type +{ +public: + PointerType(FullySpecifiedType elementType); + virtual ~PointerType(); + + FullySpecifiedType elementType() const; + + virtual bool isEqualTo(const Type *other) const; + +protected: + virtual void accept0(TypeVisitor *visitor); + +private: + FullySpecifiedType _elementType; +}; + +class CPLUSPLUS_EXPORT PointerToMemberType: public Type +{ +public: + PointerToMemberType(Name *memberName, FullySpecifiedType elementType); + virtual ~PointerToMemberType(); + + Name *memberName() const; + FullySpecifiedType elementType() const; + + virtual bool isEqualTo(const Type *other) const; + +protected: + virtual void accept0(TypeVisitor *visitor); + +private: + Name *_memberName; + FullySpecifiedType _elementType; +}; + +class CPLUSPLUS_EXPORT ReferenceType: public Type +{ +public: + ReferenceType(FullySpecifiedType elementType); + virtual ~ReferenceType(); + + FullySpecifiedType elementType() const; + + virtual bool isEqualTo(const Type *other) const; + +protected: + virtual void accept0(TypeVisitor *visitor); + +private: + FullySpecifiedType _elementType; +}; + +class CPLUSPLUS_EXPORT ArrayType: public Type +{ +public: + ArrayType(FullySpecifiedType elementType, size_t size); + virtual ~ArrayType(); + + FullySpecifiedType elementType() const; + size_t size() const; + + virtual bool isEqualTo(const Type *other) const; + +protected: + virtual void accept0(TypeVisitor *visitor); + +private: + FullySpecifiedType _elementType; + size_t _size; +}; + +class CPLUSPLUS_EXPORT NamedType: public Type +{ +public: + NamedType(Name *name); + virtual ~NamedType(); + + Name *name() const; + + virtual bool isEqualTo(const Type *other) const; + +protected: + virtual void accept0(TypeVisitor *visitor); + +private: + Name *_name; +}; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_CORETYPES_H diff --git a/src/shared/cplusplus/DiagnosticClient.cpp b/src/shared/cplusplus/DiagnosticClient.cpp new file mode 100644 index 0000000000..12670adef9 --- /dev/null +++ b/src/shared/cplusplus/DiagnosticClient.cpp @@ -0,0 +1,63 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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 "DiagnosticClient.h" + +CPLUSPLUS_BEGIN_NAMESPACE + +DiagnosticClient::DiagnosticClient() +{ } + +DiagnosticClient::~DiagnosticClient() +{ } + +CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/DiagnosticClient.h b/src/shared/cplusplus/DiagnosticClient.h new file mode 100644 index 0000000000..6fa06887c6 --- /dev/null +++ b/src/shared/cplusplus/DiagnosticClient.h @@ -0,0 +1,86 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. + +#ifndef CPLUSPLUS_DIAGNOSTICCLIENT_H +#define CPLUSPLUS_DIAGNOSTICCLIENT_H + +#include "CPlusPlusForwardDeclarations.h" +#include <cstdarg> + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +class CPLUSPLUS_EXPORT DiagnosticClient +{ + DiagnosticClient(const DiagnosticClient &other); + void operator =(const DiagnosticClient &other); + +public: + enum Level { + Warning, + Error, + Fatal + }; + + DiagnosticClient(); + virtual ~DiagnosticClient(); + + virtual void report(int level, + StringLiteral *fileName, + unsigned line, unsigned column, + const char *format, va_list ap) = 0; +}; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_DIAGNOSTICCLIENT_H diff --git a/src/shared/cplusplus/FullySpecifiedType.cpp b/src/shared/cplusplus/FullySpecifiedType.cpp new file mode 100644 index 0000000000..71dec2934b --- /dev/null +++ b/src/shared/cplusplus/FullySpecifiedType.cpp @@ -0,0 +1,204 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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 "FullySpecifiedType.h" +#include "Type.h" + +CPLUSPLUS_BEGIN_NAMESPACE + +FullySpecifiedType::FullySpecifiedType(Type *type) : + _type(type), _flags(0) +{ } + +FullySpecifiedType::~FullySpecifiedType() +{ } + +bool FullySpecifiedType::isValid() const +{ return _type != 0; } + +Type *FullySpecifiedType::type() const +{ return _type; } + +void FullySpecifiedType::setType(Type *type) +{ _type = type; } + +FullySpecifiedType FullySpecifiedType::qualifiedType() const +{ + FullySpecifiedType ty = *this; + ty.setFriend(false); + ty.setRegister(false); + ty.setStatic(false); + ty.setExtern(false); + ty.setMutable(false); + ty.setTypedef(false); + return ty; +} + +bool FullySpecifiedType::isConst() const +{ return _isConst; } + +void FullySpecifiedType::setConst(bool isConst) +{ _isConst = isConst; } + +bool FullySpecifiedType::isVolatile() const +{ return _isVolatile; } + +void FullySpecifiedType::setVolatile(bool isVolatile) +{ _isVolatile = isVolatile; } + +bool FullySpecifiedType::isSigned() const +{ return _isSigned; } + +void FullySpecifiedType::setSigned(bool isSigned) +{ _isSigned = isSigned; } + +bool FullySpecifiedType::isUnsigned() const +{ return _isUnsigned; } + +void FullySpecifiedType::setUnsigned(bool isUnsigned) +{ _isUnsigned = isUnsigned; } + +bool FullySpecifiedType::isFriend() const +{ return _isFriend; } + +void FullySpecifiedType::setFriend(bool isFriend) +{ _isFriend = isFriend; } + +bool FullySpecifiedType::isRegister() const +{ return _isRegister; } + +void FullySpecifiedType::setRegister(bool isRegister) +{ _isRegister = isRegister; } + +bool FullySpecifiedType::isStatic() const +{ return _isStatic; } + +void FullySpecifiedType::setStatic(bool isStatic) +{ _isStatic = isStatic; } + +bool FullySpecifiedType::isExtern() const +{ return _isExtern; } + +void FullySpecifiedType::setExtern(bool isExtern) +{ _isExtern = isExtern; } + +bool FullySpecifiedType::isMutable() const +{ return _isMutable; } + +void FullySpecifiedType::setMutable(bool isMutable) +{ _isMutable = isMutable; } + +bool FullySpecifiedType::isTypedef() const +{ return _isTypedef; } + +void FullySpecifiedType::setTypedef(bool isTypedef) +{ _isTypedef = isTypedef; } + +bool FullySpecifiedType::isInline() const +{ return _isInline; } + +void FullySpecifiedType::setInline(bool isInline) +{ _isInline = isInline; } + +bool FullySpecifiedType::isVirtual() const +{ return _isVirtual; } + +void FullySpecifiedType::setVirtual(bool isVirtual) +{ _isVirtual = isVirtual; } + +bool FullySpecifiedType::isExplicit() const +{ return _isExplicit; } + +void FullySpecifiedType::setExplicit(bool isExplicit) +{ _isExplicit = isExplicit; } + +bool FullySpecifiedType::isEqualTo(const FullySpecifiedType &other) const +{ + if (_flags != other._flags) + return false; + if (_type == other._type) + return true; + else if (! _type) + return false; + else + return _type->isEqualTo(other._type); +} + +Type &FullySpecifiedType::operator*() +{ return *_type; } + +FullySpecifiedType::operator bool() const +{ return _type != 0; } + +const Type &FullySpecifiedType::operator*() const +{ return *_type; } + +Type *FullySpecifiedType::operator->() +{ return _type; } + +const Type *FullySpecifiedType::operator->() const +{ return _type; } + +bool FullySpecifiedType::operator == (const FullySpecifiedType &other) const +{ return _type == other._type && _flags == other._flags; } + +bool FullySpecifiedType::operator != (const FullySpecifiedType &other) const +{ return ! operator ==(other); } + +bool FullySpecifiedType::operator < (const FullySpecifiedType &other) const +{ + if (_type == other._type) + return _flags < other._flags; + return _type < other._type; +} + +CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/FullySpecifiedType.h b/src/shared/cplusplus/FullySpecifiedType.h new file mode 100644 index 0000000000..d156fff5ab --- /dev/null +++ b/src/shared/cplusplus/FullySpecifiedType.h @@ -0,0 +1,158 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. + +#ifndef CPLUSPLUS_FULLYSPECIFIEDTYPE_H +#define CPLUSPLUS_FULLYSPECIFIEDTYPE_H + +#include "CPlusPlusForwardDeclarations.h" + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +class CPLUSPLUS_EXPORT FullySpecifiedType +{ +public: + FullySpecifiedType(Type *type = 0); + ~FullySpecifiedType(); + + bool isValid() const; + operator bool() const; + + Type *type() const; + void setType(Type *type); + + FullySpecifiedType qualifiedType() const; + + bool isConst() const; + void setConst(bool isConst); + + bool isVolatile() const; + void setVolatile(bool isVolatile); + + bool isSigned() const; + void setSigned(bool isSigned); + + bool isUnsigned() const; + void setUnsigned(bool isUnsigned); + + bool isFriend() const; + void setFriend(bool isFriend); + + bool isRegister() const; + void setRegister(bool isRegister); + + bool isStatic() const; + void setStatic(bool isStatic); + + bool isExtern() const; + void setExtern(bool isExtern); + + bool isMutable() const; + void setMutable(bool isMutable); + + bool isTypedef() const; + void setTypedef(bool isTypedef); + + bool isInline() const; + void setInline(bool isInline); + + bool isVirtual() const; + void setVirtual(bool isVirtual); + + bool isExplicit() const; + void setExplicit(bool isExplicit); + + bool isEqualTo(const FullySpecifiedType &other) const; + + Type &operator*(); + const Type &operator*() const; + + Type *operator->(); + const Type *operator->() const; + + bool operator == (const FullySpecifiedType &other) const; + bool operator != (const FullySpecifiedType &other) const; + bool operator < (const FullySpecifiedType &other) const; + +private: + Type *_type; + union { + unsigned _flags; + struct { + // cv qualifiers + unsigned _isConst: 1; + unsigned _isVolatile: 1; + + // sign + unsigned _isSigned: 1; + unsigned _isUnsigned: 1; + + // storage class specifiers + unsigned _isFriend: 1; + unsigned _isRegister: 1; + unsigned _isStatic: 1; + unsigned _isExtern: 1; + unsigned _isMutable: 1; + unsigned _isTypedef: 1; + + // function specifiers + unsigned _isInline: 1; + unsigned _isVirtual: 1; + unsigned _isExplicit: 1; + }; + }; +}; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_FULLYSPECIFIEDTYPE_H diff --git a/src/shared/cplusplus/Keywords.cpp b/src/shared/cplusplus/Keywords.cpp new file mode 100644 index 0000000000..180feb341d --- /dev/null +++ b/src/shared/cplusplus/Keywords.cpp @@ -0,0 +1,1348 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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 "Lexer.h" +#include "Token.h" + +CPLUSPLUS_BEGIN_NAMESPACE + +static inline int classify2(const char *s, bool) { + if (s[0] == 'd') { + if (s[1] == 'o') { + return T_DO; + } + } + else if (s[0] == 'i') { + if (s[1] == 'f') { + return T_IF; + } + } + return T_IDENTIFIER; +} + +static inline int classify3(const char *s, bool) { + if (s[0] == 'a') { + if (s[1] == 's') { + if (s[2] == 'm') { + return T_ASM; + } + } + } + else if (s[0] == 'f') { + if (s[1] == 'o') { + if (s[2] == 'r') { + return T_FOR; + } + } + } + else if (s[0] == 'i') { + if (s[1] == 'n') { + if (s[2] == 't') { + return T_INT; + } + } + } + else if (s[0] == 'n') { + if (s[1] == 'e') { + if (s[2] == 'w') { + return T_NEW; + } + } + } + else if (s[0] == 't') { + if (s[1] == 'r') { + if (s[2] == 'y') { + return T_TRY; + } + } + } + return T_IDENTIFIER; +} + +static inline int classify4(const char *s, bool q) { + if (s[0] == 'a') { + if (s[1] == 'u') { + if (s[2] == 't') { + if (s[3] == 'o') { + return T_AUTO; + } + } + } + } + else if (s[0] == 'b') { + if (s[1] == 'o') { + if (s[2] == 'o') { + if (s[3] == 'l') { + return T_BOOL; + } + } + } + } + else if (s[0] == 'c') { + if (s[1] == 'a') { + if (s[2] == 's') { + if (s[3] == 'e') { + return T_CASE; + } + } + } + else if (s[1] == 'h') { + if (s[2] == 'a') { + if (s[3] == 'r') { + return T_CHAR; + } + } + } + } + else if (s[0] == 'e') { + if (s[1] == 'l') { + if (s[2] == 's') { + if (s[3] == 'e') { + return T_ELSE; + } + } + } + else if (s[1] == 'n') { + if (s[2] == 'u') { + if (s[3] == 'm') { + return T_ENUM; + } + } + } + } + else if (s[0] == 'g') { + if (s[1] == 'o') { + if (s[2] == 't') { + if (s[3] == 'o') { + return T_GOTO; + } + } + } + } + else if (s[0] == 'l') { + if (s[1] == 'o') { + if (s[2] == 'n') { + if (s[3] == 'g') { + return T_LONG; + } + } + } + } + else if (s[0] == 't') { + if (s[1] == 'h') { + if (s[2] == 'i') { + if (s[3] == 's') { + return T_THIS; + } + } + } + else if (s[1] == 'r') { + if (s[2] == 'u') { + if (s[3] == 'e') { + return T_TRUE; + } + } + } + } + else if (s[0] == 'v') { + if (s[1] == 'o') { + if (s[2] == 'i') { + if (s[3] == 'd') { + return T_VOID; + } + } + } + } + else if (q && s[0] == 'S') { + if (s[1] == 'L') { + if (s[2] == 'O') { + if (s[3] == 'T') { + return T_SLOT; + } + } + } + } + return T_IDENTIFIER; +} + +static inline int classify5(const char *s, bool q) { + if (s[0] == '_') { + if (s[1] == '_') { + if (s[2] == 'a') { + if (s[3] == 's') { + if (s[4] == 'm') { + return T___ASM; + } + } + } + } + } + else if (s[0] == 'b') { + if (s[1] == 'r') { + if (s[2] == 'e') { + if (s[3] == 'a') { + if (s[4] == 'k') { + return T_BREAK; + } + } + } + } + } + else if (s[0] == 'c') { + if (s[1] == 'a') { + if (s[2] == 't') { + if (s[3] == 'c') { + if (s[4] == 'h') { + return T_CATCH; + } + } + } + } + else if (s[1] == 'l') { + if (s[2] == 'a') { + if (s[3] == 's') { + if (s[4] == 's') { + return T_CLASS; + } + } + } + } + else if (s[1] == 'o') { + if (s[2] == 'n') { + if (s[3] == 's') { + if (s[4] == 't') { + return T_CONST; + } + } + } + } + } + else if (s[0] == 'f') { + if (s[1] == 'a') { + if (s[2] == 'l') { + if (s[3] == 's') { + if (s[4] == 'e') { + return T_FALSE; + } + } + } + } + else if (s[1] == 'l') { + if (s[2] == 'o') { + if (s[3] == 'a') { + if (s[4] == 't') { + return T_FLOAT; + } + } + } + } + } + else if (s[0] == 's') { + if (s[1] == 'h') { + if (s[2] == 'o') { + if (s[3] == 'r') { + if (s[4] == 't') { + return T_SHORT; + } + } + } + } + else if (q) { + if (s[1] == 'l') { + if (s[2] == 'o') { + if (s[3] == 't') { + if (s[4] == 's') { + return T_SLOTS; + } + } + } + } + } + } + else if (s[0] == 't') { + if (s[1] == 'h') { + if (s[2] == 'r') { + if (s[3] == 'o') { + if (s[4] == 'w') { + return T_THROW; + } + } + } + } + } + else if (s[0] == 'u') { + if (s[1] == 'n') { + if (s[2] == 'i') { + if (s[3] == 'o') { + if (s[4] == 'n') { + return T_UNION; + } + } + } + } + else if (s[1] == 's') { + if (s[2] == 'i') { + if (s[3] == 'n') { + if (s[4] == 'g') { + return T_USING; + } + } + } + } + } + else if (s[0] == 'w') { + if (s[1] == 'h') { + if (s[2] == 'i') { + if (s[3] == 'l') { + if (s[4] == 'e') { + return T_WHILE; + } + } + } + } + } + return T_IDENTIFIER; +} + +static inline int classify6(const char *s, bool q) { + if (s[0] == 'd') { + if (s[1] == 'e') { + if (s[2] == 'l') { + if (s[3] == 'e') { + if (s[4] == 't') { + if (s[5] == 'e') { + return T_DELETE; + } + } + } + } + } + else if (s[1] == 'o') { + if (s[2] == 'u') { + if (s[3] == 'b') { + if (s[4] == 'l') { + if (s[5] == 'e') { + return T_DOUBLE; + } + } + } + } + } + } + else if (s[0] == 'e') { + if (s[1] == 'x') { + if (s[2] == 'p') { + if (s[3] == 'o') { + if (s[4] == 'r') { + if (s[5] == 't') { + return T_EXPORT; + } + } + } + } + else if (s[2] == 't') { + if (s[3] == 'e') { + if (s[4] == 'r') { + if (s[5] == 'n') { + return T_EXTERN; + } + } + } + } + } + } + else if (s[0] == 'f') { + if (s[1] == 'r') { + if (s[2] == 'i') { + if (s[3] == 'e') { + if (s[4] == 'n') { + if (s[5] == 'd') { + return T_FRIEND; + } + } + } + } + } + } + else if (s[0] == 'i') { + if (s[1] == 'n') { + if (s[2] == 'l') { + if (s[3] == 'i') { + if (s[4] == 'n') { + if (s[5] == 'e') { + return T_INLINE; + } + } + } + } + } + } + else if (s[0] == 'p') { + if (s[1] == 'u') { + if (s[2] == 'b') { + if (s[3] == 'l') { + if (s[4] == 'i') { + if (s[5] == 'c') { + return T_PUBLIC; + } + } + } + } + } + } + else if (s[0] == 'r') { + if (s[1] == 'e') { + if (s[2] == 't') { + if (s[3] == 'u') { + if (s[4] == 'r') { + if (s[5] == 'n') { + return T_RETURN; + } + } + } + } + } + } + else if (s[0] == 's') { + if (s[1] == 'i') { + if (s[2] == 'g') { + if (s[3] == 'n') { + if (s[4] == 'e') { + if (s[5] == 'd') { + return T_SIGNED; + } + } + } + } + else if (s[2] == 'z') { + if (s[3] == 'e') { + if (s[4] == 'o') { + if (s[5] == 'f') { + return T_SIZEOF; + } + } + } + } + } + else if (s[1] == 't') { + if (s[2] == 'a') { + if (s[3] == 't') { + if (s[4] == 'i') { + if (s[5] == 'c') { + return T_STATIC; + } + } + } + } + else if (s[2] == 'r') { + if (s[3] == 'u') { + if (s[4] == 'c') { + if (s[5] == 't') { + return T_STRUCT; + } + } + } + } + } + else if (s[1] == 'w') { + if (s[2] == 'i') { + if (s[3] == 't') { + if (s[4] == 'c') { + if (s[5] == 'h') { + return T_SWITCH; + } + } + } + } + } + } + else if (s[0] == 't') { + if (s[1] == 'y') { + if (s[2] == 'p') { + if (s[3] == 'e') { + if (s[4] == 'i') { + if (s[5] == 'd') { + return T_TYPEID; + } + } + else if (s[4] == 'o') { + if (s[5] == 'f') { + return T_TYPEOF; + } + } + } + } + } + } + else if (q && s[0] == 'S') { + if (s[1] == 'I') { + if (s[2] == 'G') { + if (s[3] == 'N') { + if (s[4] == 'A') { + if (s[5] == 'L') { + return T_SIGNAL; + } + } + } + } + } + } + return T_IDENTIFIER; +} + +static inline int classify7(const char *s, bool q) { + if (s[0] == '_') { + if (s[1] == '_') { + if (s[2] == 'a') { + if (s[3] == 's') { + if (s[4] == 'm') { + if (s[5] == '_') { + if (s[6] == '_') { + return T___ASM__; + } + } + } + } + } + else if (s[2] == 'c') { + if (s[3] == 'o') { + if (s[4] == 'n') { + if (s[5] == 's') { + if (s[6] == 't') { + return T___CONST; + } + } + } + } + } + } + } + else if (s[0] == 'd') { + if (s[1] == 'e') { + if (s[2] == 'f') { + if (s[3] == 'a') { + if (s[4] == 'u') { + if (s[5] == 'l') { + if (s[6] == 't') { + return T_DEFAULT; + } + } + } + } + } + } + } + else if (s[0] == 'm') { + if (s[1] == 'u') { + if (s[2] == 't') { + if (s[3] == 'a') { + if (s[4] == 'b') { + if (s[5] == 'l') { + if (s[6] == 'e') { + return T_MUTABLE; + } + } + } + } + } + } + } + else if (s[0] == 'p') { + if (s[1] == 'r') { + if (s[2] == 'i') { + if (s[3] == 'v') { + if (s[4] == 'a') { + if (s[5] == 't') { + if (s[6] == 'e') { + return T_PRIVATE; + } + } + } + } + } + } + } + else if (q && s[0] == 's') { + if (s[1] == 'i') { + if (s[2] == 'g') { + if (s[3] == 'n') { + if (s[4] == 'a') { + if (s[5] == 'l') { + if (s[6] == 's') { + return T_SIGNALS; + } + } + } + } + } + } + } + else if (s[0] == 't') { + if (s[1] == 'y') { + if (s[2] == 'p') { + if (s[3] == 'e') { + if (s[4] == 'd') { + if (s[5] == 'e') { + if (s[6] == 'f') { + return T_TYPEDEF; + } + } + } + } + } + } + } + else if (s[0] == 'v') { + if (s[1] == 'i') { + if (s[2] == 'r') { + if (s[3] == 't') { + if (s[4] == 'u') { + if (s[5] == 'a') { + if (s[6] == 'l') { + return T_VIRTUAL; + } + } + } + } + } + } + } + else if (s[0] == 'w') { + if (s[1] == 'c') { + if (s[2] == 'h') { + if (s[3] == 'a') { + if (s[4] == 'r') { + if (s[5] == '_') { + if (s[6] == 't') { + return T_WCHAR_T; + } + } + } + } + } + } + } + else if (q && s[0] == 'Q') { + if (s[1] == '_') { + if (s[2] == 'S') { + if (s[3] == 'L') { + if (s[4] == 'O') { + if (s[5] == 'T') { + if (s[6] == 'S') { + return T_SLOTS; + } + } + } + } + } + } + } + return T_IDENTIFIER; +} + +static inline int classify8(const char *s, bool) { + if (s[0] == '_') { + if (s[1] == '_') { + if (s[2] == 'i') { + if (s[3] == 'n') { + if (s[4] == 'l') { + if (s[5] == 'i') { + if (s[6] == 'n') { + if (s[7] == 'e') { + return T___INLINE; + } + } + } + } + } + } + else if (s[2] == 't') { + if (s[3] == 'y') { + if (s[4] == 'p') { + if (s[5] == 'e') { + if (s[6] == 'o') { + if (s[7] == 'f') { + return T___TYPEOF; + } + } + } + } + } + } + } + } + else if (s[0] == 'c') { + if (s[1] == 'o') { + if (s[2] == 'n') { + if (s[3] == 't') { + if (s[4] == 'i') { + if (s[5] == 'n') { + if (s[6] == 'u') { + if (s[7] == 'e') { + return T_CONTINUE; + } + } + } + } + } + } + } + } + else if (s[0] == 'e') { + if (s[1] == 'x') { + if (s[2] == 'p') { + if (s[3] == 'l') { + if (s[4] == 'i') { + if (s[5] == 'c') { + if (s[6] == 'i') { + if (s[7] == 't') { + return T_EXPLICIT; + } + } + } + } + } + } + } + } + else if (s[0] == 'o') { + if (s[1] == 'p') { + if (s[2] == 'e') { + if (s[3] == 'r') { + if (s[4] == 'a') { + if (s[5] == 't') { + if (s[6] == 'o') { + if (s[7] == 'r') { + return T_OPERATOR; + } + } + } + } + } + } + } + } + else if (s[0] == 'r') { + if (s[1] == 'e') { + if (s[2] == 'g') { + if (s[3] == 'i') { + if (s[4] == 's') { + if (s[5] == 't') { + if (s[6] == 'e') { + if (s[7] == 'r') { + return T_REGISTER; + } + } + } + } + } + } + } + } + else if (s[0] == 't') { + if (s[1] == 'e') { + if (s[2] == 'm') { + if (s[3] == 'p') { + if (s[4] == 'l') { + if (s[5] == 'a') { + if (s[6] == 't') { + if (s[7] == 'e') { + return T_TEMPLATE; + } + } + } + } + } + } + } + else if (s[1] == 'y') { + if (s[2] == 'p') { + if (s[3] == 'e') { + if (s[4] == 'n') { + if (s[5] == 'a') { + if (s[6] == 'm') { + if (s[7] == 'e') { + return T_TYPENAME; + } + } + } + } + } + } + } + } + else if (s[0] == 'u') { + if (s[1] == 'n') { + if (s[2] == 's') { + if (s[3] == 'i') { + if (s[4] == 'g') { + if (s[5] == 'n') { + if (s[6] == 'e') { + if (s[7] == 'd') { + return T_UNSIGNED; + } + } + } + } + } + } + } + } + else if (s[0] == 'v') { + if (s[1] == 'o') { + if (s[2] == 'l') { + if (s[3] == 'a') { + if (s[4] == 't') { + if (s[5] == 'i') { + if (s[6] == 'l') { + if (s[7] == 'e') { + return T_VOLATILE; + } + } + } + } + } + } + } + } + return T_IDENTIFIER; +} + +static inline int classify9(const char *s, bool q) { + if (s[0] == '_') { + if (s[1] == '_') { + if (s[2] == 'c') { + if (s[3] == 'o') { + if (s[4] == 'n') { + if (s[5] == 's') { + if (s[6] == 't') { + if (s[7] == '_') { + if (s[8] == '_') { + return T___CONST__; + } + } + } + } + } + } + } + } + } + else if (s[0] == 'n') { + if (s[1] == 'a') { + if (s[2] == 'm') { + if (s[3] == 'e') { + if (s[4] == 's') { + if (s[5] == 'p') { + if (s[6] == 'a') { + if (s[7] == 'c') { + if (s[8] == 'e') { + return T_NAMESPACE; + } + } + } + } + } + } + } + } + } + else if (s[0] == 'p') { + if (s[1] == 'r') { + if (s[2] == 'o') { + if (s[3] == 't') { + if (s[4] == 'e') { + if (s[5] == 'c') { + if (s[6] == 't') { + if (s[7] == 'e') { + if (s[8] == 'd') { + return T_PROTECTED; + } + } + } + } + } + } + } + } + } + else if (q && s[0] == 'Q') { + if (s[1] == '_') { + if (s[2] == 'S') { + if (s[3] == 'I') { + if (s[4] == 'G') { + if (s[5] == 'N') { + if (s[6] == 'A') { + if (s[7] == 'L') { + if (s[8] == 'S') { + return T_SIGNALS; + } + } + } + } + } + } + } + } + } + return T_IDENTIFIER; +} + +static inline int classify10(const char *s, bool) { + if (s[0] == '_') { + if (s[1] == '_') { + if (s[2] == 'i') { + if (s[3] == 'n') { + if (s[4] == 'l') { + if (s[5] == 'i') { + if (s[6] == 'n') { + if (s[7] == 'e') { + if (s[8] == '_') { + if (s[9] == '_') { + return T___INLINE__; + } + } + } + } + } + } + } + } + else if (s[2] == 't') { + if (s[3] == 'y') { + if (s[4] == 'p') { + if (s[5] == 'e') { + if (s[6] == 'o') { + if (s[7] == 'f') { + if (s[8] == '_') { + if (s[9] == '_') { + return T___TYPEOF__; + } + } + } + } + } + } + } + } + else if (s[2] == 'v') { + if (s[3] == 'o') { + if (s[4] == 'l') { + if (s[5] == 'a') { + if (s[6] == 't') { + if (s[7] == 'i') { + if (s[8] == 'l') { + if (s[9] == 'e') { + return T___VOLATILE; + } + } + } + } + } + } + } + } + } + } + else if (s[0] == 'c') { + if (s[1] == 'o') { + if (s[2] == 'n') { + if (s[3] == 's') { + if (s[4] == 't') { + if (s[5] == '_') { + if (s[6] == 'c') { + if (s[7] == 'a') { + if (s[8] == 's') { + if (s[9] == 't') { + return T_CONST_CAST; + } + } + } + } + } + } + } + } + } + } + return T_IDENTIFIER; +} + +static inline int classify11(const char *s, bool) { + if (s[0] == '_') { + if (s[1] == '_') { + if (s[2] == 'a') { + if (s[3] == 't') { + if (s[4] == 't') { + if (s[5] == 'r') { + if (s[6] == 'i') { + if (s[7] == 'b') { + if (s[8] == 'u') { + if (s[9] == 't') { + if (s[10] == 'e') { + return T___ATTRIBUTE; + } + } + } + } + } + } + } + } + } + } + } + else if (s[0] == 's') { + if (s[1] == 't') { + if (s[2] == 'a') { + if (s[3] == 't') { + if (s[4] == 'i') { + if (s[5] == 'c') { + if (s[6] == '_') { + if (s[7] == 'c') { + if (s[8] == 'a') { + if (s[9] == 's') { + if (s[10] == 't') { + return T_STATIC_CAST; + } + } + } + } + } + } + } + } + } + } + } + return T_IDENTIFIER; +} + +static inline int classify12(const char *s, bool) { + if (s[0] == '_') { + if (s[1] == '_') { + if (s[2] == 'v') { + if (s[3] == 'o') { + if (s[4] == 'l') { + if (s[5] == 'a') { + if (s[6] == 't') { + if (s[7] == 'i') { + if (s[8] == 'l') { + if (s[9] == 'e') { + if (s[10] == '_') { + if (s[11] == '_') { + return T___VOLATILE__; + } + } + } + } + } + } + } + } + } + } + } + } + else if (s[0] == 'd') { + if (s[1] == 'y') { + if (s[2] == 'n') { + if (s[3] == 'a') { + if (s[4] == 'm') { + if (s[5] == 'i') { + if (s[6] == 'c') { + if (s[7] == '_') { + if (s[8] == 'c') { + if (s[9] == 'a') { + if (s[10] == 's') { + if (s[11] == 't') { + return T_DYNAMIC_CAST; + } + } + } + } + } + } + } + } + } + } + } + } + return T_IDENTIFIER; +} + +static inline int classify13(const char *s, bool) { + if (s[0] == '_') { + if (s[1] == '_') { + if (s[2] == 'a') { + if (s[3] == 't') { + if (s[4] == 't') { + if (s[5] == 'r') { + if (s[6] == 'i') { + if (s[7] == 'b') { + if (s[8] == 'u') { + if (s[9] == 't') { + if (s[10] == 'e') { + if (s[11] == '_') { + if (s[12] == '_') { + return T___ATTRIBUTE__; + } + } + } + } + } + } + } + } + } + } + } + } + } + return T_IDENTIFIER; +} + +static inline int classify16(const char *s, bool) { + if (s[0] == 'r') { + if (s[1] == 'e') { + if (s[2] == 'i') { + if (s[3] == 'n') { + if (s[4] == 't') { + if (s[5] == 'e') { + if (s[6] == 'r') { + if (s[7] == 'p') { + if (s[8] == 'r') { + if (s[9] == 'e') { + if (s[10] == 't') { + if (s[11] == '_') { + if (s[12] == 'c') { + if (s[13] == 'a') { + if (s[14] == 's') { + if (s[15] == 't') { + return T_REINTERPRET_CAST; + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + return T_IDENTIFIER; +} + +int Lexer::classify(const char *s, int n, bool q) { + switch (n) { + case 2: return classify2(s, q); + case 3: return classify3(s, q); + case 4: return classify4(s, q); + case 5: return classify5(s, q); + case 6: return classify6(s, q); + case 7: return classify7(s, q); + case 8: return classify8(s, q); + case 9: return classify9(s, q); + case 10: return classify10(s, q); + case 11: return classify11(s, q); + case 12: return classify12(s, q); + case 13: return classify13(s, q); + case 16: return classify16(s, q); + default: return T_IDENTIFIER; + } // switch +} + +static inline int classifyOperator2(const char *s) { + if (s[0] == 'o') { + if (s[1] == 'r') { + return T_OR; + } + } + return T_IDENTIFIER; +} + +static inline int classifyOperator3(const char *s) { + if (s[0] == 'a') { + if (s[1] == 'n') { + if (s[2] == 'd') { + return T_AND; + } + } + } + else if (s[0] == 'n') { + if (s[1] == 'o') { + if (s[2] == 't') { + return T_NOT; + } + } + } + else if (s[0] == 'x') { + if (s[1] == 'o') { + if (s[2] == 'r') { + return T_XOR; + } + } + } + return T_IDENTIFIER; +} + +static inline int classifyOperator5(const char *s) { + if (s[0] == 'b') { + if (s[1] == 'i') { + if (s[2] == 't') { + if (s[3] == 'o') { + if (s[4] == 'r') { + return T_BITOR; + } + } + } + } + } + else if (s[0] == 'c') { + if (s[1] == 'o') { + if (s[2] == 'm') { + if (s[3] == 'p') { + if (s[4] == 'l') { + return T_COMPL; + } + } + } + } + } + else if (s[0] == 'o') { + if (s[1] == 'r') { + if (s[2] == '_') { + if (s[3] == 'e') { + if (s[4] == 'q') { + return T_OR_EQ; + } + } + } + } + } + return T_IDENTIFIER; +} + +static inline int classifyOperator6(const char *s) { + if (s[0] == 'a') { + if (s[1] == 'n') { + if (s[2] == 'd') { + if (s[3] == '_') { + if (s[4] == 'e') { + if (s[5] == 'q') { + return T_AND_EQ; + } + } + } + } + } + } + else if (s[0] == 'b') { + if (s[1] == 'i') { + if (s[2] == 't') { + if (s[3] == 'a') { + if (s[4] == 'n') { + if (s[5] == 'd') { + return T_BITAND; + } + } + } + } + } + } + else if (s[0] == 'n') { + if (s[1] == 'o') { + if (s[2] == 't') { + if (s[3] == '_') { + if (s[4] == 'e') { + if (s[5] == 'q') { + return T_NOT_EQ; + } + } + } + } + } + } + else if (s[0] == 'x') { + if (s[1] == 'o') { + if (s[2] == 'r') { + if (s[3] == '_') { + if (s[4] == 'e') { + if (s[5] == 'q') { + return T_XOR_EQ; + } + } + } + } + } + } + return T_IDENTIFIER; +} + +int Lexer::classifyOperator(const char *s, int n) { + switch (n) { + case 2: return classifyOperator2(s); + case 3: return classifyOperator3(s); + case 5: return classifyOperator5(s); + case 6: return classifyOperator6(s); + default: return T_IDENTIFIER; + } // switch +} + +CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/Keywords.kwgen b/src/shared/cplusplus/Keywords.kwgen new file mode 100644 index 0000000000..f23b3b7cea --- /dev/null +++ b/src/shared/cplusplus/Keywords.kwgen @@ -0,0 +1,86 @@ + +#include "Lexer.h" +#include "Token.h" + +%token-prefix=T_ +%toupper +%no-enums +%namespace=Lexer + +%% +__asm +__asm__ +__attribute +__attribute__ +__const +__const__ +__inline +__inline__ +__typeof +__typeof__ +__volatile +__volatile__ +asm +auto +bool +break +case +catch +char +class +const +const_cast +continue +default +delete +do +double +dynamic_cast +else +enum +explicit +export +extern +false +float +for +friend +goto +if +inline +int +long +mutable +namespace +new +operator +private +protected +public +register +reinterpret_cast +return +short +signed +sizeof +static +static_cast +struct +switch +template +this +throw +true +try +typedef +typeid +typename +typeof +union +unsigned +using +virtual +void +volatile +wchar_t +while diff --git a/src/shared/cplusplus/Lexer.cpp b/src/shared/cplusplus/Lexer.cpp new file mode 100644 index 0000000000..73c12524d7 --- /dev/null +++ b/src/shared/cplusplus/Lexer.cpp @@ -0,0 +1,680 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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 "Lexer.h" +#include "Control.h" +#include "TranslationUnit.h" +#include <cctype> +#include <cassert> + +CPLUSPLUS_BEGIN_NAMESPACE + +Lexer::Lexer(TranslationUnit *unit) + : _translationUnit(unit), + _state(Lexer::DefaultState), + _flags(0), + _currentLine(1) +{ + _scanKeywords = true; + setSource(_translationUnit->firstSourceChar(), + _translationUnit->lastSourceChar()); +} + +Lexer::Lexer(const char *firstChar, const char *lastChar) + : _translationUnit(0), + _state(Lexer::DefaultState), + _flags(0), + _currentLine(1) +{ + _scanKeywords = true; + setSource(firstChar, lastChar); +} + +Lexer::~Lexer() +{ } + +TranslationUnit *Lexer::translationUnit() const +{ return _translationUnit; } + +Control *Lexer::control() const +{ + if (_translationUnit) + return _translationUnit->control(); + + return 0; +} + +void Lexer::setSource(const char *firstChar, const char *lastChar) +{ + _firstChar = firstChar; + _lastChar = lastChar; + _currentChar = _firstChar - 1; + _tokenStart = _currentChar; + _yychar = '\n'; +} + +void Lexer::setStartWithNewline(bool enabled) +{ + if (enabled) + _yychar = '\n'; + else + _yychar = ' '; +} + +int Lexer::state() const +{ return _state; } + +void Lexer::setState(int state) +{ _state = state; } + +bool Lexer::qtMocRunEnabled() const +{ return _qtMocRunEnabled; } + +void Lexer::setQtMocRunEnabled(bool onoff) +{ _qtMocRunEnabled = onoff; } + +bool Lexer::objCEnabled() const +{ return _objCEnabled; } + +void Lexer::setObjCEnabled(bool onoff) +{ _objCEnabled = onoff; } + +bool Lexer::isIncremental() const +{ return _isIncremental; } + +void Lexer::setIncremental(bool isIncremental) +{ _isIncremental = isIncremental; } + +bool Lexer::scanCommentTokens() const +{ return _scanCommentTokens; } + +void Lexer::setScanCommentTokens(bool onoff) +{ _scanCommentTokens = onoff; } + +bool Lexer::scanKeywords() const +{ return _scanKeywords; } + +void Lexer::setScanKeywords(bool onoff) +{ _scanKeywords = onoff; } + +void Lexer::setScanAngleStringLiteralTokens(bool onoff) +{ _scanAngleStringLiteralTokens = onoff; } + +void Lexer::pushLineStartOffset() +{ + ++_currentLine; + + if (_translationUnit) + _translationUnit->pushLineOffset(_currentChar - _firstChar); +} + +unsigned Lexer::tokenOffset() const +{ return _tokenStart - _firstChar; } + +unsigned Lexer::tokenLength() const +{ return _currentChar - _tokenStart; } + +const char *Lexer::tokenBegin() const +{ return _tokenStart; } + +const char *Lexer::tokenEnd() const +{ return _currentChar; } + +unsigned Lexer::currentLine() const +{ return _currentLine; } + +void Lexer::scan(Token *tok) +{ + tok->reset(); + scan_helper(tok); + tok->length = _currentChar - _tokenStart; +} + +void Lexer::scan_helper(Token *tok) +{ + _Lagain: + while (_yychar && std::isspace(_yychar)) { + if (_yychar == '\n') + tok->newline = true; + else + tok->whitespace = true; + yyinp(); + } + + if (! _translationUnit) + tok->lineno = _currentLine; + + _tokenStart = _currentChar; + tok->offset = _currentChar - _firstChar; + + if (_state == MultiLineCommentState) { + if (! _yychar) { + tok->kind = T_EOF_SYMBOL; + return; + } + + while (_yychar) { + if (_yychar != '*') + yyinp(); + else { + yyinp(); + if (_yychar == '/') { + yyinp(); + _state = DefaultState; + break; + } + } + } + + if (! _scanCommentTokens) + goto _Lagain; + + tok->kind = T_COMMENT; + return; // done + } + + if (! _yychar) { + tok->kind = T_EOF_SYMBOL; + return; + } + + unsigned char ch = _yychar; + yyinp(); + + switch (ch) { + case '\\': + while (_yychar != '\n' && std::isspace(_yychar)) + yyinp(); + // ### assert(! _yychar || _yychar == '\n'); + if (_yychar == '\n') { + tok->joined = true; + tok->newline = false; + yyinp(); + } + goto _Lagain; + + case '"': case '\'': { + const char quote = ch; + + tok->kind = quote == '"' + ? T_STRING_LITERAL + : T_CHAR_LITERAL; + + const char *yytext = _currentChar; + + while (_yychar && _yychar != quote) { + if (_yychar != '\\') + yyinp(); + else { + yyinp(); // skip `\\' + + if (_yychar) + yyinp(); + } + } + // assert(_yychar == quote); + + int yylen = _currentChar - yytext; + + if (_yychar == quote) + yyinp(); + + if (control()) + tok->string = control()->findOrInsertStringLiteral(yytext, yylen); + } break; + + case '{': + tok->kind = T_LBRACE; + break; + + case '}': + tok->kind = T_RBRACE; + break; + + case '[': + tok->kind = T_LBRACKET; + break; + + case ']': + tok->kind = T_RBRACKET; + break; + + case '#': + if (_yychar == '#') { + tok->kind = T_POUND_POUND; + yyinp(); + } else { + tok->kind = T_POUND; + } + break; + + case '(': + tok->kind = T_LPAREN; + break; + + case ')': + tok->kind = T_RPAREN; + break; + + case ';': + tok->kind = T_SEMICOLON; + break; + + case ':': + if (_yychar == ':') { + yyinp(); + tok->kind = T_COLON_COLON; + } else { + tok->kind = T_COLON; + } + break; + + case '.': + if (_yychar == '*') { + yyinp(); + tok->kind = T_DOT_STAR; + } else if (_yychar == '.') { + yyinp(); + // ### assert(_yychar); + if (_yychar == '.') { + yyinp(); + tok->kind = T_DOT_DOT_DOT; + } else { + tok->kind = T_ERROR; + } + } else if (std::isdigit(_yychar)) { + const char *yytext = _currentChar - 2; + do { + if (_yychar == 'e' || _yychar == 'E') { + yyinp(); + if (_yychar == '-' || _yychar == '+') { + yyinp(); + // ### assert(std::isdigit(_yychar)); + } + } else if (std::isalnum(_yychar) || _yychar == '.') { + yyinp(); + } else { + break; + } + } while (_yychar); + int yylen = _currentChar - yytext; + tok->kind = T_INT_LITERAL; + if (control()) + tok->number = control()->findOrInsertNumericLiteral(yytext, yylen); + } else { + tok->kind = T_DOT; + } + break; + + case '?': + tok->kind = T_QUESTION; + break; + + case '+': + if (_yychar == '+') { + yyinp(); + tok->kind = T_PLUS_PLUS; + } else if (_yychar == '=') { + yyinp(); + tok->kind = T_PLUS_EQUAL; + } else { + tok->kind = T_PLUS; + } + break; + + case '-': + if (_yychar == '-') { + yyinp(); + tok->kind = T_MINUS_MINUS; + } else if (_yychar == '=') { + yyinp(); + tok->kind = T_MINUS_EQUAL; + } else if (_yychar == '>') { + yyinp(); + if (_yychar == '*') { + yyinp(); + tok->kind = T_ARROW_STAR; + } else { + tok->kind = T_ARROW; + } + } else { + tok->kind = T_MINUS; + } + break; + + case '*': + if (_yychar == '=') { + yyinp(); + tok->kind = T_STAR_EQUAL; + } else { + tok->kind = T_STAR; + } + break; + + case '/': + if (_yychar == '/') { + do { + yyinp(); + } while (_yychar && _yychar != '\n'); + if (! _scanCommentTokens) + goto _Lagain; + tok->kind = T_COMMENT; + } else if (_yychar == '*') { + yyinp(); + while (_yychar) { + if (_yychar != '*') { + yyinp(); + } else { + yyinp(); + if (_yychar == '/') + break; + } + } + + if (_yychar) + yyinp(); + else + _state = MultiLineCommentState; + + if (! _scanCommentTokens) + goto _Lagain; + tok->kind = T_COMMENT; + } else if (_yychar == '=') { + yyinp(); + tok->kind = T_SLASH_EQUAL; + } else { + tok->kind = T_SLASH; + } + break; + + case '%': + if (_yychar == '=') { + yyinp(); + tok->kind = T_PERCENT_EQUAL; + } else { + tok->kind = T_PERCENT; + } + break; + + case '^': + if (_yychar == '=') { + yyinp(); + tok->kind = T_CARET_EQUAL; + } else { + tok->kind = T_CARET; + } + break; + + case '&': + if (_yychar == '&') { + yyinp(); + tok->kind = T_AMPER_AMPER; + } else if (_yychar == '=') { + yyinp(); + tok->kind = T_AMPER_EQUAL; + } else { + tok->kind = T_AMPER; + } + break; + + case '|': + if (_yychar == '|') { + yyinp(); + tok->kind = T_PIPE_PIPE; + } else if (_yychar == '=') { + yyinp(); + tok->kind = T_PIPE_EQUAL; + } else { + tok->kind = T_PIPE; + } + break; + + case '~': + if (_yychar == '=') { + yyinp(); + tok->kind = T_TILDE_EQUAL; + } else { + tok->kind = T_TILDE; + } + break; + + case '!': + if (_yychar == '=') { + yyinp(); + tok->kind = T_EXCLAIM_EQUAL; + } else { + tok->kind = T_EXCLAIM; + } + break; + + case '=': + if (_yychar == '=') { + yyinp(); + tok->kind = T_EQUAL_EQUAL; + } else { + tok->kind = T_EQUAL; + } + break; + + case '<': + if (_scanAngleStringLiteralTokens) { + const char *yytext = _currentChar; + while (_yychar && _yychar != '>') + yyinp(); + int yylen = _currentChar - yytext; + // ### assert(_yychar == '>'); + if (_yychar == '>') + yyinp(); + if (control()) + tok->string = control()->findOrInsertStringLiteral(yytext, yylen); + tok->kind = T_ANGLE_STRING_LITERAL; + } else if (_yychar == '<') { + yyinp(); + if (_yychar == '=') { + yyinp(); + tok->kind = T_LESS_LESS_EQUAL; + } else + tok->kind = T_LESS_LESS; + } else if (_yychar == '=') { + yyinp(); + tok->kind = T_LESS_EQUAL; + } else { + tok->kind = T_LESS; + } + break; + + case '>': + if (_yychar == '>') { + yyinp(); + if (_yychar == '=') { + yyinp(); + tok->kind = T_GREATER_GREATER_EQUAL; + } else + tok->kind = T_LESS_LESS; + tok->kind = T_GREATER_GREATER; + } else if (_yychar == '=') { + yyinp(); + tok->kind = T_GREATER_EQUAL; + } else { + tok->kind = T_GREATER; + } + break; + + case ',': + tok->kind = T_COMMA; + break; + + default: { + if (_objCEnabled) { + if (ch == '@' && _yychar >= 'a' && _yychar <= 'z') { + const char *yytext = _currentChar; + + do { + yyinp(); + if (! isalnum(_yychar)) + break; + } while (_yychar); + + const int yylen = _currentChar - yytext; + tok->kind = classifyObjCAtKeyword(yytext, yylen); + break; + } else if (ch == '@' && _yychar == '"') { + // objc @string literals + ch = _yychar; + yyinp(); + tok->kind = T_AT_STRING_LITERAL; + + const char *yytext = _currentChar; + + while (_yychar && _yychar != '"') { + if (_yychar != '\\') + yyinp(); + else { + yyinp(); // skip `\\' + + if (_yychar) + yyinp(); + } + } + // assert(_yychar == '"'); + + int yylen = _currentChar - yytext; + + if (_yychar == '"') + yyinp(); + + if (control()) + tok->string = control()->findOrInsertStringLiteral(yytext, yylen); + + break; + } + } + + if (ch == 'L' && (_yychar == '"' || _yychar == '\'')) { + // wide char/string literals + ch = _yychar; + yyinp(); + + const char quote = ch; + + tok->kind = quote == '"' + ? T_WIDE_STRING_LITERAL + : T_WIDE_CHAR_LITERAL; + + const char *yytext = _currentChar; + + while (_yychar && _yychar != quote) { + if (_yychar != '\\') + yyinp(); + else { + yyinp(); // skip `\\' + + if (_yychar) + yyinp(); + } + } + // assert(_yychar == quote); + + int yylen = _currentChar - yytext; + + if (_yychar == quote) + yyinp(); + + if (control()) + tok->string = control()->findOrInsertStringLiteral(yytext, yylen); + } else if (std::isalpha(ch) || ch == '_') { + const char *yytext = _currentChar - 1; + while (std::isalnum(_yychar) || _yychar == '_') + yyinp(); + int yylen = _currentChar - yytext; + if (_scanKeywords) + tok->kind = classify(yytext, yylen, _qtMocRunEnabled); + else + tok->kind = T_IDENTIFIER; + + if (tok->kind == T_IDENTIFIER) { + tok->kind = classifyOperator(yytext, yylen); + + if (control()) + tok->identifier = control()->findOrInsertIdentifier(yytext, yylen); + } + break; + } else if (std::isdigit(ch)) { + const char *yytext = _currentChar - 1; + while (_yychar) { + if (_yychar == 'e' || _yychar == 'E') { + yyinp(); + if (_yychar == '-' || _yychar == '+') { + yyinp(); + // ### assert(std::isdigit(_yychar)); + } + } else if (std::isalnum(_yychar) || _yychar == '.') { + yyinp(); + } else { + break; + } + } + int yylen = _currentChar - yytext; + tok->kind = T_INT_LITERAL; + if (control()) + tok->number = control()->findOrInsertNumericLiteral(yytext, yylen); + break; + } else { + tok->kind = T_ERROR; + break; + } + } // default + + } // switch +} + +CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/Lexer.h b/src/shared/cplusplus/Lexer.h new file mode 100644 index 0000000000..4cb62493db --- /dev/null +++ b/src/shared/cplusplus/Lexer.h @@ -0,0 +1,159 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. + +#ifndef CPLUSPLUS_LEXER_H +#define CPLUSPLUS_LEXER_H + +#include "CPlusPlusForwardDeclarations.h" +#include "Token.h" + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +class CPLUSPLUS_EXPORT Lexer +{ + Lexer(const Lexer &other); + void operator =(const Lexer &other); + +public: + enum State { + DefaultState, + MultiLineCommentState + }; + + Lexer(TranslationUnit *unit); + Lexer(const char *firstChar, const char *lastChar); + ~Lexer(); + + Control *control() const; + TranslationUnit *translationUnit() const; + + bool qtMocRunEnabled() const; + void setQtMocRunEnabled(bool onoff); + + bool objCEnabled() const; + void setObjCEnabled(bool onoff); + + void scan(Token *tok); + + inline void operator()(Token *tok) + { scan(tok); } + + unsigned tokenOffset() const; + unsigned tokenLength() const; + const char *tokenBegin() const; + const char *tokenEnd() const; + unsigned currentLine() const; + + bool scanCommentTokens() const; + void setScanCommentTokens(bool onoff); + + bool scanKeywords() const; + void setScanKeywords(bool onoff); + + bool scanAngleStringLiteralTokens() const; + void setScanAngleStringLiteralTokens(bool onoff); + + void setStartWithNewline(bool enabled); + + int state() const; + void setState(int state); + + bool isIncremental() const; + void setIncremental(bool isIncremental); + +private: + void scan_helper(Token *tok); + void setSource(const char *firstChar, const char *lastChar); + static int classify(const char *string, int length, bool q); + static int classifyObjCAtKeyword(const char *s, int n); + static int classifyOperator(const char *string, int length); + + inline void yyinp() + { + if (++_currentChar == _lastChar) + _yychar = 0; + else { + _yychar = *_currentChar; + if (_yychar == '\n') + pushLineStartOffset(); + } + } + + void pushLineStartOffset(); + +private: + TranslationUnit *_translationUnit; + const char *_firstChar; + const char *_currentChar; + const char *_lastChar; + const char *_tokenStart; + unsigned char _yychar; + int _state; + union { + unsigned _flags; + struct { + unsigned _isIncremental: 1; + unsigned _scanCommentTokens: 1; + unsigned _scanKeywords: 1; + unsigned _scanAngleStringLiteralTokens: 1; + unsigned _qtMocRunEnabled: 1; + unsigned _objCEnabled: 1; + }; + }; + unsigned _currentLine; +}; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_LEXER_H diff --git a/src/shared/cplusplus/LiteralTable.cpp b/src/shared/cplusplus/LiteralTable.cpp new file mode 100644 index 0000000000..21e3b2d8dd --- /dev/null +++ b/src/shared/cplusplus/LiteralTable.cpp @@ -0,0 +1,34 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. +** +***************************************************************************/ + +#include "LiteralTable.h" diff --git a/src/shared/cplusplus/LiteralTable.h b/src/shared/cplusplus/LiteralTable.h new file mode 100644 index 0000000000..35744fe360 --- /dev/null +++ b/src/shared/cplusplus/LiteralTable.h @@ -0,0 +1,181 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. + +#ifndef CPLUSPLUS_LITERALTABLE_H +#define CPLUSPLUS_LITERALTABLE_H + +#include "CPlusPlusForwardDeclarations.h" +#include <cstring> +#include <cstdlib> + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +template <typename _Literal> +class LiteralTable +{ + LiteralTable(const LiteralTable &other); + void operator =(const LiteralTable &other); + +public: + typedef _Literal **iterator; + +public: + LiteralTable() + : _literals(0), + _allocatedLiterals(0), + _literalCount(-1), + _buckets(0), + _allocatedBuckets(0) + { } + + ~LiteralTable() + { + if (_literals) { + _Literal **lastLiteral = _literals + _literalCount + 1; + for (_Literal **it = _literals; it != lastLiteral; ++it) + delete *it; + free(_literals); + } + if (_buckets) + free(_buckets); + } + + bool empty() const + { return _literalCount == -1; } + + unsigned size() const + { return _literalCount + 1; } + + _Literal *at(unsigned index) const + { return _literals[index]; } + + iterator begin() const + { return _literals; } + + iterator end() const + { return _literals + _literalCount + 1; } + + _Literal *findOrInsertLiteral(const char *chars, unsigned size) + { + if (_buckets) { + unsigned h = _Literal::hashCode(chars, size); + _Literal *literal = _buckets[h % _allocatedBuckets]; + for (; literal; literal = static_cast<_Literal *>(literal->_next)) { + if (literal->size() == size && ! strncmp(literal->chars(), chars, size)) + return literal; + } + } + + _Literal *literal = new _Literal(chars, size); + + if (++_literalCount == _allocatedLiterals) { + _allocatedLiterals <<= 1; + + if (! _allocatedLiterals) + _allocatedLiterals = 256; + + _literals = (_Literal **) realloc(_literals, sizeof(_Literal *) * _allocatedLiterals); + } + + _literals[_literalCount] = literal; + + if (! _buckets || _literalCount >= _allocatedBuckets * .6) + rehash(); + else { + unsigned h = literal->hashCode() % _allocatedBuckets; + literal->_next = _buckets[h]; + _buckets[h] = literal; + } + + return literal; + } + +protected: + void rehash() + { + if (_buckets) + free(_buckets); + + _allocatedBuckets <<= 1; + + if (! _allocatedBuckets) + _allocatedBuckets = 256; + + _buckets = (_Literal **) calloc(_allocatedBuckets, sizeof(_Literal *)); + + _Literal **lastLiteral = _literals + (_literalCount + 1); + + for (_Literal **it = _literals; it != lastLiteral; ++it) { + _Literal *literal = *it; + unsigned h = literal->hashCode() % _allocatedBuckets; + + literal->_next = _buckets[h]; + _buckets[h] = literal; + } + } + +protected: + MemoryPool *_pool; + + _Literal **_literals; + int _allocatedLiterals; + int _literalCount; + + _Literal **_buckets; + int _allocatedBuckets; +}; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_LITERALTABLE_H diff --git a/src/shared/cplusplus/Literals.cpp b/src/shared/cplusplus/Literals.cpp new file mode 100644 index 0000000000..f7ac69f568 --- /dev/null +++ b/src/shared/cplusplus/Literals.cpp @@ -0,0 +1,138 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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 "Literals.h" +#include <cstring> +#include <algorithm> +#include <iostream> + +CPLUSPLUS_BEGIN_NAMESPACE + +//////////////////////////////////////////////////////////////////////////////// +Literal::Literal(const char *chars, unsigned size) + : _index(0), _next(0) +{ + _chars = new char[size + 1]; + + strncpy(_chars, chars, size); + _chars[size] = '\0'; + + _size = size; + + _hashCode = hashCode(_chars, _size); +} + +Literal::~Literal() +{ delete[] _chars; } + +Literal::iterator Literal::begin() const +{ return _chars; } + +Literal::iterator Literal::end() const +{ return _chars + _size; } + +const char *Literal::chars() const +{ return _chars; } + +char Literal::at(unsigned index) const +{ return _chars[index]; } + +unsigned Literal::size() const +{ return _size; } + +unsigned Literal::hashCode() const +{ return _hashCode; } + +unsigned Literal::hashCode(const char *chars, unsigned size) +{ + unsigned h = 0; + for (unsigned i = 0; i < size; ++i) + h = (h >> 5) - h + chars[i]; + return h; +} + +//////////////////////////////////////////////////////////////////////////////// +StringLiteral::StringLiteral(const char *chars, unsigned size) + : Literal(chars, size) +{ } + +StringLiteral::~StringLiteral() +{ } + +//////////////////////////////////////////////////////////////////////////////// +NumericLiteral::NumericLiteral(const char *chars, unsigned size) + : Literal(chars, size) +{ } + +NumericLiteral::~NumericLiteral() +{ } + +//////////////////////////////////////////////////////////////////////////////// +Identifier::Identifier(const char *chars, unsigned size) + : Literal(chars, size) +{ } + +Identifier::~Identifier() +{ } + +bool Identifier::isEqualTo(const Identifier *other) const +{ + if (this == other) + return true; + else if (hashCode() != other->hashCode()) + return false; + else if (size() != other->size()) + return false; + return ! strcmp(chars(), other->chars()); +} + +CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/Literals.h b/src/shared/cplusplus/Literals.h new file mode 100644 index 0000000000..f55978b270 --- /dev/null +++ b/src/shared/cplusplus/Literals.h @@ -0,0 +1,122 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. + +#ifndef CPLUSPLUS_LITERALS_H +#define CPLUSPLUS_LITERALS_H + +#include "CPlusPlusForwardDeclarations.h" +#include "Token.h" + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +class CPLUSPLUS_EXPORT Literal +{ + Literal(const Literal &other); + void operator =(const Literal &other); + +public: + typedef const char *iterator; + typedef iterator const_iterator; + +public: + Literal(const char *chars, unsigned size); + virtual ~Literal(); + + iterator begin() const; + iterator end() const; + + char at(unsigned index) const; + const char *chars() const; + unsigned size() const; + + unsigned hashCode() const; + static unsigned hashCode(const char *chars, unsigned size); + +private: + char *_chars; + unsigned _size; + unsigned _hashCode; + +public: + // ### private + unsigned _index; + Literal *_next; +}; + +class CPLUSPLUS_EXPORT StringLiteral: public Literal +{ +public: + StringLiteral(const char *chars, unsigned size); + virtual ~StringLiteral(); +}; + +class CPLUSPLUS_EXPORT NumericLiteral: public Literal +{ +public: + NumericLiteral(const char *chars, unsigned size); + virtual ~NumericLiteral(); +}; + +class CPLUSPLUS_EXPORT Identifier: public Literal +{ +public: + Identifier(const char *chars, unsigned size); + virtual ~Identifier(); + + bool isEqualTo(const Identifier *other) const; +}; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_LITERALS_H diff --git a/src/shared/cplusplus/MemoryPool.cpp b/src/shared/cplusplus/MemoryPool.cpp new file mode 100644 index 0000000000..880c6bb884 --- /dev/null +++ b/src/shared/cplusplus/MemoryPool.cpp @@ -0,0 +1,130 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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 "MemoryPool.h" +#include <cstdlib> +#include <cstring> +#include <cassert> + +CPLUSPLUS_BEGIN_NAMESPACE + +MemoryPool::MemoryPool() + : _initializeAllocatedMemory(true), + _blocks(0), + _allocatedBlocks(0), + _blockCount(-1), + ptr(0), + end(0) +{ } + +MemoryPool::~MemoryPool() +{ + if (_blockCount != -1) { + for (int i = 0; i < _blockCount + 1; ++i) { + free(_blocks[i]); + } + } + + if (_blocks) + free(_blocks); +} + +bool MemoryPool::initializeAllocatedMemory() const +{ return _initializeAllocatedMemory; } + +void MemoryPool::setInitializeAllocatedMemory(bool initializeAllocatedMemory) +{ _initializeAllocatedMemory = initializeAllocatedMemory; } + +void *MemoryPool::allocate_helper(size_t size) +{ + assert(size < BLOCK_SIZE); + + if (++_blockCount == _allocatedBlocks) { + if (! _allocatedBlocks) + _allocatedBlocks = 8; + else + _allocatedBlocks *= 2; + + _blocks = (char **) realloc(_blocks, sizeof(char *) * _allocatedBlocks); + } + + char *&block = _blocks[_blockCount]; + + if (_initializeAllocatedMemory) + block = (char *) calloc(1, BLOCK_SIZE); + else + block = (char *) malloc(BLOCK_SIZE); + + ptr = block; + end = ptr + BLOCK_SIZE; + + void *addr = ptr; + ptr += size; + return addr; +} + +Managed::Managed() +{ } + +Managed::~Managed() +{ } + +void *Managed::operator new(size_t size, MemoryPool *pool) +{ return pool->allocate(size); } + +void Managed::operator delete(void *) +{ } + +void Managed::operator delete(void *, MemoryPool *) +{ } + +CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/MemoryPool.h b/src/shared/cplusplus/MemoryPool.h new file mode 100644 index 0000000000..13c61c9d24 --- /dev/null +++ b/src/shared/cplusplus/MemoryPool.h @@ -0,0 +1,120 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. + +#ifndef CPLUSPLUS_MEMORYPOOL_H +#define CPLUSPLUS_MEMORYPOOL_H + +#include "CPlusPlusForwardDeclarations.h" +#include <cstddef> +#include <new> + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +class CPLUSPLUS_EXPORT MemoryPool +{ + MemoryPool(const MemoryPool &other); + void operator =(const MemoryPool &other); + +public: + MemoryPool(); + ~MemoryPool(); + + bool initializeAllocatedMemory() const; + void setInitializeAllocatedMemory(bool initializeAllocatedMemory); + + inline void *allocate(size_t size) + { + size = (size + 7) & ~7; + if (ptr && (ptr + size < end)) { + void *addr = ptr; + ptr += size; + return addr; + } + return allocate_helper(size); + } + +private: + void *allocate_helper(size_t size); + +private: + bool _initializeAllocatedMemory; + char **_blocks; + int _allocatedBlocks; + int _blockCount; + char *ptr, *end; + + enum + { + BLOCK_SIZE = 8 * 1024, + DEFAULT_BLOCK_COUNT = 8 + }; +}; + +class CPLUSPLUS_EXPORT Managed +{ + Managed(const Managed &other); + void operator = (const Managed &other); + +public: + Managed(); + virtual ~Managed(); + + void *operator new(size_t size, MemoryPool *pool); + void operator delete(void *); + void operator delete(void *, MemoryPool *); +}; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_MEMORYPOOL_H diff --git a/src/shared/cplusplus/Name.cpp b/src/shared/cplusplus/Name.cpp new file mode 100644 index 0000000000..89e875a93c --- /dev/null +++ b/src/shared/cplusplus/Name.cpp @@ -0,0 +1,133 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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 "Name.h" +#include "Names.h" +#include "NameVisitor.h" + +CPLUSPLUS_BEGIN_NAMESPACE + +Name::Name() +{ } + +Name::~Name() +{ } + +bool Name::isNameId() const +{ return dynamic_cast<const NameId *>(this) != 0; } + +bool Name::isTemplateNameId() const +{ return dynamic_cast<const TemplateNameId *>(this) != 0; } + +bool Name::isDestructorNameId() const +{ return dynamic_cast<const DestructorNameId *>(this) != 0; } + +bool Name::isOperatorNameId() const +{ return dynamic_cast<const OperatorNameId *>(this) != 0; } + +bool Name::isConversionNameId() const +{ return dynamic_cast<const ConversionNameId *>(this) != 0; } + +bool Name::isQualifiedNameId() const +{ return dynamic_cast<const QualifiedNameId *>(this) != 0; } + +const NameId *Name::asNameId() const +{ return dynamic_cast<const NameId *>(this); } + +const TemplateNameId *Name::asTemplateNameId() const +{ return dynamic_cast<const TemplateNameId *>(this); } + +const DestructorNameId *Name::asDestructorNameId() const +{ return dynamic_cast<const DestructorNameId *>(this); } + +const OperatorNameId *Name::asOperatorNameId() const +{ return dynamic_cast<const OperatorNameId *>(this); } + +const ConversionNameId *Name::asConversionNameId() const +{ return dynamic_cast<const ConversionNameId *>(this); } + +const QualifiedNameId *Name::asQualifiedNameId() const +{ return dynamic_cast<const QualifiedNameId *>(this); } + +NameId *Name::asNameId() +{ return dynamic_cast<NameId *>(this); } + +TemplateNameId *Name::asTemplateNameId() +{ return dynamic_cast<TemplateNameId *>(this); } + +DestructorNameId *Name::asDestructorNameId() +{ return dynamic_cast<DestructorNameId *>(this); } + +OperatorNameId *Name::asOperatorNameId() +{ return dynamic_cast<OperatorNameId *>(this); } + +ConversionNameId *Name::asConversionNameId() +{ return dynamic_cast<ConversionNameId *>(this); } + +QualifiedNameId *Name::asQualifiedNameId() +{ return dynamic_cast<QualifiedNameId *>(this); } + +void Name::accept(NameVisitor *visitor) +{ + if (visitor->preVisit(this)) + accept0(visitor); + visitor->postVisit(this); +} + +void Name::accept(Name *name, NameVisitor *visitor) +{ + if (! name) + return; + name->accept(visitor); +} + +CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/Name.h b/src/shared/cplusplus/Name.h new file mode 100644 index 0000000000..1f30a28516 --- /dev/null +++ b/src/shared/cplusplus/Name.h @@ -0,0 +1,103 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. + +#ifndef CPLUSPLUS_NAME_H +#define CPLUSPLUS_NAME_H + +#include "CPlusPlusForwardDeclarations.h" + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +class CPLUSPLUS_EXPORT Name +{ + Name(const Name &other); + void operator =(const Name &other); + +public: + Name(); + virtual ~Name(); + + bool isNameId() const; + bool isTemplateNameId() const; + bool isDestructorNameId() const; + bool isOperatorNameId() const; + bool isConversionNameId() const; + bool isQualifiedNameId() const; + + const NameId *asNameId() const; + const TemplateNameId *asTemplateNameId() const; + const DestructorNameId *asDestructorNameId() const; + const OperatorNameId *asOperatorNameId() const; + const ConversionNameId *asConversionNameId() const; + const QualifiedNameId *asQualifiedNameId() const; + + NameId *asNameId(); + TemplateNameId *asTemplateNameId(); + DestructorNameId *asDestructorNameId(); + OperatorNameId *asOperatorNameId(); + ConversionNameId *asConversionNameId(); + QualifiedNameId *asQualifiedNameId(); + + virtual bool isEqualTo(const Name *other) const = 0; + + void accept(NameVisitor *visitor); + static void accept(Name *name, NameVisitor *visitor); + +protected: + virtual void accept0(NameVisitor *visitor) = 0; +}; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_NAME_H diff --git a/src/shared/cplusplus/NameVisitor.cpp b/src/shared/cplusplus/NameVisitor.cpp new file mode 100644 index 0000000000..d4f1af6575 --- /dev/null +++ b/src/shared/cplusplus/NameVisitor.cpp @@ -0,0 +1,67 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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 "NameVisitor.h" +#include "Names.h" + +CPLUSPLUS_BEGIN_NAMESPACE + +NameVisitor::NameVisitor() +{ } + +NameVisitor::~NameVisitor() +{ } + +void NameVisitor::accept(Name *name) +{ Name::accept(name, this); } + +CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/NameVisitor.h b/src/shared/cplusplus/NameVisitor.h new file mode 100644 index 0000000000..5cea38b9f8 --- /dev/null +++ b/src/shared/cplusplus/NameVisitor.h @@ -0,0 +1,86 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. + +#ifndef CPLUSPLUS_NAMEVISITOR_H +#define CPLUSPLUS_NAMEVISITOR_H + +#include "CPlusPlusForwardDeclarations.h" + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +class CPLUSPLUS_EXPORT NameVisitor +{ + NameVisitor(const NameVisitor &other); + void operator =(const NameVisitor &other); + +public: + NameVisitor(); + virtual ~NameVisitor(); + + void accept(Name *name); + + virtual bool preVisit(Name *) { return true; } + virtual void postVisit(Name *) {} + + virtual void visit(NameId *) {} + virtual void visit(TemplateNameId *) {} + virtual void visit(DestructorNameId *) {} + virtual void visit(OperatorNameId *) {} + virtual void visit(ConversionNameId *) {} + virtual void visit(QualifiedNameId *) {} +}; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_NAMEVISITOR_H diff --git a/src/shared/cplusplus/Names.cpp b/src/shared/cplusplus/Names.cpp new file mode 100644 index 0000000000..35bb84b44c --- /dev/null +++ b/src/shared/cplusplus/Names.cpp @@ -0,0 +1,262 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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 "Names.h" +#include "NameVisitor.h" +#include "Literals.h" +#include <cstring> +#include <algorithm> + +CPLUSPLUS_BEGIN_NAMESPACE + +QualifiedNameId::QualifiedNameId(Name *const names[], + unsigned nameCount, + bool isGlobal) + : _names(0), + _nameCount(nameCount), + _isGlobal(isGlobal) +{ + if (_nameCount) { + _names = new Name *[_nameCount]; + std::copy(&names[0], &names[nameCount], _names); + } +} + +QualifiedNameId::~QualifiedNameId() +{ delete[] _names; } + +void QualifiedNameId::accept0(NameVisitor *visitor) +{ visitor->visit(this); } + +unsigned QualifiedNameId::nameCount() const +{ return _nameCount; } + +Name *QualifiedNameId::nameAt(unsigned index) const +{ return _names[index]; } + +Name *const *QualifiedNameId::names() const +{ return _names; } + +bool QualifiedNameId::isGlobal() const +{ return _isGlobal; } + +Name *QualifiedNameId::unqualifiedNameId() const +{ + if (! _nameCount) + return 0; + + return _names[_nameCount - 1]; +} + +bool QualifiedNameId::isEqualTo(const Name *other) const +{ + const QualifiedNameId *q = other->asQualifiedNameId(); + if (! q) + return false; + else if (isGlobal() != q->isGlobal()) + return false; + else { + const unsigned count = nameCount(); + if (count != q->nameCount()) + return false; + for (unsigned i = 0; i < count; ++i) { + Name *l = nameAt(i); + Name *r = q->nameAt(i); + if (! l->isEqualTo(r)) + return false; + } + } + return true; +} + +NameId::NameId(Identifier *identifier) + : _identifier(identifier) +{ } + +NameId::~NameId() +{ } + +void NameId::accept0(NameVisitor *visitor) +{ visitor->visit(this); } + +Identifier *NameId::identifier() const +{ return _identifier; } + +bool NameId::isEqualTo(const Name *other) const +{ + const NameId *nameId = other->asNameId(); + if (! nameId) + return false; + Identifier *l = identifier(); + Identifier *r = nameId->identifier(); + return l->isEqualTo(r); +} + +DestructorNameId::DestructorNameId(Identifier *identifier) + : _identifier(identifier) +{ } + +DestructorNameId::~DestructorNameId() +{ } + +void DestructorNameId::accept0(NameVisitor *visitor) +{ visitor->visit(this); } + +Identifier *DestructorNameId::identifier() const +{ return _identifier; } + +bool DestructorNameId::isEqualTo(const Name *other) const +{ + const DestructorNameId *d = other->asDestructorNameId(); + if (! d) + return false; + Identifier *l = identifier(); + Identifier *r = d->identifier(); + return l->isEqualTo(r); +} + +TemplateNameId::TemplateNameId(Identifier *identifier, + const FullySpecifiedType templateArguments[], + unsigned templateArgumentCount) + : _identifier(identifier), + _templateArguments(0), + _templateArgumentCount(templateArgumentCount) +{ + if (_templateArgumentCount) { + _templateArguments = new FullySpecifiedType[_templateArgumentCount]; + std::copy(&templateArguments[0], &templateArguments[_templateArgumentCount], + _templateArguments); + } +} + +TemplateNameId::~TemplateNameId() +{ delete[] _templateArguments; } + +void TemplateNameId::accept0(NameVisitor *visitor) +{ visitor->visit(this); } + +Identifier *TemplateNameId::identifier() const +{ return _identifier; } + +unsigned TemplateNameId::templateArgumentCount() const +{ return _templateArgumentCount; } + +const FullySpecifiedType &TemplateNameId::templateArgumentAt(unsigned index) const +{ return _templateArguments[index]; } + +const FullySpecifiedType *TemplateNameId::templateArguments() const +{ return _templateArguments; } + +bool TemplateNameId::isEqualTo(const Name *other) const +{ + const TemplateNameId *t = other->asTemplateNameId(); + if (! t) + return false; + Identifier *l = identifier(); + Identifier *r = t->identifier(); + if (! l->isEqualTo(r)) + return false; + if (_templateArgumentCount != t->_templateArgumentCount) + return false; + for (unsigned i = 0; i < _templateArgumentCount; ++i) { + const FullySpecifiedType &l = _templateArguments[i]; + const FullySpecifiedType &r = t->_templateArguments[i]; + if (! l.isEqualTo(r)) + return false; + } + return true; +} + +OperatorNameId::OperatorNameId(int kind) + : _kind(kind) +{ } + +OperatorNameId::~OperatorNameId() +{ } + +void OperatorNameId::accept0(NameVisitor *visitor) +{ visitor->visit(this); } + +int OperatorNameId::kind() const +{ return _kind; } + +bool OperatorNameId::isEqualTo(const Name *other) const +{ + const OperatorNameId *o = other->asOperatorNameId(); + if (! o) + return false; + return _kind == o->kind(); +} + +ConversionNameId::ConversionNameId(FullySpecifiedType type) + : _type(type) +{ } + +ConversionNameId::~ConversionNameId() +{ } + +void ConversionNameId::accept0(NameVisitor *visitor) +{ visitor->visit(this); } + +FullySpecifiedType ConversionNameId::type() const +{ return _type; } + +bool ConversionNameId::isEqualTo(const Name *other) const +{ + const ConversionNameId *c = other->asConversionNameId(); + if (! c) + return false; + return _type.isEqualTo(c->type()); +} + + +CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/Names.h b/src/shared/cplusplus/Names.h new file mode 100644 index 0000000000..86e6813c6c --- /dev/null +++ b/src/shared/cplusplus/Names.h @@ -0,0 +1,241 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. + +#ifndef CPLUSPLUS_NAMES_H +#define CPLUSPLUS_NAMES_H + +#include "CPlusPlusForwardDeclarations.h" +#include "Name.h" +#include "FullySpecifiedType.h" + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +class CPLUSPLUS_EXPORT QualifiedNameId: public Name +{ +public: + QualifiedNameId(Name *const names[], + unsigned nameCount, + bool isGlobal = false); + virtual ~QualifiedNameId(); + + unsigned nameCount() const; + Name *nameAt(unsigned index) const; + Name *const *names() const; + Name *unqualifiedNameId() const; + + bool isGlobal() const; + + virtual bool isEqualTo(const Name *other) const; + +protected: + virtual void accept0(NameVisitor *visitor); + +private: + Name **_names; + unsigned _nameCount; + bool _isGlobal; +}; + +class CPLUSPLUS_EXPORT NameId: public Name +{ +public: + NameId(Identifier *identifier); + virtual ~NameId(); + + Identifier *identifier() const; + + virtual bool isEqualTo(const Name *other) const; + +protected: + virtual void accept0(NameVisitor *visitor); + +private: + Identifier *_identifier; +}; + +class CPLUSPLUS_EXPORT DestructorNameId: public Name +{ +public: + DestructorNameId(Identifier *identifier); + virtual ~DestructorNameId(); + + Identifier *identifier() const; + + virtual bool isEqualTo(const Name *other) const; + +protected: + virtual void accept0(NameVisitor *visitor); + +private: + Identifier *_identifier; +}; + +class CPLUSPLUS_EXPORT TemplateNameId: public Name +{ +public: + TemplateNameId(Identifier *identifier, + const FullySpecifiedType templateArguments[], + unsigned templateArgumentCount); + virtual ~TemplateNameId(); + + Identifier *identifier() const; + + // ### find a better name + unsigned templateArgumentCount() const; + const FullySpecifiedType &templateArgumentAt(unsigned index) const; + const FullySpecifiedType *templateArguments() const; + + virtual bool isEqualTo(const Name *other) const; + +protected: + virtual void accept0(NameVisitor *visitor); + +private: + Identifier *_identifier; + FullySpecifiedType *_templateArguments; + unsigned _templateArgumentCount; +}; + +class CPLUSPLUS_EXPORT OperatorNameId: public Name +{ +public: + /* + new delete new[] delete[] + + - * / % ^ & | ~ + ! = < > += -= *= /= %= + ^= &= |= << >> >>= <<= == != + <= >= && || ++ -- , ->* -> + () [] + */ + enum Kind { + InvalidOp, + NewOp, + DeleteOp, + NewArrayOp, + DeleteArrayOp, + PlusOp, + MinusOp, + StarOp, + SlashOp, + PercentOp, + CaretOp, + AmpOp, + PipeOp, + TildeOp, + ExclaimOp, + EqualOp, + LessOp, + GreaterOp, + PlusEqualOp, + MinusEqualOp, + StarEqualOp, + SlashEqualOp, + PercentEqualOp, + CaretEqualOp, + AmpEqualOp, + PipeEqualOp, + LessLessOp, + GreaterGreaterOp, + LessLessEqualOp, + GreaterGreaterEqualOp, + EqualEqualOp, + ExclaimEqualOp, + LessEqualOp, + GreaterEqualOp, + AmpAmpOp, + PipePipeOp, + PlusPlusOp, + MinusMinusOp, + CommaOp, + ArrowStarOp, + ArrowOp, + FunctionCallOp, + ArrayAccessOp + }; + +public: + OperatorNameId(int kind); + virtual ~OperatorNameId(); + + int kind() const; + + virtual bool isEqualTo(const Name *other) const; + +protected: + virtual void accept0(NameVisitor *visitor); + +private: + int _kind; +}; + +class CPLUSPLUS_EXPORT ConversionNameId: public Name +{ +public: + ConversionNameId(FullySpecifiedType type); + virtual ~ConversionNameId(); + + FullySpecifiedType type() const; + + virtual bool isEqualTo(const Name *other) const; + +protected: + virtual void accept0(NameVisitor *visitor); + +private: + FullySpecifiedType _type; +}; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_NAMES_H diff --git a/src/shared/cplusplus/ObjectiveCAtKeywords.cpp b/src/shared/cplusplus/ObjectiveCAtKeywords.cpp new file mode 100644 index 0000000000..3f8fc7c396 --- /dev/null +++ b/src/shared/cplusplus/ObjectiveCAtKeywords.cpp @@ -0,0 +1,464 @@ +#include "Lexer.h" +#include "Token.h" + +CPLUSPLUS_BEGIN_NAMESPACE + +static inline int classify3(const char *s) { + if (s[0] == 'e') { + if (s[1] == 'n') { + if (s[2] == 'd') { + return T_AT_END; + } + } + } + else if (s[0] == 't') { + if (s[1] == 'r') { + if (s[2] == 'y') { + return T_AT_TRY; + } + } + } + return T_ERROR; +} + +static inline int classify4(const char *s) { + if (s[0] == 'd') { + if (s[1] == 'e') { + if (s[2] == 'f') { + if (s[3] == 's') { + return T_AT_DEFS; + } + } + } + } + return T_ERROR; +} + +static inline int classify5(const char *s) { + if (s[0] == 'c') { + if (s[1] == 'a') { + if (s[2] == 't') { + if (s[3] == 'c') { + if (s[4] == 'h') { + return T_AT_CATCH; + } + } + } + } + else if (s[1] == 'l') { + if (s[2] == 'a') { + if (s[3] == 's') { + if (s[4] == 's') { + return T_AT_CLASS; + } + } + } + } + } + else if (s[0] == 't') { + if (s[1] == 'h') { + if (s[2] == 'r') { + if (s[3] == 'o') { + if (s[4] == 'w') { + return T_AT_THROW; + } + } + } + } + } + return T_ERROR; +} + +static inline int classify6(const char *s) { + if (s[0] == 'e') { + if (s[1] == 'n') { + if (s[2] == 'c') { + if (s[3] == 'o') { + if (s[4] == 'd') { + if (s[5] == 'e') { + return T_AT_ENCODE; + } + } + } + } + } + } + else if (s[0] == 'p') { + if (s[1] == 'u') { + if (s[2] == 'b') { + if (s[3] == 'l') { + if (s[4] == 'i') { + if (s[5] == 'c') { + return T_AT_PUBLIC; + } + } + } + } + } + } + return T_ERROR; +} + +static inline int classify7(const char *s) { + if (s[0] == 'd') { + if (s[1] == 'y') { + if (s[2] == 'n') { + if (s[3] == 'a') { + if (s[4] == 'm') { + if (s[5] == 'i') { + if (s[6] == 'c') { + return T_AT_DYNAMIC; + } + } + } + } + } + } + } + else if (s[0] == 'f') { + if (s[1] == 'i') { + if (s[2] == 'n') { + if (s[3] == 'a') { + if (s[4] == 'l') { + if (s[5] == 'l') { + if (s[6] == 'y') { + return T_AT_FINALLY; + } + } + } + } + } + } + } + else if (s[0] == 'p') { + if (s[1] == 'a') { + if (s[2] == 'c') { + if (s[3] == 'k') { + if (s[4] == 'a') { + if (s[5] == 'g') { + if (s[6] == 'e') { + return T_AT_PACKAGE; + } + } + } + } + } + } + else if (s[1] == 'r') { + if (s[2] == 'i') { + if (s[3] == 'v') { + if (s[4] == 'a') { + if (s[5] == 't') { + if (s[6] == 'e') { + return T_AT_PRIVATE; + } + } + } + } + } + } + } + return T_ERROR; +} + +static inline int classify8(const char *s) { + if (s[0] == 'o') { + if (s[1] == 'p') { + if (s[2] == 't') { + if (s[3] == 'i') { + if (s[4] == 'o') { + if (s[5] == 'n') { + if (s[6] == 'a') { + if (s[7] == 'l') { + return T_AT_OPTIONAL; + } + } + } + } + } + } + } + } + else if (s[0] == 'p') { + if (s[1] == 'r') { + if (s[2] == 'o') { + if (s[3] == 'p') { + if (s[4] == 'e') { + if (s[5] == 'r') { + if (s[6] == 't') { + if (s[7] == 'y') { + return T_AT_PROPERTY; + } + } + } + } + } + else if (s[3] == 't') { + if (s[4] == 'o') { + if (s[5] == 'c') { + if (s[6] == 'o') { + if (s[7] == 'l') { + return T_AT_PROTOCOL; + } + } + } + } + } + } + } + } + else if (s[0] == 'r') { + if (s[1] == 'e') { + if (s[2] == 'q') { + if (s[3] == 'u') { + if (s[4] == 'i') { + if (s[5] == 'r') { + if (s[6] == 'e') { + if (s[7] == 'd') { + return T_AT_REQUIRED; + } + } + } + } + } + } + } + } + else if (s[0] == 's') { + if (s[1] == 'e') { + if (s[2] == 'l') { + if (s[3] == 'e') { + if (s[4] == 'c') { + if (s[5] == 't') { + if (s[6] == 'o') { + if (s[7] == 'r') { + return T_AT_SELECTOR; + } + } + } + } + } + } + } + } + return T_ERROR; +} + +static inline int classify9(const char *s) { + if (s[0] == 'i') { + if (s[1] == 'n') { + if (s[2] == 't') { + if (s[3] == 'e') { + if (s[4] == 'r') { + if (s[5] == 'f') { + if (s[6] == 'a') { + if (s[7] == 'c') { + if (s[8] == 'e') { + return T_AT_INTERFACE; + } + } + } + } + } + } + } + } + } + else if (s[0] == 'p') { + if (s[1] == 'r') { + if (s[2] == 'o') { + if (s[3] == 't') { + if (s[4] == 'e') { + if (s[5] == 'c') { + if (s[6] == 't') { + if (s[7] == 'e') { + if (s[8] == 'd') { + return T_AT_PROTECTED; + } + } + } + } + } + } + } + } + } + return T_ERROR; +} + +static inline int classify10(const char *s) { + if (s[0] == 's') { + if (s[1] == 'y') { + if (s[2] == 'n') { + if (s[3] == 't') { + if (s[4] == 'h') { + if (s[5] == 'e') { + if (s[6] == 's') { + if (s[7] == 'i') { + if (s[8] == 'z') { + if (s[9] == 'e') { + return T_AT_SYNTHESIZE; + } + } + } + } + } + } + } + } + } + } + return T_ERROR; +} + +static inline int classify11(const char *s) { + if (s[0] == 'n') { + if (s[1] == 'o') { + if (s[2] == 't') { + if (s[3] == '_') { + if (s[4] == 'k') { + if (s[5] == 'e') { + if (s[6] == 'y') { + if (s[7] == 'w') { + if (s[8] == 'o') { + if (s[9] == 'r') { + if (s[10] == 'd') { + return T_AT_NOT_KEYWORD; + } + } + } + } + } + } + } + } + } + } + } + return T_ERROR; +} + +static inline int classify12(const char *s) { + if (s[0] == 's') { + if (s[1] == 'y') { + if (s[2] == 'n') { + if (s[3] == 'c') { + if (s[4] == 'h') { + if (s[5] == 'r') { + if (s[6] == 'o') { + if (s[7] == 'n') { + if (s[8] == 'i') { + if (s[9] == 'z') { + if (s[10] == 'e') { + if (s[11] == 'd') { + return T_AT_SYNCHRONIZED; + } + } + } + } + } + } + } + } + } + } + } + } + return T_ERROR; +} + +static inline int classify14(const char *s) { + if (s[0] == 'i') { + if (s[1] == 'm') { + if (s[2] == 'p') { + if (s[3] == 'l') { + if (s[4] == 'e') { + if (s[5] == 'm') { + if (s[6] == 'e') { + if (s[7] == 'n') { + if (s[8] == 't') { + if (s[9] == 'a') { + if (s[10] == 't') { + if (s[11] == 'i') { + if (s[12] == 'o') { + if (s[13] == 'n') { + return T_AT_IMPLEMENTATION; + } + } + } + } + } + } + } + } + } + } + } + } + } + } + return T_ERROR; +} + +static inline int classify19(const char *s) { + if (s[0] == 'c') { + if (s[1] == 'o') { + if (s[2] == 'm') { + if (s[3] == 'p') { + if (s[4] == 'a') { + if (s[5] == 't') { + if (s[6] == 'i') { + if (s[7] == 'b') { + if (s[8] == 'i') { + if (s[9] == 'l') { + if (s[10] == 'i') { + if (s[11] == 't') { + if (s[12] == 'y') { + if (s[13] == '_') { + if (s[14] == 'a') { + if (s[15] == 'l') { + if (s[16] == 'i') { + if (s[17] == 'a') { + if (s[18] == 's') { + return T_AT_COMPATIBILITY_ALIAS; + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + return T_ERROR; +} + +int Lexer::classifyObjCAtKeyword(const char *s, int n) { + switch (n) { + case 3: return classify3(s); + case 4: return classify4(s); + case 5: return classify5(s); + case 6: return classify6(s); + case 7: return classify7(s); + case 8: return classify8(s); + case 9: return classify9(s); + case 10: return classify10(s); + case 11: return classify11(s); + case 12: return classify12(s); + case 14: return classify14(s); + case 19: return classify19(s); + default: return T_ERROR; + } // switch +} + +CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp new file mode 100644 index 0000000000..085c8cb54e --- /dev/null +++ b/src/shared/cplusplus/Parser.cpp @@ -0,0 +1,3810 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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 <cstring> +#include <cassert> + +CPLUSPLUS_BEGIN_NAMESPACE + +Parser::Parser(TranslationUnit *unit) + : _translationUnit(unit), + _control(_translationUnit->control()), + _pool(_translationUnit->memoryPool()), + _tokenIndex(1), + _templateArguments(0), + _qtMocRunEnabled(false), + _objCEnabled(false), + _inFunctionBody(false), + _inObjCImplementationContext(false) +{ } + +Parser::~Parser() +{ } + +bool Parser::qtMocRunEnabled() const +{ return _qtMocRunEnabled; } + +void Parser::setQtMocRunEnabled(bool onoff) +{ _qtMocRunEnabled = onoff; } + +bool Parser::objCEnabled() const +{ return _objCEnabled; } + +void Parser::setObjCEnabled(bool onoff) +{ _objCEnabled = 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); + + // ObjcC++ + case T_AT_CLASS: + return parseObjCClassDeclaration(node); + + case T_AT_INTERFACE: + return parseObjCInterface(node); + + case T_AT_PROTOCOL: + return parseObjCProtocol(node); + + case T_AT_IMPLEMENTATION: + return parseObjCImplementation(node); + + case T_AT_END: + return parseObjCEnd(node); + + default: { + if (_objCEnabled && LA() == T___ATTRIBUTE__) { + const unsigned start = cursor(); + SpecifierAST *attributes = 0, **attr = &attributes; + while (parseAttributeSpecifier(*attr)) + attr = &(*attr)->next; + if (LA() == T_AT_INTERFACE) + return parseObjCInterface(node, attributes); + else if (LA() == T_AT_PROTOCOL) + return parseObjCProtocol(node, attributes); + else if (LA() == T_AT_PROPERTY) + return parseObjCPropertyDeclaration(node, attributes); + rewind(start); + } + + 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); + } break; // default + + } // end switch + + return false; +} + +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 if(LA() == T___ATTRIBUTE__) { + parseAttributeSpecifier(*ast); + 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); + match(T_RBRACE, &ast->rbrace_token); + 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: { + NameAST *name = 0; + if (parseNameId(name)) { + node = name; + return true; + } + break; + } // default + + } // switch + + return false; +} + +bool Parser::parseNameId(NameAST *&name) +{ + unsigned start = cursor(); + if (! parseName(name)) + return false; + + if (LA() == T_IDENTIFIER || + tok().isLiteral() || + (tok().isOperator() && LA() != T_LPAREN && LA() != T_LBRACKET)) + { + rewind(start); + return parseName(name, false); + } + + return true; +} + +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; + } + } + rewind(start); + + // look for compound literals + if (LA() == T_LPAREN) { + unsigned lparen_token = consumeToken(); + ExpressionAST *type_id = 0; + if (parseTypeId(type_id) && LA() == T_RPAREN) { + unsigned rparen_token = consumeToken(); + if (LA() == T_LBRACE) { + blockErrors(blocked); + + CompoundLiteralAST *ast = new (_pool) CompoundLiteralAST; + ast->lparen_token = lparen_token; + ast->type_id = type_id; + ast->rparen_token = rparen_token; + parseInitializerClause(ast->initializer); + node = ast; + return true; + } + } + rewind(start); + } + + blockErrors(blocked); + 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 (! parseNameId(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; +} + +bool Parser::lookAtObjCSelector() const +{ + switch (LA()) { + case T_IDENTIFIER: + case T_OR: + case T_AND: + case T_NOT: + case T_XOR: + case T_BITOR: + case T_COMPL: + case T_OR_EQ: + case T_AND_EQ: + case T_BITAND: + case T_NOT_EQ: + case T_XOR_EQ: + return true; + + default: + if (tok().isKeyword()) + return true; + } // switch + + return false; +} + +// objc-class-declaraton ::= T_AT_CLASS (T_IDENTIFIER @ T_COMMA) T_SEMICOLON +// +bool Parser::parseObjCClassDeclaration(DeclarationAST *&) +{ + if (LA() != T_AT_CLASS) + return false; + + /*unsigned objc_class_token = */ consumeToken(); + unsigned identifier_token = 0; + match(T_IDENTIFIER, &identifier_token); + while (LA() == T_COMMA) { + consumeToken(); // skip T_COMMA + match(T_IDENTIFIER, &identifier_token); + } + + unsigned semicolon_token = 0; + match(T_SEMICOLON, &semicolon_token); + return true; +} + +// objc-interface ::= attribute-specifier-list-opt objc-class-interface +// objc-interface ::= objc-category-interface +// +// objc-class-interface ::= T_AT_INTERFACE T_IDENTIFIER (T_COLON T_IDENTIFIER)? +// objc-protocol-refs-opt +// objc-class-instance-variables-opt +// objc-interface-declaration-list +// T_AT_END +// +// objc-category-interface ::= T_AT_INTERFACE T_IDENTIFIER +// T_LPAREN T_IDENTIFIER? T_RPAREN +// objc-protocol-refs-opt +// objc-interface-declaration-list +// T_AT_END +// +bool Parser::parseObjCInterface(DeclarationAST *&, + SpecifierAST *attributes) +{ + if (! attributes && LA() == T___ATTRIBUTE__) { + SpecifierAST **attr = &attributes; + while (parseAttributeSpecifier(*attr)) + attr = &(*attr)->next; + } + + if (LA() != T_AT_INTERFACE) + return false; + + /*unsigned objc_interface_token = */ consumeToken(); + unsigned identifier_token = 0; + match(T_IDENTIFIER, &identifier_token); + + if (LA() == T_LPAREN) { + // a category interface + + if (attributes) + _translationUnit->error(attributes->firstToken(), + "invalid attributes for category interface declaration"); + + unsigned lparen_token = 0, rparen_token = 0; + match(T_LPAREN, &lparen_token); + if (LA() == T_IDENTIFIER) + consumeToken(); + + match(T_RPAREN, &rparen_token); + + parseObjCProtocolRefs(); + while (parseObjCInterfaceMemberDeclaration()) { + } + unsigned objc_end_token = 0; + match(T_AT_END, &objc_end_token); + return true; + } + + // a class interface declaration + if (LA() == T_COLON) { + consumeToken(); + unsigned identifier_token = 0; + match(T_IDENTIFIER, &identifier_token); + } + + parseObjCProtocolRefs(); + parseObjClassInstanceVariables(); + while (parseObjCInterfaceMemberDeclaration()) { + } + unsigned objc_end_token = 0; + match(T_AT_END, &objc_end_token); + return true; +} + +// objc-protocol ::= T_AT_PROTOCOL (T_IDENTIFIER @ T_COMMA) T_SEMICOLON +// +bool Parser::parseObjCProtocol(DeclarationAST *&, + SpecifierAST *attributes) +{ + if (! attributes && LA() == T___ATTRIBUTE__) { + SpecifierAST **attr = &attributes; + while (parseAttributeSpecifier(*attr)) + attr = &(*attr)->next; + } + + if (LA() != T_AT_PROTOCOL) + return false; + + /*unsigned objc_protocol_token = */ consumeToken(); + unsigned identifier_token = 0; + match(T_IDENTIFIER, &identifier_token); + + if (LA() == T_COMMA || LA() == T_SEMICOLON) { + // a protocol forward declaration + + while (LA() == T_COMMA) { + consumeToken(); + match(T_IDENTIFIER, &identifier_token); + } + unsigned semicolon_token = 0; + match(T_SEMICOLON, &semicolon_token); + return true; + } + + // a protocol definition + parseObjCProtocolRefs(); + + while (parseObjCInterfaceMemberDeclaration()) { + } + + unsigned objc_end_token = 0; + match(T_AT_END, &objc_end_token); + + return true; +} + +// objc-implementation ::= T_AT_IMPLEMENTAION T_IDENTIFIER (T_COLON T_IDENTIFIER)? +// objc-class-instance-variables-opt +// objc-implementation ::= T_AT_IMPLEMENTAION T_IDENTIFIER T_LPAREN T_IDENTIFIER T_RPAREN +// +bool Parser::parseObjCImplementation(DeclarationAST *&) +{ + if (LA() != T_AT_IMPLEMENTATION) + return false; + + consumeToken(); + + unsigned identifier_token = 0; + match(T_IDENTIFIER, &identifier_token); + + if (LA() == T_LPAREN) { + // a category implementation + unsigned lparen_token = 0, rparen_token = 0; + unsigned category_name_token = 0; + match(T_LPAREN, &lparen_token); + match(T_IDENTIFIER, &category_name_token); + match(T_RPAREN, &rparen_token); + return true; + } + + // a class implementation + if (LA() == T_COLON) { + consumeToken(); + unsigned super_class_name_token = 0; + match(T_IDENTIFIER, &super_class_name_token); + } + + parseObjClassInstanceVariables(); + return true; +} + +// objc-protocol-refs ::= T_LESS (T_IDENTIFIER @ T_COMMA) T_GREATER +// +bool Parser::parseObjCProtocolRefs() +{ + if (LA() != T_LESS) + return false; + unsigned less_token = 0, greater_token = 0; + unsigned identifier_token = 0; + match(T_LESS, &less_token); + match(T_IDENTIFIER, &identifier_token); + while (LA() == T_COMMA) { + consumeToken(); + match(T_IDENTIFIER, &identifier_token); + } + match(T_GREATER, &greater_token); + return true; +} + +// objc-class-instance-variables ::= T_LBRACE +// objc-instance-variable-decl-list-opt +// T_RBRACE +// +bool Parser::parseObjClassInstanceVariables() +{ + if (LA() != T_LBRACE) + return false; + + unsigned lbrace_token = 0, rbrace_token = 0; + + match(T_LBRACE, &lbrace_token); + while (LA()) { + if (LA() == T_RBRACE) + break; + + const unsigned start = cursor(); + + DeclarationAST *declaration = 0; + parseObjCInstanceVariableDeclaration(declaration); + + if (start == cursor()) { + // skip stray token. + _translationUnit->error(cursor(), "skip stray token `%s'", tok().spell()); + consumeToken(); + } + } + + match(T_RBRACE, &rbrace_token); + return true; +} + +// objc-interface-declaration ::= T_AT_REQUIRED +// objc-interface-declaration ::= T_AT_OPTIONAL +// objc-interface-declaration ::= T_SEMICOLON +// objc-interface-declaration ::= objc-property-declaration +// objc-interface-declaration ::= objc-method-prototype +bool Parser::parseObjCInterfaceMemberDeclaration() +{ + switch (LA()) { + case T_AT_END: + return false; + + case T_AT_REQUIRED: + case T_AT_OPTIONAL: + consumeToken(); + return true; + + case T_SEMICOLON: + consumeToken(); + return true; + + case T_AT_PROPERTY: { + DeclarationAST *declaration = 0; + return parseObjCPropertyDeclaration(declaration); + } + + case T_PLUS: + case T_MINUS: + return parseObjCMethodPrototype(); + + case T_ENUM: + case T_CLASS: + case T_STRUCT: + case T_UNION: { + DeclarationAST *declaration = 0; + return parseSimpleDeclaration(declaration, /*accept struct declarators */ true); + } + + default: { + DeclarationAST *declaration = 0; + return parseSimpleDeclaration(declaration, /*accept struct declarators */ true); + } // default + + } // switch +} + +// objc-instance-variable-declaration ::= objc-visibility-specifier +// objc-instance-variable-declaration ::= block-declaration +// +bool Parser::parseObjCInstanceVariableDeclaration(DeclarationAST *&node) +{ + switch (LA()) { + case T_AT_PRIVATE: + case T_AT_PROTECTED: + case T_AT_PUBLIC: + case T_AT_PACKAGE: + consumeToken(); + return true; + + default: + return parseSimpleDeclaration(node, true); + } +} + +// objc-property-declaration ::= +// T_AT_PROPERTY T_LPAREN (property-attribute @ T_COMMA) T_RPAREN simple-declaration +// +bool Parser::parseObjCPropertyDeclaration(DeclarationAST *&, SpecifierAST *) +{ + if (LA() != T_AT_PROPERTY) + return false; + + /*unsigned objc_property_token = */ consumeToken(); + + if (LA() == T_LPAREN) { + unsigned lparen_token = 0, rparen_token = 0; + match(T_LPAREN, &lparen_token); + while (parseObjCPropertyAttribute()) { + } + match(T_RPAREN, &rparen_token); + } + + DeclarationAST *simple_declaration = 0; + parseSimpleDeclaration(simple_declaration, /*accept-struct-declarators = */ true); + return true; +} + +// objc-method-prototype ::= (T_PLUS | T_MINUS) objc-method-decl objc-method-attrs-opt +// +// objc-method-decl ::= objc-type-name? objc-selector +// objc-method-decl ::= objc-type-name? objc-keyword-decl-list objc-parmlist-opt +// +bool Parser::parseObjCMethodPrototype() +{ + if (LA() != T_PLUS && LA() != T_MINUS) + return false; + + /*unsigned method_type_token = */ consumeToken(); + + parseObjCTypeName(); + + if ((lookAtObjCSelector() && LA(2) == T_COLON) || LA() == T_COLON) { + while (parseObjCKeywordDeclaration()) { + } + + while (LA() == T_COMMA) { + consumeToken(); + + if (LA() == T_DOT_DOT_DOT) { + consumeToken(); + break; + } + + DeclarationAST *parameter_declaration = 0; + parseParameterDeclaration(parameter_declaration); + } + } else if (lookAtObjCSelector()) { + parseObjCSelector(); + } else { + _translationUnit->error(cursor(), "expected a selector"); + } + + SpecifierAST *attributes = 0, **attr = &attributes; + while (parseAttributeSpecifier(*attr)) + attr = &(*attr)->next; + + return true; +} + +// objc-property-attribute ::= getter '=' identifier +// objc-property-attribute ::= setter '=' identifier ':' +// objc-property-attribute ::= readonly +// objc-property-attribute ::= readwrite +// objc-property-attribute ::= assign +// objc-property-attribute ::= retain +// objc-property-attribute ::= copy +// objc-property-attribute ::= nonatomic +bool Parser::parseObjCPropertyAttribute() +{ + if (LA() != T_IDENTIFIER) + return false; + + unsigned identifier_token = 0; + match(T_IDENTIFIER, &identifier_token); + if (LA() == T_EQUAL) { + consumeToken(); + match(T_IDENTIFIER, &identifier_token); + if (LA() == T_COLON) + consumeToken(); + } + + return true; +} + +// objc-type-name ::= T_LPAREN objc-type-qualifiers-opt type-id T_RPAREN +// +bool Parser::parseObjCTypeName() +{ + if (LA() != T_LPAREN) + return false; + + unsigned lparen_token = 0, rparen_token = 0; + match(T_LPAREN, &lparen_token); + parseObjCTypeQualifiers(); + ExpressionAST *type_id = 0; + parseTypeId(type_id); + match(T_RPAREN, &rparen_token); + return true; +} + +// objc-selector ::= T_IDENTIFIER | keyword +// +bool Parser::parseObjCSelector() +{ + if (! lookAtObjCSelector()) + return false; + + consumeToken(); + return true; +} + +// objc-keyword-decl ::= objc-selector? T_COLON objc-type-name? objc-keyword-attributes-opt T_IDENTIFIER +// +bool Parser::parseObjCKeywordDeclaration() +{ + if (! (LA() == T_COLON || (lookAtObjCSelector() && LA(2) == T_COLON))) + return false; + + parseObjCSelector(); + + unsigned colon_token = 0; + match(T_COLON, &colon_token); + + parseObjCTypeName(); + + SpecifierAST *attributes = 0, **attr = &attributes; + while (parseAttributeSpecifier(*attr)) + attr = &(*attr)->next; + + unsigned identifier_token = 0; + match(T_IDENTIFIER, &identifier_token); + + return true; +} + +bool Parser::parseObjCTypeQualifiers() +{ + if (LA() != T_IDENTIFIER) + return false; + + Identifier *id = tok().identifier; + if (! strcmp("in", id->chars()) || + ! strcmp("out", id->chars()) || + ! strcmp("inout", id->chars()) || + ! strcmp("bycopy", id->chars()) || + ! strcmp("byref", id->chars()) || + ! strcmp("oneway", id->chars())) { + consumeToken(); + return true; + } + return false; +} + +// objc-end: T_AT_END +bool Parser::parseObjCEnd(DeclarationAST *&) +{ + if (LA() != T_AT_END) + return false; + + consumeToken(); + return true; +} + + +CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/Parser.h b/src/shared/cplusplus/Parser.h new file mode 100644 index 0000000000..d99d8d27fc --- /dev/null +++ b/src/shared/cplusplus/Parser.h @@ -0,0 +1,292 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. + +#ifndef CPLUSPLUS_PARSER_H +#define CPLUSPLUS_PARSER_H + +#include "CPlusPlusForwardDeclarations.h" +#include "ASTfwd.h" +#include "Token.h" +#include "TranslationUnit.h" + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +class CPLUSPLUS_EXPORT Parser +{ +public: + Parser(TranslationUnit *translationUnit); + ~Parser(); + + bool qtMocRunEnabled() const; + void setQtMocRunEnabled(bool onoff); + + bool objCEnabled() const; + void setObjCEnabled(bool onoff); + + bool parseTranslationUnit(TranslationUnitAST *&node); + +public: + bool parseAccessSpecifier(SpecifierAST *&node); + bool parseExpressionList(ExpressionListAST *&node); + bool parseAbstractCoreDeclarator(DeclaratorAST *&node); + bool parseAbstractDeclarator(DeclaratorAST *&node); + bool parseEmptyDeclaration(DeclarationAST *&node); + bool parseAccessDeclaration(DeclarationAST *&node); + bool parseAdditiveExpression(ExpressionAST *&node); + bool parseAndExpression(ExpressionAST *&node); + bool parseAsmDefinition(DeclarationAST *&node); + bool parseAssignmentExpression(ExpressionAST *&node); + bool parseBaseClause(BaseSpecifierAST *&node); + bool parseBaseSpecifier(BaseSpecifierAST *&node); + bool parseBlockDeclaration(DeclarationAST *&node); + bool parseCppCastExpression(ExpressionAST *&node); + bool parseCastExpression(ExpressionAST *&node); + bool parseClassSpecifier(SpecifierAST *&node); + bool parseCommaExpression(ExpressionAST *&node); + bool parseCompoundStatement(StatementAST *&node); + bool parseBreakStatement(StatementAST *&node); + bool parseContinueStatement(StatementAST *&node); + bool parseGotoStatement(StatementAST *&node); + bool parseReturnStatement(StatementAST *&node); + bool parseCondition(ExpressionAST *&node); + bool parseConditionalExpression(ExpressionAST *&node); + bool parseConstantExpression(ExpressionAST *&node); + bool parseCtorInitializer(CtorInitializerAST *&node); + bool parseCvQualifiers(SpecifierAST *&node); + bool parseDeclaratorOrAbstractDeclarator(DeclaratorAST *&node); + bool parseDeclaration(DeclarationAST *&node); + bool parseSimpleDeclaration(DeclarationAST *&node, bool acceptStructDeclarator = false); + bool parseDeclarationStatement(StatementAST *&node); + bool parseCoreDeclarator(DeclaratorAST *&node); + bool parseDeclarator(DeclaratorAST *&node); + bool parseDeleteExpression(ExpressionAST *&node); + bool parseDoStatement(StatementAST *&node); + bool parseElaboratedTypeSpecifier(SpecifierAST *&node); + bool parseEnumSpecifier(SpecifierAST *&node); + bool parseEnumerator(EnumeratorAST *&node); + bool parseEqualityExpression(ExpressionAST *&node); + bool parseExceptionDeclaration(ExceptionDeclarationAST *&node); + bool parseExceptionSpecification(ExceptionSpecificationAST *&node); + bool parseExclusiveOrExpression(ExpressionAST *&node); + bool parseExpression(ExpressionAST *&node); + bool parseExpressionOrDeclarationStatement(StatementAST *&node); + bool parseExpressionStatement(StatementAST *&node); + bool parseForInitStatement(StatementAST *&node); + bool parseForStatement(StatementAST *&node); + bool parseFunctionBody(StatementAST *&node); + bool parseIfStatement(StatementAST *&node); + bool parseInclusiveOrExpression(ExpressionAST *&node); + bool parseInitDeclarator(DeclaratorAST *&node, bool acceptStructDeclarator); + bool parseInitializerList(ExpressionListAST *&node); + bool parseInitializer(ExpressionAST *&node); + bool parseInitializerClause(ExpressionAST *&node); + bool parseLabeledStatement(StatementAST *&node); + bool parseLinkageBody(DeclarationAST *&node); + bool parseLinkageSpecification(DeclarationAST *&node); + bool parseLogicalAndExpression(ExpressionAST *&node); + bool parseLogicalOrExpression(ExpressionAST *&node); + bool parseMemInitializer(MemInitializerAST *&node); + bool parseMemInitializerList(MemInitializerAST *&node); + bool parseMemberSpecification(DeclarationAST *&node); + bool parseMultiplicativeExpression(ExpressionAST *&node); + bool parseTemplateId(NameAST *&node); + bool parseClassOrNamespaceName(NameAST *&node); + bool parseNameId(NameAST *&node); + bool parseName(NameAST *&node, bool acceptTemplateId = true); + bool parseNestedNameSpecifier(NestedNameSpecifierAST *&node, bool acceptTemplateId); + bool parseNestedNameSpecifierOpt(NestedNameSpecifierAST *&name, bool acceptTemplateId); + bool parseNamespace(DeclarationAST *&node); + bool parseNamespaceAliasDefinition(DeclarationAST *&node); + bool parseNewDeclarator(NewDeclaratorAST *&node); + bool parseNewExpression(ExpressionAST *&node); + bool parseNewInitializer(NewInitializerAST *&node); + bool parseNewTypeId(NewTypeIdAST *&node); + bool parseOperator(OperatorAST *&node); + bool parseConversionFunctionId(NameAST *&node); + bool parseOperatorFunctionId(NameAST *&node); + bool parseParameterDeclaration(DeclarationAST *&node); + bool parseParameterDeclarationClause(ParameterDeclarationClauseAST *&node); + bool parseParameterDeclarationList(DeclarationAST *&node); + bool parsePmExpression(ExpressionAST *&node); + bool parseTypeidExpression(ExpressionAST *&node); + bool parseTypenameCallExpression(ExpressionAST *&node); + bool parseCorePostfixExpression(ExpressionAST *&node); + bool parsePostfixExpression(ExpressionAST *&node); + bool parsePostfixExpressionInternal(ExpressionAST *&node); + bool parsePrimaryExpression(ExpressionAST *&node); + bool parseNestedExpression(ExpressionAST *&node); + bool parsePtrOperator(PtrOperatorAST *&node); + bool parseRelationalExpression(ExpressionAST *&node); + bool parseShiftExpression(ExpressionAST *&node); + bool parseStatement(StatementAST *&node); + bool parseThisExpression(ExpressionAST *&node); + bool parseBoolLiteral(ExpressionAST *&node); + bool parseNumericLiteral(ExpressionAST *&node); + bool parseStringLiteral(ExpressionAST *&node); + bool parseSwitchStatement(StatementAST *&node); + bool parseTemplateArgument(ExpressionAST *&node); + bool parseTemplateArgumentList(TemplateArgumentListAST *&node); + bool parseTemplateDeclaration(DeclarationAST *&node); + bool parseTemplateParameter(DeclarationAST *&node); + bool parseTemplateParameterList(DeclarationAST *&node); + bool parseThrowExpression(ExpressionAST *&node); + bool parseTryBlockStatement(StatementAST *&node); + bool parseCatchClause(CatchClauseAST *&node); + bool parseTypeId(ExpressionAST *&node); + bool parseTypeIdList(ExpressionListAST *&node); + bool parseTypenameTypeParameter(DeclarationAST *&node); + bool parseTemplateTypeParameter(DeclarationAST *&node); + bool parseTypeParameter(DeclarationAST *&node); + + bool parseBuiltinTypeSpecifier(SpecifierAST *&node); + bool parseAttributeSpecifier(SpecifierAST *&node); + bool parseAttributeList(AttributeAST *&node); + + bool parseSimpleTypeSpecifier(SpecifierAST *&node) + { return parseDeclSpecifierSeq(node, true, true); } + + bool parseTypeSpecifier(SpecifierAST *&node) + { return parseDeclSpecifierSeq(node, true); } + + bool parseDeclSpecifierSeq(SpecifierAST *&node, + bool onlyTypeSpecifiers = false, + bool simplified = false); + bool parseUnaryExpression(ExpressionAST *&node); + bool parseUnqualifiedName(NameAST *&node, bool acceptTemplateId = true); + bool parseUsing(DeclarationAST *&node); + bool parseUsingDirective(DeclarationAST *&node); + bool parseWhileStatement(StatementAST *&node); + + // Qt MOC run + bool parseQtMethod(ExpressionAST *&node); + + // ObjC++ + bool parseObjCClassDeclaration(DeclarationAST *&node); + bool parseObjCInterface(DeclarationAST *&node, + SpecifierAST *attributes = 0); + bool parseObjCProtocol(DeclarationAST *&node, + SpecifierAST *attributes = 0); + + bool parseObjCProtocolRefs(); + bool parseObjClassInstanceVariables(); + bool parseObjCInterfaceMemberDeclaration(); + bool parseObjCInstanceVariableDeclaration(DeclarationAST *&node); + bool parseObjCPropertyDeclaration(DeclarationAST *&node, + SpecifierAST *attributes = 0); + bool parseObjCImplementation(DeclarationAST *&node); + bool parseObjCMethodPrototype(); + bool parseObjCPropertyAttribute(); + bool parseObjCTypeName(); + bool parseObjCSelector(); + bool parseObjCKeywordDeclaration(); + bool parseObjCTypeQualifiers(); + bool parseObjCEnd(DeclarationAST *&node); + + bool lookAtObjCSelector() const; + + bool skipUntil(int token); + bool skipUntilDeclaration(); + bool skipUntilStatement(); + bool skip(int l, int r); + + bool lookAtCVQualifier() const; + bool lookAtFunctionSpecifier() const; + bool lookAtStorageClassSpecifier() const; + bool lookAtBuiltinTypeSpecifier() const; + bool lookAtClassKey() const; + bool lookAtAssignmentOperator() const; + + void match(int kind, unsigned *token); + + bool maybeFunctionCall(SimpleDeclarationAST *simpleDecl) const; + bool maybeSimpleExpression(SimpleDeclarationAST *simpleDecl) const; + +private: + bool switchTemplateArguments(bool templateArguments); + bool blockErrors(bool block); + + inline const Token &tok(int i = 1) const + { return _translationUnit->tokenAt(_tokenIndex + i - 1); } + + inline int LA(int n = 1) const + { return _translationUnit->tokenKind(_tokenIndex + n - 1); } + + inline int consumeToken() + { return _tokenIndex++; } + + inline unsigned cursor() const + { return _tokenIndex; } + + inline void rewind(unsigned cursor) + { _tokenIndex = cursor; } + +private: + TranslationUnit *_translationUnit; + Control *_control; + MemoryPool *_pool; + unsigned _tokenIndex; + bool _templateArguments: 1; + bool _qtMocRunEnabled: 1; + bool _objCEnabled: 1; + bool _inFunctionBody: 1; + bool _inObjCImplementationContext: 1; + +private: + Parser(const Parser& source); + void operator =(const Parser& source); +}; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_PARSER_H diff --git a/src/shared/cplusplus/PrettyPrinter.cpp b/src/shared/cplusplus/PrettyPrinter.cpp new file mode 100644 index 0000000000..6acb109dcf --- /dev/null +++ b/src/shared/cplusplus/PrettyPrinter.cpp @@ -0,0 +1,1293 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. +** +***************************************************************************/ + +#include "PrettyPrinter.h" +#include "AST.h" +#include "Token.h" +#include <iostream> +#include <string> +#include <cassert> + +CPLUSPLUS_USE_NAMESPACE + +PrettyPrinter::PrettyPrinter(Control *control, std::ostream &out) + : ASTVisitor(control), + out(out), + depth(0) +{ } + +void PrettyPrinter::operator()(AST *ast) +{ accept(ast); } + +void PrettyPrinter::indent() +{ ++depth; } + +void PrettyPrinter::deindent() +{ --depth; } + +void PrettyPrinter::newline() +{ out << '\n' << std::string(depth * 4, ' '); } + +bool PrettyPrinter::visit(AccessDeclarationAST *ast) +{ + deindent(); + newline(); + out << spell(ast->access_specifier_token); + if (ast->slots_token) + out << ' ' << spell(ast->slots_token); + out << ':' << std::endl; + indent(); + return false; +} + +bool PrettyPrinter::visit(ArrayAccessAST *ast) +{ + out << '['; + accept(ast->expression); + out << ']'; + return false; +} + +bool PrettyPrinter::visit(ArrayDeclaratorAST *ast) +{ + out << '['; + accept(ast->expression); + out << ']'; + return false; +} + +bool PrettyPrinter::visit(ArrayInitializerAST *ast) +{ + out << '{'; + for (ExpressionListAST *it = ast->expression_list; it; it = it->next) { + accept(it->expression); + if (it->next) + out << ", "; + } + out << '}'; + return false; +} + +bool PrettyPrinter::visit(AsmDefinitionAST *ast) +{ + out << spell(ast->asm_token); + for (SpecifierAST *it = ast->cv_qualifier_seq; it; it = it->next) { + out << ' '; + accept(it); + } + out << '('; + out << "/* ### implement me */"; + out << ");"; + return false; +} + +bool PrettyPrinter::visit(AttributeSpecifierAST *ast) +{ + out << "attribute(("; + for (AttributeAST *it = ast->attributes; it; it = it->next) { + accept(it); + if (it->next) + out << ", "; + } + out << "))"; + return false; +} + +bool PrettyPrinter::visit(AttributeAST *ast) +{ + out << spell(ast->identifier_token); + if (ast->lparen_token) { + out << '('; + out << spell(ast->tag_token); + if (ast->expression_list) { + out << '('; + for (ExpressionListAST *it = ast->expression_list; it; it = it->next) { + accept(it->expression); + if (it->next) + out << ", "; + } + out << ')'; + } + out << ')'; + } + return false; +} + +bool PrettyPrinter::visit(BaseSpecifierAST *ast) +{ + if (ast->token_virtual && ast->token_access_specifier) { + out << "virtual"; + out << ' '; + out << spell(ast->token_access_specifier); + out << ' '; + } else if (ast->token_virtual) { + out << "virtual"; + out << ' '; + } else if (ast->token_access_specifier) { + out << spell(ast->token_access_specifier); + out << ' '; + } + accept(ast->name); + return false; +} + +bool PrettyPrinter::visit(BinaryExpressionAST *ast) +{ + accept(ast->left_expression); + out << ' ' << spell(ast->binary_op_token) << ' '; + accept(ast->right_expression); + return false; +} + +bool PrettyPrinter::visit(BoolLiteralAST *ast) +{ + out << spell(ast->token); + return false; +} + +bool PrettyPrinter::visit(BreakStatementAST *) +{ + out << "break;"; + return false; +} + +bool PrettyPrinter::visit(CallAST *ast) +{ + out << '('; + for (ExpressionListAST *it = ast->expression_list; it; it = it->next) { + accept(it->expression); + if (it->next) + out << ", "; + } + out << ')'; + return false; +} + +bool PrettyPrinter::visit(CaseStatementAST *ast) +{ + out << "case "; + accept(ast->expression); + out << ':'; + if (! ast->statement) { + newline(); + return false; + } + + if (ast->statement->asCompoundStatement()) { + out << ' '; + accept(ast->statement); + } else if (ast->statement->asCaseStatement() || ast->statement->asLabeledStatement()) { + newline(); + accept(ast->statement); + } else { + indent(); + newline(); + accept(ast->statement); + deindent(); + newline(); + } + return false; +} + +bool PrettyPrinter::visit(CastExpressionAST *ast) +{ + out << '('; + accept(ast->type_id); + out << ')'; + accept(ast->expression); + return false; +} + +bool PrettyPrinter::visit(CatchClauseAST *ast) +{ + out << "catch"; + out << '('; + accept(ast->exception_declaration); + out << ')'; + accept(ast->statement); + return false; +} + +bool PrettyPrinter::visit(ClassSpecifierAST *ast) +{ + out << spell(ast->classkey_token); + out << ' '; + if (ast->attributes) { + accept(ast->attributes); + out << ' '; + } + accept(ast->name); + if (ast->colon_token) { + out << ':'; + out << ' '; + for (BaseSpecifierAST *it = ast->base_clause; it; it = it->next) { + accept(it); + if (it->next) + out << ", "; + } + } + newline(); + out << '{'; + if (ast->member_specifiers) { + indent(); + newline(); + if (ast->member_specifiers) { + for (DeclarationAST *it = ast->member_specifiers; it; it = it->next) { + accept(it); + if (it->next) + newline(); + } + } + deindent(); + newline(); + } + out << '}'; + return false; +} + +bool PrettyPrinter::visit(CompoundStatementAST *ast) +{ + out << '{'; + if (ast->statements) { + indent(); + newline(); + for (StatementAST *it = ast->statements; it; it = it->next) { + accept(it); + if (it->next) + newline(); + } + deindent(); + newline(); + } + out << '}'; + return false; +} + +bool PrettyPrinter::visit(ConditionAST *ast) +{ + for (SpecifierAST *it = ast->type_specifier; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + if (ast->declarator) { + if (ast->type_specifier) + out << ' '; + + accept(ast->declarator); + } + return false; +} + +bool PrettyPrinter::visit(ConditionalExpressionAST *ast) +{ + accept(ast->condition); + out << '?'; + accept(ast->left_expression); + out << ':'; + accept(ast->right_expression); + return false; +} + +bool PrettyPrinter::visit(ContinueStatementAST *) +{ + out << "continue"; + out << ';'; + return false; +} + +bool PrettyPrinter::visit(ConversionFunctionIdAST *ast) +{ + out << "operator"; + out << ' '; + for (SpecifierAST *it = ast->type_specifier; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + for (PtrOperatorAST *it = ast->ptr_operators; it; it = it->next) { + accept(it); + } + return false; +} + +bool PrettyPrinter::visit(CppCastExpressionAST *ast) +{ + out << spell(ast->cast_token); + out << '<'; + out << ' '; + accept(ast->type_id); + out << ' '; + out << '>'; + out << '('; + accept(ast->expression); + out << ')'; + return false; +} + +bool PrettyPrinter::visit(CtorInitializerAST *ast) +{ + out << ':'; + out << ' '; + for (MemInitializerAST *it = ast->member_initializers; it; it = it->next) { + accept(it->name); + out << '('; + accept(it->expression); + out << ')'; + if (it->next) + out << ", "; + } + return false; +} + +bool PrettyPrinter::visit(DeclaratorAST *ast) +{ + for (PtrOperatorAST *it = ast->ptr_operators; it; it = it->next) { + accept(it); + } + if (ast->core_declarator) { + if (ast->ptr_operators) + out << ' '; + accept(ast->core_declarator); + } + for (PostfixDeclaratorAST *it = ast->postfix_declarators; it; it = it->next) { + accept(it); + } + for (SpecifierAST *it = ast->attributes; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + if (ast->initializer) { + out << ' '; + out << '='; + out << ' '; + accept(ast->initializer); + } + return false; +} + +bool PrettyPrinter::visit(DeclarationStatementAST *ast) +{ + accept(ast->declaration); + return false; +} + +bool PrettyPrinter::visit(DeclaratorIdAST *ast) +{ + accept(ast->name); + return false; +} + +bool PrettyPrinter::visit(DeclaratorListAST *ast) +{ + for (DeclaratorListAST *it = ast; it; it = it->next) { + accept(it->declarator); + if (it->next) + out << ", "; + } + return false; +} + +bool PrettyPrinter::visit(DeleteExpressionAST *ast) +{ + if (ast->scope_token) + out << "::"; + out << "delete"; + if (ast->expression) { + out << ' '; + accept(ast->expression); + } + return false; +} + +bool PrettyPrinter::visit(DestructorNameAST *ast) +{ + out << '~'; + out << spell(ast->identifier_token); + return false; +} + +bool PrettyPrinter::visit(DoStatementAST *ast) +{ + out << "do"; + if (ast->statement) { + out << ' '; + accept(ast->statement); + } + out << "while"; + out << '('; + accept(ast->expression); + out << ')'; + out << ';'; + return false; +} + +bool PrettyPrinter::visit(ElaboratedTypeSpecifierAST *ast) +{ + out << spell(ast->classkey_token); + if (ast->name) { + out << ' '; + accept(ast->name); + } + return false; +} + +bool PrettyPrinter::visit(EmptyDeclarationAST *) +{ + out << ';'; + return false; +} + +bool PrettyPrinter::visit(EnumSpecifierAST *ast) +{ + out << "enum"; + if (ast->name) { + out << ' '; + accept(ast->name); + } + out << ' '; + out << '{'; + if (ast->enumerators) { + indent(); + newline(); + for (EnumeratorAST *it = ast->enumerators; it; it = it->next) { + accept(it); + if (it->next) { + out << ", "; + newline(); + } + } + deindent(); + newline(); + } + out << '}'; + return false; +} + +bool PrettyPrinter::visit(EnumeratorAST *ast) +{ + out << spell(ast->identifier_token); + if (ast->equal_token) { + out << ' '; + out << '='; + out << ' '; + accept(ast->expression); + } + return false; +} + +bool PrettyPrinter::visit(ExceptionDeclarationAST *ast) +{ + for (SpecifierAST *it = ast->type_specifier; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + if (ast->declarator) { + if (ast->type_specifier) + out << ' '; + accept(ast->declarator); + } + if (ast->dot_dot_dot_token) + out << "..."; + return false; +} + +bool PrettyPrinter::visit(ExceptionSpecificationAST *ast) +{ + out << "throw"; + out << '('; + if (ast->dot_dot_dot_token) + out << "..."; + else { + for (ExpressionListAST *it = ast->type_ids; it; it = it->next) { + accept(it->expression); + if (it->next) + out << ", "; + } + } + out << ')'; + return false; +} + +bool PrettyPrinter::visit(ExpressionListAST *ast) +{ + for (ExpressionListAST *it = ast; it; it = it->next) { + accept(it->expression); + if (it->next) + out << ", "; + } + return false; +} + +bool PrettyPrinter::visit(ExpressionOrDeclarationStatementAST *ast) +{ + accept(ast->declaration); + return false; +} + +bool PrettyPrinter::visit(ExpressionStatementAST *ast) +{ + accept(ast->expression); + out << ';'; + return false; +} + +bool PrettyPrinter::visit(ForStatementAST *ast) +{ + out << "for"; + out << ' '; + out << '('; + accept(ast->initializer); + accept(ast->condition); + out << ';'; + accept(ast->expression); + out << ')'; + accept(ast->statement); + return false; +} + +bool PrettyPrinter::visit(FunctionDeclaratorAST *ast) +{ + out << '('; + accept(ast->parameters); + out << ')'; + for (SpecifierAST *it = ast->cv_qualifier_seq; it; it = it->next) { + out << ' '; + accept(it); + } + if (ast->exception_specification) { + out << ' '; + accept(ast->exception_specification); + } + return false; +} + +bool PrettyPrinter::visit(FunctionDefinitionAST *ast) +{ + for (SpecifierAST *it = ast->decl_specifier_seq; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + if (ast->declarator) { + if (ast->decl_specifier_seq) + out << ' '; + accept(ast->declarator); + } + accept(ast->ctor_initializer); + newline(); + accept(ast->function_body); + if (ast->next) + newline(); // one extra line after the function definiton. + return false; +} + +bool PrettyPrinter::visit(GotoStatementAST *ast) +{ + out << "goto"; + out << ' '; + out << spell(ast->identifier_token); + out << ';'; + return false; +} + +bool PrettyPrinter::visit(IfStatementAST *ast) +{ + out << "if"; + out << ' '; + out << '('; + accept(ast->condition); + out << ')'; + if (ast->statement->asCompoundStatement()) { + out << ' '; + accept(ast->statement); + } else { + indent(); + newline(); + accept(ast->statement); + deindent(); + newline(); + } + if (ast->else_token) { + out << "else"; + out << ' '; + accept(ast->else_statement); + } + return false; +} + +bool PrettyPrinter::visit(LabeledStatementAST *ast) +{ + out << spell(ast->label_token); + out << ':'; + accept(ast->statement); + return false; +} + +bool PrettyPrinter::visit(LinkageBodyAST *ast) +{ + out << '{'; + if (ast->declarations) { + indent(); + newline(); + for (DeclarationAST *it = ast->declarations; it; it = it->next) { + accept(it); + if (it->next) + newline(); + } + deindent(); + newline(); + } + out << '}'; + return false; +} + +bool PrettyPrinter::visit(LinkageSpecificationAST *ast) +{ + out << "extern"; + out << ' '; + if (ast->extern_type) { + out << '"' << spell(ast->extern_type) << '"'; + out << ' '; + } + + accept(ast->declaration); + return false; +} + +bool PrettyPrinter::visit(MemInitializerAST *ast) +{ + accept(ast->name); + out << '('; + accept(ast->expression); + out << ')'; + return false; +} + +bool PrettyPrinter::visit(MemberAccessAST *ast) +{ + out << spell(ast->access_token); + if (ast->template_token) { + out << "template"; + out << ' '; + } + accept(ast->member_name); + return false; +} + +bool PrettyPrinter::visit(NamedTypeSpecifierAST *ast) +{ + accept(ast->name); + return false; +} + +bool PrettyPrinter::visit(NamespaceAST *ast) +{ + out << "namespace"; + if (ast->identifier_token) { + out << ' '; + out << spell(ast->identifier_token); + } + for (SpecifierAST *it = ast->attributes; it; it = it->next) { + out << ' '; + accept(it); + } + out << ' '; + accept(ast->linkage_body); + return false; +} + +bool PrettyPrinter::visit(NamespaceAliasDefinitionAST *ast) +{ + out << "namespace"; + out << ' '; + out << spell(ast->namespace_name); + out << ' '; + out << '='; + out << ' '; + accept(ast->name); + out << ';'; + return false; +} + +bool PrettyPrinter::visit(NestedDeclaratorAST *ast) +{ + out << '('; + accept(ast->declarator); + out << ')'; + return false; +} + +bool PrettyPrinter::visit(NestedExpressionAST *ast) +{ + out << '('; + accept(ast->expression); + out << ')'; + return false; +} + +bool PrettyPrinter::visit(NestedNameSpecifierAST *ast) +{ + accept(ast->class_or_namespace_name); + if (ast->scope_token) + out << "::"; + return false; +} + +bool PrettyPrinter::visit(NewDeclaratorAST *ast) +{ + for (PtrOperatorAST *it = ast->ptr_operators; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + if (ast->declarator) + accept(ast->declarator); + return false; +} + +bool PrettyPrinter::visit(NewExpressionAST *ast) +{ + if (ast->scope_token) + out << "::"; + out << "new"; + out << ' '; + if (ast->expression) { + accept(ast->expression); + if (ast->type_id) + out << ' '; + } + if (ast->type_id) { + accept(ast->type_id); + if (ast->new_type_id) + out << ' '; + } + if (ast->new_type_id) { + accept(ast->new_type_id); + if (ast->new_initializer) + out << ' '; + } + accept(ast->new_initializer); + return false; +} + +bool PrettyPrinter::visit(NewInitializerAST *ast) +{ + out << '('; + accept(ast->expression); + out << ')'; + return false; +} + +bool PrettyPrinter::visit(NewTypeIdAST *ast) +{ + for (SpecifierAST *it = ast->type_specifier; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + if (ast->type_specifier) + out << ' '; + if (ast->new_initializer) { + accept(ast->new_initializer); + if (ast->new_declarator) + out << ' '; + } + accept(ast->new_declarator); + return false; +} + +bool PrettyPrinter::visit(NumericLiteralAST *ast) +{ + switch (tokenKind(ast->token)) { + case T_CHAR_LITERAL: + out << '\'' << spell(ast->token) << '\''; + break; + case T_WIDE_CHAR_LITERAL: + out << "L\'" << spell(ast->token) << '\''; + break; + + default: + out << spell(ast->token); + } + return false; +} + +bool PrettyPrinter::visit(OperatorAST *ast) +{ + out << spell(ast->op_token); + if (ast->open_token) { + out << spell(ast->open_token); + out << spell(ast->close_token); + } + return false; +} + +bool PrettyPrinter::visit(OperatorFunctionIdAST *ast) +{ + out << "operator"; + out << ' '; + accept(ast->op); + return false; +} + +bool PrettyPrinter::visit(ParameterDeclarationAST *ast) +{ + for (SpecifierAST *it = ast->type_specifier; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + if (ast->declarator) { + out << ' '; + accept(ast->declarator); + } + if (ast->equal_token) { + out << ' '; + out << '='; + out << ' '; + } + accept(ast->expression); + return false; +} + +bool PrettyPrinter::visit(ParameterDeclarationClauseAST *ast) +{ + for (DeclarationAST *it = ast->parameter_declarations; it; it = it->next) { + accept(it); + if (it->next) + out << ", "; + } + return false; +} + +bool PrettyPrinter::visit(PointerAST *ast) +{ + out << '*'; + for (SpecifierAST *it = ast->cv_qualifier_seq; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + return false; +} + +bool PrettyPrinter::visit(PointerToMemberAST *ast) +{ + if (ast->global_scope_token) + out << "::"; + for (NestedNameSpecifierAST *it = ast->nested_name_specifier; it; it = it->next) { + accept(it); + } + out << '*'; + for (SpecifierAST *it = ast->cv_qualifier_seq; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + return false; +} + +bool PrettyPrinter::visit(PostIncrDecrAST *ast) +{ + out << spell(ast->incr_decr_token); + return false; +} + +bool PrettyPrinter::visit(PostfixExpressionAST *ast) +{ + accept(ast->base_expression); + for (PostfixAST *it = ast->postfix_expressions; it; it = it->next) { + accept(it); + } + return false; +} + +bool PrettyPrinter::visit(QualifiedNameAST *ast) +{ + if (ast->global_scope_token) + out << "::"; + for (NestedNameSpecifierAST *it = ast->nested_name_specifier; it; it = it->next) { + accept(it); + } + accept(ast->unqualified_name); + return false; +} + +bool PrettyPrinter::visit(ReferenceAST *) +{ + out << '&'; + return false; +} + +bool PrettyPrinter::visit(ReturnStatementAST *ast) +{ + out << "return"; + if (ast->expression) { + out << ' '; + accept(ast->expression); + } + out << ';'; + return false; +} + +bool PrettyPrinter::visit(SimpleDeclarationAST *ast) +{ + for (SpecifierAST *it = ast->decl_specifier_seq; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + if (ast->declarators) { + if (ast->decl_specifier_seq) + out << ' '; + + for (DeclaratorListAST *it = ast->declarators; it; it = it->next) { + accept(it->declarator); + if (it->next) + out << ", "; + } + } + out << ';'; + return false; +} + +bool PrettyPrinter::visit(SimpleNameAST *ast) +{ + out << spell(ast->identifier_token); + return false; +} + +bool PrettyPrinter::visit(SimpleSpecifierAST *ast) +{ + out << spell(ast->specifier_token); + return false; +} + +bool PrettyPrinter::visit(SizeofExpressionAST *ast) +{ + out << "sizeof"; + out << ' '; + accept(ast->expression); + return false; +} + +bool PrettyPrinter::visit(StringLiteralAST *ast) +{ + for (StringLiteralAST *it = ast; it; it = it->next) { + if (tokenKind(ast->token) == T_STRING_LITERAL) + out << '"' << spell(ast->token) << '"'; + else + out << "L\"" << spell(ast->token) << '"'; + if (it->next) + out << ' '; + } + return false; +} + +bool PrettyPrinter::visit(SwitchStatementAST *ast) +{ + out << "switch"; + out << ' '; + out << '('; + accept(ast->condition); + out << ')'; + accept(ast->statement); + return false; +} + +bool PrettyPrinter::visit(TemplateArgumentListAST *ast) +{ + for (TemplateArgumentListAST *it = ast; it; it = it->next) { + accept(it->template_argument); + if (it->next) + out << ", "; + } + return false; +} + +bool PrettyPrinter::visit(TemplateDeclarationAST *ast) +{ + if (ast->export_token) { + out << "export"; + out << ' '; + } + out << "template"; + out << ' '; + out << '<'; + if (ast->template_parameters) { + out << ' '; + for (DeclarationAST *it = ast->template_parameters; it; it = it->next) { + accept(it); + if (it->next) + out << ", "; + } + out << ' '; + } + out << '>'; + newline(); + accept(ast->declaration); + return false; +} + +bool PrettyPrinter::visit(TemplateIdAST *ast) +{ + out << spell(ast->identifier_token); + out << '<'; + if (ast->template_arguments) { + out << ' '; + for (TemplateArgumentListAST *it = ast->template_arguments; it; it = it->next) { + accept(it->template_argument); + if (it->next) + out << ", "; + } + out << ' '; + } + out << '>'; + return false; +} + +bool PrettyPrinter::visit(TemplateTypeParameterAST *ast) +{ + out << "template"; + out << ' '; + out << '<'; + if (ast->template_parameters) { + out << ' '; + for (DeclarationAST *it = ast->template_parameters; it; it = it->next) { + accept(it); + if (it->next) + out << ", "; + } + out << ' '; + } + out << '>'; + out << ' '; + out << "class"; + out << ' '; + accept(ast->name); + if (ast->equal_token) { + out << ' '; + out << '='; + out << ' '; + accept(ast->type_id); + } + return false; +} + +bool PrettyPrinter::visit(ThisExpressionAST *) +{ + out << "this"; + return false; +} + +bool PrettyPrinter::visit(ThrowExpressionAST *ast) +{ + out << "throw"; + out << ' '; + accept(ast->expression); + return false; +} + +bool PrettyPrinter::visit(TranslationUnitAST *ast) +{ + for (DeclarationAST *it = ast->declarations; it; it = it->next) { + accept(it); + if (it->next) + newline(); + } + return false; +} + +bool PrettyPrinter::visit(TryBlockStatementAST *ast) +{ + out << "try"; + out << ' '; + accept(ast->statement); + for (CatchClauseAST *it = ast->catch_clause_seq; it; it = it->next) { + accept(it); + } + return false; +} + +bool PrettyPrinter::visit(TypeConstructorCallAST *ast) +{ + for (SpecifierAST *it = ast->type_specifier; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + out << '('; + for (ExpressionListAST *it = ast->expression_list; it; it = it->next) { + accept(it->expression); + if (it->next) + out << ", "; + } + out << ')'; + return false; +} + +bool PrettyPrinter::visit(TypeIdAST *ast) +{ + for (SpecifierAST *it = ast->type_specifier; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + if (ast->type_specifier && ast->declarator) { + out << ' '; + accept(ast->declarator); + } + return false; +} + +bool PrettyPrinter::visit(TypeidExpressionAST *ast) +{ + out << "typeid"; + out << '('; + accept(ast->expression); + out << ')'; + return false; +} + +bool PrettyPrinter::visit(TypeofSpecifierAST *ast) +{ + out << "typeof"; + out << '('; + accept(ast->expression); + out << ')'; + return false; +} + +bool PrettyPrinter::visit(TypenameCallExpressionAST *ast) +{ + out << "typename"; + out << ' '; + accept(ast->name); + out << '('; + for (ExpressionListAST *it = ast->expression_list; it; it = it->next) { + accept(it->expression); + if (it->next) + out << ", "; + } + out << ')'; + return false; +} + +bool PrettyPrinter::visit(TypenameTypeParameterAST *ast) +{ + out << spell(ast->classkey_token); + if (ast->name) { + out << ' '; + accept(ast->name); + } + if (ast->equal_token) { + out << ' '; + out << '='; + out << ' '; + accept(ast->type_id); + } + return false; +} + +bool PrettyPrinter::visit(UnaryExpressionAST *ast) +{ + out << spell(ast->unary_op_token); + accept(ast->expression); + return false; +} + +bool PrettyPrinter::visit(UsingAST *ast) +{ + out << "using"; + out << ' '; + if (ast->typename_token) { + out << "typename"; + out << ' '; + } + accept(ast->name); + out << ';'; + return false; +} + +bool PrettyPrinter::visit(UsingDirectiveAST *ast) +{ + out << "using"; + out << ' '; + out << "namespace"; + out << ' '; + accept(ast->name); + out << ';'; + return false; +} + +bool PrettyPrinter::visit(WhileStatementAST *ast) +{ + out << "while"; + out << ' '; + out << '('; + accept(ast->condition); + out << ')'; + out << ' '; + if (ast->statement && ast->statement->asCompoundStatement()) + accept(ast->statement); + else { + indent(); + newline(); + accept(ast->statement); + deindent(); + newline(); + } + return false; +} + +bool PrettyPrinter::visit(QtMethodAST *ast) +{ + out << ast->method_token; + out << '('; + accept(ast->declarator); + out << ')'; + return false; +} + +bool PrettyPrinter::visit(CompoundLiteralAST *ast) +{ + out << '('; + accept(ast->type_id); + out << ')'; + out << ' '; + accept(ast->initializer); + return false; +} diff --git a/src/shared/cplusplus/PrettyPrinter.h b/src/shared/cplusplus/PrettyPrinter.h new file mode 100644 index 0000000000..c69ea2cf54 --- /dev/null +++ b/src/shared/cplusplus/PrettyPrinter.h @@ -0,0 +1,163 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. +** +***************************************************************************/ + +#ifndef CPLUSPLUS_PRETTYPRINTER_H +#define CPLUSPLUS_PRETTYPRINTER_H + +#include "CPlusPlusForwardDeclarations.h" +#include "ASTVisitor.h" + +#include <iosfwd> + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +class PrettyPrinter: protected ASTVisitor +{ +public: + PrettyPrinter(Control *control, std::ostream &out); + + void operator()(AST *ast); + +protected: + virtual bool visit(AccessDeclarationAST *ast); + virtual bool visit(ArrayAccessAST *ast); + virtual bool visit(ArrayDeclaratorAST *ast); + virtual bool visit(ArrayInitializerAST *ast); + virtual bool visit(AsmDefinitionAST *ast); + virtual bool visit(AttributeSpecifierAST *ast); + virtual bool visit(AttributeAST *ast); + virtual bool visit(BaseSpecifierAST *ast); + virtual bool visit(BinaryExpressionAST *ast); + virtual bool visit(BoolLiteralAST *ast); + virtual bool visit(BreakStatementAST *ast); + virtual bool visit(CallAST *ast); + virtual bool visit(CaseStatementAST *ast); + virtual bool visit(CastExpressionAST *ast); + virtual bool visit(CatchClauseAST *ast); + virtual bool visit(ClassSpecifierAST *ast); + virtual bool visit(CompoundLiteralAST *ast); + virtual bool visit(CompoundStatementAST *ast); + virtual bool visit(ConditionAST *ast); + virtual bool visit(ConditionalExpressionAST *ast); + virtual bool visit(ContinueStatementAST *ast); + virtual bool visit(ConversionFunctionIdAST *ast); + virtual bool visit(CppCastExpressionAST *ast); + virtual bool visit(CtorInitializerAST *ast); + virtual bool visit(DeclaratorAST *ast); + virtual bool visit(DeclarationStatementAST *ast); + virtual bool visit(DeclaratorIdAST *ast); + virtual bool visit(DeclaratorListAST *ast); + virtual bool visit(DeleteExpressionAST *ast); + virtual bool visit(DestructorNameAST *ast); + virtual bool visit(DoStatementAST *ast); + virtual bool visit(ElaboratedTypeSpecifierAST *ast); + virtual bool visit(EmptyDeclarationAST *ast); + virtual bool visit(EnumSpecifierAST *ast); + virtual bool visit(EnumeratorAST *ast); + virtual bool visit(ExceptionDeclarationAST *ast); + virtual bool visit(ExceptionSpecificationAST *ast); + virtual bool visit(ExpressionListAST *ast); + virtual bool visit(ExpressionOrDeclarationStatementAST *ast); + virtual bool visit(ExpressionStatementAST *ast); + virtual bool visit(ForStatementAST *ast); + virtual bool visit(FunctionDeclaratorAST *ast); + virtual bool visit(FunctionDefinitionAST *ast); + virtual bool visit(GotoStatementAST *ast); + virtual bool visit(IfStatementAST *ast); + virtual bool visit(LabeledStatementAST *ast); + virtual bool visit(LinkageBodyAST *ast); + virtual bool visit(LinkageSpecificationAST *ast); + virtual bool visit(MemInitializerAST *ast); + virtual bool visit(MemberAccessAST *ast); + virtual bool visit(NamedTypeSpecifierAST *ast); + virtual bool visit(NamespaceAST *ast); + virtual bool visit(NamespaceAliasDefinitionAST *ast); + virtual bool visit(NestedDeclaratorAST *ast); + virtual bool visit(NestedExpressionAST *ast); + virtual bool visit(NestedNameSpecifierAST *ast); + virtual bool visit(NewDeclaratorAST *ast); + virtual bool visit(NewExpressionAST *ast); + virtual bool visit(NewInitializerAST *ast); + virtual bool visit(NewTypeIdAST *ast); + virtual bool visit(NumericLiteralAST *ast); + virtual bool visit(OperatorAST *ast); + virtual bool visit(OperatorFunctionIdAST *ast); + virtual bool visit(ParameterDeclarationAST *ast); + virtual bool visit(ParameterDeclarationClauseAST *ast); + virtual bool visit(PointerAST *ast); + virtual bool visit(PointerToMemberAST *ast); + virtual bool visit(PostIncrDecrAST *ast); + virtual bool visit(PostfixExpressionAST *ast); + virtual bool visit(QualifiedNameAST *ast); + virtual bool visit(ReferenceAST *ast); + virtual bool visit(ReturnStatementAST *ast); + virtual bool visit(SimpleDeclarationAST *ast); + virtual bool visit(SimpleNameAST *ast); + virtual bool visit(SimpleSpecifierAST *ast); + virtual bool visit(SizeofExpressionAST *ast); + virtual bool visit(StringLiteralAST *ast); + virtual bool visit(SwitchStatementAST *ast); + virtual bool visit(TemplateArgumentListAST *ast); + virtual bool visit(TemplateDeclarationAST *ast); + virtual bool visit(TemplateIdAST *ast); + virtual bool visit(TemplateTypeParameterAST *ast); + virtual bool visit(ThisExpressionAST *ast); + virtual bool visit(ThrowExpressionAST *ast); + virtual bool visit(TranslationUnitAST *ast); + virtual bool visit(TryBlockStatementAST *ast); + virtual bool visit(TypeConstructorCallAST *ast); + virtual bool visit(TypeIdAST *ast); + virtual bool visit(TypeidExpressionAST *ast); + virtual bool visit(TypeofSpecifierAST *ast); + virtual bool visit(TypenameCallExpressionAST *ast); + virtual bool visit(TypenameTypeParameterAST *ast); + virtual bool visit(UnaryExpressionAST *ast); + virtual bool visit(UsingAST *ast); + virtual bool visit(UsingDirectiveAST *ast); + virtual bool visit(WhileStatementAST *ast); + virtual bool visit(QtMethodAST *ast); + + void indent(); + void deindent(); + void newline(); + +private: + std::ostream &out; + unsigned depth; +}; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_PRETTYPRINTER_H diff --git a/src/shared/cplusplus/Scope.cpp b/src/shared/cplusplus/Scope.cpp new file mode 100644 index 0000000000..bdca9f8536 --- /dev/null +++ b/src/shared/cplusplus/Scope.cpp @@ -0,0 +1,310 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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 "Scope.h" +#include "Symbols.h" +#include "Names.h" +#include "Literals.h" +#include <cstdlib> +#include <cassert> +#include <cstring> +#include <iostream> + +CPLUSPLUS_BEGIN_NAMESPACE + +Scope::Scope(ScopedSymbol *owner) + : _owner(owner), + _symbols(0), + _allocatedSymbols(0), + _symbolCount(-1), + _hash(0), + _hashSize(0), + _uses(0), + _allocatedUses(0), + _useCount(-1) +{ } + +Scope::~Scope() +{ + if (_symbols) + free(_symbols); + if (_hash) + free(_hash); + if (_uses) + free(_uses); +} + +ScopedSymbol *Scope::owner() const +{ return _owner; } + +void Scope::setOwner(ScopedSymbol *owner) +{ _owner = owner; } + +Scope *Scope::enclosingScope() const +{ + if (! _owner) + return 0; + + return _owner->scope(); +} + +Scope *Scope::enclosingNamespaceScope() const +{ + Scope *scope = enclosingScope(); + for (; scope; scope = scope->enclosingScope()) { + if (scope->owner()->isNamespace()) + break; + } + return scope; +} + +Scope *Scope::enclosingClassScope() const +{ + Scope *scope = enclosingScope(); + for (; scope; scope = scope->enclosingScope()) { + if (scope->owner()->isClass()) + break; + } + return scope; +} + +Scope *Scope::enclosingEnumScope() const +{ + Scope *scope = enclosingScope(); + for (; scope; scope = scope->enclosingScope()) { + if (scope->owner()->isEnum()) + break; + } + return scope; +} + +Scope *Scope::enclosingFunctionScope() const +{ + Scope *scope = enclosingScope(); + for (; scope; scope = scope->enclosingScope()) { + if (scope->owner()->isFunction()) + break; + } + return scope; +} + +Scope *Scope::enclosingBlockScope() const +{ + Scope *scope = enclosingScope(); + for (; scope; scope = scope->enclosingScope()) { + if (scope->owner()->isBlock()) + break; + } + return scope; +} + +bool Scope::isNamespaceScope() const +{ return dynamic_cast<const Namespace *>(_owner) != 0; } + +bool Scope::isClassScope() const +{ return dynamic_cast<const Class *>(_owner) != 0; } + +bool Scope::isEnumScope() const +{ return dynamic_cast<const Enum *>(_owner) != 0; } + +bool Scope::isBlockScope() const +{ return dynamic_cast<const Block *>(_owner) != 0; } + +bool Scope::isPrototypeScope() const +{ + if (const Function *f = dynamic_cast<const Function *>(_owner)) + return f->arguments() == this; + return false; +} + +bool Scope::isFunctionScope() const +{ + if (const Function *f = dynamic_cast<const Function *>(_owner)) + return f->arguments() != this; + return false; +} + +void Scope::enterSymbol(Symbol *symbol) +{ + if (++_symbolCount == _allocatedSymbols) { + _allocatedSymbols <<= 1; + if (! _allocatedSymbols) + _allocatedSymbols = DefaultInitialSize; + + _symbols = reinterpret_cast<Symbol **>(realloc(_symbols, sizeof(Symbol *) * _allocatedSymbols)); + } + + assert(! symbol->_scope || symbol->scope() == this); + symbol->_index = _symbolCount; + symbol->_scope = this; + _symbols[_symbolCount] = symbol; + + if (_symbolCount >= _hashSize * 0.6) + rehash(); + else { + const unsigned h = hashValue(symbol); + symbol->_next = _hash[h]; + _hash[h] = symbol; + } +} + +Symbol *Scope::lookat(Identifier *id) const +{ + if (! _hash) + return 0; + + const unsigned h = id->hashCode() % _hashSize; + Symbol *symbol = _hash[h]; + for (; symbol; symbol = symbol->_next) { + Name *identity = symbol->identity(); + if (NameId *nameId = identity->asNameId()) { + if (nameId->identifier()->isEqualTo(id)) + break; + } else if (TemplateNameId *t = identity->asTemplateNameId()) { + if (t->identifier()->isEqualTo(id)) + break; + } else if (DestructorNameId *d = identity->asDestructorNameId()) { + if (d->identifier()->isEqualTo(id)) + break; + } else if (identity->isQualifiedNameId()) { + assert(0); + } + } + return symbol; +} + +Symbol *Scope::lookat(int operatorId) const +{ + if (! _hash) + return 0; + + const unsigned h = operatorId % _hashSize; + Symbol *symbol = _hash[h]; + for (; symbol; symbol = symbol->_next) { + Name *identity = symbol->identity(); + if (OperatorNameId *op = identity->asOperatorNameId()) { + if (op->kind() == operatorId) + break; + } + } + return symbol; +} + +void Scope::rehash() +{ + _hashSize <<= 1; + + if (! _hashSize) + _hashSize = DefaultInitialSize; + + _hash = reinterpret_cast<Symbol **>(realloc(_hash, sizeof(Symbol *) * _hashSize)); + memset(_hash, 0, sizeof(Symbol *) * _hashSize); + + for (int index = 0; index < _symbolCount + 1; ++index) { + Symbol *symbol = _symbols[index]; + const unsigned h = hashValue(symbol); + symbol->_next = _hash[h]; + _hash[h] = symbol; + } +} + +unsigned Scope::hashValue(Symbol *symbol) const +{ + if (! symbol) + return 0; + + return symbol->hashCode() % _hashSize; +} + +bool Scope::isEmpty() const +{ return _symbolCount == -1; } + +unsigned Scope::symbolCount() const +{ return _symbolCount + 1; } + +Symbol *Scope::symbolAt(unsigned index) const +{ + if (! _symbols) + return 0; + return _symbols[index]; +} + +Scope::iterator Scope::firstSymbol() const +{ return _symbols; } + +Scope::iterator Scope::lastSymbol() const +{ return _symbols + _symbolCount + 1; } + +unsigned Scope::useCount() const +{ return _useCount + 1; } + +Use *Scope::useAt(unsigned index) const +{ return &_uses[index]; } + +void Scope::addUse(unsigned sourceOffset, Name *name) +{ +#ifdef CPLUSPLUS_WITH_USES + if (++_useCount == _allocatedUses) { + _allocatedUses += 4; + _uses = reinterpret_cast<Use *>(realloc(_uses, _allocatedUses * sizeof(Use))); + } + + Symbol *lastVisibleSymbol; + if (_symbolCount == -1) + lastVisibleSymbol = owner(); + else + lastVisibleSymbol = _symbols[_symbolCount]; + _uses[_useCount].init(sourceOffset, name, lastVisibleSymbol); +#endif +} + +CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/Scope.h b/src/shared/cplusplus/Scope.h new file mode 100644 index 0000000000..44387718ff --- /dev/null +++ b/src/shared/cplusplus/Scope.h @@ -0,0 +1,198 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. + +#ifndef CPLUSPLUS_SCOPE_H +#define CPLUSPLUS_SCOPE_H + +#include "CPlusPlusForwardDeclarations.h" + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +class CPLUSPLUS_EXPORT Use +{ +public: + inline Name *name() const + { return _name; } + + inline unsigned sourceOffset() const + { return _sourceOffset; } + + inline Symbol *lastVisibleSymbol() const + { return _lastVisibleSymbol; } + +private: + void init(unsigned sourceOffset, Name *name, Symbol *lastVisibleSymbol) + { + _sourceOffset = sourceOffset; + _name = name; + _lastVisibleSymbol = lastVisibleSymbol; + } + + unsigned _sourceOffset; + + Name *_name; + Symbol *_lastVisibleSymbol; + + friend class Scope; +}; + +class CPLUSPLUS_EXPORT Scope +{ + Scope(const Scope &other); + void operator =(const Scope &other); + +public: + typedef Symbol **iterator; + +public: + /// Constructs an empty Scope. + Scope(ScopedSymbol *owner = 0); + + /// Destroy this scope. + ~Scope(); + + /// Returns this scope's owner Symbol. + ScopedSymbol *owner() const; + + /// Sets this scope's owner Symbol. + void setOwner(ScopedSymbol *owner); // ### remove me + + /// Returns the enclosing scope. + Scope *enclosingScope() const; + + /// Returns the eclosing namespace scope. + Scope *enclosingNamespaceScope() const; + + /// Returns the enclosing class scope. + Scope *enclosingClassScope() const; + + /// Returns the enclosing enum scope. + Scope *enclosingEnumScope() const; + + /// Rerturns the enclosing function scope. + Scope *enclosingFunctionScope() const; + + /// Rerturns the enclosing Block scope. + Scope *enclosingBlockScope() const; + + /// Returns true if this scope's owner is a Namespace Symbol. + bool isNamespaceScope() const; + + /// Returns true if this scope's owner is a Class Symbol. + bool isClassScope() const; + + /// Returns true if this scope's owner is an Enum Symbol. + bool isEnumScope() const; + + /// Returns true if this scope's owner is a Block Symbol. + bool isBlockScope() const; + + /// Returns true if this scope's owner is a Function Symbol. + bool isFunctionScope() const; + + /// Returns true if this scope's owner is a Prototype Symbol. + bool isPrototypeScope() const; + + /// Adds a Symbol to this Scope. + void enterSymbol(Symbol *symbol); + + /// Returns true if this Scope is empty; otherwise returns false. + bool isEmpty() const; + + /// Returns the number of symbols is in the scope. + unsigned symbolCount() const; + + /// Returns the Symbol at the given position. + Symbol *symbolAt(unsigned index) const; + + /// Returns the first Symbol in the scope. + iterator firstSymbol() const; + + /// Returns the last Symbol in the scope. + iterator lastSymbol() const; + + Symbol *lookat(Identifier *id) const; + Symbol *lookat(int operatorId) const; + + unsigned useCount() const; + Use *useAt(unsigned index) const; + void addUse(unsigned sourceOffset, Name *name); + +private: + /// Returns the hash value for the given Symbol. + unsigned hashValue(Symbol *symbol) const; + + /// Updates the hash table. + void rehash(); + +private: + enum { DefaultInitialSize = 11 }; + + ScopedSymbol *_owner; + + Symbol **_symbols; + int _allocatedSymbols; + int _symbolCount; + + Symbol **_hash; + int _hashSize; + + Use *_uses; + int _allocatedUses; + int _useCount; +}; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_SCOPE_H diff --git a/src/shared/cplusplus/Semantic.cpp b/src/shared/cplusplus/Semantic.cpp new file mode 100644 index 0000000000..41716eb5aa --- /dev/null +++ b/src/shared/cplusplus/Semantic.cpp @@ -0,0 +1,198 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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 "Semantic.h" +#include "TranslationUnit.h" +#include "Control.h" +#include "Scope.h" +#include "Symbols.h" +#include "Token.h" +#include "CheckSpecifier.h" +#include "CheckDeclaration.h" +#include "CheckDeclarator.h" +#include "CheckStatement.h" +#include "CheckExpression.h" +#include "CheckName.h" + +CPLUSPLUS_BEGIN_NAMESPACE + +class Semantic::Data +{ +public: + Data(Semantic *semantic, Control *control) + : semantic(semantic), + control(control), + visibility(Symbol::Public), + methodKey(Function::NormalMethod), + checkSpecifier(0), + checkDeclaration(0), + checkDeclarator(0), + checkExpression(0), + checkStatement(0), + checkName(0) + { } + + ~Data() + { + delete checkSpecifier; + delete checkDeclaration; + delete checkDeclarator; + delete checkExpression; + delete checkStatement; + delete checkName; + } + + Semantic *semantic; + Control *control; + int visibility; + int methodKey; + CheckSpecifier *checkSpecifier; + CheckDeclaration *checkDeclaration; + CheckDeclarator *checkDeclarator; + CheckExpression *checkExpression; + CheckStatement *checkStatement; + CheckName *checkName; +}; + +Semantic::Semantic(Control *control) +{ + d = new Data(this, control); + d->checkSpecifier = new CheckSpecifier(this); + d->checkDeclaration = new CheckDeclaration(this); + d->checkDeclarator = new CheckDeclarator(this); + d->checkExpression = new CheckExpression(this); + d->checkStatement = new CheckStatement(this); + d->checkName = new CheckName(this); +} + +Semantic::~Semantic() +{ delete d; } + +Control *Semantic::control() const +{ return d->control; } + +FullySpecifiedType Semantic::check(SpecifierAST *specifier, Scope *scope) +{ return d->checkSpecifier->check(specifier, scope); } + +void Semantic::check(DeclarationAST *declaration, Scope *scope, Scope *templateParameters) +{ d->checkDeclaration->check(declaration, scope, templateParameters); } + +FullySpecifiedType Semantic::check(DeclaratorAST *declarator, FullySpecifiedType type, + Scope *scope, Name **name) +{ return d->checkDeclarator->check(declarator, type, scope, name); } + +FullySpecifiedType Semantic::check(PtrOperatorAST *ptrOperators, FullySpecifiedType type, + Scope *scope) +{ return d->checkDeclarator->check(ptrOperators, type, scope); } + +FullySpecifiedType Semantic::check(ExpressionAST *expression, Scope *scope) +{ return d->checkExpression->check(expression, scope); } + +void Semantic::check(StatementAST *statement, Scope *scope) +{ d->checkStatement->check(statement, scope); } + +Name *Semantic::check(NameAST *name, Scope *scope) +{ return d->checkName->check(name, scope); } + +Name *Semantic::check(NestedNameSpecifierAST *name, Scope *scope) +{ return d->checkName->check(name, scope); } + +int Semantic::currentVisibility() const +{ return d->visibility; } + +int Semantic::switchVisibility(int visibility) +{ + int previousVisibility = d->visibility; + d->visibility = visibility; + return previousVisibility; +} + +int Semantic::currentMethodKey() const +{ return d->methodKey; } + +int Semantic::switchMethodKey(int methodKey) +{ + int previousMethodKey = d->methodKey; + d->methodKey = methodKey; + return previousMethodKey; +} + +int Semantic::visibilityForAccessSpecifier(int tokenKind) const +{ + switch (tokenKind) { + case T_PUBLIC: + return Symbol::Public; + case T_PROTECTED: + return Symbol::Protected; + case T_PRIVATE: + return Symbol::Private; + case T_SIGNALS: + return Symbol::Protected; + default: + return Symbol::Public; + } +} + +int Semantic::visibilityForClassKey(int tokenKind) const +{ + switch (tokenKind) { + case T_CLASS: + return Symbol::Private; + case T_STRUCT: + case T_UNION: + return Symbol::Public; + default: + return Symbol::Public; + } +} + +CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/Semantic.h b/src/shared/cplusplus/Semantic.h new file mode 100644 index 0000000000..ac7b1b8c86 --- /dev/null +++ b/src/shared/cplusplus/Semantic.h @@ -0,0 +1,109 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. + +#ifndef CPLUSPLUS_SEMANTIC_H +#define CPLUSPLUS_SEMANTIC_H + +#include "CPlusPlusForwardDeclarations.h" +#include "ASTfwd.h" + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +class CPLUSPLUS_EXPORT Semantic +{ + Semantic(const Semantic &other); + void operator =(const Semantic &other); + +public: + Semantic(Control *control); + virtual ~Semantic(); + + Control *control() const; + + FullySpecifiedType check(SpecifierAST *specifier, Scope *scope); + + FullySpecifiedType check(DeclaratorAST *declarator, FullySpecifiedType type, + Scope *scope, Name **name = 0); // ### ugly + + FullySpecifiedType check(PtrOperatorAST *ptrOperators, FullySpecifiedType type, + Scope *scope); + + FullySpecifiedType check(ExpressionAST *expression, Scope *scope); + + void check(DeclarationAST *declaration, Scope *scope, Scope *templateParameters = 0); + + void check(StatementAST *statement, Scope *scope); + + Name *check(NameAST *name, Scope *scope); + + Name *check(NestedNameSpecifierAST *name, Scope *scope); + + int currentVisibility() const; + int switchVisibility(int visibility); + + int currentMethodKey() const; + int switchMethodKey(int methodKey); + + int visibilityForClassKey(int tokenKind) const; + int visibilityForAccessSpecifier(int tokenKind) const; + +private: + class Data; + friend class Data; + Data *d; +}; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_SEMANTIC_H diff --git a/src/shared/cplusplus/SemanticCheck.cpp b/src/shared/cplusplus/SemanticCheck.cpp new file mode 100644 index 0000000000..27b1a56429 --- /dev/null +++ b/src/shared/cplusplus/SemanticCheck.cpp @@ -0,0 +1,72 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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 "SemanticCheck.h" +#include "Semantic.h" + +CPLUSPLUS_BEGIN_NAMESPACE + +SemanticCheck::SemanticCheck(Semantic *semantic) + : ASTVisitor(semantic->control()), + _semantic(semantic) +{ } + +SemanticCheck::~SemanticCheck() +{ } + +Semantic *SemanticCheck::semantic() const +{ return _semantic; } + +Control *SemanticCheck::control() const +{ return _semantic->control(); } + +CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/SemanticCheck.h b/src/shared/cplusplus/SemanticCheck.h new file mode 100644 index 0000000000..0ecdeac603 --- /dev/null +++ b/src/shared/cplusplus/SemanticCheck.h @@ -0,0 +1,78 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. + +#ifndef CPLUSPLUS_SEMANTICCHECK_H +#define CPLUSPLUS_SEMANTICCHECK_H + +#include "CPlusPlusForwardDeclarations.h" +#include "ASTVisitor.h" + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +class CPLUSPLUS_EXPORT SemanticCheck: public ASTVisitor +{ +public: + SemanticCheck(Semantic *semantic); + virtual ~SemanticCheck(); + + Control *control() const; + Semantic *semantic() const; + +private: + Semantic *_semantic; +}; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_SEMANTICCHECK_H diff --git a/src/shared/cplusplus/Symbol.cpp b/src/shared/cplusplus/Symbol.cpp new file mode 100644 index 0000000000..cdcd389118 --- /dev/null +++ b/src/shared/cplusplus/Symbol.cpp @@ -0,0 +1,421 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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 "Symbol.h" +#include "Symbols.h" +#include "Control.h" +#include "Names.h" +#include "TranslationUnit.h" +#include "Literals.h" +#include "MemoryPool.h" +#include "SymbolVisitor.h" +#include "NameVisitor.h" +#include <cstddef> +#include <cassert> + +CPLUSPLUS_BEGIN_NAMESPACE + +class Symbol::HashCode: protected NameVisitor +{ +public: + HashCode() + : _value(0) + { } + + virtual ~HashCode() + { } + + unsigned operator()(Name *name) + { + unsigned previousValue = switchValue(0); + accept(name); + return switchValue(previousValue); + } + +protected: + unsigned switchValue(unsigned value) + { + unsigned previousValue = _value; + _value = value; + return previousValue; + } + + virtual void visit(NameId *name) + { _value = name->identifier()->hashCode(); } + + virtual void visit(TemplateNameId *name) + { _value = name->identifier()->hashCode(); } + + virtual void visit(DestructorNameId *name) + { _value = name->identifier()->hashCode(); } + + virtual void visit(OperatorNameId *name) + { _value = unsigned(name->kind()); } + + virtual void visit(ConversionNameId *) + { _value = 0; } // ### TODO: implement me + + virtual void visit(QualifiedNameId *name) + { _value = operator()(name->unqualifiedNameId()); } + +private: + unsigned _value; +}; + +class Symbol::IdentityForName: protected NameVisitor +{ +public: + IdentityForName() + : _identity(0) + { } + + virtual ~IdentityForName() + { } + + Name *operator()(Name *name) + { + Name *previousIdentity = switchIdentity(0); + accept(name); + return switchIdentity(previousIdentity); + } + +protected: + Name *switchIdentity(Name *identity) + { + Name *previousIdentity = _identity; + _identity = identity; + return previousIdentity; + } + + virtual void visit(NameId *name) + { _identity = name; } + + virtual void visit(TemplateNameId *name) + { _identity = name; } + + virtual void visit(DestructorNameId *name) + { _identity = name; } + + virtual void visit(OperatorNameId *name) + { _identity = name; } + + virtual void visit(ConversionNameId *name) + { _identity = name; } + + virtual void visit(QualifiedNameId *name) + { _identity = name->unqualifiedNameId(); } + +private: + Name *_identity; +}; + +Symbol::Symbol(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name) + : _control(translationUnit->control()), + _sourceLocation(sourceLocation), + _sourceOffset(0), + _name(0), + _hashCode(0), + _storage(Symbol::NoStorage), + _visibility(Symbol::Public), + _scope(0), + _index(0), + _next(0) +{ + if (sourceLocation) + _sourceOffset = translationUnit->tokenAt(sourceLocation).offset; + + setName(name); +} + +Symbol::~Symbol() +{ } + +Control *Symbol::control() const +{ return _control; } + +TranslationUnit *Symbol::translationUnit() const +{ return _control->translationUnit(); } + +void Symbol::visitSymbol(SymbolVisitor *visitor) +{ + if (visitor->preVisit(this)) + visitSymbol0(visitor); + visitor->postVisit(this); +} + +void Symbol::visitSymbol(Symbol *symbol, SymbolVisitor *visitor) +{ + if (! symbol) + return; + + symbol->visitSymbol(visitor); +} + +unsigned Symbol::sourceLocation() const +{ return _sourceLocation; } + +unsigned Symbol::sourceOffset() const +{ return _sourceOffset; } + +unsigned Symbol::line() const +{ + unsigned line = 0, column = 0; + StringLiteral *fileId = 0; + translationUnit()->getPosition(_sourceOffset, &line, &column, &fileId); + return line; +} + +unsigned Symbol::column() const +{ +#ifdef CPLUSPLUS_WITH_COLUMNS + unsigned line = 0, column = 0; + StringLiteral *fileId = 0; + translationUnit()->getPosition(_sourceOffset, &line, &column, &fileId); + return column; +#else + return 0; +#endif +} + +StringLiteral *Symbol::fileId() const +{ + unsigned line = 0, column = 0; + StringLiteral *fileId = 0; + translationUnit()->getPosition(_sourceOffset, &line, &column, &fileId); + return fileId; +} + +const char *Symbol::fileName() const +{ return fileId()->chars(); } + +unsigned Symbol::fileNameLength() const +{ return fileId()->size(); } + +Name *Symbol::identity() const +{ + IdentityForName id; + return id(_name); +} + +Name *Symbol::name() const +{ return _name; } + +void Symbol::setName(Name *name) +{ + _name = name; + + if (! _name) + _hashCode = 0; + else { + IdentityForName identityForName; + HashCode hh; + _hashCode = hh(identityForName(_name)); + } +} + +Scope *Symbol::scope() const +{ return _scope; } + +void Symbol::setScope(Scope *scope) +{ + assert(! _scope); + _scope = scope; +} + +unsigned Symbol::index() const +{ return _index; } + +Symbol *Symbol::next() const +{ return _next; } + +unsigned Symbol::hashCode() const +{ return _hashCode; } + +int Symbol::storage() const +{ return _storage; } + +void Symbol::setStorage(int storage) +{ _storage = storage; } + +int Symbol::visibility() const +{ return _visibility; } + +void Symbol::setVisibility(int visibility) +{ _visibility = visibility; } + +bool Symbol::isFriend() const +{ return _storage == Friend; } + +bool Symbol::isRegister() const +{ return _storage == Register; } + +bool Symbol::isStatic() const +{ return _storage == Static; } + +bool Symbol::isExtern() const +{ return _storage == Extern; } + +bool Symbol::isMutable() const +{ return _storage == Mutable; } + +bool Symbol::isTypedef() const +{ return _storage == Typedef; } + +bool Symbol::isPublic() const +{ return _visibility == Public; } + +bool Symbol::isProtected() const +{ return _visibility == Protected; } + +bool Symbol::isPrivate() const +{ return _visibility == Private; } + +bool Symbol::isScopedSymbol() const +{ return dynamic_cast<const ScopedSymbol *>(this) != 0; } + +bool Symbol::isEnum() const +{ return dynamic_cast<const Enum *>(this) != 0; } + +bool Symbol::isFunction() const +{ return dynamic_cast<const Function *>(this) != 0; } + +bool Symbol::isNamespace() const +{ return dynamic_cast<const Namespace *>(this) != 0; } + +bool Symbol::isClass() const +{ return dynamic_cast<const Class *>(this) != 0; } + +bool Symbol::isBlock() const +{ return dynamic_cast<const Block *>(this) != 0; } + +bool Symbol::isUsingNamespaceDirective() const +{ return dynamic_cast<const UsingNamespaceDirective *>(this) != 0; } + +bool Symbol::isUsingDeclaration() const +{ return dynamic_cast<const UsingDeclaration *>(this) != 0; } + +bool Symbol::isDeclaration() const +{ return dynamic_cast<const Declaration *>(this) != 0; } + +bool Symbol::isArgument() const +{ return dynamic_cast<const Argument *>(this) != 0; } + +bool Symbol::isBaseClass() const +{ return dynamic_cast<const BaseClass *>(this) != 0; } + +const ScopedSymbol *Symbol::asScopedSymbol() const +{ return dynamic_cast<const ScopedSymbol *>(this); } + +const Enum *Symbol::asEnum() const +{ return dynamic_cast<const Enum *>(this); } + +const Function *Symbol::asFunction() const +{ return dynamic_cast<const Function *>(this); } + +const Namespace *Symbol::asNamespace() const +{ return dynamic_cast<const Namespace *>(this); } + +const Class *Symbol::asClass() const +{ return dynamic_cast<const Class *>(this); } + +const Block *Symbol::asBlock() const +{ return dynamic_cast<const Block *>(this); } + +const UsingNamespaceDirective *Symbol::asUsingNamespaceDirective() const +{ return dynamic_cast<const UsingNamespaceDirective *>(this); } + +const UsingDeclaration *Symbol::asUsingDeclaration() const +{ return dynamic_cast<const UsingDeclaration *>(this); } + +const Declaration *Symbol::asDeclaration() const +{ return dynamic_cast<const Declaration *>(this); } + +const Argument *Symbol::asArgument() const +{ return dynamic_cast<const Argument *>(this); } + +const BaseClass *Symbol::asBaseClass() const +{ return dynamic_cast<const BaseClass *>(this); } + +ScopedSymbol *Symbol::asScopedSymbol() +{ return dynamic_cast<ScopedSymbol *>(this); } + +Enum *Symbol::asEnum() +{ return dynamic_cast<Enum *>(this); } + +Function *Symbol::asFunction() +{ return dynamic_cast<Function *>(this); } + +Namespace *Symbol::asNamespace() +{ return dynamic_cast<Namespace *>(this); } + +Class *Symbol::asClass() +{ return dynamic_cast<Class *>(this); } + +Block *Symbol::asBlock() +{ return dynamic_cast<Block *>(this); } + +UsingNamespaceDirective *Symbol::asUsingNamespaceDirective() +{ return dynamic_cast<UsingNamespaceDirective *>(this); } + +UsingDeclaration *Symbol::asUsingDeclaration() +{ return dynamic_cast<UsingDeclaration *>(this); } + +Declaration *Symbol::asDeclaration() +{ return dynamic_cast<Declaration *>(this); } + +Argument *Symbol::asArgument() +{ return dynamic_cast<Argument *>(this); } + +BaseClass *Symbol::asBaseClass() +{ return dynamic_cast<BaseClass *>(this); } + +CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/Symbol.h b/src/shared/cplusplus/Symbol.h new file mode 100644 index 0000000000..e9d150e8d5 --- /dev/null +++ b/src/shared/cplusplus/Symbol.h @@ -0,0 +1,266 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. + +#ifndef CPLUSPLUS_SYMBOL_H +#define CPLUSPLUS_SYMBOL_H + +#include "CPlusPlusForwardDeclarations.h" + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +class CPLUSPLUS_EXPORT Symbol +{ + Symbol(const Symbol &other); + void operator =(const Symbol &other); + +public: + /// Storage class specifier + enum Storage { + NoStorage = 0, + Friend, + Register, + Static, + Extern, + Mutable, + Typedef + }; + + /// Access specifier. + enum Visibility { + Public, + Protected, + Private + }; + +public: + /// Constructs a Symbol with the given source location, name and translation unit. + Symbol(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name); + + /// Destroy this Symbol. + virtual ~Symbol(); + + /// Returns this Symbol's Control object. + Control *control() const; + + /// Returns this Symbol's source location. + unsigned sourceLocation() const; + + /// Returns this Symbol's source offset. + unsigned sourceOffset() const; + + /// Returns this Symbol's line number. + unsigned line() const; + + /// Returns this Symbol's column number. + unsigned column() const; + + /// Returns this Symbol's file name. + StringLiteral *fileId() const; + + /// Returns this Symbol's file name. + const char *fileName() const; + + /// Returns this Symbol's file name length. + unsigned fileNameLength() const; + + /// Returns this Symbol's name. + Name *name() const; + + /// Sets this Symbol's name. + void setName(Name *name); // ### dangerous + + /// Returns this Symbol's storage class specifier. + int storage() const; + + /// Sets this Symbol's storage class specifier. + void setStorage(int storage); + + /// Returns this Symbol's visibility. + int visibility() const; + + /// Sets this Symbol's visibility. + void setVisibility(int visibility); + + /// Returns this Symbol's scope. + Scope *scope() const; + + /// Returns the next chained Symbol. + Symbol *next() const; + + /// Returns true if this Symbol has friend storage specifier. + bool isFriend() const; + + /// Returns true if this Symbol has register storage specifier. + bool isRegister() const; + + /// Returns true if this Symbol has static storage specifier. + bool isStatic() const; + + /// Returns true if this Symbol has extern storage specifier. + bool isExtern() const; + + /// Returns true if this Symbol has mutable storage specifier. + bool isMutable() const; + + /// Returns true if this Symbol has typedef storage specifier. + bool isTypedef() const; + + /// Returns true if this Symbol's visibility is public. + bool isPublic() const; + + /// Returns true if this Symbol's visibility is protected. + bool isProtected() const; + + /// Returns true if this Symbol's visibility is private. + bool isPrivate() const; + + /// Returns true if this Symbol is a ScopedSymbol. + bool isScopedSymbol() const; + + /// Returns true if this Symbol is an Enum. + bool isEnum() const; + + /// Returns true if this Symbol is an Function. + bool isFunction() const; + + /// Returns true if this Symbol is a Namespace. + bool isNamespace() const; + + /// Returns true if this Symbol is a Class. + bool isClass() const; + + /// Returns true if this Symbol is a Block. + bool isBlock() const; + + /// Returns true if this Symbol is a UsingNamespaceDirective. + bool isUsingNamespaceDirective() const; + + /// Returns true if this Symbol is a UsingDeclaration. + bool isUsingDeclaration() const; + + /// Returns true if this Symbol is a Declaration. + bool isDeclaration() const; + + /// Returns true if this Symbol is an Argument. + bool isArgument() const; + + /// Returns true if this Symbol is a BaseClass. + bool isBaseClass() const; + + const ScopedSymbol *asScopedSymbol() const; + const Enum *asEnum() const; + const Function *asFunction() const; + const Namespace *asNamespace() const; + const Class *asClass() const; + const Block *asBlock() const; + const UsingNamespaceDirective *asUsingNamespaceDirective() const; + const UsingDeclaration *asUsingDeclaration() const; + const Declaration *asDeclaration() const; + const Argument *asArgument() const; + const BaseClass *asBaseClass() const; + + ScopedSymbol *asScopedSymbol(); + Enum *asEnum(); + Function *asFunction(); + Namespace *asNamespace(); + Class *asClass(); + Block *asBlock(); + UsingNamespaceDirective *asUsingNamespaceDirective(); + UsingDeclaration *asUsingDeclaration(); + Declaration *asDeclaration(); + Argument *asArgument(); + BaseClass *asBaseClass(); + + /// Returns this Symbol's type. + virtual FullySpecifiedType type() const = 0; + + /// Returns this Symbol's hash value. + unsigned hashCode() const; + + /// Returns this Symbol's index. + unsigned index() const; + + Name *identity() const; + + void setScope(Scope *scope); // ### make me private + + void visitSymbol(SymbolVisitor *visitor); + static void visitSymbol(Symbol *symbol, SymbolVisitor *visitor); + +protected: + virtual void visitSymbol0(SymbolVisitor *visitor) = 0; + + TranslationUnit *translationUnit() const; + +private: + Control *_control; + unsigned _sourceLocation; + unsigned _sourceOffset; + Name *_name; + unsigned _hashCode; + int _storage; + int _visibility; + Scope *_scope; + unsigned _index; + Symbol *_next; + + class IdentityForName; + class HashCode; + + friend class Scope; +}; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_SYMBOL_H diff --git a/src/shared/cplusplus/SymbolVisitor.cpp b/src/shared/cplusplus/SymbolVisitor.cpp new file mode 100644 index 0000000000..95cab998ed --- /dev/null +++ b/src/shared/cplusplus/SymbolVisitor.cpp @@ -0,0 +1,66 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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 "SymbolVisitor.h" +#include "Symbol.h" + +CPLUSPLUS_USE_NAMESPACE + +SymbolVisitor::SymbolVisitor() +{ } + +SymbolVisitor::~SymbolVisitor() +{ } + +void SymbolVisitor::accept(Symbol *symbol) +{ Symbol::visitSymbol(symbol, this); } + diff --git a/src/shared/cplusplus/SymbolVisitor.h b/src/shared/cplusplus/SymbolVisitor.h new file mode 100644 index 0000000000..f0f4738de7 --- /dev/null +++ b/src/shared/cplusplus/SymbolVisitor.h @@ -0,0 +1,90 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. + +#ifndef SYMBOLVISITOR_H +#define SYMBOLVISITOR_H + +#include "CPlusPlusForwardDeclarations.h" + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +class CPLUSPLUS_EXPORT SymbolVisitor +{ + SymbolVisitor(const SymbolVisitor &other); + void operator =(const SymbolVisitor &other); + +public: + SymbolVisitor(); + virtual ~SymbolVisitor(); + + void accept(Symbol *symbol); + + virtual bool preVisit(Symbol *) { return true; } + virtual void postVisit(Symbol *) {} + + virtual bool visit(UsingNamespaceDirective *) { return true; } + virtual bool visit(UsingDeclaration *) { return true; } + virtual bool visit(Declaration *) { return true; } + virtual bool visit(Argument *) { return true; } + virtual bool visit(BaseClass *) { return true; } + virtual bool visit(Enum *) { return true; } + virtual bool visit(Function *) { return true; } + virtual bool visit(Namespace *) { return true; } + virtual bool visit(Class *) { return true; } + virtual bool visit(Block *) { return true; } +}; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // SYMBOLVISITOR_H diff --git a/src/shared/cplusplus/Symbols.cpp b/src/shared/cplusplus/Symbols.cpp new file mode 100644 index 0000000000..a7ed4682ff --- /dev/null +++ b/src/shared/cplusplus/Symbols.cpp @@ -0,0 +1,484 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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 "Symbols.h" +#include "Names.h" +#include "TypeVisitor.h" +#include "SymbolVisitor.h" +#include "Scope.h" +#include <cstdlib> + +CPLUSPLUS_BEGIN_NAMESPACE + +UsingNamespaceDirective::UsingNamespaceDirective(TranslationUnit *translationUnit, + unsigned sourceLocation, Name *name) + : Symbol(translationUnit, sourceLocation, name) +{ } + +UsingNamespaceDirective::~UsingNamespaceDirective() +{ } + +FullySpecifiedType UsingNamespaceDirective::type() const +{ return FullySpecifiedType(); } + +void UsingNamespaceDirective::visitSymbol0(SymbolVisitor *visitor) +{ visitor->visit(this); } + +UsingDeclaration::UsingDeclaration(TranslationUnit *translationUnit, + unsigned sourceLocation, Name *name) + : Symbol(translationUnit, sourceLocation, name) +{ } + +UsingDeclaration::~UsingDeclaration() +{ } + +FullySpecifiedType UsingDeclaration::type() const +{ return FullySpecifiedType(); } + +void UsingDeclaration::visitSymbol0(SymbolVisitor *visitor) +{ visitor->visit(this); } + +Declaration::Declaration(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name) + : Symbol(translationUnit, sourceLocation, name), + _templateParameters(0) +{ } + +Declaration::~Declaration() +{ delete _templateParameters; } + +unsigned Declaration::templateParameterCount() const +{ + if (! _templateParameters) + return 0; + return _templateParameters->symbolCount(); +} + +Symbol *Declaration::templateParameterAt(unsigned index) const +{ return _templateParameters->symbolAt(index); } + +Scope *Declaration::templateParameters() const +{ return _templateParameters; } + +void Declaration::setTemplateParameters(Scope *templateParameters) +{ _templateParameters = templateParameters; } + +void Declaration::setType(FullySpecifiedType type) +{ _type = type; } + +FullySpecifiedType Declaration::type() const +{ return _type; } + +void Declaration::visitSymbol0(SymbolVisitor *visitor) +{ visitor->visit(this); } + +Argument::Argument(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name) + : Symbol(translationUnit, sourceLocation, name), + _initializer(false) +{ } + +Argument::~Argument() +{ } + +bool Argument::hasInitializer() const +{ return _initializer; } + +void Argument::setInitializer(bool hasInitializer) +{ _initializer = hasInitializer; } + +void Argument::setType(FullySpecifiedType type) +{ _type = type; } + +FullySpecifiedType Argument::type() const +{ return _type; } + +void Argument::visitSymbol0(SymbolVisitor *visitor) +{ visitor->visit(this); } + +Function::Function(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name) + : ScopedSymbol(translationUnit, sourceLocation, name), + _templateParameters(0), + _flags(0) +{ _arguments = new Scope(this); } + +Function::~Function() +{ + delete _templateParameters; + delete _arguments; +} + +bool Function::isNormal() const +{ return _methodKey == NormalMethod; } + +bool Function::isSignal() const +{ return _methodKey == SignalMethod; } + +bool Function::isSlot() const +{ return _methodKey == SlotMethod; } + +int Function::methodKey() const +{ return _methodKey; } + +void Function::setMethodKey(int key) +{ _methodKey = key; } + +unsigned Function::templateParameterCount() const +{ + if (! _templateParameters) + return 0; + return _templateParameters->symbolCount(); +} + +Symbol *Function::templateParameterAt(unsigned index) const +{ return _templateParameters->symbolAt(index); } + +Scope *Function::templateParameters() const +{ return _templateParameters; } + +void Function::setTemplateParameters(Scope *templateParameters) +{ _templateParameters = templateParameters; } + +bool Function::isEqualTo(const Type *other) const +{ + const Function *o = other->asFunction(); + if (! o) + return false; + Name *l = identity(); + Name *r = o->identity(); + if (l == r || (l && l->isEqualTo(r))) { + if (_arguments->symbolCount() != o->_arguments->symbolCount()) + return false; + else if (! _returnType.isEqualTo(o->_returnType)) + return false; + for (unsigned i = 0; i < _arguments->symbolCount(); ++i) { + Symbol *l = _arguments->symbolAt(i); + Symbol *r = o->_arguments->symbolAt(i); + if (! l->type().isEqualTo(r->type())) + return false; + } + return true; + } + return false; +} + +void Function::accept0(TypeVisitor *visitor) +{ visitor->visit(this); } + +FullySpecifiedType Function::type() const +{ return FullySpecifiedType(const_cast<Function *>(this)); } + +FullySpecifiedType Function::returnType() const +{ return _returnType; } + +void Function::setReturnType(FullySpecifiedType returnType) +{ _returnType = returnType; } + +unsigned Function::argumentCount() const +{ + if (! _arguments) + return 0; + + return _arguments->symbolCount(); +} + +Symbol *Function::argumentAt(unsigned index) const +{ return _arguments->symbolAt(index); } + +Scope *Function::arguments() const +{ return _arguments; } + +bool Function::isVariadic() const +{ return _isVariadic; } + +void Function::setVariadic(bool isVariadic) +{ _isVariadic = isVariadic; } + +bool Function::isConst() const +{ return _isConst; } + +void Function::setConst(bool isConst) +{ _isConst = isConst; } + +bool Function::isVolatile() const +{ return _isVolatile; } + +void Function::setVolatile(bool isVolatile) +{ _isVolatile = isVolatile; } + +bool Function::isPureVirtual() const +{ return _isPureVirtual; } + +void Function::setPureVirtual(bool isPureVirtual) +{ _isPureVirtual = isPureVirtual; } + +void Function::visitSymbol0(SymbolVisitor *visitor) +{ + if (visitor->visit(this)) { + for (unsigned i = 0; i < _arguments->symbolCount(); ++i) { + visitSymbol(_arguments->symbolAt(i), visitor); + } + for (unsigned i = 0; i < memberCount(); ++i) { + visitSymbol(memberAt(i), visitor); + } + } +} + +ScopedSymbol::ScopedSymbol(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name) + : Symbol(translationUnit, sourceLocation, name) +{ _members = new Scope(this); } + +ScopedSymbol::~ScopedSymbol() +{ delete _members; } + +unsigned ScopedSymbol::memberCount() const +{ + if (! _members) + return 0; + return _members->symbolCount(); +} + +Symbol *ScopedSymbol::memberAt(unsigned index) const +{ + if (! _members) + return 0; + return _members->symbolAt(index); +} + +Scope *ScopedSymbol::members() const +{ return _members; } + +void ScopedSymbol::addMember(Symbol *member) +{ _members->enterSymbol(member); } + +Block::Block(TranslationUnit *translationUnit, unsigned sourceLocation) + : ScopedSymbol(translationUnit, sourceLocation, /*name = */ 0) +{ } + +Block::~Block() +{ } + +FullySpecifiedType Block::type() const +{ return FullySpecifiedType(); } + +void Block::visitSymbol0(SymbolVisitor *visitor) +{ visitor->visit(this); } + +Enum::Enum(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name) + : ScopedSymbol(translationUnit, sourceLocation, name) +{ } + +Enum::~Enum() +{ } + +FullySpecifiedType Enum::type() const +{ return FullySpecifiedType(const_cast<Enum *>(this)); } + +bool Enum::isEqualTo(const Type *other) const +{ + const Enum *o = other->asEnum(); + if (! o) + return false; + Name *l = identity(); + Name *r = o->identity(); + if (l == r) + return true; + else if (! l) + return false; + return l->isEqualTo(r); +} + +void Enum::accept0(TypeVisitor *visitor) +{ visitor->visit(this); } + +void Enum::visitSymbol0(SymbolVisitor *visitor) +{ + if (visitor->visit(this)) { + for (unsigned i = 0; i < memberCount(); ++i) { + visitSymbol(memberAt(i), visitor); + } + } +} + +Namespace::Namespace(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name) + : ScopedSymbol(translationUnit, sourceLocation, name) +{ } + +Namespace::~Namespace() +{ } + +bool Namespace::isEqualTo(const Type *other) const +{ + const Namespace *o = other->asNamespace(); + if (! o) + return false; + Name *l = identity(); + Name *r = o->identity(); + if (l == r || (l && l->isEqualTo(r))) + return true; + return false; +} + +void Namespace::accept0(TypeVisitor *visitor) +{ visitor->visit(this); } + +void Namespace::visitSymbol0(SymbolVisitor *visitor) +{ + if (visitor->visit(this)) { + for (unsigned i = 0; i < memberCount(); ++i) { + visitSymbol(memberAt(i), visitor); + } + } +} + +FullySpecifiedType Namespace::type() const +{ return FullySpecifiedType(const_cast<Namespace *>(this)); } + +BaseClass::BaseClass(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name) + : Symbol(translationUnit, sourceLocation, name), + _isVirtual(false) +{ } + +BaseClass::~BaseClass() +{ } + +FullySpecifiedType BaseClass::type() const +{ return FullySpecifiedType(); } + +bool BaseClass::isVirtual() const +{ return _isVirtual; } + +void BaseClass::setVirtual(bool isVirtual) +{ _isVirtual = isVirtual; } + +void BaseClass::visitSymbol0(SymbolVisitor *visitor) +{ visitor->visit(this); } + +Class::Class(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name) + : ScopedSymbol(translationUnit, sourceLocation, name), + _key(ClassKey), + _templateParameters(0) +{ } + +Class::~Class() +{ delete _templateParameters; } + +bool Class::isClass() const +{ return _key == ClassKey; } + +bool Class::isStruct() const +{ return _key == StructKey; } + +bool Class::isUnion() const +{ return _key == UnionKey; } + +Class::Key Class::classKey() const +{ return _key; } + +void Class::setClassKey(Key key) +{ _key = key; } + +unsigned Class::templateParameterCount() const +{ + if (! _templateParameters) + return 0; + return _templateParameters->symbolCount(); +} + +Symbol *Class::templateParameterAt(unsigned index) const +{ return _templateParameters->symbolAt(index); } + +Scope *Class::templateParameters() const +{ return _templateParameters; } + +void Class::setTemplateParameters(Scope *templateParameters) +{ _templateParameters = templateParameters; } + +void Class::accept0(TypeVisitor *visitor) +{ visitor->visit(this); } + +unsigned Class::baseClassCount() const +{ return _baseClasses.count(); } + +BaseClass *Class::baseClassAt(unsigned index) const +{ return _baseClasses.at(index); } + +void Class::addBaseClass(BaseClass *baseClass) +{ _baseClasses.push_back(baseClass); } + +FullySpecifiedType Class::type() const +{ return FullySpecifiedType(const_cast<Class *>(this)); } + +bool Class::isEqualTo(const Type *other) const +{ + const Class *o = other->asClass(); + if (! o) + return false; + Name *l = identity(); + Name *r = o->identity(); + if (l == r || (l && l->isEqualTo(r))) + return true; + else + return false; +} + +void Class::visitSymbol0(SymbolVisitor *visitor) +{ + if (visitor->visit(this)) { + for (unsigned i = 0; i < _baseClasses.size(); ++i) { + visitSymbol(_baseClasses.at(i), visitor); + } + for (unsigned i = 0; i < memberCount(); ++i) { + visitSymbol(memberAt(i), visitor); + } + } +} + +CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/Symbols.h b/src/shared/cplusplus/Symbols.h new file mode 100644 index 0000000000..c69483a251 --- /dev/null +++ b/src/shared/cplusplus/Symbols.h @@ -0,0 +1,338 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. + +#ifndef CPLUSPLUS_SYMBOLS_H +#define CPLUSPLUS_SYMBOLS_H + +#include "CPlusPlusForwardDeclarations.h" +#include "Symbol.h" +#include "Type.h" +#include "FullySpecifiedType.h" +#include "Array.h" + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +class CPLUSPLUS_EXPORT UsingNamespaceDirective: public Symbol +{ +public: + UsingNamespaceDirective(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name); + virtual ~UsingNamespaceDirective(); + + // Symbol's interface + virtual FullySpecifiedType type() const; + +protected: + virtual void visitSymbol0(SymbolVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT UsingDeclaration: public Symbol +{ +public: + UsingDeclaration(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name); + virtual ~UsingDeclaration(); + + // Symbol's interface + virtual FullySpecifiedType type() const; + +protected: + virtual void visitSymbol0(SymbolVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT Declaration: public Symbol +{ +public: + Declaration(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name); + virtual ~Declaration(); + + unsigned templateParameterCount() const; + Symbol *templateParameterAt(unsigned index) const; + + Scope *templateParameters() const; + void setTemplateParameters(Scope *templateParameters); + + void setType(FullySpecifiedType type); + + // Symbol's interface + virtual FullySpecifiedType type() const; + +protected: + virtual void visitSymbol0(SymbolVisitor *visitor); + +private: + FullySpecifiedType _type; + Scope *_templateParameters; +}; + +class CPLUSPLUS_EXPORT Argument: public Symbol +{ +public: + Argument(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name); + virtual ~Argument(); + + void setType(FullySpecifiedType type); + + bool hasInitializer() const; + void setInitializer(bool hasInitializer); + + // Symbol's interface + virtual FullySpecifiedType type() const; + +protected: + virtual void visitSymbol0(SymbolVisitor *visitor); + +private: + FullySpecifiedType _type; + bool _initializer: 1; +}; + +class CPLUSPLUS_EXPORT ScopedSymbol: public Symbol +{ +public: + ScopedSymbol(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name); + virtual ~ScopedSymbol(); + + unsigned memberCount() const; + Symbol *memberAt(unsigned index) const; + Scope *members() const; + void addMember(Symbol *member); + +private: + Scope *_members; +}; + +class CPLUSPLUS_EXPORT Block: public ScopedSymbol +{ +public: + Block(TranslationUnit *translationUnit, unsigned sourceLocation); + virtual ~Block(); + + // Symbol's interface + virtual FullySpecifiedType type() const; + +protected: + virtual void visitSymbol0(SymbolVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT Enum: public ScopedSymbol, public Type +{ +public: + Enum(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name); + virtual ~Enum(); + + // Symbol's interface + virtual FullySpecifiedType type() const; + + // Type's interface + virtual bool isEqualTo(const Type *other) const; + +protected: + virtual void visitSymbol0(SymbolVisitor *visitor); + virtual void accept0(TypeVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT Function: public ScopedSymbol, public Type +{ +public: + enum MethodKey { + NormalMethod, + SlotMethod, + SignalMethod + }; + +public: + Function(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name); + virtual ~Function(); + + bool isNormal() const; + bool isSignal() const; + bool isSlot() const; + int methodKey() const; + void setMethodKey(int key); + + unsigned templateParameterCount() const; + Symbol *templateParameterAt(unsigned index) const; + + Scope *templateParameters() const; + void setTemplateParameters(Scope *templateParameters); + + FullySpecifiedType returnType() const; + void setReturnType(FullySpecifiedType returnType); + + unsigned argumentCount() const; + Symbol *argumentAt(unsigned index) const; + Scope *arguments() const; + + bool isVariadic() const; + void setVariadic(bool isVariadic); + + bool isConst() const; + void setConst(bool isConst); + + bool isVolatile() const; + void setVolatile(bool isVolatile); + + bool isPureVirtual() const; + void setPureVirtual(bool isPureVirtual); + + // Symbol's interface + virtual FullySpecifiedType type() const; + + // Type's interface + virtual bool isEqualTo(const Type *other) const; + +protected: + virtual void visitSymbol0(SymbolVisitor *visitor); + virtual void accept0(TypeVisitor *visitor); + +private: + Name *_name; + Scope *_templateParameters; + FullySpecifiedType _returnType; + union { + unsigned _flags; + + struct { + unsigned _isVariadic: 1; + unsigned _isPureVirtual: 1; + unsigned _isConst: 1; + unsigned _isVolatile: 1; + unsigned _methodKey: 3; + }; + }; + Scope *_arguments; +}; + +class CPLUSPLUS_EXPORT Namespace: public ScopedSymbol, public Type +{ +public: + Namespace(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name); + virtual ~Namespace(); + + // Symbol's interface + virtual FullySpecifiedType type() const; + + // Type's interface + virtual bool isEqualTo(const Type *other) const; + +protected: + virtual void visitSymbol0(SymbolVisitor *visitor); + virtual void accept0(TypeVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT BaseClass: public Symbol +{ +public: + BaseClass(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name); + virtual ~BaseClass(); + + bool isVirtual() const; + void setVirtual(bool isVirtual); + + // Symbol's interface + virtual FullySpecifiedType type() const; + +protected: + virtual void visitSymbol0(SymbolVisitor *visitor); + +private: + bool _isVirtual; +}; + +class CPLUSPLUS_EXPORT Class: public ScopedSymbol, public Type +{ +public: + Class(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name); + virtual ~Class(); + + enum Key { + ClassKey, + StructKey, + UnionKey + }; + + bool isClass() const; + bool isStruct() const; + bool isUnion() const; + Key classKey() const; + void setClassKey(Key key); + + unsigned templateParameterCount() const; + Symbol *templateParameterAt(unsigned index) const; + + Scope *templateParameters() const; + void setTemplateParameters(Scope *templateParameters); + + unsigned baseClassCount() const; + BaseClass *baseClassAt(unsigned index) const; + void addBaseClass(BaseClass *baseClass); + + // Symbol's interface + virtual FullySpecifiedType type() const; + + // Type's interface + virtual bool isEqualTo(const Type *other) const; + +protected: + virtual void visitSymbol0(SymbolVisitor *visitor); + virtual void accept0(TypeVisitor *visitor); + +private: + Key _key; + Scope *_templateParameters; + Array<BaseClass *> _baseClasses; +}; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_SYMBOLS_H diff --git a/src/shared/cplusplus/Token.cpp b/src/shared/cplusplus/Token.cpp new file mode 100644 index 0000000000..eb672958cd --- /dev/null +++ b/src/shared/cplusplus/Token.cpp @@ -0,0 +1,140 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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 "Token.h" +#include "Literals.h" + +CPLUSPLUS_BEGIN_NAMESPACE + +static const char *token_names[] = { + (""), ("<error>"), + + ("<comment>"), + + ("<identifier>"), ("<int literal>"), ("<float literal>"), ("<char literal>"), + ("<wide char literal>"), ("<string literal>"), ("<wide char literal>"), + ("<@string literal>"), ("<angle string literal>"), + + ("&"), ("&&"), ("&="), ("->"), ("->*"), ("^"), ("^="), (":"), ("::"), + (","), ("/"), ("/="), ("."), ("..."), (".*"), ("="), ("=="), ("!"), + ("!="), (">"), (">="), (">>"), (">>="), ("{"), ("["), ("<"), ("<="), + ("<<"), ("<<="), ("("), ("-"), ("-="), ("--"), ("%"), ("%="), ("|"), + ("|="), ("||"), ("+"), ("+="), ("++"), ("#"), ("##"), ("?"), ("}"), + ("]"), (")"), (";"), ("*"), ("*="), ("~"), ("~="), + + ("asm"), ("auto"), ("bool"), ("break"), ("case"), ("catch"), ("char"), + ("class"), ("const"), ("const_cast"), ("continue"), ("default"), + ("delete"), ("do"), ("double"), ("dynamic_cast"), ("else"), ("enum"), + ("explicit"), ("export"), ("extern"), ("false"), ("float"), ("for"), + ("friend"), ("goto"), ("if"), ("inline"), ("int"), ("long"), + ("mutable"), ("namespace"), ("new"), ("operator"), ("private"), + ("protected"), ("public"), ("register"), ("reinterpret_cast"), + ("return"), ("short"), ("signed"), ("sizeof"), ("static"), + ("static_cast"), ("struct"), ("switch"), ("template"), ("this"), + ("throw"), ("true"), ("try"), ("typedef"), ("typeid"), ("typename"), + ("union"), ("unsigned"), ("using"), ("virtual"), ("void"), + ("volatile"), ("wchar_t"), ("while"), + + // gnu + ("__attribute__"), ("__typeof__"), + + // objc @keywords + ("@catch"), ("@class"), ("@compatibility_alias"), ("@defs"), ("@dynamic"), + ("@encode"), ("@end"), ("@finally"), ("@implementation"), ("@interface"), + ("@not_keyword"), ("@optional"), ("@package"), ("@private"), ("@property"), + ("@protected"), ("@protocol"), ("@public"), ("@required"), ("@selector"), + ("@synchronized"), ("@synthesize"), ("@throw"), ("@try"), + + ("SIGNAL"), ("SLOT"), ("Q_SIGNALS"), ("Q_SLOTS") +}; + +Token::Token() : + flags(0), offset(0), ptr(0) +{ +} + +Token::~Token() +{ +} + +void Token::reset() +{ + flags = 0; + offset = 0; + ptr = 0; +} + +const char *Token::name(int kind) +{ return token_names[kind]; } + +const char *Token::spell() const +{ + switch (kind) { + case T_IDENTIFIER: + return identifier->chars(); + + case T_INT_LITERAL: + case T_FLOAT_LITERAL: + case T_CHAR_LITERAL: + case T_STRING_LITERAL: + case T_AT_STRING_LITERAL: + case T_ANGLE_STRING_LITERAL: + case T_WIDE_CHAR_LITERAL: + case T_WIDE_STRING_LITERAL: + return literal->chars(); + + default: + return token_names[kind]; + } // switch +} + +CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/Token.h b/src/shared/cplusplus/Token.h new file mode 100644 index 0000000000..f48654aa77 --- /dev/null +++ b/src/shared/cplusplus/Token.h @@ -0,0 +1,336 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. + +#ifndef CPLUSPLUS_TOKEN_H +#define CPLUSPLUS_TOKEN_H + +#include "CPlusPlusForwardDeclarations.h" +#include <cstddef> + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +enum Kind { + T_EOF_SYMBOL = 0, + T_ERROR, + + T_COMMENT, + T_IDENTIFIER, + + T_FIRST_LITERAL, + T_INT_LITERAL = T_FIRST_LITERAL, + T_FLOAT_LITERAL, + T_CHAR_LITERAL, + T_WIDE_CHAR_LITERAL, + T_STRING_LITERAL, + T_WIDE_STRING_LITERAL, + T_AT_STRING_LITERAL, + T_ANGLE_STRING_LITERAL, + T_LAST_LITERAL = T_ANGLE_STRING_LITERAL, + + T_FIRST_OPERATOR, + T_AMPER = T_FIRST_OPERATOR, + T_AMPER_AMPER, + T_AMPER_EQUAL, + T_ARROW, + T_ARROW_STAR, + T_CARET, + T_CARET_EQUAL, + T_COLON, + T_COLON_COLON, + T_COMMA, + T_SLASH, + T_SLASH_EQUAL, + T_DOT, + T_DOT_DOT_DOT, + T_DOT_STAR, + T_EQUAL, + T_EQUAL_EQUAL, + T_EXCLAIM, + T_EXCLAIM_EQUAL, + T_GREATER, + T_GREATER_EQUAL, + T_GREATER_GREATER, + T_GREATER_GREATER_EQUAL, + T_LBRACE, + T_LBRACKET, + T_LESS, + T_LESS_EQUAL, + T_LESS_LESS, + T_LESS_LESS_EQUAL, + T_LPAREN, + T_MINUS, + T_MINUS_EQUAL, + T_MINUS_MINUS, + T_PERCENT, + T_PERCENT_EQUAL, + T_PIPE, + T_PIPE_EQUAL, + T_PIPE_PIPE, + T_PLUS, + T_PLUS_EQUAL, + T_PLUS_PLUS, + T_POUND, + T_POUND_POUND, + T_QUESTION, + T_RBRACE, + T_RBRACKET, + T_RPAREN, + T_SEMICOLON, + T_STAR, + T_STAR_EQUAL, + T_TILDE, + T_TILDE_EQUAL, + T_LAST_OPERATOR = T_TILDE_EQUAL, + + T_FIRST_KEYWORD, + T_ASM = T_FIRST_KEYWORD, + T_AUTO, + T_BOOL, + T_BREAK, + T_CASE, + T_CATCH, + T_CHAR, + T_CLASS, + T_CONST, + T_CONST_CAST, + T_CONTINUE, + T_DEFAULT, + T_DELETE, + T_DO, + T_DOUBLE, + T_DYNAMIC_CAST, + T_ELSE, + T_ENUM, + T_EXPLICIT, + T_EXPORT, + T_EXTERN, + T_FALSE, + T_FLOAT, + T_FOR, + T_FRIEND, + T_GOTO, + T_IF, + T_INLINE, + T_INT, + T_LONG, + T_MUTABLE, + T_NAMESPACE, + T_NEW, + T_OPERATOR, + T_PRIVATE, + T_PROTECTED, + T_PUBLIC, + T_REGISTER, + T_REINTERPRET_CAST, + T_RETURN, + T_SHORT, + T_SIGNED, + T_SIZEOF, + T_STATIC, + T_STATIC_CAST, + T_STRUCT, + T_SWITCH, + T_TEMPLATE, + T_THIS, + T_THROW, + T_TRUE, + T_TRY, + T_TYPEDEF, + T_TYPEID, + T_TYPENAME, + T_UNION, + T_UNSIGNED, + T_USING, + T_VIRTUAL, + T_VOID, + T_VOLATILE, + T_WCHAR_T, + T_WHILE, + + T___ATTRIBUTE__, + T___TYPEOF__, + + // obj c++ @ keywords + T_FIRST_OBJC_AT_KEYWORD, + + T_AT_CATCH = T_FIRST_OBJC_AT_KEYWORD, + T_AT_CLASS, + T_AT_COMPATIBILITY_ALIAS, + T_AT_DEFS, + T_AT_DYNAMIC, + T_AT_ENCODE, + T_AT_END, + T_AT_FINALLY, + T_AT_IMPLEMENTATION, + T_AT_INTERFACE, + T_AT_NOT_KEYWORD, + T_AT_OPTIONAL, + T_AT_PACKAGE, + T_AT_PRIVATE, + T_AT_PROPERTY, + T_AT_PROTECTED, + T_AT_PROTOCOL, + T_AT_PUBLIC, + T_AT_REQUIRED, + T_AT_SELECTOR, + T_AT_SYNCHRONIZED, + T_AT_SYNTHESIZE, + T_AT_THROW, + T_AT_TRY, + + T_LAST_OBJC_AT_KEYWORD, + + T_FIRST_QT_KEYWORD = T_LAST_OBJC_AT_KEYWORD, + + // Qt keywords + T_SIGNAL = T_FIRST_QT_KEYWORD, + T_SLOT, + T_SIGNALS, + T_SLOTS, + + T_LAST_KEYWORD = T_SLOTS, + + // aliases + T_OR = T_PIPE_PIPE, + T_AND = T_AMPER_AMPER, + T_NOT = T_EXCLAIM, + T_XOR = T_CARET, + T_BITOR = T_PIPE, + T_COMPL = T_TILDE, + T_OR_EQ = T_PIPE_EQUAL, + T_AND_EQ = T_AMPER_EQUAL, + T_BITAND = T_AMPER, + T_NOT_EQ = T_EXCLAIM_EQUAL, + T_XOR_EQ = T_CARET_EQUAL, + + T___ASM = T_ASM, + T___ASM__ = T_ASM, + + T_TYPEOF = T___TYPEOF__, + T___TYPEOF = T___TYPEOF__, + + T___INLINE = T_INLINE, + T___INLINE__ = T_INLINE, + + T___CONST = T_CONST, + T___CONST__ = T_CONST, + + T___VOLATILE = T_VOLATILE, + T___VOLATILE__ = T_VOLATILE, + + T___ATTRIBUTE = T___ATTRIBUTE__ +}; + +class CPLUSPLUS_EXPORT Token +{ +public: + Token(); + ~Token(); + + inline bool is(unsigned k) const { return kind == k; } + inline bool isNot(unsigned k) const { return kind != k; } + const char *spell() const; + void reset(); + + inline unsigned begin() const + { return offset; } + + inline unsigned end() const + { return offset + length; } + + inline bool isLiteral() const + { return kind >= T_FIRST_LITERAL && kind <= T_LAST_LITERAL; } + + inline bool isOperator() const + { return kind >= T_FIRST_OPERATOR && kind <= T_LAST_OPERATOR; } + + inline bool isKeyword() const + { return kind >= T_FIRST_KEYWORD && kind < T_FIRST_QT_KEYWORD; } + + inline bool isObjCAtKeyword() const + { return kind >= T_FIRST_OBJC_AT_KEYWORD && kind < T_LAST_OBJC_AT_KEYWORD; } + + static const char *name(int kind); + +public: + union { + unsigned flags; + + struct { + unsigned kind : 8; + unsigned newline : 1; + unsigned whitespace : 1; + unsigned joined : 1; + unsigned expanded : 1; + unsigned pad : 4; + unsigned length : 16; + }; + }; + + unsigned offset; + + union { + void *ptr; + Literal *literal; + NumericLiteral *number; + StringLiteral *string; + Identifier *identifier; + unsigned close_brace; + unsigned lineno; + }; +}; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_TOKEN_H diff --git a/src/shared/cplusplus/TranslationUnit.cpp b/src/shared/cplusplus/TranslationUnit.cpp new file mode 100644 index 0000000000..40a95c0f05 --- /dev/null +++ b/src/shared/cplusplus/TranslationUnit.cpp @@ -0,0 +1,474 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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 "TranslationUnit.h" +#include "Control.h" +#include "Parser.h" +#include "Lexer.h" +#include "MemoryPool.h" +#include "AST.h" +#include "Literals.h" +#include "DiagnosticClient.h" +#include <stack> +#include <cstdlib> +#include <cstdarg> +#include <algorithm> + +CPLUSPLUS_BEGIN_NAMESPACE + +TranslationUnit::TranslationUnit(Control *control, StringLiteral *fileId) + : _control(control), + _fileId(fileId), + _firstSourceChar(0), + _lastSourceChar(0), + _pool(0), + _ast(0), + _flags(0) +{ + _tokens = new Array<Token, 8>(); + _previousTranslationUnit = control->switchTranslationUnit(this); + _pool = new MemoryPool(); +} + +TranslationUnit::~TranslationUnit() +{ + (void) _control->switchTranslationUnit(_previousTranslationUnit); + delete _tokens; + delete _pool; +} + +bool TranslationUnit::qtMocRunEnabled() const +{ return _qtMocRunEnabled; } + +void TranslationUnit::setQtMocRunEnabled(bool onoff) +{ _qtMocRunEnabled = onoff; } + +bool TranslationUnit::objCEnabled() const +{ return _objCEnabled; } + +void TranslationUnit::setObjCEnabled(bool onoff) +{ _objCEnabled = onoff; } + +Control *TranslationUnit::control() const +{ return _control; } + +StringLiteral *TranslationUnit::fileId() const +{ return _fileId; } + +const char *TranslationUnit::fileName() const +{ return _fileId->chars(); } + +unsigned TranslationUnit::fileNameLength() const +{ return _fileId->size(); } + +const char *TranslationUnit::firstSourceChar() const +{ return _firstSourceChar; } + +const char *TranslationUnit::lastSourceChar() const +{ return _lastSourceChar; } + +unsigned TranslationUnit::sourceLength() const +{ return _lastSourceChar - _firstSourceChar; } + +void TranslationUnit::setSource(const char *source, unsigned size) +{ + _firstSourceChar = source; + _lastSourceChar = source + size; +} + +unsigned TranslationUnit::tokenCount() const +{ return _tokens->size(); } + +const Token &TranslationUnit::tokenAt(unsigned index) const +{ return _tokens->at(index); } + +int TranslationUnit::tokenKind(unsigned index) const +{ return _tokens->at(index).kind; } + +Identifier *TranslationUnit::identifier(unsigned index) const +{ return _tokens->at(index).identifier; } + +Literal *TranslationUnit::literal(unsigned index) const +{ return _tokens->at(index).literal; } + +StringLiteral *TranslationUnit::stringLiteral(unsigned index) const +{ return _tokens->at(index).string; } + +NumericLiteral *TranslationUnit::numericLiteral(unsigned index) const +{ return _tokens->at(index).number; } + +unsigned TranslationUnit::matchingBrace(unsigned index) const +{ return _tokens->at(index).close_brace; } + +MemoryPool *TranslationUnit::memoryPool() const +{ return _pool; } + +AST *TranslationUnit::ast() const +{ return _ast; } + +bool TranslationUnit::isTokenized() const +{ return _tokenized; } + +bool TranslationUnit::isParsed() const +{ return _parsed; } + +void TranslationUnit::tokenize() +{ + if (isTokenized()) + return; + + _tokenized = true; + + Lexer lex(this); + lex.setQtMocRunEnabled(_qtMocRunEnabled); + lex.setObjCEnabled(_objCEnabled); + + std::stack<unsigned> braces; + _tokens->push_back(Token()); // the first token needs to be invalid! + + pushLineOffset(0); + pushPreprocessorLine(0, 1, fileId()); + + Identifier *lineId = control()->findOrInsertIdentifier("line"); + + Token tk; + do { + lex(&tk); + + _Lrecognize: + if (tk.is(T_POUND)) { + unsigned offset = tk.offset; + lex(&tk); + if (! tk.newline && tk.is(T_IDENTIFIER) && tk.identifier == lineId) + lex(&tk); + if (! tk.newline && tk.is(T_INT_LITERAL)) { + unsigned line = (unsigned) strtoul(tk.spell(), 0, 0); + lex(&tk); + if (! tk.newline && tk.is(T_STRING_LITERAL)) { + StringLiteral *fileName = control()->findOrInsertFileName(tk.string->chars(), + tk.string->size()); + pushPreprocessorLine(offset, line, fileName); + lex(&tk); + } + } + while (tk.isNot(T_EOF_SYMBOL) && ! tk.newline) + lex(&tk); + goto _Lrecognize; + } else if (tk.kind == T_LBRACE) { + braces.push(_tokens->size()); + } else if (tk.kind == T_RBRACE && ! braces.empty()) { + const unsigned open_brace_index = braces.top(); + braces.pop(); + (*_tokens)[open_brace_index].close_brace = _tokens->size(); + } + _tokens->push_back(tk); + } while (tk.kind); + + for (; ! braces.empty(); braces.pop()) { + unsigned open_brace_index = braces.top(); + (*_tokens)[open_brace_index].close_brace = _tokens->size(); + } +} + +bool TranslationUnit::skipFunctionBody() const +{ return _skipFunctionBody; } + +void TranslationUnit::setSkipFunctionBody(bool skipFunctionBody) +{ _skipFunctionBody = skipFunctionBody; } + +bool TranslationUnit::parse(ParseMode mode) +{ + if (isParsed()) + return false; + + if (! isTokenized()) + tokenize(); + + Parser parser(this); + parser.setQtMocRunEnabled(_qtMocRunEnabled); + parser.setObjCEnabled(_objCEnabled); + + bool parsed = false; + + switch (mode) { + case ParseTranlationUnit: { + TranslationUnitAST *node = 0; + parsed = parser.parseTranslationUnit(node); + _ast = node; + } break; + + case ParseDeclaration: { + DeclarationAST *node = 0; + parsed = parser.parseDeclaration(node); + _ast = node; + } break; + + case ParseExpression: { + ExpressionAST *node = 0; + parsed = parser.parseExpression(node); + _ast = node; + } break; + + case ParseStatement: { + StatementAST *node = 0; + parsed = parser.parseStatement(node); + _ast = node; + } break; + + default: + break; + } // switch + + return parsed; +} + +void TranslationUnit::pushLineOffset(unsigned offset) +{ _lineOffsets.push_back(offset); } + +void TranslationUnit::pushPreprocessorLine(unsigned offset, + unsigned line, + StringLiteral *fileName) +{ _ppLines.push_back(PPLine(offset, line, fileName)); } + +unsigned TranslationUnit::findLineNumber(unsigned offset) const +{ + std::vector<unsigned>::const_iterator it = + std::lower_bound(_lineOffsets.begin(), _lineOffsets.end(), offset); + + if (it != _lineOffsets.begin()) + --it; + + return it - _lineOffsets.begin(); +} + +TranslationUnit::PPLine TranslationUnit::findPreprocessorLine(unsigned offset) const +{ + std::vector<PPLine>::const_iterator it = + std::lower_bound(_ppLines.begin(), _ppLines.end(), PPLine(offset)); + + if (it != _ppLines.begin()) + --it; + + return *it; +} + +unsigned TranslationUnit::findColumnNumber(unsigned offset, unsigned lineNumber) const +{ + if (! offset) + return 0; + + return offset - _lineOffsets[lineNumber]; +} + +void TranslationUnit::getTokenPosition(unsigned index, + unsigned *line, + unsigned *column, + StringLiteral **fileName) const +{ return getPosition(tokenAt(index).offset, line, column, fileName); } + +void TranslationUnit::getPosition(unsigned tokenOffset, + unsigned *line, + unsigned *column, + StringLiteral **fileName) const +{ + unsigned lineNumber = findLineNumber(tokenOffset); + unsigned columnNumber = findColumnNumber(tokenOffset, lineNumber); + const PPLine ppLine = findPreprocessorLine(tokenOffset); + + lineNumber -= findLineNumber(ppLine.offset) + 1; + lineNumber += ppLine.line; + + if (line) + *line = lineNumber; + + if (column) + *column = columnNumber; + + if (fileName) + *fileName = ppLine.fileName; +} + +bool TranslationUnit::blockErrors(bool block) +{ + bool previous = _blockErrors; + _blockErrors = block; + return previous; +} + +void TranslationUnit::warning(unsigned index, const char *format, ...) +{ + if (_blockErrors) + return; + + index = std::min(index, tokenCount() - 1); + + unsigned line = 0, column = 0; + StringLiteral *fileName = 0; + getTokenPosition(index, &line, &column, &fileName); + + if (DiagnosticClient *client = control()->diagnosticClient()) { + va_list args; + va_start(args, format); + client->report(DiagnosticClient::Warning, fileName, line, column, + format, args); + va_end(args); + } else { + fprintf(stderr, "%s:%d: ", fileName->chars(), line); + fprintf(stderr, "warning: "); + + va_list args; + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fputc('\n', stderr); + + showErrorLine(index, column, stderr); + } +} + +void TranslationUnit::error(unsigned index, const char *format, ...) +{ + if (_blockErrors) + return; + + index = std::min(index, tokenCount() - 1); + + unsigned line = 0, column = 0; + StringLiteral *fileName = 0; + getTokenPosition(index, &line, &column, &fileName); + + if (DiagnosticClient *client = control()->diagnosticClient()) { + va_list args; + va_start(args, format); + client->report(DiagnosticClient::Error, fileName, line, column, + format, args); + va_end(args); + } else { + fprintf(stderr, "%s:%d: ", fileName->chars(), line); + fprintf(stderr, "error: "); + + va_list args; + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fputc('\n', stderr); + + showErrorLine(index, column, stderr); + } +} + +void TranslationUnit::fatal(unsigned index, const char *format, ...) +{ + if (_blockErrors) + return; + + index = std::min(index, tokenCount() - 1); + + unsigned line = 0, column = 0; + StringLiteral *fileName = 0; + getTokenPosition(index, &line, &column, &fileName); + + if (DiagnosticClient *client = control()->diagnosticClient()) { + va_list args; + va_start(args, format); + client->report(DiagnosticClient::Fatal, fileName, line, column, + format, args); + va_end(args); + } else { + fprintf(stderr, "%s:%d: ", fileName->chars(), line); + fprintf(stderr, "fatal: "); + + va_list args; + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fputc('\n', stderr); + + showErrorLine(index, column, stderr); + } + + exit(EXIT_FAILURE); +} + +void TranslationUnit::showErrorLine(unsigned index, unsigned column, FILE *out) +{ + unsigned lineOffset = _lineOffsets[findLineNumber(_tokens->at(index).offset)]; + for (const char *cp = _firstSourceChar + lineOffset + 1; *cp && *cp != '\n'; ++cp) { + fputc(*cp, out); + } + fputc('\n', out); + + const char *end = _firstSourceChar + lineOffset + 1 + column - 1; + for (const char *cp = _firstSourceChar + lineOffset + 1; cp != end; ++cp) { + if (*cp != '\t') + fputc(' ', out); + else + fputc('\t', out); + } + fputc('^', out); + fputc('\n', out); +} + +void TranslationUnit::resetAST() +{ + delete _pool; + _pool = 0; +} + +void TranslationUnit::release() +{ + resetAST(); + delete _tokens; + _tokens = 0; +} + +CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/TranslationUnit.h b/src/shared/cplusplus/TranslationUnit.h new file mode 100644 index 0000000000..aa490701ef --- /dev/null +++ b/src/shared/cplusplus/TranslationUnit.h @@ -0,0 +1,201 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. + +#ifndef CPLUSPLUS_TRANSLATIONUNIT_H +#define CPLUSPLUS_TRANSLATIONUNIT_H + +#include "CPlusPlusForwardDeclarations.h" +#include "ASTfwd.h" +#include "Token.h" +#include "Array.h" +#include <cstdio> +#include <vector> // ### remove me + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +class CPLUSPLUS_EXPORT TranslationUnit +{ + TranslationUnit(const TranslationUnit &other); + void operator =(const TranslationUnit &other); + +public: + TranslationUnit(Control *control, StringLiteral *fileId); + ~TranslationUnit(); + + Control *control() const; + + StringLiteral *fileId() const; + const char *fileName() const; + unsigned fileNameLength() const; + + const char *firstSourceChar() const; + const char *lastSourceChar() const; + unsigned sourceLength() const; + + void setSource(const char *source, unsigned size); + + unsigned tokenCount() const; + const Token &tokenAt(unsigned index) const; + int tokenKind(unsigned index) const; + + unsigned matchingBrace(unsigned index) const; + Identifier *identifier(unsigned index) const; + Literal *literal(unsigned index) const; + StringLiteral *stringLiteral(unsigned index) const; + NumericLiteral *numericLiteral(unsigned index) const; + + MemoryPool *memoryPool() const; + AST *ast() const; + + bool blockErrors(bool block); + + bool qtMocRunEnabled() const; + void setQtMocRunEnabled(bool onoff); + + bool objCEnabled() const; + void setObjCEnabled(bool onoff); + + void warning(unsigned index, const char *fmt, ...); + void error(unsigned index, const char *fmt, ...); + void fatal(unsigned index, const char *fmt, ...); + + bool isTokenized() const; + void tokenize(); + + bool skipFunctionBody() const; + void setSkipFunctionBody(bool skipFunctionBody); + + bool isParsed() const; + + enum ParseMode { + ParseTranlationUnit, + ParseDeclaration, + ParseExpression, + ParseStatement + }; + + bool parse(ParseMode mode = ParseTranlationUnit); + + void resetAST(); + void release(); + + void getPosition(unsigned offset, + unsigned *line, + unsigned *column = 0, + StringLiteral **fileName = 0) const; + + void getTokenPosition(unsigned index, + unsigned *line, + unsigned *column = 0, + StringLiteral **fileName = 0) const; + + void pushLineOffset(unsigned offset); + void pushPreprocessorLine(unsigned offset, + unsigned line, + StringLiteral *fileName); + +public: + struct PPLine { + unsigned offset; + unsigned line; + StringLiteral *fileName; + + PPLine(unsigned offset = 0, + unsigned line = 0, + StringLiteral *fileName = 0) + : offset(offset), line(line), fileName(fileName) + { } + + bool operator == (const PPLine &other) const + { return offset == other.offset; } + + bool operator != (const PPLine &other) const + { return offset != other.offset; } + + bool operator < (const PPLine &other) const + { return offset < other.offset; } + }; + +private: + unsigned findLineNumber(unsigned offset) const; + unsigned findColumnNumber(unsigned offset, unsigned lineNumber) const; + PPLine findPreprocessorLine(unsigned offset) const; + void showErrorLine(unsigned index, unsigned column, FILE *out); + + Control *_control; + StringLiteral *_fileId; + const char *_firstSourceChar; + const char *_lastSourceChar; + Array<Token, 8> *_tokens; + std::vector<unsigned> _lineOffsets; + std::vector<PPLine> _ppLines; + MemoryPool *_pool; + AST *_ast; + TranslationUnit *_previousTranslationUnit; + union { + unsigned _flags; + struct { + unsigned _tokenized: 1; + unsigned _parsed: 1; + unsigned _blockErrors: 1; + unsigned _skipFunctionBody: 1; + unsigned _qtMocRunEnabled: 1; + unsigned _objCEnabled: 1; + }; + }; +}; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_TRANSLATIONUNIT_H diff --git a/src/shared/cplusplus/Type.cpp b/src/shared/cplusplus/Type.cpp new file mode 100644 index 0000000000..98ccd3c893 --- /dev/null +++ b/src/shared/cplusplus/Type.cpp @@ -0,0 +1,198 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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 "Type.h" +#include "TypeVisitor.h" +#include "CoreTypes.h" +#include "Symbols.h" + +CPLUSPLUS_BEGIN_NAMESPACE + +Type::Type() +{ } + +Type::~Type() +{ } + +bool Type::isVoidType() const +{ return dynamic_cast<const VoidType *>(this) != 0; } + +bool Type::isIntegerType() const +{ return dynamic_cast<const IntegerType *>(this) != 0; } + +bool Type::isFloatType() const +{ return dynamic_cast<const FloatType *>(this) != 0; } + +bool Type::isPointerType() const +{ return dynamic_cast<const PointerType *>(this) != 0; } + +bool Type::isPointerToMemberType() const +{ return dynamic_cast<const PointerToMemberType *>(this) != 0; } + +bool Type::isReferenceType() const +{ return dynamic_cast<const ReferenceType *>(this) != 0; } + +bool Type::isArrayType() const +{ return dynamic_cast<const ArrayType *>(this) != 0; } + +bool Type::isNamedType() const +{ return dynamic_cast<const NamedType *>(this) != 0; } + +bool Type::isFunction() const +{ return dynamic_cast<const Function *>(this) != 0; } + +bool Type::isNamespace() const +{ return dynamic_cast<const Namespace *>(this) != 0; } + +bool Type::isClass() const +{ return dynamic_cast<const Class *>(this) != 0; } + +bool Type::isEnum() const +{ return dynamic_cast<const Enum *>(this) != 0; } + +bool Type::isScopedSymbol() const +{ return dynamic_cast<const ScopedSymbol *>(this) != 0; } + +const VoidType *Type::asVoidType() const +{ return dynamic_cast<const VoidType *>(this); } + +const IntegerType *Type::asIntegerType() const +{ return dynamic_cast<const IntegerType *>(this); } + +const FloatType *Type::asFloatType() const +{ return dynamic_cast<const FloatType *>(this); } + +const PointerType *Type::asPointerType() const +{ return dynamic_cast<const PointerType *>(this); } + +const PointerToMemberType *Type::asPointerToMemberType() const +{ return dynamic_cast<const PointerToMemberType *>(this); } + +const ReferenceType *Type::asReferenceType() const +{ return dynamic_cast<const ReferenceType *>(this); } + +const ArrayType *Type::asArrayType() const +{ return dynamic_cast<const ArrayType *>(this); } + +const NamedType *Type::asNamedType() const +{ return dynamic_cast<const NamedType *>(this); } + +const Function *Type::asFunction() const +{ return dynamic_cast<const Function *>(this); } + +const Namespace *Type::asNamespace() const +{ return dynamic_cast<const Namespace *>(this); } + +const Class *Type::asClass() const +{ return dynamic_cast<const Class *>(this); } + +const Enum *Type::asEnum() const +{ return dynamic_cast<const Enum *>(this); } + +const ScopedSymbol *Type::asScopedSymbol() const +{ return dynamic_cast<const ScopedSymbol *>(this); } + +VoidType *Type::asVoidType() +{ return dynamic_cast<VoidType *>(this); } + +IntegerType *Type::asIntegerType() +{ return dynamic_cast<IntegerType *>(this); } + +FloatType *Type::asFloatType() +{ return dynamic_cast<FloatType *>(this); } + +PointerType *Type::asPointerType() +{ return dynamic_cast<PointerType *>(this); } + +PointerToMemberType *Type::asPointerToMemberType() +{ return dynamic_cast<PointerToMemberType *>(this); } + +ReferenceType *Type::asReferenceType() +{ return dynamic_cast<ReferenceType *>(this); } + +ArrayType *Type::asArrayType() +{ return dynamic_cast<ArrayType *>(this); } + +NamedType *Type::asNamedType() +{ return dynamic_cast<NamedType *>(this); } + +Function *Type::asFunction() +{ return dynamic_cast<Function *>(this); } + +Namespace *Type::asNamespace() +{ return dynamic_cast<Namespace *>(this); } + +Class *Type::asClass() +{ return dynamic_cast<Class *>(this); } + +Enum *Type::asEnum() +{ return dynamic_cast<Enum *>(this); } + +ScopedSymbol *Type::asScopedSymbol() +{ return dynamic_cast<ScopedSymbol *>(this); } + +void Type::accept(TypeVisitor *visitor) +{ + if (visitor->preVisit(this)) + accept0(visitor); + visitor->postVisit(this); +} + +void Type::accept(Type *type, TypeVisitor *visitor) +{ + if (! type) + return; + + type->accept(visitor); +} + +CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/Type.h b/src/shared/cplusplus/Type.h new file mode 100644 index 0000000000..7cc347d553 --- /dev/null +++ b/src/shared/cplusplus/Type.h @@ -0,0 +1,124 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. + +#ifndef CPLUSPLUS_TYPE_H +#define CPLUSPLUS_TYPE_H + +#include "CPlusPlusForwardDeclarations.h" + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +class CPLUSPLUS_EXPORT Type +{ + Type(const Type &other); + void operator =(const Type &other); + +public: + Type(); + virtual ~Type(); + + bool isVoidType() const; + bool isIntegerType() const; + bool isFloatType() const; + bool isPointerType() const; + bool isPointerToMemberType() const; + bool isReferenceType() const; + bool isArrayType() const; + bool isNamedType() const; + bool isFunction() const; + bool isNamespace() const; + bool isClass() const; + bool isEnum() const; + bool isScopedSymbol() const; + + const VoidType *asVoidType() const; + const IntegerType *asIntegerType() const; + const FloatType *asFloatType() const; + const PointerType *asPointerType() const; + const PointerToMemberType *asPointerToMemberType() const; + const ReferenceType *asReferenceType() const; + const ArrayType *asArrayType() const; + const NamedType *asNamedType() const; + const Function *asFunction() const; + const Namespace *asNamespace() const; + const Class *asClass() const; + const Enum *asEnum() const; + const ScopedSymbol *asScopedSymbol() const; + + VoidType *asVoidType(); + IntegerType *asIntegerType(); + FloatType *asFloatType(); + PointerType *asPointerType(); + PointerToMemberType *asPointerToMemberType(); + ReferenceType *asReferenceType(); + ArrayType *asArrayType(); + NamedType *asNamedType(); + Function *asFunction(); + Namespace *asNamespace(); + Class *asClass(); + Enum *asEnum(); + ScopedSymbol *asScopedSymbol(); + + void accept(TypeVisitor *visitor); + static void accept(Type *type, TypeVisitor *visitor); + + virtual bool isEqualTo(const Type *other) const = 0; + +protected: + virtual void accept0(TypeVisitor *visitor) = 0; +}; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_TYPE_H diff --git a/src/shared/cplusplus/TypeVisitor.cpp b/src/shared/cplusplus/TypeVisitor.cpp new file mode 100644 index 0000000000..937080e5a5 --- /dev/null +++ b/src/shared/cplusplus/TypeVisitor.cpp @@ -0,0 +1,67 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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 "TypeVisitor.h" +#include "Type.h" + +CPLUSPLUS_BEGIN_NAMESPACE + +TypeVisitor::TypeVisitor() +{ } + +TypeVisitor::~TypeVisitor() +{ } + +void TypeVisitor::accept(Type *type) +{ Type::accept(type, this); } + +CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/TypeVisitor.h b/src/shared/cplusplus/TypeVisitor.h new file mode 100644 index 0000000000..16fb37c4ad --- /dev/null +++ b/src/shared/cplusplus/TypeVisitor.h @@ -0,0 +1,92 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008-2009 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. + +#ifndef CPLUSPLUS_TYPEVISITOR_H +#define CPLUSPLUS_TYPEVISITOR_H + +#include "CPlusPlusForwardDeclarations.h" + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +class CPLUSPLUS_EXPORT TypeVisitor +{ + TypeVisitor(const TypeVisitor &other); + void operator =(const TypeVisitor &other); + +public: + TypeVisitor(); + virtual ~TypeVisitor(); + + void accept(Type *type); + + virtual bool preVisit(Type *) { return true; } + virtual void postVisit(Type *) {} + + virtual void visit(VoidType *) {} + virtual void visit(IntegerType *) {} + virtual void visit(FloatType *) {} + virtual void visit(PointerToMemberType *) {} + virtual void visit(PointerType *) {} + virtual void visit(ReferenceType *) {} + virtual void visit(ArrayType *) {} + virtual void visit(NamedType *) {} + virtual void visit(Function *) {} + virtual void visit(Namespace *) {} + virtual void visit(Class *) {} + virtual void visit(Enum *) {} +}; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_TYPEVISITOR_H diff --git a/src/shared/cplusplus/cplusplus.pri b/src/shared/cplusplus/cplusplus.pri new file mode 100644 index 0000000000..041aff67be --- /dev/null +++ b/src/shared/cplusplus/cplusplus.pri @@ -0,0 +1,77 @@ + +DEPENDPATH += $$PWD +INCLUDEPATH += $$PWD + +HEADERS += \ + $$PWD/AST.h \ + $$PWD/ASTVisitor.h \ + $$PWD/ASTfwd.h \ + $$PWD/Array.h \ + $$PWD/CPlusPlusForwardDeclarations.h \ + $$PWD/CheckDeclaration.h \ + $$PWD/CheckDeclarator.h \ + $$PWD/CheckExpression.h \ + $$PWD/CheckName.h \ + $$PWD/CheckSpecifier.h \ + $$PWD/CheckStatement.h \ + $$PWD/Control.h \ + $$PWD/CoreTypes.h \ + $$PWD/DiagnosticClient.h \ + $$PWD/FullySpecifiedType.h \ + $$PWD/Lexer.h \ + $$PWD/LiteralTable.h \ + $$PWD/Literals.h \ + $$PWD/MemoryPool.h \ + $$PWD/Name.h \ + $$PWD/NameVisitor.h \ + $$PWD/Names.h \ + $$PWD/Parser.h \ + $$PWD/Scope.h \ + $$PWD/Semantic.h \ + $$PWD/SemanticCheck.h \ + $$PWD/Symbol.h \ + $$PWD/Symbols.h \ + $$PWD/SymbolVisitor.h \ + $$PWD/Token.h \ + $$PWD/TranslationUnit.h \ + $$PWD/Type.h \ + $$PWD/TypeVisitor.h \ + $$PWD/PrettyPrinter.h + + +SOURCES += \ + $$PWD/AST.cpp \ + $$PWD/ASTVisitor.cpp \ + $$PWD/Array.cpp \ + $$PWD/CheckDeclaration.cpp \ + $$PWD/CheckDeclarator.cpp \ + $$PWD/CheckExpression.cpp \ + $$PWD/CheckName.cpp \ + $$PWD/CheckSpecifier.cpp \ + $$PWD/CheckStatement.cpp \ + $$PWD/Control.cpp \ + $$PWD/CoreTypes.cpp \ + $$PWD/DiagnosticClient.cpp \ + $$PWD/FullySpecifiedType.cpp \ + $$PWD/Keywords.cpp \ + $$PWD/ObjectiveCAtKeywords.cpp \ + $$PWD/Lexer.cpp \ + $$PWD/LiteralTable.cpp \ + $$PWD/Literals.cpp \ + $$PWD/MemoryPool.cpp \ + $$PWD/Name.cpp \ + $$PWD/NameVisitor.cpp \ + $$PWD/Names.cpp \ + $$PWD/Parser.cpp \ + $$PWD/Scope.cpp \ + $$PWD/Semantic.cpp \ + $$PWD/SemanticCheck.cpp \ + $$PWD/Symbol.cpp \ + $$PWD/Symbols.cpp \ + $$PWD/SymbolVisitor.cpp \ + $$PWD/Token.cpp \ + $$PWD/TranslationUnit.cpp \ + $$PWD/Type.cpp \ + $$PWD/TypeVisitor.cpp \ + $$PWD/PrettyPrinter.cpp + |