diff --git a/src/tools/cplusplus/generate-ast.cpp b/src/tools/cplusplus/generate-ast.cpp index e9a50d219df74ff04b7e7da52668ab38268ffc99..bbde757934c7d611031def385aa2985766f68e12 100644 --- a/src/tools/cplusplus/generate-ast.cpp +++ b/src/tools/cplusplus/generate-ast.cpp @@ -735,6 +735,138 @@ protected: } }; +class GenerateDumpers: protected ASTVisitor +{ + QTextStream out; + +public: + GenerateDumpers(QFile *file, TranslationUnit *unit) + : ASTVisitor(unit), out(file) + { } + + static void go(const QString &fileName, TranslationUnit *unit) + { + QFile file(fileName); + if (! file.open(QFile::WriteOnly)) { + std::cerr << "Cannot open dumpers file." << std::endl; + return; + } + + GenerateDumpers d(&file, unit); + d.out << copyrightHeader + << generatedHeader + << endl; + + + d.accept(unit->ast()); + + file.close(); + } + +protected: + using ASTVisitor::visit; + + QMap<QByteArray, ClassSpecifierAST *> classMap; + + QByteArray id_cast(NameAST *name) + { + if (! name) + return QByteArray(); + + const Identifier *id = identifier(name->asSimpleName()->identifier_token); + + return QByteArray::fromRawData(id->chars(), id->size()); + } + + void visitMembers(Class *klass) + { + for (unsigned i = 0; i < klass->memberCount(); ++i) { + Symbol *member = klass->memberAt(i); + if (! member->name()) + continue; + + const Identifier *id = member->name()->identifier(); + + if (! id) + continue; + + const QByteArray memberName = QByteArray::fromRawData(id->chars(), id->size()); + if (member->type().isUnsigned() && memberName.endsWith("_token")) { + out << " if (ast->" << memberName << ")" << endl; + out << " terminal(ast->" << memberName << ", ast);" << endl; + } else if (PointerType *ptrTy = member->type()->asPointerType()) { + if (NamedType *namedTy = ptrTy->elementType()->asNamedType()) { + QByteArray typeName = namedTy->name()->identifier()->chars(); + + if (typeName.endsWith("ListAST")) { + out << " for (" << typeName << " *iter = ast->" << memberName << "; iter; iter = iter->next)" << endl + << " nonterminal(iter->value);" << endl; + } else if (typeName.endsWith("AST")) { + out << " nonterminal(ast->" << memberName << ");" << endl; + } + } + } + } + + for (unsigned i = 0; i < klass->baseClassCount(); ++i) { + const QByteArray baseClassName = klass->baseClassAt(i)->identifier()->chars(); + + if (ClassSpecifierAST *baseClassSpec = classMap.value(baseClassName, 0)) { + visitMembers(baseClassSpec->symbol); + } + } + } + + bool checkMethod(Symbol *cloneMethod) const + { + Declaration *decl = cloneMethod->asDeclaration(); + if (! decl) + return false; + + Function *funTy = decl->type()->asFunctionType(); + if (! funTy) + return false; + + else if (funTy->isPureVirtual()) + return false; + + return true; + } + + virtual bool visit(ClassSpecifierAST *ast) + { + Class *klass = ast->symbol; + const QByteArray className = id_cast(ast->name); + if (! className.endsWith("AST")) + return false; + + const Identifier *clone_id = control()->findOrInsertIdentifier("clone"); + Symbol *cloneMethod = klass->members()->lookat(clone_id); + for (; cloneMethod; cloneMethod = cloneMethod->next()) { + if (cloneMethod->identifier() != clone_id) + continue; + + if (checkMethod(cloneMethod)) + break; + } + + if (! cloneMethod) + return true; + + classMap.insert(className, ast); + + out << "virtual bool visit(" << className.constData() << " *ast)" << endl + << "{" << endl; + + visitMembers(klass); + + out << " return false;" << endl + << "}" << endl << endl; + + return false; + } +}; + class RemoveCastMethods: protected ASTVisitor { public: @@ -1093,7 +1225,7 @@ void generateAST_cpp(const Snapshot &snapshot, const QDir &cplusplusDir) } } -QStringList generateAST_H(const Snapshot &snapshot, const QDir &cplusplusDir) +QStringList generateAST_H(const Snapshot &snapshot, const QDir &cplusplusDir, const QString &dumpersFile) { QStringList astDerivedClasses; @@ -1193,6 +1325,9 @@ QStringList generateAST_H(const Snapshot &snapshot, const QDir &cplusplusDir) generateAST_cpp(snapshot, cplusplusDir); + if (!dumpersFile.isEmpty()) + GenerateDumpers::go(dumpersFile, AST_h_document->translationUnit()); + return astDerivedClasses; } @@ -1393,8 +1528,9 @@ int main(int argc, char *argv[]) QStringList files = app.arguments(); files.removeFirst(); - if (files.isEmpty()) { + if (files.size() != 1 && files.size() != 2) { std::cerr << "Usage: cplusplus [path to C++ front-end]" << std::endl; + std::cerr << " or: cplusplus [path to C++ front-end] [dumpers file name]" << std::endl; return EXIT_FAILURE; } @@ -1405,8 +1541,12 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; } + QString dumpersFile; + if (files.size() == 2) + dumpersFile = files.last(); + Snapshot snapshot; - QStringList astDerivedClasses = generateAST_H(snapshot, cplusplusDir); + QStringList astDerivedClasses = generateAST_H(snapshot, cplusplusDir, dumpersFile); astDerivedClasses.sort(); generateASTFwd_h(snapshot, cplusplusDir, astDerivedClasses); diff --git a/tests/manual/cplusplus-dump/dumpers.inc b/tests/manual/cplusplus-dump/dumpers.inc new file mode 100644 index 0000000000000000000000000000000000000000..8e414f5f830a5a6fdfd804c22c490a6eb13ccfe5 --- /dev/null +++ b/tests/manual/cplusplus-dump/dumpers.inc @@ -0,0 +1,1607 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is automatically generated. +// Changes will be lost. +// + + +virtual bool visit(ObjCSelectorArgumentAST *ast) +{ + if (ast->name_token) + terminal(ast->name_token, ast); + if (ast->colon_token) + terminal(ast->colon_token, ast); + return false; +} + +virtual bool visit(ObjCSelectorAST *ast) +{ + for (ObjCSelectorArgumentListAST *iter = ast->selector_argument_list; iter; iter = iter->next) + nonterminal(iter->value); + return false; +} + +virtual bool visit(SimpleSpecifierAST *ast) +{ + if (ast->specifier_token) + terminal(ast->specifier_token, ast); + return false; +} + +virtual bool visit(AttributeSpecifierAST *ast) +{ + if (ast->attribute_token) + terminal(ast->attribute_token, ast); + if (ast->first_lparen_token) + terminal(ast->first_lparen_token, ast); + if (ast->second_lparen_token) + terminal(ast->second_lparen_token, ast); + for (AttributeListAST *iter = ast->attribute_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->first_rparen_token) + terminal(ast->first_rparen_token, ast); + if (ast->second_rparen_token) + terminal(ast->second_rparen_token, ast); + return false; +} + +virtual bool visit(AttributeAST *ast) +{ + if (ast->identifier_token) + terminal(ast->identifier_token, ast); + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + if (ast->tag_token) + terminal(ast->tag_token, ast); + for (ExpressionListAST *iter = ast->expression_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + return false; +} + +virtual bool visit(TypeofSpecifierAST *ast) +{ + if (ast->typeof_token) + terminal(ast->typeof_token, ast); + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + nonterminal(ast->expression); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + return false; +} + +virtual bool visit(DeclaratorAST *ast) +{ + for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next) + nonterminal(iter->value); + for (PtrOperatorListAST *iter = ast->ptr_operator_list; iter; iter = iter->next) + nonterminal(iter->value); + nonterminal(ast->core_declarator); + for (PostfixDeclaratorListAST *iter = ast->postfix_declarator_list; iter; iter = iter->next) + nonterminal(iter->value); + for (SpecifierListAST *iter = ast->post_attribute_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->equals_token) + terminal(ast->equals_token, ast); + nonterminal(ast->initializer); + return false; +} + +virtual bool visit(SimpleDeclarationAST *ast) +{ + if (ast->qt_invokable_token) + terminal(ast->qt_invokable_token, ast); + for (SpecifierListAST *iter = ast->decl_specifier_list; iter; iter = iter->next) + nonterminal(iter->value); + for (DeclaratorListAST *iter = ast->declarator_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->semicolon_token) + terminal(ast->semicolon_token, ast); + return false; +} + +virtual bool visit(EmptyDeclarationAST *ast) +{ + if (ast->semicolon_token) + terminal(ast->semicolon_token, ast); + return false; +} + +virtual bool visit(AccessDeclarationAST *ast) +{ + if (ast->access_specifier_token) + terminal(ast->access_specifier_token, ast); + if (ast->slots_token) + terminal(ast->slots_token, ast); + if (ast->colon_token) + terminal(ast->colon_token, ast); + return false; +} + +virtual bool visit(QtObjectTagAST *ast) +{ + if (ast->q_object_token) + terminal(ast->q_object_token, ast); + return false; +} + +virtual bool visit(QtPrivateSlotAST *ast) +{ + if (ast->q_private_slot_token) + terminal(ast->q_private_slot_token, ast); + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + if (ast->dptr_token) + terminal(ast->dptr_token, ast); + if (ast->dptr_lparen_token) + terminal(ast->dptr_lparen_token, ast); + if (ast->dptr_rparen_token) + terminal(ast->dptr_rparen_token, ast); + if (ast->comma_token) + terminal(ast->comma_token, ast); + for (SpecifierListAST *iter = ast->type_specifiers; iter; iter = iter->next) + nonterminal(iter->value); + nonterminal(ast->declarator); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + return false; +} + +virtual bool visit(QtPropertyDeclarationItemAST *ast) +{ + if (ast->item_name_token) + terminal(ast->item_name_token, ast); + nonterminal(ast->expression); + return false; +} + +virtual bool visit(QtPropertyDeclarationAST *ast) +{ + if (ast->property_specifier_token) + terminal(ast->property_specifier_token, ast); + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + nonterminal(ast->type_id); + nonterminal(ast->property_name); + for (QtPropertyDeclarationItemListAST *iter = ast->property_declaration_items; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + return false; +} + +virtual bool visit(QtEnumDeclarationAST *ast) +{ + if (ast->enum_specifier_token) + terminal(ast->enum_specifier_token, ast); + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + for (NameListAST *iter = ast->enumerator_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + return false; +} + +virtual bool visit(QtFlagsDeclarationAST *ast) +{ + if (ast->flags_specifier_token) + terminal(ast->flags_specifier_token, ast); + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + for (NameListAST *iter = ast->flag_enums_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + return false; +} + +virtual bool visit(QtInterfaceNameAST *ast) +{ + nonterminal(ast->interface_name); + for (NameListAST *iter = ast->constraint_list; iter; iter = iter->next) + nonterminal(iter->value); + return false; +} + +virtual bool visit(QtInterfacesDeclarationAST *ast) +{ + if (ast->interfaces_token) + terminal(ast->interfaces_token, ast); + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + for (QtInterfaceNameListAST *iter = ast->interface_name_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + return false; +} + +virtual bool visit(AsmDefinitionAST *ast) +{ + if (ast->asm_token) + terminal(ast->asm_token, ast); + if (ast->volatile_token) + terminal(ast->volatile_token, ast); + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + if (ast->semicolon_token) + terminal(ast->semicolon_token, ast); + return false; +} + +virtual bool visit(BaseSpecifierAST *ast) +{ + if (ast->virtual_token) + terminal(ast->virtual_token, ast); + if (ast->access_specifier_token) + terminal(ast->access_specifier_token, ast); + nonterminal(ast->name); + return false; +} + +virtual bool visit(CompoundExpressionAST *ast) +{ + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + nonterminal(ast->statement); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + return false; +} + +virtual bool visit(CompoundLiteralAST *ast) +{ + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + nonterminal(ast->type_id); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + nonterminal(ast->initializer); + return false; +} + +virtual bool visit(QtMethodAST *ast) +{ + if (ast->method_token) + terminal(ast->method_token, ast); + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + nonterminal(ast->declarator); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + return false; +} + +virtual bool visit(QtMemberDeclarationAST *ast) +{ + if (ast->q_token) + terminal(ast->q_token, ast); + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + nonterminal(ast->type_id); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + return false; +} + +virtual bool visit(BinaryExpressionAST *ast) +{ + nonterminal(ast->left_expression); + if (ast->binary_op_token) + terminal(ast->binary_op_token, ast); + nonterminal(ast->right_expression); + return false; +} + +virtual bool visit(CastExpressionAST *ast) +{ + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + nonterminal(ast->type_id); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + nonterminal(ast->expression); + return false; +} + +virtual bool visit(ClassSpecifierAST *ast) +{ + if (ast->classkey_token) + terminal(ast->classkey_token, ast); + for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next) + nonterminal(iter->value); + nonterminal(ast->name); + if (ast->colon_token) + terminal(ast->colon_token, ast); + for (BaseSpecifierListAST *iter = ast->base_clause_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->dot_dot_dot_token) + terminal(ast->dot_dot_dot_token, ast); + if (ast->lbrace_token) + terminal(ast->lbrace_token, ast); + for (DeclarationListAST *iter = ast->member_specifier_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->rbrace_token) + terminal(ast->rbrace_token, ast); + return false; +} + +virtual bool visit(CaseStatementAST *ast) +{ + if (ast->case_token) + terminal(ast->case_token, ast); + nonterminal(ast->expression); + if (ast->colon_token) + terminal(ast->colon_token, ast); + nonterminal(ast->statement); + return false; +} + +virtual bool visit(CompoundStatementAST *ast) +{ + if (ast->lbrace_token) + terminal(ast->lbrace_token, ast); + for (StatementListAST *iter = ast->statement_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->rbrace_token) + terminal(ast->rbrace_token, ast); + return false; +} + +virtual bool visit(ConditionAST *ast) +{ + for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next) + nonterminal(iter->value); + nonterminal(ast->declarator); + return false; +} + +virtual bool visit(ConditionalExpressionAST *ast) +{ + nonterminal(ast->condition); + if (ast->question_token) + terminal(ast->question_token, ast); + nonterminal(ast->left_expression); + if (ast->colon_token) + terminal(ast->colon_token, ast); + nonterminal(ast->right_expression); + return false; +} + +virtual bool visit(CppCastExpressionAST *ast) +{ + if (ast->cast_token) + terminal(ast->cast_token, ast); + if (ast->less_token) + terminal(ast->less_token, ast); + nonterminal(ast->type_id); + if (ast->greater_token) + terminal(ast->greater_token, ast); + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + nonterminal(ast->expression); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + return false; +} + +virtual bool visit(CtorInitializerAST *ast) +{ + if (ast->colon_token) + terminal(ast->colon_token, ast); + for (MemInitializerListAST *iter = ast->member_initializer_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->dot_dot_dot_token) + terminal(ast->dot_dot_dot_token, ast); + return false; +} + +virtual bool visit(DeclarationStatementAST *ast) +{ + nonterminal(ast->declaration); + return false; +} + +virtual bool visit(DeclaratorIdAST *ast) +{ + if (ast->dot_dot_dot_token) + terminal(ast->dot_dot_dot_token, ast); + nonterminal(ast->name); + return false; +} + +virtual bool visit(NestedDeclaratorAST *ast) +{ + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + nonterminal(ast->declarator); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + return false; +} + +virtual bool visit(FunctionDeclaratorAST *ast) +{ + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + nonterminal(ast->parameters); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + for (SpecifierListAST *iter = ast->cv_qualifier_list; iter; iter = iter->next) + nonterminal(iter->value); + nonterminal(ast->exception_specification); + nonterminal(ast->trailing_return_type); + nonterminal(ast->as_cpp_initializer); + return false; +} + +virtual bool visit(ArrayDeclaratorAST *ast) +{ + if (ast->lbracket_token) + terminal(ast->lbracket_token, ast); + nonterminal(ast->expression); + if (ast->rbracket_token) + terminal(ast->rbracket_token, ast); + return false; +} + +virtual bool visit(DeleteExpressionAST *ast) +{ + if (ast->scope_token) + terminal(ast->scope_token, ast); + if (ast->delete_token) + terminal(ast->delete_token, ast); + if (ast->lbracket_token) + terminal(ast->lbracket_token, ast); + if (ast->rbracket_token) + terminal(ast->rbracket_token, ast); + nonterminal(ast->expression); + return false; +} + +virtual bool visit(DoStatementAST *ast) +{ + if (ast->do_token) + terminal(ast->do_token, ast); + nonterminal(ast->statement); + if (ast->while_token) + terminal(ast->while_token, ast); + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + nonterminal(ast->expression); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + if (ast->semicolon_token) + terminal(ast->semicolon_token, ast); + return false; +} + +virtual bool visit(NamedTypeSpecifierAST *ast) +{ + nonterminal(ast->name); + return false; +} + +virtual bool visit(ElaboratedTypeSpecifierAST *ast) +{ + if (ast->classkey_token) + terminal(ast->classkey_token, ast); + for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next) + nonterminal(iter->value); + nonterminal(ast->name); + return false; +} + +virtual bool visit(EnumSpecifierAST *ast) +{ + if (ast->enum_token) + terminal(ast->enum_token, ast); + nonterminal(ast->name); + if (ast->lbrace_token) + terminal(ast->lbrace_token, ast); + for (EnumeratorListAST *iter = ast->enumerator_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->rbrace_token) + terminal(ast->rbrace_token, ast); + return false; +} + +virtual bool visit(EnumeratorAST *ast) +{ + if (ast->identifier_token) + terminal(ast->identifier_token, ast); + if (ast->equal_token) + terminal(ast->equal_token, ast); + nonterminal(ast->expression); + return false; +} + +virtual bool visit(ExceptionDeclarationAST *ast) +{ + for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next) + nonterminal(iter->value); + nonterminal(ast->declarator); + if (ast->dot_dot_dot_token) + terminal(ast->dot_dot_dot_token, ast); + return false; +} + +virtual bool visit(ExceptionSpecificationAST *ast) +{ + if (ast->throw_token) + terminal(ast->throw_token, ast); + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + if (ast->dot_dot_dot_token) + terminal(ast->dot_dot_dot_token, ast); + for (ExpressionListAST *iter = ast->type_id_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + return false; +} + +virtual bool visit(ExpressionOrDeclarationStatementAST *ast) +{ + nonterminal(ast->expression); + nonterminal(ast->declaration); + return false; +} + +virtual bool visit(ExpressionStatementAST *ast) +{ + nonterminal(ast->expression); + if (ast->semicolon_token) + terminal(ast->semicolon_token, ast); + return false; +} + +virtual bool visit(FunctionDefinitionAST *ast) +{ + if (ast->qt_invokable_token) + terminal(ast->qt_invokable_token, ast); + for (SpecifierListAST *iter = ast->decl_specifier_list; iter; iter = iter->next) + nonterminal(iter->value); + nonterminal(ast->declarator); + nonterminal(ast->ctor_initializer); + nonterminal(ast->function_body); + return false; +} + +virtual bool visit(ForeachStatementAST *ast) +{ + if (ast->foreach_token) + terminal(ast->foreach_token, ast); + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next) + nonterminal(iter->value); + nonterminal(ast->declarator); + nonterminal(ast->initializer); + if (ast->comma_token) + terminal(ast->comma_token, ast); + nonterminal(ast->expression); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + nonterminal(ast->statement); + return false; +} + +virtual bool visit(ForStatementAST *ast) +{ + if (ast->for_token) + terminal(ast->for_token, ast); + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + nonterminal(ast->initializer); + nonterminal(ast->condition); + if (ast->semicolon_token) + terminal(ast->semicolon_token, ast); + nonterminal(ast->expression); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + nonterminal(ast->statement); + return false; +} + +virtual bool visit(IfStatementAST *ast) +{ + if (ast->if_token) + terminal(ast->if_token, ast); + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + nonterminal(ast->condition); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + nonterminal(ast->statement); + if (ast->else_token) + terminal(ast->else_token, ast); + nonterminal(ast->else_statement); + return false; +} + +virtual bool visit(ArrayInitializerAST *ast) +{ + if (ast->lbrace_token) + terminal(ast->lbrace_token, ast); + for (ExpressionListAST *iter = ast->expression_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->rbrace_token) + terminal(ast->rbrace_token, ast); + return false; +} + +virtual bool visit(LabeledStatementAST *ast) +{ + if (ast->label_token) + terminal(ast->label_token, ast); + if (ast->colon_token) + terminal(ast->colon_token, ast); + nonterminal(ast->statement); + return false; +} + +virtual bool visit(LinkageBodyAST *ast) +{ + if (ast->lbrace_token) + terminal(ast->lbrace_token, ast); + for (DeclarationListAST *iter = ast->declaration_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->rbrace_token) + terminal(ast->rbrace_token, ast); + return false; +} + +virtual bool visit(LinkageSpecificationAST *ast) +{ + if (ast->extern_token) + terminal(ast->extern_token, ast); + if (ast->extern_type_token) + terminal(ast->extern_type_token, ast); + nonterminal(ast->declaration); + return false; +} + +virtual bool visit(MemInitializerAST *ast) +{ + nonterminal(ast->name); + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + for (ExpressionListAST *iter = ast->expression_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + return false; +} + +virtual bool visit(NestedNameSpecifierAST *ast) +{ + nonterminal(ast->class_or_namespace_name); + if (ast->scope_token) + terminal(ast->scope_token, ast); + return false; +} + +virtual bool visit(QualifiedNameAST *ast) +{ + if (ast->global_scope_token) + terminal(ast->global_scope_token, ast); + for (NestedNameSpecifierListAST *iter = ast->nested_name_specifier_list; iter; iter = iter->next) + nonterminal(iter->value); + nonterminal(ast->unqualified_name); + return false; +} + +virtual bool visit(OperatorFunctionIdAST *ast) +{ + if (ast->operator_token) + terminal(ast->operator_token, ast); + nonterminal(ast->op); + return false; +} + +virtual bool visit(ConversionFunctionIdAST *ast) +{ + if (ast->operator_token) + terminal(ast->operator_token, ast); + for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next) + nonterminal(iter->value); + for (PtrOperatorListAST *iter = ast->ptr_operator_list; iter; iter = iter->next) + nonterminal(iter->value); + return false; +} + +virtual bool visit(SimpleNameAST *ast) +{ + if (ast->identifier_token) + terminal(ast->identifier_token, ast); + return false; +} + +virtual bool visit(DestructorNameAST *ast) +{ + if (ast->tilde_token) + terminal(ast->tilde_token, ast); + if (ast->identifier_token) + terminal(ast->identifier_token, ast); + return false; +} + +virtual bool visit(TemplateIdAST *ast) +{ + if (ast->identifier_token) + terminal(ast->identifier_token, ast); + if (ast->less_token) + terminal(ast->less_token, ast); + for (TemplateArgumentListAST *iter = ast->template_argument_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->greater_token) + terminal(ast->greater_token, ast); + return false; +} + +virtual bool visit(NamespaceAST *ast) +{ + if (ast->namespace_token) + terminal(ast->namespace_token, ast); + if (ast->identifier_token) + terminal(ast->identifier_token, ast); + for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next) + nonterminal(iter->value); + nonterminal(ast->linkage_body); + return false; +} + +virtual bool visit(NamespaceAliasDefinitionAST *ast) +{ + if (ast->namespace_token) + terminal(ast->namespace_token, ast); + if (ast->namespace_name_token) + terminal(ast->namespace_name_token, ast); + if (ast->equal_token) + terminal(ast->equal_token, ast); + nonterminal(ast->name); + if (ast->semicolon_token) + terminal(ast->semicolon_token, ast); + return false; +} + +virtual bool visit(NewPlacementAST *ast) +{ + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + for (ExpressionListAST *iter = ast->expression_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + return false; +} + +virtual bool visit(NewArrayDeclaratorAST *ast) +{ + if (ast->lbracket_token) + terminal(ast->lbracket_token, ast); + nonterminal(ast->expression); + if (ast->rbracket_token) + terminal(ast->rbracket_token, ast); + return false; +} + +virtual bool visit(NewExpressionAST *ast) +{ + if (ast->scope_token) + terminal(ast->scope_token, ast); + if (ast->new_token) + terminal(ast->new_token, ast); + nonterminal(ast->new_placement); + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + nonterminal(ast->type_id); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + nonterminal(ast->new_type_id); + nonterminal(ast->new_initializer); + return false; +} + +virtual bool visit(NewInitializerAST *ast) +{ + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + nonterminal(ast->expression); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + return false; +} + +virtual bool visit(NewTypeIdAST *ast) +{ + for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next) + nonterminal(iter->value); + for (PtrOperatorListAST *iter = ast->ptr_operator_list; iter; iter = iter->next) + nonterminal(iter->value); + for (NewArrayDeclaratorListAST *iter = ast->new_array_declarator_list; iter; iter = iter->next) + nonterminal(iter->value); + return false; +} + +virtual bool visit(OperatorAST *ast) +{ + if (ast->op_token) + terminal(ast->op_token, ast); + if (ast->open_token) + terminal(ast->open_token, ast); + if (ast->close_token) + terminal(ast->close_token, ast); + return false; +} + +virtual bool visit(ParameterDeclarationAST *ast) +{ + for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next) + nonterminal(iter->value); + nonterminal(ast->declarator); + if (ast->equal_token) + terminal(ast->equal_token, ast); + nonterminal(ast->expression); + return false; +} + +virtual bool visit(ParameterDeclarationClauseAST *ast) +{ + for (DeclarationListAST *iter = ast->parameter_declaration_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->dot_dot_dot_token) + terminal(ast->dot_dot_dot_token, ast); + return false; +} + +virtual bool visit(CallAST *ast) +{ + nonterminal(ast->base_expression); + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + for (ExpressionListAST *iter = ast->expression_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + return false; +} + +virtual bool visit(ArrayAccessAST *ast) +{ + nonterminal(ast->base_expression); + if (ast->lbracket_token) + terminal(ast->lbracket_token, ast); + nonterminal(ast->expression); + if (ast->rbracket_token) + terminal(ast->rbracket_token, ast); + return false; +} + +virtual bool visit(PostIncrDecrAST *ast) +{ + nonterminal(ast->base_expression); + if (ast->incr_decr_token) + terminal(ast->incr_decr_token, ast); + return false; +} + +virtual bool visit(MemberAccessAST *ast) +{ + nonterminal(ast->base_expression); + if (ast->access_token) + terminal(ast->access_token, ast); + if (ast->template_token) + terminal(ast->template_token, ast); + nonterminal(ast->member_name); + return false; +} + +virtual bool visit(TypeidExpressionAST *ast) +{ + if (ast->typeid_token) + terminal(ast->typeid_token, ast); + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + nonterminal(ast->expression); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + return false; +} + +virtual bool visit(TypenameCallExpressionAST *ast) +{ + if (ast->typename_token) + terminal(ast->typename_token, ast); + nonterminal(ast->name); + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + for (ExpressionListAST *iter = ast->expression_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + return false; +} + +virtual bool visit(TypeConstructorCallAST *ast) +{ + for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + for (ExpressionListAST *iter = ast->expression_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + return false; +} + +virtual bool visit(PointerToMemberAST *ast) +{ + if (ast->global_scope_token) + terminal(ast->global_scope_token, ast); + for (NestedNameSpecifierListAST *iter = ast->nested_name_specifier_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->star_token) + terminal(ast->star_token, ast); + for (SpecifierListAST *iter = ast->cv_qualifier_list; iter; iter = iter->next) + nonterminal(iter->value); + return false; +} + +virtual bool visit(PointerAST *ast) +{ + if (ast->star_token) + terminal(ast->star_token, ast); + for (SpecifierListAST *iter = ast->cv_qualifier_list; iter; iter = iter->next) + nonterminal(iter->value); + return false; +} + +virtual bool visit(ReferenceAST *ast) +{ + if (ast->reference_token) + terminal(ast->reference_token, ast); + return false; +} + +virtual bool visit(BreakStatementAST *ast) +{ + if (ast->break_token) + terminal(ast->break_token, ast); + if (ast->semicolon_token) + terminal(ast->semicolon_token, ast); + return false; +} + +virtual bool visit(ContinueStatementAST *ast) +{ + if (ast->continue_token) + terminal(ast->continue_token, ast); + if (ast->semicolon_token) + terminal(ast->semicolon_token, ast); + return false; +} + +virtual bool visit(GotoStatementAST *ast) +{ + if (ast->goto_token) + terminal(ast->goto_token, ast); + if (ast->identifier_token) + terminal(ast->identifier_token, ast); + if (ast->semicolon_token) + terminal(ast->semicolon_token, ast); + return false; +} + +virtual bool visit(ReturnStatementAST *ast) +{ + if (ast->return_token) + terminal(ast->return_token, ast); + nonterminal(ast->expression); + if (ast->semicolon_token) + terminal(ast->semicolon_token, ast); + return false; +} + +virtual bool visit(SizeofExpressionAST *ast) +{ + if (ast->sizeof_token) + terminal(ast->sizeof_token, ast); + if (ast->dot_dot_dot_token) + terminal(ast->dot_dot_dot_token, ast); + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + nonterminal(ast->expression); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + return false; +} + +virtual bool visit(NumericLiteralAST *ast) +{ + if (ast->literal_token) + terminal(ast->literal_token, ast); + return false; +} + +virtual bool visit(BoolLiteralAST *ast) +{ + if (ast->literal_token) + terminal(ast->literal_token, ast); + return false; +} + +virtual bool visit(ThisExpressionAST *ast) +{ + if (ast->this_token) + terminal(ast->this_token, ast); + return false; +} + +virtual bool visit(NestedExpressionAST *ast) +{ + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + nonterminal(ast->expression); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + return false; +} + +virtual bool visit(StringLiteralAST *ast) +{ + if (ast->literal_token) + terminal(ast->literal_token, ast); + nonterminal(ast->next); + return false; +} + +virtual bool visit(SwitchStatementAST *ast) +{ + if (ast->switch_token) + terminal(ast->switch_token, ast); + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + nonterminal(ast->condition); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + nonterminal(ast->statement); + return false; +} + +virtual bool visit(TemplateDeclarationAST *ast) +{ + if (ast->export_token) + terminal(ast->export_token, ast); + if (ast->template_token) + terminal(ast->template_token, ast); + if (ast->less_token) + terminal(ast->less_token, ast); + for (DeclarationListAST *iter = ast->template_parameter_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->greater_token) + terminal(ast->greater_token, ast); + nonterminal(ast->declaration); + return false; +} + +virtual bool visit(ThrowExpressionAST *ast) +{ + if (ast->throw_token) + terminal(ast->throw_token, ast); + nonterminal(ast->expression); + return false; +} + +virtual bool visit(TranslationUnitAST *ast) +{ + for (DeclarationListAST *iter = ast->declaration_list; iter; iter = iter->next) + nonterminal(iter->value); + return false; +} + +virtual bool visit(TryBlockStatementAST *ast) +{ + if (ast->try_token) + terminal(ast->try_token, ast); + nonterminal(ast->statement); + for (CatchClauseListAST *iter = ast->catch_clause_list; iter; iter = iter->next) + nonterminal(iter->value); + return false; +} + +virtual bool visit(CatchClauseAST *ast) +{ + if (ast->catch_token) + terminal(ast->catch_token, ast); + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + nonterminal(ast->exception_declaration); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + nonterminal(ast->statement); + return false; +} + +virtual bool visit(TypeIdAST *ast) +{ + for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next) + nonterminal(iter->value); + nonterminal(ast->declarator); + return false; +} + +virtual bool visit(TypenameTypeParameterAST *ast) +{ + if (ast->classkey_token) + terminal(ast->classkey_token, ast); + if (ast->dot_dot_dot_token) + terminal(ast->dot_dot_dot_token, ast); + nonterminal(ast->name); + if (ast->equal_token) + terminal(ast->equal_token, ast); + nonterminal(ast->type_id); + return false; +} + +virtual bool visit(TemplateTypeParameterAST *ast) +{ + if (ast->template_token) + terminal(ast->template_token, ast); + if (ast->less_token) + terminal(ast->less_token, ast); + for (DeclarationListAST *iter = ast->template_parameter_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->greater_token) + terminal(ast->greater_token, ast); + if (ast->class_token) + terminal(ast->class_token, ast); + if (ast->dot_dot_dot_token) + terminal(ast->dot_dot_dot_token, ast); + nonterminal(ast->name); + if (ast->equal_token) + terminal(ast->equal_token, ast); + nonterminal(ast->type_id); + return false; +} + +virtual bool visit(UnaryExpressionAST *ast) +{ + if (ast->unary_op_token) + terminal(ast->unary_op_token, ast); + nonterminal(ast->expression); + return false; +} + +virtual bool visit(UsingAST *ast) +{ + if (ast->using_token) + terminal(ast->using_token, ast); + if (ast->typename_token) + terminal(ast->typename_token, ast); + nonterminal(ast->name); + if (ast->semicolon_token) + terminal(ast->semicolon_token, ast); + return false; +} + +virtual bool visit(UsingDirectiveAST *ast) +{ + if (ast->using_token) + terminal(ast->using_token, ast); + if (ast->namespace_token) + terminal(ast->namespace_token, ast); + nonterminal(ast->name); + if (ast->semicolon_token) + terminal(ast->semicolon_token, ast); + return false; +} + +virtual bool visit(WhileStatementAST *ast) +{ + if (ast->while_token) + terminal(ast->while_token, ast); + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + nonterminal(ast->condition); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + nonterminal(ast->statement); + return false; +} + +virtual bool visit(ObjCClassForwardDeclarationAST *ast) +{ + for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->class_token) + terminal(ast->class_token, ast); + for (NameListAST *iter = ast->identifier_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->semicolon_token) + terminal(ast->semicolon_token, ast); + return false; +} + +virtual bool visit(ObjCClassDeclarationAST *ast) +{ + for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->interface_token) + terminal(ast->interface_token, ast); + if (ast->implementation_token) + terminal(ast->implementation_token, ast); + nonterminal(ast->class_name); + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + nonterminal(ast->category_name); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + if (ast->colon_token) + terminal(ast->colon_token, ast); + nonterminal(ast->superclass); + nonterminal(ast->protocol_refs); + nonterminal(ast->inst_vars_decl); + for (DeclarationListAST *iter = ast->member_declaration_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->end_token) + terminal(ast->end_token, ast); + return false; +} + +virtual bool visit(ObjCProtocolForwardDeclarationAST *ast) +{ + for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->protocol_token) + terminal(ast->protocol_token, ast); + for (NameListAST *iter = ast->identifier_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->semicolon_token) + terminal(ast->semicolon_token, ast); + return false; +} + +virtual bool visit(ObjCProtocolDeclarationAST *ast) +{ + for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->protocol_token) + terminal(ast->protocol_token, ast); + nonterminal(ast->name); + nonterminal(ast->protocol_refs); + for (DeclarationListAST *iter = ast->member_declaration_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->end_token) + terminal(ast->end_token, ast); + return false; +} + +virtual bool visit(ObjCProtocolRefsAST *ast) +{ + if (ast->less_token) + terminal(ast->less_token, ast); + for (NameListAST *iter = ast->identifier_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->greater_token) + terminal(ast->greater_token, ast); + return false; +} + +virtual bool visit(ObjCMessageArgumentAST *ast) +{ + nonterminal(ast->parameter_value_expression); + return false; +} + +virtual bool visit(ObjCMessageExpressionAST *ast) +{ + if (ast->lbracket_token) + terminal(ast->lbracket_token, ast); + nonterminal(ast->receiver_expression); + nonterminal(ast->selector); + for (ObjCMessageArgumentListAST *iter = ast->argument_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->rbracket_token) + terminal(ast->rbracket_token, ast); + return false; +} + +virtual bool visit(ObjCProtocolExpressionAST *ast) +{ + if (ast->protocol_token) + terminal(ast->protocol_token, ast); + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + if (ast->identifier_token) + terminal(ast->identifier_token, ast); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + return false; +} + +virtual bool visit(ObjCTypeNameAST *ast) +{ + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + if (ast->type_qualifier_token) + terminal(ast->type_qualifier_token, ast); + nonterminal(ast->type_id); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + return false; +} + +virtual bool visit(ObjCEncodeExpressionAST *ast) +{ + if (ast->encode_token) + terminal(ast->encode_token, ast); + nonterminal(ast->type_name); + return false; +} + +virtual bool visit(ObjCSelectorExpressionAST *ast) +{ + if (ast->selector_token) + terminal(ast->selector_token, ast); + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + nonterminal(ast->selector); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + return false; +} + +virtual bool visit(ObjCInstanceVariablesDeclarationAST *ast) +{ + if (ast->lbrace_token) + terminal(ast->lbrace_token, ast); + for (DeclarationListAST *iter = ast->instance_variable_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->rbrace_token) + terminal(ast->rbrace_token, ast); + return false; +} + +virtual bool visit(ObjCVisibilityDeclarationAST *ast) +{ + if (ast->visibility_token) + terminal(ast->visibility_token, ast); + return false; +} + +virtual bool visit(ObjCPropertyAttributeAST *ast) +{ + if (ast->attribute_identifier_token) + terminal(ast->attribute_identifier_token, ast); + if (ast->equals_token) + terminal(ast->equals_token, ast); + nonterminal(ast->method_selector); + return false; +} + +virtual bool visit(ObjCPropertyDeclarationAST *ast) +{ + for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->property_token) + terminal(ast->property_token, ast); + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + for (ObjCPropertyAttributeListAST *iter = ast->property_attribute_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + nonterminal(ast->simple_declaration); + return false; +} + +virtual bool visit(ObjCMessageArgumentDeclarationAST *ast) +{ + nonterminal(ast->type_name); + for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next) + nonterminal(iter->value); + nonterminal(ast->param_name); + return false; +} + +virtual bool visit(ObjCMethodPrototypeAST *ast) +{ + if (ast->method_type_token) + terminal(ast->method_type_token, ast); + nonterminal(ast->type_name); + nonterminal(ast->selector); + for (ObjCMessageArgumentDeclarationListAST *iter = ast->argument_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->dot_dot_dot_token) + terminal(ast->dot_dot_dot_token, ast); + for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next) + nonterminal(iter->value); + return false; +} + +virtual bool visit(ObjCMethodDeclarationAST *ast) +{ + nonterminal(ast->method_prototype); + nonterminal(ast->function_body); + if (ast->semicolon_token) + terminal(ast->semicolon_token, ast); + return false; +} + +virtual bool visit(ObjCSynthesizedPropertyAST *ast) +{ + if (ast->property_identifier_token) + terminal(ast->property_identifier_token, ast); + if (ast->equals_token) + terminal(ast->equals_token, ast); + if (ast->alias_identifier_token) + terminal(ast->alias_identifier_token, ast); + return false; +} + +virtual bool visit(ObjCSynthesizedPropertiesDeclarationAST *ast) +{ + if (ast->synthesized_token) + terminal(ast->synthesized_token, ast); + for (ObjCSynthesizedPropertyListAST *iter = ast->property_identifier_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->semicolon_token) + terminal(ast->semicolon_token, ast); + return false; +} + +virtual bool visit(ObjCDynamicPropertiesDeclarationAST *ast) +{ + if (ast->dynamic_token) + terminal(ast->dynamic_token, ast); + for (NameListAST *iter = ast->property_identifier_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->semicolon_token) + terminal(ast->semicolon_token, ast); + return false; +} + +virtual bool visit(ObjCFastEnumerationAST *ast) +{ + if (ast->for_token) + terminal(ast->for_token, ast); + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next) + nonterminal(iter->value); + nonterminal(ast->declarator); + nonterminal(ast->initializer); + if (ast->in_token) + terminal(ast->in_token, ast); + nonterminal(ast->fast_enumeratable_expression); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + nonterminal(ast->statement); + return false; +} + +virtual bool visit(ObjCSynchronizedStatementAST *ast) +{ + if (ast->synchronized_token) + terminal(ast->synchronized_token, ast); + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + nonterminal(ast->synchronized_object); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + nonterminal(ast->statement); + return false; +} + +virtual bool visit(LambdaExpressionAST *ast) +{ + nonterminal(ast->lambda_introducer); + nonterminal(ast->lambda_declarator); + nonterminal(ast->statement); + return false; +} + +virtual bool visit(LambdaIntroducerAST *ast) +{ + if (ast->lbracket_token) + terminal(ast->lbracket_token, ast); + nonterminal(ast->lambda_capture); + if (ast->rbracket_token) + terminal(ast->rbracket_token, ast); + return false; +} + +virtual bool visit(LambdaCaptureAST *ast) +{ + if (ast->default_capture_token) + terminal(ast->default_capture_token, ast); + for (CaptureListAST *iter = ast->capture_list; iter; iter = iter->next) + nonterminal(iter->value); + return false; +} + +virtual bool visit(CaptureAST *ast) +{ + return false; +} + +virtual bool visit(LambdaDeclaratorAST *ast) +{ + if (ast->lparen_token) + terminal(ast->lparen_token, ast); + nonterminal(ast->parameter_declaration_clause); + if (ast->rparen_token) + terminal(ast->rparen_token, ast); + for (SpecifierListAST *iter = ast->attributes; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->mutable_token) + terminal(ast->mutable_token, ast); + nonterminal(ast->exception_specification); + nonterminal(ast->trailing_return_type); + return false; +} + +virtual bool visit(TrailingReturnTypeAST *ast) +{ + if (ast->arrow_token) + terminal(ast->arrow_token, ast); + for (SpecifierListAST *iter = ast->attributes; iter; iter = iter->next) + nonterminal(iter->value); + for (SpecifierListAST *iter = ast->type_specifiers; iter; iter = iter->next) + nonterminal(iter->value); + nonterminal(ast->declarator); + return false; +} + +virtual bool visit(BracedInitializerAST *ast) +{ + if (ast->lbrace_token) + terminal(ast->lbrace_token, ast); + for (ExpressionListAST *iter = ast->expression_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->comma_token) + terminal(ast->comma_token, ast); + if (ast->rbrace_token) + terminal(ast->rbrace_token, ast); + return false; +} + diff --git a/tests/manual/cplusplus-dump/main.cpp b/tests/manual/cplusplus-dump/main.cpp index a87adfe364b4b090ed58da56e2c98b0a47ffe1cc..c45d1b4718a26c85fe709d86e7ee1b74ccce29ff 100644 --- a/tests/manual/cplusplus-dump/main.cpp +++ b/tests/manual/cplusplus-dump/main.cpp @@ -73,13 +73,14 @@ public: basename.append(".ast.dot"); out.open(basename.constData()); - out << "digraph AST {" << std::endl; + out << "digraph AST { ordering=out;" << std::endl; // std::cout << "rankdir = \"LR\";" << std::endl; accept(ast); - foreach (const QByteArray &terminalShape, _terminalShapes) { - out << std::string(terminalShape) << " [shape=rect]" << std::endl; - } + typedef QPair<QByteArray, QByteArray> Pair; + + foreach (const Pair &conn, _connections) + out << conn.first.constData() << " -> " << conn.second.constData() << std::endl; alignTerminals(); @@ -88,6 +89,10 @@ public: std::cout << basename.constData() << std::endl; } + // the following file can be generated by using: + // generate-ast <path to cpp stuff> <path to dumpers.inc> +#include "dumpers.inc" + protected: void alignTerminals() { out<<"{ rank=same;" << std::endl; @@ -97,59 +102,47 @@ protected: out<<"}"<<std::endl; } - QByteArray addTerminalInfo(AST *ast) const { - if (SimpleNameAST *simpleName = ast->asSimpleName()) { - return spell(simpleName->identifier_token); - } else if (BinaryExpressionAST *binExpr = ast->asBinaryExpression()) { - return spell(binExpr->binary_op_token); - } else if (SimpleSpecifierAST *simpleSpec = ast->asSimpleSpecifier()) { - return spell(simpleSpec->specifier_token); - } else if (NumericLiteralAST *numLit = ast->asNumericLiteral()) { - return spell(numLit->literal_token); - } else if (StringLiteralAST *strLit = ast->asStringLiteral()) { - return spell(strLit->literal_token); - } else if (BoolLiteralAST *boolLit = ast->asBoolLiteral()) { - return spell(boolLit->literal_token); - } else if (ObjCSelectorArgumentAST *selArg = ast->asObjCSelectorArgument()) { - QByteArray t = spell(selArg->name_token); - if (selArg->colon_token) - t.append(spell(selArg->colon_token)); - return t; - } else if (AttributeAST *attr = ast->asAttribute()) { - return spell(attr->identifier_token); - } else { - return QByteArray(); - } - } - - std::string name(AST *ast) { + static QByteArray name(AST *ast) { QByteArray name = abi::__cxa_demangle(typeid(*ast).name(), 0, 0, 0) + 11; name.truncate(name.length() - 3); - name = QByteArray::number(_id.value(ast)) + ". " + name; - QByteArray info = addTerminalInfo(ast); - if (!info.isEmpty()) { - name.append("\\n"); - name.append(info); - } - name.prepend('"'); - name.append('"'); + return name; + } + + void terminal(unsigned token, AST *node) { + static int count = 1; + QByteArray id = 't' + QByteArray::number(count++); + _connections.append(qMakePair(_id[node], id)); + + QByteArray t; + t.append(id); + t.append(" [label = \""); + t.append(spell(token)); + t.append("\" shape=rect]"); + _terminalShapes.append(t); + } - if (!info.isEmpty()) - _terminalShapes.insert(name); + virtual void nonterminal(AST *ast) { + accept(ast); + } - return std::string(name); + virtual void node(AST *ast) { + out << _id[ast].constData() << " [label=\"" << name(ast).constData() << "\"];" << std::endl; } virtual bool preVisit(AST *ast) { static int count = 1; - _id[ast] = count++; + const QByteArray id = 'n' + QByteArray::number(count++); + _id[ast] = id; + if (! _stack.isEmpty()) - out << name(_stack.last()) << " -> " << name(ast) << ";" << std::endl; + _connections.append(qMakePair(_id[_stack.last()], id)); _stack.append(ast); + node(ast); + return true; } @@ -158,9 +151,10 @@ protected: } private: - QHash<AST *, int> _id; + QHash<AST *, QByteArray> _id; + QList<QPair<QByteArray, QByteArray> > _connections; QList<AST *> _stack; - QSet<QByteArray> _terminalShapes; + QList<QByteArray> _terminalShapes; std::ofstream out; }; @@ -183,7 +177,7 @@ public: basename.append(".symbols.dot"); out.open(basename.constData()); - out << "digraph Symbols {" << std::endl; + out << "digraph Symbols { ordering=out;" << std::endl; // std::cout << "rankdir = \"LR\";" << std::endl; accept(s);