aboutsummaryrefslogtreecommitdiffstats
path: root/parser
diff options
context:
space:
mode:
authorHugo Lima <hugo.lima@openbossa.org>2009-08-17 17:32:08 -0300
committerHugo Lima <hugo.lima@openbossa.org>2009-08-17 17:32:08 -0300
commit9732e0c744e45a67094fc6ce08bdadb1f9a08d4a (patch)
tree566e389f406515b040317bffa075f4e5021020f7 /parser
The genesis...
Diffstat (limited to 'parser')
-rw-r--r--parser/ast.cpp33
-rw-r--r--parser/ast.h879
-rw-r--r--parser/binder.cpp852
-rw-r--r--parser/binder.h125
-rw-r--r--parser/class_compiler.cpp66
-rw-r--r--parser/class_compiler.h72
-rw-r--r--parser/codemodel.cpp932
-rw-r--r--parser/codemodel.h838
-rw-r--r--parser/codemodel_finder.cpp98
-rw-r--r--parser/codemodel_finder.h70
-rw-r--r--parser/codemodel_fwd.h80
-rw-r--r--parser/codemodel_pointer.h60
-rw-r--r--parser/compiler_utils.cpp50
-rw-r--r--parser/compiler_utils.h47
-rw-r--r--parser/control.cpp130
-rw-r--r--parser/control.h160
-rw-r--r--parser/declarator_compiler.cpp147
-rw-r--r--parser/declarator_compiler.h96
-rw-r--r--parser/default_visitor.cpp459
-rw-r--r--parser/default_visitor.h118
-rw-r--r--parser/dumptree.cpp125
-rw-r--r--parser/dumptree.h46
-rw-r--r--parser/lexer.cpp1695
-rw-r--r--parser/lexer.h290
-rw-r--r--parser/list.cpp28
-rw-r--r--parser/list.h100
-rw-r--r--parser/name_compiler.cpp134
-rw-r--r--parser/name_compiler.h69
-rw-r--r--parser/parser.cpp4056
-rw-r--r--parser/parser.h198
-rw-r--r--parser/r++.macros28
-rw-r--r--parser/rpp-allocator.h24
-rw-r--r--parser/rpp/builtin-macros.cpp23
-rw-r--r--parser/rpp/pp-cctype.h57
-rw-r--r--parser/rpp/pp-configuration86
-rw-r--r--parser/rpp/pp-engine-bits.h1252
-rw-r--r--parser/rpp/pp-engine.h274
-rw-r--r--parser/rpp/pp-environment.h137
-rw-r--r--parser/rpp/pp-fwd.h39
-rw-r--r--parser/rpp/pp-internal.h117
-rw-r--r--parser/rpp/pp-iterator.h88
-rw-r--r--parser/rpp/pp-macro-expander.h351
-rw-r--r--parser/rpp/pp-macro.h72
-rw-r--r--parser/rpp/pp-main.cpp295
-rw-r--r--parser/rpp/pp-qt-configuration24
-rw-r--r--parser/rpp/pp-scanner.h313
-rw-r--r--parser/rpp/pp-string.h107
-rw-r--r--parser/rpp/pp-symbol.h87
-rw-r--r--parser/rpp/pp.h91
-rw-r--r--parser/rpp/preprocessor.cpp158
-rw-r--r--parser/rpp/preprocessor.h66
-rw-r--r--parser/rxx_allocator.h130
-rw-r--r--parser/smallobject.cpp28
-rw-r--r--parser/smallobject.h47
-rw-r--r--parser/symbol.h122
-rw-r--r--parser/tokens.cpp249
-rw-r--r--parser/tokens.h145
-rw-r--r--parser/type_compiler.cpp129
-rw-r--r--parser/type_compiler.h71
-rw-r--r--parser/visitor.cpp122
-rw-r--r--parser/visitor.h140
61 files changed, 16925 insertions, 0 deletions
diff --git a/parser/ast.cpp b/parser/ast.cpp
new file mode 100644
index 00000000..ff5b7dfc
--- /dev/null
+++ b/parser/ast.cpp
@@ -0,0 +1,33 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include "ast.h"
+#include "lexer.h"
+
+QString AST::toString(TokenStream *stream) const
+{
+ const Token &tk = stream->token((int) start_token);
+ const Token &end_tk = stream->token((int) end_token);
+ return QString::fromLatin1(tk.text + tk.position, end_tk.position - tk.position);
+}
diff --git a/parser/ast.h b/parser/ast.h
new file mode 100644
index 00000000..aa98ee4d
--- /dev/null
+++ b/parser/ast.h
@@ -0,0 +1,879 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+
+#ifndef AST_H
+#define AST_H
+
+#include "smallobject.h"
+#include "list.h"
+
+class QString;
+
+#define DECLARE_AST_NODE(k) \
+ enum { __node_kind = Kind_##k };
+
+class TokenStream;
+
+struct AccessSpecifierAST;
+struct AsmDefinitionAST;
+struct BaseClauseAST;
+struct BaseSpecifierAST;
+struct BinaryExpressionAST;
+struct CastExpressionAST;
+struct ClassMemberAccessAST;
+struct ClassSpecifierAST;
+struct CompoundStatementAST;
+struct ConditionAST;
+struct ConditionalExpressionAST;
+struct CppCastExpressionAST;
+struct CtorInitializerAST;
+struct DeclarationAST;
+struct DeclarationStatementAST;
+struct DeclaratorAST;
+struct DeleteExpressionAST;
+struct DoStatementAST;
+struct ElaboratedTypeSpecifierAST;
+struct EnumSpecifierAST;
+struct EnumeratorAST;
+struct ExceptionSpecificationAST;
+struct ExpressionAST;
+struct ExpressionOrDeclarationStatementAST;
+struct ExpressionStatementAST;
+struct ForStatementAST;
+struct FunctionCallAST;
+struct FunctionDefinitionAST;
+struct IfStatementAST;
+struct IncrDecrExpressionAST;
+struct InitDeclaratorAST;
+struct InitializerAST;
+struct InitializerClauseAST;
+struct LabeledStatementAST;
+struct LinkageBodyAST;
+struct LinkageSpecificationAST;
+struct MemInitializerAST;
+struct NameAST;
+struct NamespaceAST;
+struct NamespaceAliasDefinitionAST;
+struct NewDeclaratorAST;
+struct NewExpressionAST;
+struct NewInitializerAST;
+struct NewTypeIdAST;
+struct OperatorAST;
+struct OperatorFunctionIdAST;
+struct ParameterDeclarationAST;
+struct ParameterDeclarationClauseAST;
+struct PostfixExpressionAST;
+struct PrimaryExpressionAST;
+struct PtrOperatorAST;
+struct PtrToMemberAST;
+struct ReturnStatementAST;
+struct SimpleDeclarationAST;
+struct SimpleTypeSpecifierAST;
+struct SizeofExpressionAST;
+struct StatementAST;
+struct StringLiteralAST;
+struct SubscriptExpressionAST;
+struct SwitchStatementAST;
+struct TemplateArgumentAST;
+struct TemplateDeclarationAST;
+struct TemplateParameterAST;
+struct ThrowExpressionAST;
+struct TranslationUnitAST;
+struct TryBlockStatementAST;
+struct TypeIdAST;
+struct TypeIdentificationAST;
+struct TypeParameterAST;
+struct TypeSpecifierAST;
+struct TypedefAST;
+struct UnaryExpressionAST;
+struct UnqualifiedNameAST;
+struct UsingAST;
+struct UsingDirectiveAST;
+struct WhileStatementAST;
+struct WinDeclSpecAST;
+struct QPropertyAST;
+struct QEnumsAST;
+
+struct AST
+{
+ enum NODE_KIND {
+ Kind_UNKNOWN = 0,
+
+ Kind_AccessSpecifier,
+ Kind_AsmDefinition,
+ Kind_BaseClause,
+ Kind_BaseSpecifier,
+ Kind_BinaryExpression,
+ Kind_CastExpression,
+ Kind_ClassMemberAccess,
+ Kind_ClassSpecifier,
+ Kind_CompoundStatement,
+ Kind_Condition,
+ Kind_ConditionalExpression,
+ Kind_CppCastExpression,
+ Kind_CtorInitializer,
+ Kind_DeclarationStatement,
+ Kind_Declarator,
+ Kind_DeleteExpression,
+ Kind_DoStatement,
+ Kind_ElaboratedTypeSpecifier,
+ Kind_EnumSpecifier,
+ Kind_Enumerator,
+ Kind_ExceptionSpecification,
+ Kind_ExpressionOrDeclarationStatement,
+ Kind_ExpressionStatement,
+ Kind_ForStatement,
+ Kind_FunctionCall,
+ Kind_FunctionDefinition,
+ Kind_IfStatement,
+ Kind_IncrDecrExpression,
+ Kind_InitDeclarator,
+ Kind_Initializer,
+ Kind_InitializerClause,
+ Kind_LabeledStatement,
+ Kind_LinkageBody,
+ Kind_LinkageSpecification,
+ Kind_MemInitializer,
+ Kind_Name,
+ Kind_Namespace,
+ Kind_NamespaceAliasDefinition,
+ Kind_NewDeclarator,
+ Kind_NewExpression,
+ Kind_NewInitializer,
+ Kind_NewTypeId,
+ Kind_Operator,
+ Kind_OperatorFunctionId,
+ Kind_ParameterDeclaration,
+ Kind_ParameterDeclarationClause,
+ Kind_PostfixExpression,
+ Kind_PrimaryExpression,
+ Kind_PtrOperator,
+ Kind_PtrToMember,
+ Kind_ReturnStatement,
+ Kind_SimpleDeclaration,
+ Kind_SimpleTypeSpecifier,
+ Kind_SizeofExpression,
+ Kind_StringLiteral,
+ Kind_SubscriptExpression,
+ Kind_SwitchStatement,
+ Kind_TemplateArgument,
+ Kind_TemplateDeclaration,
+ Kind_TemplateParameter,
+ Kind_ThrowExpression,
+ Kind_TranslationUnit,
+ Kind_TryBlockStatement,
+ Kind_TypeId,
+ Kind_TypeIdentification,
+ Kind_TypeParameter,
+ Kind_Typedef,
+ Kind_UnaryExpression,
+ Kind_UnqualifiedName,
+ Kind_Using,
+ Kind_UsingDirective,
+ Kind_WhileStatement,
+ Kind_WinDeclSpec,
+ Kind_QPropertyAST,
+ Kind_ForwardDeclarationSpecifier,
+ Kind_QEnumsAST,
+
+ NODE_KIND_COUNT
+ };
+
+ QString toString(TokenStream *stream) const;
+
+ int kind;
+
+ std::size_t start_token;
+ std::size_t end_token;
+};
+
+struct TypeSpecifierAST: public AST
+{
+ const ListNode<std::size_t> *cv;
+};
+
+struct StatementAST: public AST
+{
+};
+
+struct ExpressionAST: public AST
+{
+};
+
+struct DeclarationAST: public AST
+{
+};
+
+struct AccessSpecifierAST: public DeclarationAST
+{
+ DECLARE_AST_NODE(AccessSpecifier)
+
+ const ListNode<std::size_t> *specs;
+};
+
+struct AsmDefinitionAST: public DeclarationAST
+{
+ DECLARE_AST_NODE(AsmDefinition)
+
+ const ListNode<std::size_t> *cv;
+};
+
+struct BaseClauseAST: public AST
+{ // ### kill me
+ DECLARE_AST_NODE(BaseClause)
+
+ const ListNode<BaseSpecifierAST*> *base_specifiers;
+};
+
+struct BaseSpecifierAST: public AST
+{
+ DECLARE_AST_NODE(BaseSpecifier)
+
+ std::size_t virt;
+ std::size_t access_specifier;
+ NameAST *name;
+};
+
+struct BinaryExpressionAST: public ExpressionAST
+{
+ DECLARE_AST_NODE(BinaryExpression)
+
+ std::size_t op;
+ ExpressionAST *left_expression;
+ ExpressionAST *right_expression;
+};
+
+struct CastExpressionAST: public ExpressionAST
+{
+ DECLARE_AST_NODE(CastExpression)
+
+ TypeIdAST *type_id;
+ ExpressionAST *expression;
+};
+
+struct ClassMemberAccessAST: public ExpressionAST
+{
+ DECLARE_AST_NODE(ClassMemberAccess)
+
+ std::size_t op;
+ NameAST *name;
+};
+
+struct ClassSpecifierAST: public TypeSpecifierAST
+{
+ DECLARE_AST_NODE(ClassSpecifier)
+
+ WinDeclSpecAST *win_decl_specifiers;
+ std::size_t class_key;
+ NameAST *name;
+ BaseClauseAST *base_clause;
+ const ListNode<DeclarationAST*> *member_specs;
+};
+
+struct ForwardDeclarationSpecifierAST: public TypeSpecifierAST
+{
+ DECLARE_AST_NODE(ForwardDeclarationSpecifier)
+
+ std::size_t class_key;
+ NameAST *name;
+ BaseClauseAST *base_clause;
+};
+
+struct CompoundStatementAST: public StatementAST
+{
+ DECLARE_AST_NODE(CompoundStatement)
+
+ const ListNode<StatementAST*> *statements;
+};
+
+struct ConditionAST: public AST
+{
+ DECLARE_AST_NODE(Condition)
+
+ TypeSpecifierAST *type_specifier;
+ DeclaratorAST *declarator;
+ ExpressionAST *expression;
+};
+
+struct ConditionalExpressionAST: public ExpressionAST
+{
+ DECLARE_AST_NODE(ConditionalExpression)
+
+ ExpressionAST *condition;
+ ExpressionAST *left_expression;
+ ExpressionAST *right_expression;
+};
+
+struct CppCastExpressionAST: public ExpressionAST
+{
+ DECLARE_AST_NODE(CppCastExpression)
+
+ std::size_t op;
+ TypeIdAST *type_id;
+ ExpressionAST *expression;
+ const ListNode<ExpressionAST*> *sub_expressions;
+};
+
+struct CtorInitializerAST: public AST
+{
+ DECLARE_AST_NODE(CtorInitializer)
+
+ std::size_t colon;
+ const ListNode<MemInitializerAST*> *member_initializers;
+};
+
+struct DeclarationStatementAST: public StatementAST
+{
+ DECLARE_AST_NODE(DeclarationStatement)
+
+ DeclarationAST *declaration;
+};
+
+struct DeclaratorAST: public AST
+{
+ DECLARE_AST_NODE(Declarator)
+
+ const ListNode<PtrOperatorAST*> *ptr_ops;
+ DeclaratorAST *sub_declarator;
+ NameAST *id;
+ ExpressionAST *bit_expression;
+ const ListNode<ExpressionAST*> *array_dimensions;
+ ParameterDeclarationClauseAST *parameter_declaration_clause;
+ const ListNode<std::size_t> *fun_cv;
+ ExceptionSpecificationAST *exception_spec;
+};
+
+struct DeleteExpressionAST: public ExpressionAST
+{
+ DECLARE_AST_NODE(DeleteExpression)
+
+ std::size_t scope_token;
+ std::size_t delete_token;
+ std::size_t lbracket_token;
+ std::size_t rbracket_token;
+ ExpressionAST *expression;
+};
+
+struct DoStatementAST: public StatementAST
+{
+ DECLARE_AST_NODE(DoStatement)
+
+ StatementAST *statement;
+ ExpressionAST *expression;
+};
+
+struct ElaboratedTypeSpecifierAST: public TypeSpecifierAST
+{
+ DECLARE_AST_NODE(ElaboratedTypeSpecifier)
+
+ std::size_t type;
+ NameAST *name;
+};
+
+struct EnumSpecifierAST: public TypeSpecifierAST
+{
+ DECLARE_AST_NODE(EnumSpecifier)
+
+ NameAST *name;
+ const ListNode<EnumeratorAST*> *enumerators;
+};
+
+struct EnumeratorAST: public AST
+{
+ DECLARE_AST_NODE(Enumerator)
+
+ std::size_t id;
+ ExpressionAST *expression;
+};
+
+struct ExceptionSpecificationAST: public AST
+{
+ DECLARE_AST_NODE(ExceptionSpecification)
+
+ std::size_t ellipsis;
+ const ListNode<TypeIdAST*> *type_ids;
+};
+
+struct ExpressionOrDeclarationStatementAST: public StatementAST
+{
+ DECLARE_AST_NODE(ExpressionOrDeclarationStatement)
+
+ StatementAST *expression;
+ StatementAST *declaration;
+};
+
+struct ExpressionStatementAST: public StatementAST
+{
+ DECLARE_AST_NODE(ExpressionStatement)
+
+ ExpressionAST *expression;
+};
+
+struct FunctionCallAST: public ExpressionAST
+{
+ DECLARE_AST_NODE(FunctionCall)
+
+ ExpressionAST *arguments;
+};
+
+struct FunctionDefinitionAST: public DeclarationAST
+{
+ DECLARE_AST_NODE(FunctionDefinition)
+
+ const ListNode<std::size_t> *storage_specifiers;
+ const ListNode<std::size_t> *function_specifiers;
+ TypeSpecifierAST *type_specifier;
+ InitDeclaratorAST *init_declarator;
+ StatementAST *function_body;
+ WinDeclSpecAST *win_decl_specifiers;
+};
+
+struct ForStatementAST: public StatementAST
+{
+ DECLARE_AST_NODE(ForStatement)
+
+ StatementAST *init_statement;
+ ConditionAST *condition;
+ ExpressionAST *expression;
+ StatementAST *statement;
+};
+
+struct IfStatementAST: public StatementAST
+{
+ DECLARE_AST_NODE(IfStatement)
+
+ ConditionAST *condition;
+ StatementAST *statement;
+ StatementAST *else_statement;
+};
+
+struct IncrDecrExpressionAST: public ExpressionAST
+{
+ DECLARE_AST_NODE(IncrDecrExpression)
+
+ std::size_t op;
+};
+
+struct InitDeclaratorAST: public AST
+{
+ DECLARE_AST_NODE(InitDeclarator)
+
+ DeclaratorAST *declarator;
+ InitializerAST *initializer;
+};
+
+struct InitializerAST: public AST
+{
+ DECLARE_AST_NODE(Initializer)
+
+ InitializerClauseAST *initializer_clause;
+ ExpressionAST *expression;
+};
+
+struct InitializerClauseAST: public AST
+{
+ DECLARE_AST_NODE(InitializerClause)
+
+ ExpressionAST *expression;
+};
+
+struct LabeledStatementAST: public StatementAST
+{
+ DECLARE_AST_NODE(LabeledStatement)
+};
+
+struct LinkageBodyAST: public AST
+{
+ DECLARE_AST_NODE(LinkageBody)
+
+ const ListNode<DeclarationAST*> *declarations;
+};
+
+struct LinkageSpecificationAST: public DeclarationAST
+{
+ DECLARE_AST_NODE(LinkageSpecification)
+
+ std::size_t extern_type;
+ LinkageBodyAST *linkage_body;
+ DeclarationAST *declaration;
+};
+
+struct MemInitializerAST: public AST
+{
+ DECLARE_AST_NODE(MemInitializer)
+
+ NameAST *initializer_id;
+ ExpressionAST *expression;
+};
+
+struct NameAST: public AST
+{
+ DECLARE_AST_NODE(Name)
+
+ bool global;
+ const ListNode<UnqualifiedNameAST*> *qualified_names;
+ UnqualifiedNameAST *unqualified_name;
+};
+
+struct NamespaceAST: public DeclarationAST
+{
+ DECLARE_AST_NODE(Namespace)
+
+ std::size_t namespace_name;
+ LinkageBodyAST *linkage_body;
+};
+
+struct NamespaceAliasDefinitionAST: public DeclarationAST
+{
+ DECLARE_AST_NODE(NamespaceAliasDefinition)
+
+ std::size_t namespace_name;
+ NameAST *alias_name;
+};
+
+struct NewDeclaratorAST: public AST
+{
+ DECLARE_AST_NODE(NewDeclarator)
+
+ PtrOperatorAST *ptr_op;
+ NewDeclaratorAST *sub_declarator;
+ const ListNode<ExpressionAST*> *expressions;
+};
+
+struct NewExpressionAST: public ExpressionAST
+{
+ DECLARE_AST_NODE(NewExpression)
+
+ std::size_t scope_token;
+ std::size_t new_token;
+ ExpressionAST *expression;
+ TypeIdAST *type_id;
+ NewTypeIdAST *new_type_id;
+ NewInitializerAST *new_initializer;
+};
+
+struct NewInitializerAST: public AST
+{
+ DECLARE_AST_NODE(NewInitializer)
+
+ ExpressionAST *expression;
+};
+
+struct NewTypeIdAST: public AST
+{
+ DECLARE_AST_NODE(NewTypeId)
+
+ TypeSpecifierAST *type_specifier;
+ NewInitializerAST *new_initializer;
+ NewDeclaratorAST *new_declarator;
+};
+
+struct OperatorAST: public AST
+{
+ DECLARE_AST_NODE(Operator)
+
+ std::size_t op;
+ std::size_t open;
+ std::size_t close;
+};
+
+struct OperatorFunctionIdAST: public AST
+{
+ DECLARE_AST_NODE(OperatorFunctionId)
+
+ OperatorAST *op;
+ TypeSpecifierAST *type_specifier;
+ const ListNode<PtrOperatorAST*> *ptr_ops;
+};
+
+struct ParameterDeclarationAST: public AST
+{
+ DECLARE_AST_NODE(ParameterDeclaration)
+
+ TypeSpecifierAST *type_specifier;
+ DeclaratorAST *declarator;
+ ExpressionAST *expression;
+};
+
+struct ParameterDeclarationClauseAST: public AST
+{
+ DECLARE_AST_NODE(ParameterDeclarationClause)
+
+ const ListNode<ParameterDeclarationAST*> *parameter_declarations;
+ std::size_t ellipsis;
+};
+
+struct PostfixExpressionAST: public ExpressionAST
+{
+ DECLARE_AST_NODE(PostfixExpression)
+
+ TypeSpecifierAST *type_specifier;
+ ExpressionAST *expression;
+ const ListNode<ExpressionAST*> *sub_expressions;
+};
+
+struct PrimaryExpressionAST: public ExpressionAST
+{
+ DECLARE_AST_NODE(PrimaryExpression)
+
+ StringLiteralAST *literal;
+ std::size_t token;
+ StatementAST *expression_statement;
+ ExpressionAST *sub_expression;
+ NameAST *name;
+};
+
+struct PtrOperatorAST: public AST
+{
+ DECLARE_AST_NODE(PtrOperator)
+
+ const ListNode<std::size_t> *cv;
+ std::size_t op;
+ PtrToMemberAST *mem_ptr;
+};
+
+struct PtrToMemberAST: public AST
+{
+ DECLARE_AST_NODE(PtrToMember)
+};
+
+struct ReturnStatementAST: public StatementAST
+{
+ DECLARE_AST_NODE(ReturnStatement)
+
+ ExpressionAST *expression;
+};
+
+struct SimpleDeclarationAST: public DeclarationAST
+{
+ DECLARE_AST_NODE(SimpleDeclaration)
+
+ const ListNode<std::size_t> *storage_specifiers;
+ const ListNode<std::size_t> *function_specifiers;
+ TypeSpecifierAST *type_specifier;
+ const ListNode<InitDeclaratorAST*> *init_declarators;
+ WinDeclSpecAST *win_decl_specifiers;
+};
+
+struct SimpleTypeSpecifierAST: public TypeSpecifierAST
+{
+ DECLARE_AST_NODE(SimpleTypeSpecifier)
+
+ const ListNode<std::size_t> *integrals;
+ std::size_t type_of;
+ TypeIdAST *type_id;
+ ExpressionAST *expression;
+ NameAST *name;
+};
+
+struct SizeofExpressionAST: public ExpressionAST
+{
+ DECLARE_AST_NODE(SizeofExpression)
+
+ std::size_t sizeof_token;
+ TypeIdAST *type_id;
+ ExpressionAST *expression;
+};
+
+struct StringLiteralAST: public AST
+{
+ DECLARE_AST_NODE(StringLiteral)
+
+ const ListNode<std::size_t> *literals;
+};
+
+struct SubscriptExpressionAST: public ExpressionAST
+{
+ DECLARE_AST_NODE(SubscriptExpression)
+
+ ExpressionAST *subscript;
+};
+
+struct SwitchStatementAST: public StatementAST
+{
+ DECLARE_AST_NODE(SwitchStatement)
+
+ ConditionAST *condition;
+ StatementAST *statement;
+};
+
+struct TemplateArgumentAST: public AST
+{
+ DECLARE_AST_NODE(TemplateArgument)
+
+ TypeIdAST *type_id;
+ ExpressionAST *expression;
+};
+
+struct TemplateDeclarationAST: public DeclarationAST
+{
+ DECLARE_AST_NODE(TemplateDeclaration)
+
+ std::size_t exported;
+ const ListNode<TemplateParameterAST*> *template_parameters;
+ DeclarationAST* declaration;
+};
+
+struct TemplateParameterAST: public AST
+{
+ DECLARE_AST_NODE(TemplateParameter)
+
+ TypeParameterAST *type_parameter;
+ ParameterDeclarationAST *parameter_declaration;
+};
+
+struct ThrowExpressionAST: public ExpressionAST
+{
+ DECLARE_AST_NODE(ThrowExpression)
+
+ std::size_t throw_token;
+ ExpressionAST *expression;
+};
+
+struct TranslationUnitAST: public AST
+{
+ DECLARE_AST_NODE(TranslationUnit)
+
+ const ListNode<DeclarationAST*> *declarations;
+};
+
+struct TryBlockStatementAST: public StatementAST
+{
+ DECLARE_AST_NODE(TryBlockStatement)
+};
+
+struct TypeIdAST: public AST
+{
+ DECLARE_AST_NODE(TypeId)
+
+ TypeSpecifierAST *type_specifier;
+ DeclaratorAST *declarator;
+};
+
+struct TypeIdentificationAST: public ExpressionAST
+{
+ DECLARE_AST_NODE(TypeIdentification)
+
+ std::size_t typename_token;
+ NameAST *name;
+ ExpressionAST *expression;
+};
+
+struct TypeParameterAST: public AST
+{
+ DECLARE_AST_NODE(TypeParameter)
+
+ std::size_t type;
+ NameAST *name;
+ TypeIdAST *type_id;
+ const ListNode<TemplateParameterAST*> *template_parameters;
+ NameAST *template_name;
+};
+
+struct TypedefAST: public DeclarationAST
+{
+ DECLARE_AST_NODE(Typedef)
+
+ TypeSpecifierAST *type_specifier;
+ const ListNode<InitDeclaratorAST*> *init_declarators;
+};
+
+struct UnaryExpressionAST: public ExpressionAST
+{
+ DECLARE_AST_NODE(UnaryExpression)
+
+ std::size_t op;
+ ExpressionAST *expression;
+};
+
+struct UnqualifiedNameAST: public AST
+{
+ DECLARE_AST_NODE(UnqualifiedName)
+
+ std::size_t tilde;
+ std::size_t id;
+ OperatorFunctionIdAST *operator_id;
+ const ListNode<TemplateArgumentAST*> *template_arguments;
+};
+
+struct UsingAST: public DeclarationAST
+{
+ DECLARE_AST_NODE(Using)
+
+ std::size_t type_name;
+ NameAST *name;
+};
+
+struct UsingDirectiveAST: public DeclarationAST
+{
+ DECLARE_AST_NODE(UsingDirective)
+
+ NameAST *name;
+};
+
+struct WhileStatementAST: public StatementAST
+{
+ DECLARE_AST_NODE(WhileStatement)
+
+ ConditionAST *condition;
+ StatementAST *statement;
+};
+
+struct WinDeclSpecAST: public AST
+{
+ DECLARE_AST_NODE(WinDeclSpec)
+
+ std::size_t specifier;
+ std::size_t modifier;
+};
+
+struct QPropertyAST : public DeclarationAST
+{
+ DECLARE_AST_NODE(QPropertyAST)
+};
+
+struct QEnumsAST : public DeclarationAST
+{
+ DECLARE_AST_NODE(QEnumsAST)
+};
+
+template <class _Tp>
+_Tp *CreateNode(pool *memory_pool)
+{
+ _Tp *node = reinterpret_cast<_Tp*>(memory_pool->allocate(sizeof(_Tp)));
+ node->kind = _Tp::__node_kind;
+ return node;
+}
+
+template <class _Tp>
+_Tp ast_cast(AST *item)
+{
+ if (item && static_cast<_Tp>(0)->__node_kind == item->kind)
+ return static_cast<_Tp>(item);
+
+ return 0;
+}
+
+#endif // AST_H
diff --git a/parser/binder.cpp b/parser/binder.cpp
new file mode 100644
index 00000000..8b6c4c02
--- /dev/null
+++ b/parser/binder.cpp
@@ -0,0 +1,852 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include "binder.h"
+#include "lexer.h"
+#include "control.h"
+#include "symbol.h"
+#include "codemodel_finder.h"
+#include "class_compiler.h"
+#include "compiler_utils.h"
+#include "tokens.h"
+#include "dumptree.h"
+
+#include <iostream>
+#include <QDebug>
+
+Binder::Binder(CodeModel *__model, LocationManager &__location, Control *__control)
+ : _M_model(__model),
+ _M_location(__location),
+ _M_token_stream(&_M_location.token_stream),
+ _M_control(__control),
+ _M_current_function_type(CodeModel::Normal),
+ type_cc(this),
+ name_cc(this),
+ decl_cc(this)
+{
+ _M_qualified_types["char"] = QString();
+ _M_qualified_types["double"] = QString();
+ _M_qualified_types["float"] = QString();
+ _M_qualified_types["int"] = QString();
+ _M_qualified_types["long"] = QString();
+ _M_qualified_types["short"] = QString();
+ _M_qualified_types["void"] = QString();
+}
+
+Binder::~Binder()
+{
+}
+
+FileModelItem Binder::run(AST *node)
+{
+ FileModelItem old = _M_current_file;
+ _M_current_access = CodeModel::Public;
+
+ _M_current_file = model()->create<FileModelItem>();
+ updateItemPosition(_M_current_file->toItem(), node);
+ visit(node);
+ FileModelItem result = _M_current_file;
+
+ _M_current_file = old; // restore
+
+ return result;
+}
+
+ScopeModelItem Binder::currentScope()
+{
+ if (_M_current_class)
+ return model_static_cast<ScopeModelItem>(_M_current_class);
+ else if (_M_current_namespace)
+ return model_static_cast<ScopeModelItem>(_M_current_namespace);
+
+ return model_static_cast<ScopeModelItem>(_M_current_file);
+}
+
+TemplateParameterList Binder::changeTemplateParameters(TemplateParameterList templateParameters)
+{
+ TemplateParameterList old = _M_current_template_parameters;
+ _M_current_template_parameters = templateParameters;
+ return old;
+}
+
+CodeModel::FunctionType Binder::changeCurrentFunctionType(CodeModel::FunctionType functionType)
+{
+ CodeModel::FunctionType old = _M_current_function_type;
+ _M_current_function_type = functionType;
+ return old;
+}
+
+CodeModel::AccessPolicy Binder::changeCurrentAccess(CodeModel::AccessPolicy accessPolicy)
+{
+ CodeModel::AccessPolicy old = _M_current_access;
+ _M_current_access = accessPolicy;
+ return old;
+}
+
+NamespaceModelItem Binder::changeCurrentNamespace(NamespaceModelItem item)
+{
+ NamespaceModelItem old = _M_current_namespace;
+ _M_current_namespace = item;
+ return old;
+}
+
+ClassModelItem Binder::changeCurrentClass(ClassModelItem item)
+{
+ ClassModelItem old = _M_current_class;
+ _M_current_class = item;
+ return old;
+}
+
+FunctionDefinitionModelItem Binder::changeCurrentFunction(FunctionDefinitionModelItem item)
+{
+ FunctionDefinitionModelItem old = _M_current_function;
+ _M_current_function = item;
+ return old;
+}
+
+int Binder::decode_token(std::size_t index) const
+{
+ return _M_token_stream->kind(index);
+}
+
+CodeModel::AccessPolicy Binder::decode_access_policy(std::size_t index) const
+{
+ switch (decode_token(index)) {
+ case Token_class:
+ return CodeModel::Private;
+
+ case Token_struct:
+ case Token_union:
+ return CodeModel::Public;
+
+ default:
+ return CodeModel::Public;
+ }
+}
+
+CodeModel::ClassType Binder::decode_class_type(std::size_t index) const
+{
+ switch (decode_token(index)) {
+ case Token_class:
+ return CodeModel::Class;
+ case Token_struct:
+ return CodeModel::Struct;
+ case Token_union:
+ return CodeModel::Union;
+ default:
+ std::cerr << "** WARNING unrecognized class type" << std::endl;
+ }
+ return CodeModel::Class;
+}
+
+const NameSymbol *Binder::decode_symbol(std::size_t index) const
+{
+ return _M_token_stream->symbol(index);
+}
+
+void Binder::visitAccessSpecifier(AccessSpecifierAST *node)
+{
+ const ListNode<std::size_t> *it = node->specs;
+ if (!it)
+ return;
+
+ it = it->toFront();
+ const ListNode<std::size_t> *end = it;
+
+ do {
+ switch (decode_token(it->element)) {
+ default:
+ break;
+
+ case Token_public:
+ changeCurrentAccess(CodeModel::Public);
+ changeCurrentFunctionType(CodeModel::Normal);
+ break;
+ case Token_protected:
+ changeCurrentAccess(CodeModel::Protected);
+ changeCurrentFunctionType(CodeModel::Normal);
+ break;
+ case Token_private:
+ changeCurrentAccess(CodeModel::Private);
+ changeCurrentFunctionType(CodeModel::Normal);
+ break;
+ case Token_signals:
+ changeCurrentAccess(CodeModel::Protected);
+ changeCurrentFunctionType(CodeModel::Signal);
+ break;
+ case Token_slots:
+ changeCurrentFunctionType(CodeModel::Slot);
+ break;
+ }
+ it = it->next;
+ } while (it != end);
+}
+
+void Binder::visitSimpleDeclaration(SimpleDeclarationAST *node)
+{
+ visit(node->type_specifier);
+
+ if (const ListNode<InitDeclaratorAST*> *it = node->init_declarators) {
+ it = it->toFront();
+ const ListNode<InitDeclaratorAST*> *end = it;
+ do {
+ InitDeclaratorAST *init_declarator = it->element;
+ declare_symbol(node, init_declarator);
+ it = it->next;
+ } while (it != end);
+ }
+}
+
+void Binder::declare_symbol(SimpleDeclarationAST *node, InitDeclaratorAST *init_declarator)
+{
+ DeclaratorAST *declarator = init_declarator->declarator;
+
+ while (declarator && declarator->sub_declarator)
+ declarator = declarator->sub_declarator;
+
+ NameAST *id = declarator->id;
+ if (!declarator->id) {
+ std::cerr << "** WARNING expected a declarator id" << std::endl;
+ return;
+ }
+
+ CodeModelFinder finder(model(), this);
+ ScopeModelItem symbolScope = finder.resolveScope(id, currentScope());
+ if (!symbolScope) {
+ name_cc.run(id);
+ std::cerr << "** WARNING scope not found for symbol:"
+ << qPrintable(name_cc.name()) << std::endl;
+ return;
+ }
+
+ decl_cc.run(declarator);
+
+ if (decl_cc.isFunction()) {
+ name_cc.run(id->unqualified_name);
+
+ FunctionModelItem fun = model()->create<FunctionModelItem>();
+ updateItemPosition(fun->toItem(), node);
+ fun->setAccessPolicy(_M_current_access);
+ fun->setFunctionType(_M_current_function_type);
+ fun->setName(name_cc.name());
+ fun->setAbstract(init_declarator->initializer != 0);
+ fun->setConstant(declarator->fun_cv != 0);
+ fun->setTemplateParameters(_M_current_template_parameters);
+ applyStorageSpecifiers(node->storage_specifiers, model_static_cast<MemberModelItem>(fun));
+ applyFunctionSpecifiers(node->function_specifiers, fun);
+
+ // build the type
+ TypeInfo typeInfo = CompilerUtils::typeDescription(node->type_specifier,
+ declarator,
+ this);
+
+ fun->setType(qualifyType(typeInfo, symbolScope->qualifiedName()));
+
+
+ fun->setVariadics(decl_cc.isVariadics());
+
+ // ... and the signature
+ foreach (DeclaratorCompiler::Parameter p, decl_cc.parameters()) {
+ ArgumentModelItem arg = model()->create<ArgumentModelItem>();
+ arg->setType(qualifyType(p.type, _M_context));
+ arg->setName(p.name);
+ arg->setDefaultValue(p.defaultValue);
+ if (p.defaultValue)
+ arg->setDefaultValueExpression(p.defaultValueExpression);
+ fun->addArgument(arg);
+ }
+
+ fun->setScope(symbolScope->qualifiedName());
+ symbolScope->addFunction(fun);
+ } else {
+ VariableModelItem var = model()->create<VariableModelItem>();
+ updateItemPosition(var->toItem(), node);
+ var->setTemplateParameters(_M_current_template_parameters);
+ var->setAccessPolicy(_M_current_access);
+ name_cc.run(id->unqualified_name);
+ var->setName(name_cc.name());
+ TypeInfo typeInfo = CompilerUtils::typeDescription(node->type_specifier,
+ declarator,
+ this);
+ if (declarator != init_declarator->declarator
+ && init_declarator->declarator->parameter_declaration_clause) {
+ typeInfo.setFunctionPointer(true);
+ decl_cc.run(init_declarator->declarator);
+ foreach (DeclaratorCompiler::Parameter p, decl_cc.parameters())
+ typeInfo.addArgument(p.type);
+ }
+
+ var->setType(qualifyType(typeInfo, _M_context));
+ applyStorageSpecifiers(node->storage_specifiers, model_static_cast<MemberModelItem>(var));
+
+ var->setScope(symbolScope->qualifiedName());
+ symbolScope->addVariable(var);
+ }
+}
+
+void Binder::visitFunctionDefinition(FunctionDefinitionAST *node)
+{
+ Q_ASSERT(node->init_declarator);
+
+ ScopeModelItem scope = currentScope();
+
+ InitDeclaratorAST *init_declarator = node->init_declarator;
+ DeclaratorAST *declarator = init_declarator->declarator;
+
+ // in the case of "void (func)()" or "void ((func))()" we need to
+ // skip to the inner most. This is in line with how the declarator
+ // node is generated in 'parser.cpp'
+ while (declarator && declarator->sub_declarator)
+ declarator = declarator->sub_declarator;
+ Q_ASSERT(declarator->id);
+
+ CodeModelFinder finder(model(), this);
+
+ ScopeModelItem functionScope = finder.resolveScope(declarator->id, scope);
+ if (!functionScope) {
+ name_cc.run(declarator->id);
+ std::cerr << "** WARNING scope not found for function definition:"
+ << qPrintable(name_cc.name()) << std::endl
+ << "\tdefinition *ignored*"
+ << std::endl;
+ return;
+ }
+
+ decl_cc.run(declarator);
+
+ Q_ASSERT(!decl_cc.id().isEmpty());
+
+ FunctionDefinitionModelItem
+ old = changeCurrentFunction(_M_model->create<FunctionDefinitionModelItem>());
+ _M_current_function->setScope(functionScope->qualifiedName());
+ updateItemPosition(_M_current_function->toItem(), node);
+
+ Q_ASSERT(declarator->id->unqualified_name);
+ name_cc.run(declarator->id->unqualified_name);
+ QString unqualified_name = name_cc.name();
+
+ _M_current_function->setName(unqualified_name);
+ TypeInfo tmp_type = CompilerUtils::typeDescription(node->type_specifier,
+ declarator, this);
+
+ _M_current_function->setType(qualifyType(tmp_type, _M_context));
+ _M_current_function->setAccessPolicy(_M_current_access);
+ _M_current_function->setFunctionType(_M_current_function_type);
+ _M_current_function->setConstant(declarator->fun_cv);
+ _M_current_function->setTemplateParameters(_M_current_template_parameters);
+
+ applyStorageSpecifiers(node->storage_specifiers,
+ model_static_cast<MemberModelItem>(_M_current_function));
+ applyFunctionSpecifiers(node->function_specifiers,
+ model_static_cast<FunctionModelItem>(_M_current_function));
+
+ _M_current_function->setVariadics(decl_cc.isVariadics());
+
+ foreach (DeclaratorCompiler::Parameter p, decl_cc.parameters()) {
+ ArgumentModelItem arg = model()->create<ArgumentModelItem>();
+ arg->setType(qualifyType(p.type, functionScope->qualifiedName()));
+ arg->setName(p.name);
+ arg->setDefaultValue(p.defaultValue);
+ if (p.defaultValue)
+ arg->setDefaultValueExpression(p.defaultValueExpression);
+ _M_current_function->addArgument(arg);
+ }
+
+ functionScope->addFunctionDefinition(_M_current_function);
+
+ FunctionModelItem prototype = model_static_cast<FunctionModelItem>(_M_current_function);
+ FunctionModelItem declared = functionScope->declaredFunction(prototype);
+
+ // try to find a function declaration for this definition..
+ if (!declared) {
+ functionScope->addFunction(prototype);
+ } else {
+ applyFunctionSpecifiers(node->function_specifiers, declared);
+
+ // fix the function type and the access policy
+ _M_current_function->setAccessPolicy(declared->accessPolicy());
+ _M_current_function->setFunctionType(declared->functionType());
+ }
+
+ changeCurrentFunction(old);
+}
+
+void Binder::visitTemplateDeclaration(TemplateDeclarationAST *node)
+{
+ const ListNode<TemplateParameterAST*> *it = node->template_parameters;
+ if (!it) {
+ // QtScript: we want to visit the declaration still, so that
+ // e.g. QMetaTypeId<Foo> is added to the code model
+ visit(node->declaration);
+ return;
+ }
+
+ TemplateParameterList savedTemplateParameters = changeTemplateParameters(TemplateParameterList());
+
+ it = it->toFront();
+ const ListNode<TemplateParameterAST*> *end = it;
+
+ TemplateParameterList templateParameters;
+ do {
+ TemplateParameterAST *parameter = it->element;
+ TypeParameterAST *type_parameter = parameter->type_parameter;
+
+ NameAST *name;
+ if (!type_parameter) {
+ // A hacky hack to work around missing support for parameter declarations in
+ // templates. We just need the to get the name of the variable, since we
+ // aren't actually compiling these anyway. We are still not supporting much
+ // more, but we are refusing to fail for a few more declarations
+ if (!parameter->parameter_declaration ||
+ !parameter->parameter_declaration->declarator ||
+ !parameter->parameter_declaration->declarator->id) {
+
+ /*std::cerr << "** WARNING template declaration not supported ``";
+ Token const &tk = _M_token_stream->token ((int) node->start_token);
+ Token const &end_tk = _M_token_stream->token ((int) node->declaration->start_token);
+
+ std::cerr << std::string (&tk.text[tk.position], (end_tk.position) - tk.position) << "''"
+ << std::endl << std::endl;*/
+
+ changeTemplateParameters(savedTemplateParameters);
+ return;
+
+ }
+
+ name = parameter->parameter_declaration->declarator->id;
+ } else {
+ int tk = decode_token(type_parameter->type);
+ if (tk != Token_typename && tk != Token_class) {
+ /*std::cerr << "** WARNING template declaration not supported ``";
+ Token const &tk = _M_token_stream->token ((int) node->start_token);
+ Token const &end_tk = _M_token_stream->token ((int) node->declaration->start_token);
+
+ std::cerr << std::string (&tk.text[tk.position], (end_tk.position) - tk.position) << "''"
+ << std::endl << std::endl;*/
+
+ changeTemplateParameters(savedTemplateParameters);
+ return;
+ }
+ assert(tk == Token_typename || tk == Token_class);
+
+ name = type_parameter->name;
+ }
+
+ TemplateParameterModelItem p = model()->create<TemplateParameterModelItem>();
+ name_cc.run(name);
+ p->setName(name_cc.name());
+
+ _M_current_template_parameters.append(p);
+ it = it->next;
+ } while (it != end);
+
+ visit(node->declaration);
+
+ changeTemplateParameters(savedTemplateParameters);
+}
+
+void Binder::visitTypedef(TypedefAST *node)
+{
+ const ListNode<InitDeclaratorAST*> *it = node->init_declarators;
+ if (!it)
+ return;
+
+ it = it->toFront();
+ const ListNode<InitDeclaratorAST*> *end = it;
+
+ do {
+ InitDeclaratorAST *init_declarator = it->element;
+ it = it->next;
+
+ Q_ASSERT(init_declarator->declarator);
+
+ // the name
+ decl_cc.run(init_declarator->declarator);
+ QString alias_name = decl_cc.id();
+
+ if (alias_name.isEmpty()) {
+ std::cerr << "** WARNING anonymous typedef not supported! ``";
+ Token const &tk = _M_token_stream->token((int) node->start_token);
+ Token const &end_tk = _M_token_stream->token((int) node->end_token);
+
+ std::cerr << std::string(&tk.text[tk.position], end_tk.position - tk.position) << "''"
+ << std::endl << std::endl;
+ continue;
+ }
+
+ // build the type
+ TypeInfo typeInfo = CompilerUtils::typeDescription(node->type_specifier,
+ init_declarator->declarator,
+ this);
+ DeclaratorAST *decl = init_declarator->declarator;
+ while (decl && decl->sub_declarator)
+ decl = decl->sub_declarator;
+
+ if (decl != init_declarator->declarator
+ && init_declarator->declarator->parameter_declaration_clause) {
+ typeInfo.setFunctionPointer(true);
+ decl_cc.run(init_declarator->declarator);
+ foreach (DeclaratorCompiler::Parameter p, decl_cc.parameters())
+ typeInfo.addArgument(p.type);
+ }
+
+ ScopeModelItem scope = currentScope();
+ DeclaratorAST *declarator = init_declarator->declarator;
+ CodeModelFinder finder(model(), this);
+ ScopeModelItem typedefScope = finder.resolveScope(declarator->id, scope);
+
+ TypeAliasModelItem typeAlias = model()->create<TypeAliasModelItem> ();
+ updateItemPosition(typeAlias->toItem(), node);
+ typeAlias->setName(alias_name);
+ typeAlias->setType(qualifyType(typeInfo, currentScope()->qualifiedName()));
+ typeAlias->setScope(typedefScope->qualifiedName());
+ _M_qualified_types[typeAlias->qualifiedName().join(".")] = QString();
+ currentScope()->addTypeAlias(typeAlias);
+ } while (it != end);
+}
+
+void Binder::visitNamespace(NamespaceAST *node)
+{
+ bool anonymous = (node->namespace_name == 0);
+
+ ScopeModelItem scope = currentScope();
+
+ NamespaceModelItem old;
+ if (!anonymous) {
+ QString name = decode_symbol(node->namespace_name)->as_string();
+
+ QStringList qualified_name = scope->qualifiedName();
+ qualified_name += name;
+ NamespaceModelItem ns =
+ model_safe_cast<NamespaceModelItem>(_M_model->findItem(qualified_name,
+ _M_current_file->toItem()));
+ if (!ns) {
+ ns = _M_model->create<NamespaceModelItem>();
+ updateItemPosition(ns->toItem(), node);
+ ns->setName(name);
+ ns->setScope(scope->qualifiedName());
+ }
+ old = changeCurrentNamespace(ns);
+
+ _M_context.append(name);
+ }
+
+ DefaultVisitor::visitNamespace(node);
+
+ if (!anonymous) {
+ Q_ASSERT(scope->kind() == _CodeModelItem::Kind_Namespace
+ || scope->kind() == _CodeModelItem::Kind_File);
+
+ _M_context.removeLast();
+
+ if (NamespaceModelItem ns = model_static_cast<NamespaceModelItem>(scope))
+ ns->addNamespace(_M_current_namespace);
+
+ changeCurrentNamespace(old);
+ }
+}
+
+void Binder::visitForwardDeclarationSpecifier(ForwardDeclarationSpecifierAST *node)
+{
+ name_cc.run(node->name);
+ if (name_cc.name().isEmpty())
+ return;
+
+ ScopeModelItem scope = currentScope();
+ _M_qualified_types[(scope->qualifiedName() + name_cc.qualifiedName()).join(".")] = QString();
+}
+
+void Binder::visitClassSpecifier(ClassSpecifierAST *node)
+{
+ ClassCompiler class_cc(this);
+ class_cc.run(node);
+
+ if (class_cc.name().isEmpty()) {
+ // anonymous not supported
+ return;
+ }
+
+ Q_ASSERT(node->name && node->name->unqualified_name);
+
+ ScopeModelItem scope = currentScope();
+
+ ClassModelItem old = changeCurrentClass(_M_model->create<ClassModelItem>());
+ updateItemPosition(_M_current_class->toItem(), node);
+ _M_current_class->setName(class_cc.name());
+
+ QStringList baseClasses = class_cc.baseClasses();
+ TypeInfo info;
+ for (int i = 0; i < baseClasses.size(); ++i) {
+ info.setQualifiedName(baseClasses.at(i).split("::"));
+ baseClasses[i] = qualifyType(info, scope->qualifiedName()).qualifiedName().join("::");
+ }
+
+ _M_current_class->setBaseClasses(baseClasses);
+ _M_current_class->setClassType(decode_class_type(node->class_key));
+ _M_current_class->setTemplateParameters(_M_current_template_parameters);
+
+ if (!_M_current_template_parameters.isEmpty()) {
+ QString name = _M_current_class->name();
+ name += "<";
+ for (int i = 0; i < _M_current_template_parameters.size(); ++i) {
+ if (i > 0)
+ name += ",";
+
+ name += _M_current_template_parameters.at(i)->name();
+ }
+
+ name += ">";
+ _M_current_class->setName(name);
+ }
+
+ CodeModel::AccessPolicy oldAccessPolicy = changeCurrentAccess(decode_access_policy(node->class_key));
+ CodeModel::FunctionType oldFunctionType = changeCurrentFunctionType(CodeModel::Normal);
+
+ _M_current_class->setScope(scope->qualifiedName());
+ _M_qualified_types[_M_current_class->qualifiedName().join(".")] = QString();
+
+ scope->addClass(_M_current_class);
+
+ name_cc.run(node->name->unqualified_name);
+ _M_context.append(name_cc.name());
+ visitNodes(this, node->member_specs);
+ _M_context.removeLast();
+
+ changeCurrentClass(old);
+ changeCurrentAccess(oldAccessPolicy);
+ changeCurrentFunctionType(oldFunctionType);
+}
+
+void Binder::visitLinkageSpecification(LinkageSpecificationAST *node)
+{
+ DefaultVisitor::visitLinkageSpecification(node);
+}
+
+void Binder::visitUsing(UsingAST *node)
+{
+ DefaultVisitor::visitUsing(node);
+}
+
+void Binder::visitEnumSpecifier(EnumSpecifierAST *node)
+{
+ CodeModelFinder finder(model(), this);
+ ScopeModelItem scope = currentScope();
+ ScopeModelItem enumScope = finder.resolveScope(node->name, scope);
+
+ name_cc.run(node->name);
+ QString name = name_cc.name();
+
+ if (name.isEmpty()) {
+ // anonymous enum
+ QString key = _M_context.join("::");
+ int current = ++_M_anonymous_enums[key];
+ name += QLatin1String("enum_");
+ name += QString::number(current);
+ }
+
+ _M_current_enum = model()->create<EnumModelItem>();
+ _M_current_enum->setAccessPolicy(_M_current_access);
+ updateItemPosition(_M_current_enum->toItem(), node);
+ _M_current_enum->setName(name);
+ _M_current_enum->setScope(enumScope->qualifiedName());
+
+ _M_qualified_types[_M_current_enum->qualifiedName().join(".")] = QString();
+
+ enumScope->addEnum(_M_current_enum);
+
+ DefaultVisitor::visitEnumSpecifier(node);
+
+ _M_current_enum = 0;
+}
+
+static QString strip_preprocessor_lines(const QString &name)
+{
+ QStringList lst = name.split("\n");
+ QString s;
+ for (int i = 0; i < lst.size(); ++i) {
+ if (!lst.at(i).startsWith('#'))
+ s += lst.at(i);
+ }
+ return s.trimmed();
+}
+
+void Binder::visitEnumerator(EnumeratorAST *node)
+{
+ Q_ASSERT(_M_current_enum);
+ EnumeratorModelItem e = model()->create<EnumeratorModelItem>();
+ updateItemPosition(e->toItem(), node);
+ e->setName(decode_symbol(node->id)->as_string());
+
+ if (ExpressionAST *expr = node->expression) {
+ const Token &start_token = _M_token_stream->token((int) expr->start_token);
+ const Token &end_token = _M_token_stream->token((int) expr->end_token);
+
+ e->setValue(strip_preprocessor_lines(QString::fromUtf8(&start_token.text[start_token.position],
+ (int)(end_token.position - start_token.position)).trimmed()).remove(' '));
+ }
+
+ _M_current_enum->addEnumerator(e);
+}
+
+void Binder::visitUsingDirective(UsingDirectiveAST *node)
+{
+ DefaultVisitor::visitUsingDirective(node);
+}
+
+void Binder::visitQEnums(QEnumsAST *node)
+{
+ const Token &start = _M_token_stream->token((int) node->start_token);
+ const Token &end = _M_token_stream->token((int) node->end_token);
+ QStringList enum_list = QString::fromLatin1(start.text + start.position,
+ end.position - start.position).split(' ');
+
+ ScopeModelItem scope = currentScope();
+ for (int i = 0; i < enum_list.size(); ++i)
+ scope->addEnumsDeclaration(enum_list.at(i));
+}
+
+void Binder::visitQProperty(QPropertyAST *node)
+{
+ const Token &start = _M_token_stream->token((int) node->start_token);
+ const Token &end = _M_token_stream->token((int) node->end_token);
+ QString property = QString::fromLatin1(start.text + start.position,
+ end.position - start.position);
+ _M_current_class->addPropertyDeclaration(property);
+}
+
+void Binder::applyStorageSpecifiers(const ListNode<std::size_t> *it, MemberModelItem item)
+{
+ if (!it)
+ return;
+
+ it = it->toFront();
+ const ListNode<std::size_t> *end = it;
+
+ do {
+ switch (decode_token(it->element)) {
+ default:
+ break;
+
+ case Token_friend:
+ item->setFriend(true);
+ break;
+ case Token_auto:
+ item->setAuto(true);
+ break;
+ case Token_register:
+ item->setRegister(true);
+ break;
+ case Token_static:
+ item->setStatic(true);
+ break;
+ case Token_extern:
+ item->setExtern(true);
+ break;
+ case Token_mutable:
+ item->setMutable(true);
+ break;
+ }
+ it = it->next;
+ } while (it != end);
+}
+
+void Binder::applyFunctionSpecifiers(const ListNode<std::size_t> *it, FunctionModelItem item)
+{
+ if (!it)
+ return;
+
+ it = it->toFront();
+ const ListNode<std::size_t> *end = it;
+
+ do {
+ switch (decode_token(it->element)) {
+ default:
+ break;
+
+ case Token_inline:
+ item->setInline(true);
+ break;
+
+ case Token_virtual:
+ item->setVirtual(true);
+ break;
+
+ case Token_explicit:
+ item->setExplicit(true);
+ break;
+
+ case Token_Q_INVOKABLE:
+ item->setInvokable(true);
+ break;
+ }
+ it = it->next;
+ } while (it != end);
+}
+
+TypeInfo Binder::qualifyType(const TypeInfo &type, const QStringList &context) const
+{
+ // ### Potentially improve to use string list in the name table to
+ if (!context.size()) {
+ // ### We can assume that this means global namespace for now...
+ return type;
+ } else if (_M_qualified_types.contains(type.qualifiedName().join("."))) {
+ return type;
+ } else {
+ QStringList expanded = context;
+ expanded << type.qualifiedName();
+ if (_M_qualified_types.contains(expanded.join("."))) {
+ TypeInfo modified_type = type;
+ modified_type.setQualifiedName(expanded);
+ return modified_type;
+ } else {
+ CodeModelItem scope = model()->findItem(context, _M_current_file->toItem());
+
+ if (ClassModelItem klass = model_dynamic_cast<ClassModelItem> (scope)) {
+ foreach (QString base, klass->baseClasses()) {
+ QStringList ctx = context;
+ ctx.removeLast();
+ ctx.append(base);
+
+ TypeInfo qualified = qualifyType(type, ctx);
+ if (qualified != type)
+ return qualified;
+ }
+ }
+
+ QStringList copy = context;
+ copy.removeLast();
+ return qualifyType(type, copy);
+ }
+ }
+}
+
+void Binder::updateItemPosition(CodeModelItem item, AST *node)
+{
+ QString filename;
+ int line, column;
+
+ assert(node);
+ _M_location.positionAt(_M_token_stream->position(node->start_token), &line, &column, &filename);
+ item->setFileName(filename);
+}
diff --git a/parser/binder.h b/parser/binder.h
new file mode 100644
index 00000000..b4d4da66
--- /dev/null
+++ b/parser/binder.h
@@ -0,0 +1,125 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+
+#ifndef BINDER_H
+#define BINDER_H
+
+#include "default_visitor.h"
+#include "codemodel.h"
+#include "type_compiler.h"
+#include "name_compiler.h"
+#include "declarator_compiler.h"
+
+class TokenStream;
+class LocationManager;
+class Control;
+struct NameSymbol;
+
+class Binder: protected DefaultVisitor
+{
+public:
+ Binder(CodeModel *__model, LocationManager &__location, Control *__control = 0);
+ virtual ~Binder();
+
+ inline TokenStream *tokenStream() const
+ {
+ return _M_token_stream;
+ }
+
+ inline CodeModel *model() const
+ {
+ return _M_model;
+ }
+
+ ScopeModelItem currentScope();
+
+ FileModelItem run(AST *node);
+
+// utils
+ TypeInfo qualifyType(const TypeInfo &type, const QStringList &context) const;
+
+protected:
+ virtual void visitAccessSpecifier(AccessSpecifierAST *);
+ virtual void visitClassSpecifier(ClassSpecifierAST *);
+ virtual void visitEnumSpecifier(EnumSpecifierAST *);
+ virtual void visitEnumerator(EnumeratorAST *);
+ virtual void visitFunctionDefinition(FunctionDefinitionAST *);
+ virtual void visitLinkageSpecification(LinkageSpecificationAST *);
+ virtual void visitNamespace(NamespaceAST *);
+ virtual void visitSimpleDeclaration(SimpleDeclarationAST *);
+ virtual void visitTemplateDeclaration(TemplateDeclarationAST *);
+ virtual void visitTypedef(TypedefAST *);
+ virtual void visitUsing(UsingAST *);
+ virtual void visitUsingDirective(UsingDirectiveAST *);
+ virtual void visitQProperty(QPropertyAST *);
+ virtual void visitForwardDeclarationSpecifier(ForwardDeclarationSpecifierAST *);
+ virtual void visitQEnums(QEnumsAST *);
+
+private:
+
+ int decode_token(std::size_t index) const;
+ const NameSymbol *decode_symbol(std::size_t index) const;
+ CodeModel::AccessPolicy decode_access_policy(std::size_t index) const;
+ CodeModel::ClassType decode_class_type(std::size_t index) const;
+
+ CodeModel::FunctionType changeCurrentFunctionType(CodeModel::FunctionType functionType);
+ CodeModel::AccessPolicy changeCurrentAccess(CodeModel::AccessPolicy accessPolicy);
+ NamespaceModelItem changeCurrentNamespace(NamespaceModelItem item);
+ ClassModelItem changeCurrentClass(ClassModelItem item);
+ FunctionDefinitionModelItem changeCurrentFunction(FunctionDefinitionModelItem item);
+ TemplateParameterList changeTemplateParameters(TemplateParameterList templateParameters);
+
+ void declare_symbol(SimpleDeclarationAST *node, InitDeclaratorAST *init_declarator);
+
+ void applyStorageSpecifiers(const ListNode<std::size_t> *storage_specifiers, MemberModelItem item);
+ void applyFunctionSpecifiers(const ListNode<std::size_t> *it, FunctionModelItem item);
+
+ void updateItemPosition(CodeModelItem item, AST *node);
+
+private:
+ CodeModel *_M_model;
+ LocationManager &_M_location;
+ TokenStream *_M_token_stream;
+ Control *_M_control;
+
+ CodeModel::FunctionType _M_current_function_type;
+ CodeModel::AccessPolicy _M_current_access;
+ FileModelItem _M_current_file;
+ NamespaceModelItem _M_current_namespace;
+ ClassModelItem _M_current_class;
+ FunctionDefinitionModelItem _M_current_function;
+ EnumModelItem _M_current_enum;
+ QStringList _M_context;
+ TemplateParameterList _M_current_template_parameters; // ### check me
+ QHash<QString, QString> _M_qualified_types;
+ QHash<QString, int> _M_anonymous_enums;
+
+protected:
+ TypeCompiler type_cc;
+ NameCompiler name_cc;
+ DeclaratorCompiler decl_cc;
+};
+
+#endif // BINDER_H
diff --git a/parser/class_compiler.cpp b/parser/class_compiler.cpp
new file mode 100644
index 00000000..e04ffe10
--- /dev/null
+++ b/parser/class_compiler.cpp
@@ -0,0 +1,66 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+
+#include "class_compiler.h"
+#include "lexer.h"
+#include "binder.h"
+
+ClassCompiler::ClassCompiler(Binder *binder)
+ : _M_binder(binder),
+ _M_token_stream(binder->tokenStream()),
+ name_cc(_M_binder),
+ type_cc(_M_binder)
+{
+}
+
+ClassCompiler::~ClassCompiler()
+{
+}
+
+void ClassCompiler::run(ClassSpecifierAST *node)
+{
+ name_cc.run(node->name);
+ _M_name = name_cc.name();
+ _M_base_classes.clear();
+
+ visit(node);
+}
+
+void ClassCompiler::visitClassSpecifier(ClassSpecifierAST *node)
+{
+ visit(node->base_clause);
+}
+
+void ClassCompiler::visitBaseSpecifier(BaseSpecifierAST *node)
+{
+ name_cc.run(node->name);
+ QString name = name_cc.name();
+
+ if (!name.isEmpty())
+ _M_base_classes.append(name);
+}
+
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/class_compiler.h b/parser/class_compiler.h
new file mode 100644
index 00000000..69fccf75
--- /dev/null
+++ b/parser/class_compiler.h
@@ -0,0 +1,72 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+
+#ifndef CLASS_COMPILER_H
+#define CLASS_COMPILER_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/QStringList>
+
+#include <default_visitor.h>
+#include <name_compiler.h>
+#include <type_compiler.h>
+
+class TokenStream;
+class Binder;
+
+class ClassCompiler: protected DefaultVisitor
+{
+public:
+ ClassCompiler(Binder *binder);
+ virtual ~ClassCompiler();
+
+ inline QString name() const
+ {
+ return _M_name;
+ }
+
+ inline QStringList baseClasses() const
+ {
+ return _M_base_classes;
+ }
+
+ void run(ClassSpecifierAST *node);
+
+protected:
+ virtual void visitClassSpecifier(ClassSpecifierAST *node);
+ virtual void visitBaseSpecifier(BaseSpecifierAST *node);
+
+private:
+ Binder *_M_binder;
+ TokenStream *_M_token_stream;
+ QString _M_name;
+ QStringList _M_base_classes;
+ NameCompiler name_cc;
+ TypeCompiler type_cc;
+};
+
+#endif // CLASS_COMPILER_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/codemodel.cpp b/parser/codemodel.cpp
new file mode 100644
index 00000000..ecc8e303
--- /dev/null
+++ b/parser/codemodel.cpp
@@ -0,0 +1,932 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+
+#include "codemodel.h"
+
+// ---------------------------------------------------------------------------
+CodeModel::CodeModel()
+ : _M_creation_id(0)
+{
+ _M_globalNamespace = create<NamespaceModelItem>();
+}
+
+CodeModel::~CodeModel()
+{
+}
+
+void CodeModel::wipeout()
+{
+ _M_globalNamespace = create<NamespaceModelItem>();
+ _M_files.clear();
+}
+
+FileList CodeModel::files() const
+{
+ return _M_files.values();
+}
+
+NamespaceModelItem CodeModel::globalNamespace() const
+{
+ return _M_globalNamespace;
+}
+
+void CodeModel::addFile(FileModelItem item)
+{
+ _M_creation_id = 0; // reset the creation id
+ _M_files.insert(item->name(), item);
+}
+
+void CodeModel::removeFile(FileModelItem item)
+{
+ QHash<QString, FileModelItem>::Iterator it = _M_files.find(item->name());
+
+ if (it != _M_files.end() && it.value() == item)
+ _M_files.erase(it);
+}
+
+FileModelItem CodeModel::findFile(const QString &name) const
+{
+ return _M_files.value(name);
+}
+
+QHash<QString, FileModelItem> CodeModel::fileMap() const
+{
+ return _M_files;
+}
+
+CodeModelItem CodeModel::findItem(const QStringList &qualifiedName, CodeModelItem scope) const
+{
+ for (int i = 0; i < qualifiedName.size(); ++i) {
+ // ### Extend to look for members etc too.
+ const QString &name = qualifiedName.at(i);
+
+ if (NamespaceModelItem ns = model_dynamic_cast<NamespaceModelItem>(scope)) {
+ if (NamespaceModelItem tmp_ns = ns->findNamespace(name)) {
+ scope = tmp_ns;
+ continue;
+ }
+ }
+
+ if (ScopeModelItem ss = model_dynamic_cast<ScopeModelItem>(scope)) {
+ if (ClassModelItem cs = ss->findClass(name)) {
+ scope = cs;
+ } else if (EnumModelItem es = ss->findEnum(name)) {
+ if (i == qualifiedName.size() - 1)
+ return es->toItem();
+ } else if (TypeAliasModelItem tp = ss->findTypeAlias(name)) {
+ if (i == qualifiedName.size() - 1)
+ return tp->toItem();
+ } else {
+ // If we don't find the name in the scope chain we
+ // need to return an empty item to indicate failure...
+ return CodeModelItem();
+ }
+ }
+ }
+
+ return scope;
+}
+
+
+// ---------------------------------------------------------------------------
+TypeInfo TypeInfo::combine(const TypeInfo &__lhs, const TypeInfo &__rhs)
+{
+ TypeInfo __result = __lhs;
+
+ __result.setConstant(__result.isConstant() || __rhs.isConstant());
+ __result.setVolatile(__result.isVolatile() || __rhs.isVolatile());
+ __result.setReference(__result.isReference() || __rhs.isReference());
+ __result.setIndirections(__result.indirections() + __rhs.indirections());
+ __result.setArrayElements(__result.arrayElements() + __rhs.arrayElements());
+
+ return __result;
+}
+
+TypeInfo TypeInfo::resolveType(TypeInfo const &__type, CodeModelItem __scope)
+{
+ CodeModel *__model = __scope->model();
+ Q_ASSERT(__model != 0);
+
+ CodeModelItem __item = __model->findItem(__type.qualifiedName(), __scope);
+
+ // Copy the type and replace with the proper qualified name. This
+ // only makes sence to do if we're actually getting a resolved
+ // type with a namespace. We only get this if the returned type
+ // has more than 2 entries in the qualified name... This test
+ // could be improved by returning if the type was found or not.
+ TypeInfo otherType(__type);
+ if (__item && __item->qualifiedName().size() > 1) {
+ otherType.setQualifiedName(__item->qualifiedName());
+ }
+
+ if (TypeAliasModelItem __alias = model_dynamic_cast<TypeAliasModelItem> (__item))
+ return resolveType(TypeInfo::combine(__alias->type(), otherType), __scope);
+
+ return otherType;
+}
+
+QString TypeInfo::toString() const
+{
+ QString tmp;
+
+ tmp += m_qualifiedName.join("::");
+ if (isConstant())
+ tmp += QLatin1String(" const");
+
+ if (isVolatile())
+ tmp += QLatin1String(" volatile");
+
+ if (indirections())
+ tmp += QString(indirections(), QLatin1Char('*'));
+
+ if (isReference())
+ tmp += QLatin1Char('&');
+
+ if (isFunctionPointer()) {
+ tmp += QLatin1String(" (*)(");
+ for (int i = 0; i < m_arguments.count(); ++i) {
+ if (i != 0)
+ tmp += QLatin1String(", ");
+
+ tmp += m_arguments.at(i).toString();
+ }
+ tmp += QLatin1String(")");
+ }
+
+ foreach(QString elt, arrayElements()) {
+ tmp += QLatin1String("[");
+ tmp += elt;
+ tmp += QLatin1String("]");
+ }
+
+ return tmp;
+}
+
+bool TypeInfo::operator==(const TypeInfo &other)
+{
+ if (arrayElements().count() != other.arrayElements().count())
+ return false;
+
+#if defined (RXX_CHECK_ARRAY_ELEMENTS) // ### it'll break
+ for (int i = 0; i < arrayElements().count(); ++i) {
+ QString elt1 = arrayElements().at(i).trimmed();
+ QString elt2 = other.arrayElements().at(i).trimmed();
+
+ if (elt1 != elt2)
+ return false;
+ }
+#endif
+
+ return flags == other.flags
+ && m_qualifiedName == other.m_qualifiedName
+ && (!m_functionPointer || m_arguments == other.m_arguments);
+}
+
+// ---------------------------------------------------------------------------
+_CodeModelItem::_CodeModelItem(CodeModel *model, int kind)
+ : _M_model(model),
+ _M_kind(kind),
+ _M_startLine(0),
+ _M_startColumn(0),
+ _M_endLine(0),
+ _M_endColumn(0),
+ _M_creation_id(0)
+{
+}
+
+_CodeModelItem::~_CodeModelItem()
+{
+}
+
+CodeModelItem _CodeModelItem::toItem() const
+{
+ return CodeModelItem(const_cast<_CodeModelItem*>(this));
+}
+
+int _CodeModelItem::kind() const
+{
+ return _M_kind;
+}
+
+void _CodeModelItem::setKind(int kind)
+{
+ _M_kind = kind;
+}
+
+QStringList _CodeModelItem::qualifiedName() const
+{
+ QStringList q = scope();
+
+ if (!name().isEmpty())
+ q += name();
+
+ return q;
+}
+
+QString _CodeModelItem::name() const
+{
+ return _M_name;
+}
+
+void _CodeModelItem::setName(const QString &name)
+{
+ _M_name = name;
+}
+
+QStringList _CodeModelItem::scope() const
+{
+ return _M_scope;
+}
+
+void _CodeModelItem::setScope(const QStringList &scope)
+{
+ _M_scope = scope;
+}
+
+QString _CodeModelItem::fileName() const
+{
+ return _M_fileName;
+}
+
+void _CodeModelItem::setFileName(const QString &fileName)
+{
+ _M_fileName = fileName;
+}
+
+FileModelItem _CodeModelItem::file() const
+{
+ return model()->findFile(fileName());
+}
+
+void _CodeModelItem::getStartPosition(int *line, int *column)
+{
+ *line = _M_startLine;
+ *column = _M_startColumn;
+}
+
+void _CodeModelItem::setStartPosition(int line, int column)
+{
+ _M_startLine = line;
+ _M_startColumn = column;
+}
+
+void _CodeModelItem::getEndPosition(int *line, int *column)
+{
+ *line = _M_endLine;
+ *column = _M_endColumn;
+}
+
+void _CodeModelItem::setEndPosition(int line, int column)
+{
+ _M_endLine = line;
+ _M_endColumn = column;
+}
+
+// ---------------------------------------------------------------------------
+QStringList _ClassModelItem::baseClasses() const
+{
+ return _M_baseClasses;
+}
+
+void _ClassModelItem::setBaseClasses(const QStringList &baseClasses)
+{
+ _M_baseClasses = baseClasses;
+}
+
+TemplateParameterList _ClassModelItem::templateParameters() const
+{
+ return _M_templateParameters;
+}
+
+void _ClassModelItem::setTemplateParameters(const TemplateParameterList &templateParameters)
+{
+ _M_templateParameters = templateParameters;
+}
+
+void _ClassModelItem::addBaseClass(const QString &baseClass)
+{
+ _M_baseClasses.append(baseClass);
+}
+
+void _ClassModelItem::removeBaseClass(const QString &baseClass)
+{
+ _M_baseClasses.removeAt(_M_baseClasses.indexOf(baseClass));
+}
+
+bool _ClassModelItem::extendsClass(const QString &name) const
+{
+ return _M_baseClasses.contains(name);
+}
+
+void _ClassModelItem::setClassType(CodeModel::ClassType type)
+{
+ _M_classType = type;
+}
+
+CodeModel::ClassType _ClassModelItem::classType() const
+{
+ return _M_classType;
+}
+
+void _ClassModelItem::addPropertyDeclaration(const QString &propertyDeclaration)
+{
+ _M_propertyDeclarations << propertyDeclaration;
+}
+
+
+// ---------------------------------------------------------------------------
+FunctionModelItem _ScopeModelItem::declaredFunction(FunctionModelItem item)
+{
+ FunctionList function_list = findFunctions(item->name());
+
+ foreach(FunctionModelItem fun, function_list) {
+ if (fun->isSimilar(item))
+ return fun;
+ }
+
+ return FunctionModelItem();
+}
+
+ClassList _ScopeModelItem::classes() const
+{
+ return _M_classes.values();
+}
+
+TypeAliasList _ScopeModelItem::typeAliases() const
+{
+ return _M_typeAliases.values();
+}
+
+VariableList _ScopeModelItem::variables() const
+{
+ return _M_variables.values();
+}
+
+FunctionList _ScopeModelItem::functions() const
+{
+ return _M_functions.values();
+}
+
+void _ScopeModelItem::addEnumsDeclaration(const QString &enumsDeclaration)
+{
+ _M_enumsDeclarations << enumsDeclaration;
+}
+
+FunctionDefinitionList _ScopeModelItem::functionDefinitions() const
+{
+ return _M_functionDefinitions.values();
+}
+
+EnumList _ScopeModelItem::enums() const
+{
+ return _M_enums.values();
+}
+
+void _ScopeModelItem::addClass(ClassModelItem item)
+{
+ QString name = item->name();
+ int idx = name.indexOf("<");
+ if (idx > 0)
+ _M_classes.insert(name.left(idx), item);
+ _M_classes.insert(name, item);
+}
+
+void _ScopeModelItem::addFunction(FunctionModelItem item)
+{
+ _M_functions.insert(item->name(), item);
+}
+
+void _ScopeModelItem::addFunctionDefinition(FunctionDefinitionModelItem item)
+{
+ _M_functionDefinitions.insert(item->name(), item);
+}
+
+void _ScopeModelItem::addVariable(VariableModelItem item)
+{
+ _M_variables.insert(item->name(), item);
+}
+
+void _ScopeModelItem::addTypeAlias(TypeAliasModelItem item)
+{
+ _M_typeAliases.insert(item->name(), item);
+}
+
+void _ScopeModelItem::addEnum(EnumModelItem item)
+{
+ _M_enums.insert(item->name(), item);
+}
+
+void _ScopeModelItem::removeClass(ClassModelItem item)
+{
+ QHash<QString, ClassModelItem>::Iterator it = _M_classes.find(item->name());
+
+ if (it != _M_classes.end() && it.value() == item)
+ _M_classes.erase(it);
+}
+
+void _ScopeModelItem::removeFunction(FunctionModelItem item)
+{
+ QMultiHash<QString, FunctionModelItem>::Iterator it = _M_functions.find(item->name());
+
+ while (it != _M_functions.end() && it.key() == item->name()
+ && it.value() != item) {
+ ++it;
+ }
+
+ if (it != _M_functions.end() && it.value() == item) {
+ _M_functions.erase(it);
+ }
+}
+
+void _ScopeModelItem::removeFunctionDefinition(FunctionDefinitionModelItem item)
+{
+ QMultiHash<QString, FunctionDefinitionModelItem>::Iterator it = _M_functionDefinitions.find(item->name());
+
+ while (it != _M_functionDefinitions.end() && it.key() == item->name()
+ && it.value() != item) {
+ ++it;
+ }
+
+ if (it != _M_functionDefinitions.end() && it.value() == item) {
+ _M_functionDefinitions.erase(it);
+ }
+}
+
+void _ScopeModelItem::removeVariable(VariableModelItem item)
+{
+ QHash<QString, VariableModelItem>::Iterator it = _M_variables.find(item->name());
+
+ if (it != _M_variables.end() && it.value() == item)
+ _M_variables.erase(it);
+}
+
+void _ScopeModelItem::removeTypeAlias(TypeAliasModelItem item)
+{
+ QHash<QString, TypeAliasModelItem>::Iterator it = _M_typeAliases.find(item->name());
+
+ if (it != _M_typeAliases.end() && it.value() == item)
+ _M_typeAliases.erase(it);
+}
+
+void _ScopeModelItem::removeEnum(EnumModelItem item)
+{
+ QHash<QString, EnumModelItem>::Iterator it = _M_enums.find(item->name());
+
+ if (it != _M_enums.end() && it.value() == item)
+ _M_enums.erase(it);
+}
+
+ClassModelItem _ScopeModelItem::findClass(const QString &name) const
+{
+ return _M_classes.value(name);
+}
+
+VariableModelItem _ScopeModelItem::findVariable(const QString &name) const
+{
+ return _M_variables.value(name);
+}
+
+TypeAliasModelItem _ScopeModelItem::findTypeAlias(const QString &name) const
+{
+ return _M_typeAliases.value(name);
+}
+
+EnumModelItem _ScopeModelItem::findEnum(const QString &name) const
+{
+ return _M_enums.value(name);
+}
+
+FunctionList _ScopeModelItem::findFunctions(const QString &name) const
+{
+ return _M_functions.values(name);
+}
+
+FunctionDefinitionList _ScopeModelItem::findFunctionDefinitions(const QString &name) const
+{
+ return _M_functionDefinitions.values(name);
+}
+
+// ---------------------------------------------------------------------------
+NamespaceList _NamespaceModelItem::namespaces() const
+{
+ return _M_namespaces.values();
+}
+void _NamespaceModelItem::addNamespace(NamespaceModelItem item)
+{
+ _M_namespaces.insert(item->name(), item);
+}
+void _NamespaceModelItem::removeNamespace(NamespaceModelItem item)
+{
+ QHash<QString, NamespaceModelItem>::Iterator it = _M_namespaces.find(item->name());
+
+ if (it != _M_namespaces.end() && it.value() == item)
+ _M_namespaces.erase(it);
+}
+
+NamespaceModelItem _NamespaceModelItem::findNamespace(const QString &name) const
+{
+ return _M_namespaces.value(name);
+}
+
+// ---------------------------------------------------------------------------
+TypeInfo _ArgumentModelItem::type() const
+{
+ return _M_type;
+}
+
+void _ArgumentModelItem::setType(const TypeInfo &type)
+{
+ _M_type = type;
+}
+
+bool _ArgumentModelItem::defaultValue() const
+{
+ return _M_defaultValue;
+}
+
+void _ArgumentModelItem::setDefaultValue(bool defaultValue)
+{
+ _M_defaultValue = defaultValue;
+}
+
+// ---------------------------------------------------------------------------
+bool _FunctionModelItem::isSimilar(FunctionModelItem other) const
+{
+ if (name() != other->name())
+ return false;
+
+ if (isConstant() != other->isConstant())
+ return false;
+
+ if (isVariadics() != other->isVariadics())
+ return false;
+
+ if (arguments().count() != other->arguments().count())
+ return false;
+
+ // ### check the template parameters
+
+ for (int i = 0; i < arguments().count(); ++i) {
+ ArgumentModelItem arg1 = arguments().at(i);
+ ArgumentModelItem arg2 = other->arguments().at(i);
+
+ if (arg1->type() != arg2->type())
+ return false;
+ }
+
+ return true;
+}
+
+ArgumentList _FunctionModelItem::arguments() const
+{
+ return _M_arguments;
+}
+
+void _FunctionModelItem::addArgument(ArgumentModelItem item)
+{
+ _M_arguments.append(item);
+}
+
+void _FunctionModelItem::removeArgument(ArgumentModelItem item)
+{
+ _M_arguments.removeAt(_M_arguments.indexOf(item));
+}
+
+CodeModel::FunctionType _FunctionModelItem::functionType() const
+{
+ return _M_functionType;
+}
+
+void _FunctionModelItem::setFunctionType(CodeModel::FunctionType functionType)
+{
+ _M_functionType = functionType;
+}
+
+bool _FunctionModelItem::isVariadics() const
+{
+ return _M_isVariadics;
+}
+
+void _FunctionModelItem::setVariadics(bool isVariadics)
+{
+ _M_isVariadics = isVariadics;
+}
+
+bool _FunctionModelItem::isVirtual() const
+{
+ return _M_isVirtual;
+}
+
+void _FunctionModelItem::setVirtual(bool isVirtual)
+{
+ _M_isVirtual = isVirtual;
+}
+
+bool _FunctionModelItem::isInline() const
+{
+ return _M_isInline;
+}
+
+void _FunctionModelItem::setInline(bool isInline)
+{
+ _M_isInline = isInline;
+}
+
+bool _FunctionModelItem::isExplicit() const
+{
+ return _M_isExplicit;
+}
+
+void _FunctionModelItem::setExplicit(bool isExplicit)
+{
+ _M_isExplicit = isExplicit;
+}
+
+bool _FunctionModelItem::isAbstract() const
+{
+ return _M_isAbstract;
+}
+
+void _FunctionModelItem::setAbstract(bool isAbstract)
+{
+ _M_isAbstract = isAbstract;
+}
+
+// Qt
+bool _FunctionModelItem::isInvokable() const
+{
+ return _M_isInvokable;
+}
+
+void _FunctionModelItem::setInvokable(bool isInvokable)
+{
+ _M_isInvokable = isInvokable;
+}
+
+// ---------------------------------------------------------------------------
+TypeInfo _TypeAliasModelItem::type() const
+{
+ return _M_type;
+}
+
+void _TypeAliasModelItem::setType(const TypeInfo &type)
+{
+ _M_type = type;
+}
+
+// ---------------------------------------------------------------------------
+CodeModel::AccessPolicy _EnumModelItem::accessPolicy() const
+{
+ return _M_accessPolicy;
+}
+
+void _EnumModelItem::setAccessPolicy(CodeModel::AccessPolicy accessPolicy)
+{
+ _M_accessPolicy = accessPolicy;
+}
+
+EnumeratorList _EnumModelItem::enumerators() const
+{
+ return _M_enumerators;
+}
+
+void _EnumModelItem::addEnumerator(EnumeratorModelItem item)
+{
+ _M_enumerators.append(item);
+}
+
+void _EnumModelItem::removeEnumerator(EnumeratorModelItem item)
+{
+ _M_enumerators.removeAt(_M_enumerators.indexOf(item));
+}
+
+// ---------------------------------------------------------------------------
+QString _EnumeratorModelItem::value() const
+{
+ return _M_value;
+}
+
+void _EnumeratorModelItem::setValue(const QString &value)
+{
+ _M_value = value;
+}
+
+// ---------------------------------------------------------------------------
+TypeInfo _TemplateParameterModelItem::type() const
+{
+ return _M_type;
+}
+
+void _TemplateParameterModelItem::setType(const TypeInfo &type)
+{
+ _M_type = type;
+}
+
+bool _TemplateParameterModelItem::defaultValue() const
+{
+ return _M_defaultValue;
+}
+
+void _TemplateParameterModelItem::setDefaultValue(bool defaultValue)
+{
+ _M_defaultValue = defaultValue;
+}
+
+// ---------------------------------------------------------------------------
+ScopeModelItem _ScopeModelItem::create(CodeModel *model)
+{
+ ScopeModelItem item(new _ScopeModelItem(model));
+ return item;
+}
+
+ClassModelItem _ClassModelItem::create(CodeModel *model)
+{
+ ClassModelItem item(new _ClassModelItem(model));
+ return item;
+}
+
+NamespaceModelItem _NamespaceModelItem::create(CodeModel *model)
+{
+ NamespaceModelItem item(new _NamespaceModelItem(model));
+ return item;
+}
+
+FileModelItem _FileModelItem::create(CodeModel *model)
+{
+ FileModelItem item(new _FileModelItem(model));
+ return item;
+}
+
+ArgumentModelItem _ArgumentModelItem::create(CodeModel *model)
+{
+ ArgumentModelItem item(new _ArgumentModelItem(model));
+ return item;
+}
+
+FunctionModelItem _FunctionModelItem::create(CodeModel *model)
+{
+ FunctionModelItem item(new _FunctionModelItem(model));
+ return item;
+}
+
+FunctionDefinitionModelItem _FunctionDefinitionModelItem::create(CodeModel *model)
+{
+ FunctionDefinitionModelItem item(new _FunctionDefinitionModelItem(model));
+ return item;
+}
+
+VariableModelItem _VariableModelItem::create(CodeModel *model)
+{
+ VariableModelItem item(new _VariableModelItem(model));
+ return item;
+}
+
+TypeAliasModelItem _TypeAliasModelItem::create(CodeModel *model)
+{
+ TypeAliasModelItem item(new _TypeAliasModelItem(model));
+ return item;
+}
+
+EnumModelItem _EnumModelItem::create(CodeModel *model)
+{
+ EnumModelItem item(new _EnumModelItem(model));
+ return item;
+}
+
+EnumeratorModelItem _EnumeratorModelItem::create(CodeModel *model)
+{
+ EnumeratorModelItem item(new _EnumeratorModelItem(model));
+ return item;
+}
+
+TemplateParameterModelItem _TemplateParameterModelItem::create(CodeModel *model)
+{
+ TemplateParameterModelItem item(new _TemplateParameterModelItem(model));
+ return item;
+}
+
+// ---------------------------------------------------------------------------
+TypeInfo _MemberModelItem::type() const
+{
+ return _M_type;
+}
+
+void _MemberModelItem::setType(const TypeInfo &type)
+{
+ _M_type = type;
+}
+
+CodeModel::AccessPolicy _MemberModelItem::accessPolicy() const
+{
+ return _M_accessPolicy;
+}
+
+void _MemberModelItem::setAccessPolicy(CodeModel::AccessPolicy accessPolicy)
+{
+ _M_accessPolicy = accessPolicy;
+}
+
+bool _MemberModelItem::isStatic() const
+{
+ return _M_isStatic;
+}
+
+void _MemberModelItem::setStatic(bool isStatic)
+{
+ _M_isStatic = isStatic;
+}
+
+bool _MemberModelItem::isConstant() const
+{
+ return _M_isConstant;
+}
+
+void _MemberModelItem::setConstant(bool isConstant)
+{
+ _M_isConstant = isConstant;
+}
+
+bool _MemberModelItem::isVolatile() const
+{
+ return _M_isVolatile;
+}
+
+void _MemberModelItem::setVolatile(bool isVolatile)
+{
+ _M_isVolatile = isVolatile;
+}
+
+bool _MemberModelItem::isAuto() const
+{
+ return _M_isAuto;
+}
+
+void _MemberModelItem::setAuto(bool isAuto)
+{
+ _M_isAuto = isAuto;
+}
+
+bool _MemberModelItem::isFriend() const
+{
+ return _M_isFriend;
+}
+
+void _MemberModelItem::setFriend(bool isFriend)
+{
+ _M_isFriend = isFriend;
+}
+
+bool _MemberModelItem::isRegister() const
+{
+ return _M_isRegister;
+}
+
+void _MemberModelItem::setRegister(bool isRegister)
+{
+ _M_isRegister = isRegister;
+}
+
+bool _MemberModelItem::isExtern() const
+{
+ return _M_isExtern;
+}
+
+void _MemberModelItem::setExtern(bool isExtern)
+{
+ _M_isExtern = isExtern;
+}
+
+bool _MemberModelItem::isMutable() const
+{
+ return _M_isMutable;
+}
+
+void _MemberModelItem::setMutable(bool isMutable)
+{
+ _M_isMutable = isMutable;
+}
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
+
diff --git a/parser/codemodel.h b/parser/codemodel.h
new file mode 100644
index 00000000..3ea94480
--- /dev/null
+++ b/parser/codemodel.h
@@ -0,0 +1,838 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+
+#ifndef CODEMODEL_H
+#define CODEMODEL_H
+
+#include "codemodel_fwd.h"
+#include "codemodel_pointer.h"
+
+#include <QtCore/QHash>
+#include <QtCore/QList>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QVector>
+
+#define DECLARE_MODEL_NODE(k) \
+ enum { __node_kind = Kind_##k }; \
+ typedef CodeModelPointer<k##ModelItem> Pointer;
+
+template <class _Target, class _Source>
+_Target model_static_cast(_Source item)
+{
+ typedef typename _Target::Type * _Target_pointer;
+
+ _Target ptr(static_cast<_Target_pointer>(item.data()));
+ return ptr;
+}
+
+class CodeModel
+{
+public:
+ enum AccessPolicy {
+ Public,
+ Protected,
+ Private
+ };
+
+ enum FunctionType {
+ Normal,
+ Signal,
+ Slot
+ };
+
+ enum ClassType {
+ Class,
+ Struct,
+ Union
+ };
+
+public:
+ CodeModel();
+ virtual ~CodeModel();
+
+ template <class _Target> _Target create()
+ {
+ typedef typename _Target::Type _Target_type;
+
+ _Target result = _Target_type::create(this);
+ result->setCreationId(_M_creation_id++);
+ return result;
+ }
+
+ FileList files() const;
+ NamespaceModelItem globalNamespace() const;
+
+ void addFile(FileModelItem item);
+ void removeFile(FileModelItem item);
+ FileModelItem findFile(const QString &name) const;
+ QHash<QString, FileModelItem> fileMap() const;
+
+ CodeModelItem findItem(const QStringList &qualifiedName, CodeModelItem scope) const;
+
+ void wipeout();
+
+private:
+ QHash<QString, FileModelItem> _M_files;
+ NamespaceModelItem _M_globalNamespace;
+ std::size_t _M_creation_id;
+
+private:
+ CodeModel(const CodeModel &other);
+ void operator = (const CodeModel &other);
+};
+
+class TypeInfo
+{
+public:
+ TypeInfo(const TypeInfo &other)
+ : flags(other.flags),
+ m_qualifiedName(other.m_qualifiedName),
+ m_arrayElements(other.m_arrayElements),
+ m_arguments(other.m_arguments)
+ {}
+
+ TypeInfo():
+ flags(0) {}
+
+ QStringList qualifiedName() const
+ {
+ return m_qualifiedName;
+ }
+
+ void setQualifiedName(const QStringList &qualified_name)
+ {
+ m_qualifiedName = qualified_name;
+ }
+
+ bool isConstant() const
+ {
+ return m_constant;
+ }
+
+ void setConstant(bool is)
+ {
+ m_constant = is;
+ }
+
+ bool isVolatile() const
+ {
+ return m_volatile;
+ }
+
+ void setVolatile(bool is)
+ {
+ m_volatile = is;
+ }
+
+ bool isReference() const
+ {
+ return m_reference;
+ }
+
+ void setReference(bool is)
+ {
+ m_reference = is;
+ }
+
+ int indirections() const
+ {
+ return m_indirections;
+ }
+
+ void setIndirections(int indirections)
+ {
+ m_indirections = indirections;
+ }
+
+ bool isFunctionPointer() const
+ {
+ return m_functionPointer;
+ }
+ void setFunctionPointer(bool is)
+ {
+ m_functionPointer = is;
+ }
+
+ QStringList arrayElements() const
+ {
+ return m_arrayElements;
+ }
+ void setArrayElements(const QStringList &arrayElements)
+ {
+ m_arrayElements = arrayElements;
+ }
+
+ QList<TypeInfo> arguments() const
+ {
+ return m_arguments;
+ }
+
+ void setArguments(const QList<TypeInfo> &arguments);
+
+ void addArgument(const TypeInfo &arg)
+ {
+ m_arguments.append(arg);
+ }
+
+ bool operator==(const TypeInfo &other);
+
+ bool operator!=(const TypeInfo &other)
+ {
+ return !(*this == other);
+ }
+
+ // ### arrays and templates??
+
+ QString toString() const;
+
+ static TypeInfo combine(const TypeInfo &__lhs, const TypeInfo &__rhs);
+ static TypeInfo resolveType(TypeInfo const &__type, CodeModelItem __scope);
+
+private:
+ union {
+ uint flags;
+
+ struct {
+ uint m_constant: 1;
+ uint m_volatile: 1;
+ uint m_reference: 1;
+ uint m_functionPointer: 1;
+ uint m_indirections: 6;
+ uint m_padding: 22;
+ };
+ };
+
+ QStringList m_qualifiedName;
+ QStringList m_arrayElements;
+ QList<TypeInfo> m_arguments;
+};
+
+class _CodeModelItem: public QSharedData
+{
+public:
+ enum Kind {
+ /* These are bit-flags resembling inheritance */
+ Kind_Scope = 0x1,
+ Kind_Namespace = 0x2 | Kind_Scope,
+ Kind_Member = 0x4,
+ Kind_Function = 0x8 | Kind_Member,
+ KindMask = 0xf,
+
+ /* These are for classes that are not inherited from */
+ FirstKind = 0x8,
+ Kind_Argument = 1 << FirstKind,
+ Kind_Class = 2 << FirstKind | Kind_Scope,
+ Kind_Enum = 3 << FirstKind,
+ Kind_Enumerator = 4 << FirstKind,
+ Kind_File = 5 << FirstKind | Kind_Namespace,
+ Kind_FunctionDefinition = 6 << FirstKind | Kind_Function,
+ Kind_TemplateParameter = 7 << FirstKind,
+ Kind_TypeAlias = 8 << FirstKind,
+ Kind_Variable = 9 << FirstKind | Kind_Member
+ };
+
+public:
+ virtual ~_CodeModelItem();
+
+ int kind() const;
+
+ QStringList qualifiedName() const;
+
+ QString name() const;
+ void setName(const QString &name);
+
+ QStringList scope() const;
+ void setScope(const QStringList &scope);
+
+ QString fileName() const;
+ void setFileName(const QString &fileName);
+
+ FileModelItem file() const;
+
+ void getStartPosition(int *line, int *column);
+ void setStartPosition(int line, int column);
+
+ void getEndPosition(int *line, int *column);
+ void setEndPosition(int line, int column);
+
+ inline std::size_t creationId() const
+ {
+ return _M_creation_id;
+ }
+
+ inline void setCreationId(std::size_t creation_id)
+ {
+ _M_creation_id = creation_id;
+ }
+
+ inline CodeModel *model() const
+ {
+ return _M_model;
+ }
+
+ CodeModelItem toItem() const;
+
+protected:
+ _CodeModelItem(CodeModel *model, int kind);
+ void setKind(int kind);
+
+private:
+ CodeModel *_M_model;
+ int _M_kind;
+ int _M_startLine;
+ int _M_startColumn;
+ int _M_endLine;
+ int _M_endColumn;
+ std::size_t _M_creation_id;
+ QString _M_name;
+ QString _M_fileName;
+ QStringList _M_scope;
+
+private:
+ _CodeModelItem(const _CodeModelItem &other);
+ void operator = (const _CodeModelItem &other);
+};
+
+class _ScopeModelItem: public _CodeModelItem
+{
+public:
+ DECLARE_MODEL_NODE(Scope)
+
+ static ScopeModelItem create(CodeModel *model);
+
+public:
+ ClassList classes() const;
+ EnumList enums() const;
+ FunctionDefinitionList functionDefinitions() const;
+ FunctionList functions() const;
+ TypeAliasList typeAliases() const;
+ VariableList variables() const;
+
+ void addClass(ClassModelItem item);
+ void addEnum(EnumModelItem item);
+ void addFunction(FunctionModelItem item);
+ void addFunctionDefinition(FunctionDefinitionModelItem item);
+ void addTypeAlias(TypeAliasModelItem item);
+ void addVariable(VariableModelItem item);
+
+ void removeClass(ClassModelItem item);
+ void removeEnum(EnumModelItem item);
+ void removeFunction(FunctionModelItem item);
+ void removeFunctionDefinition(FunctionDefinitionModelItem item);
+ void removeTypeAlias(TypeAliasModelItem item);
+ void removeVariable(VariableModelItem item);
+
+ ClassModelItem findClass(const QString &name) const;
+ EnumModelItem findEnum(const QString &name) const;
+ FunctionDefinitionList findFunctionDefinitions(const QString &name) const;
+ FunctionList findFunctions(const QString &name) const;
+ TypeAliasModelItem findTypeAlias(const QString &name) const;
+ VariableModelItem findVariable(const QString &name) const;
+
+ void addEnumsDeclaration(const QString &enumsDeclaration);
+ QStringList enumsDeclarations() const
+ {
+ return _M_enumsDeclarations;
+ }
+
+ inline QHash<QString, ClassModelItem> classMap() const
+ {
+ return _M_classes;
+ }
+ inline QHash<QString, EnumModelItem> enumMap() const
+ {
+ return _M_enums;
+ }
+ inline QHash<QString, TypeAliasModelItem> typeAliasMap() const
+ {
+ return _M_typeAliases;
+ }
+ inline QHash<QString, VariableModelItem> variableMap() const
+ {
+ return _M_variables;
+ }
+ inline QMultiHash<QString, FunctionDefinitionModelItem> functionDefinitionMap() const
+ {
+ return _M_functionDefinitions;
+ }
+ inline QMultiHash<QString, FunctionModelItem> functionMap() const
+ {
+ return _M_functions;
+ }
+
+ FunctionModelItem declaredFunction(FunctionModelItem item);
+
+protected:
+ _ScopeModelItem(CodeModel *model, int kind = __node_kind)
+ : _CodeModelItem(model, kind) {}
+
+private:
+ QHash<QString, ClassModelItem> _M_classes;
+ QHash<QString, EnumModelItem> _M_enums;
+ QHash<QString, TypeAliasModelItem> _M_typeAliases;
+ QHash<QString, VariableModelItem> _M_variables;
+ QMultiHash<QString, FunctionDefinitionModelItem> _M_functionDefinitions;
+ QMultiHash<QString, FunctionModelItem> _M_functions;
+
+private:
+ _ScopeModelItem(const _ScopeModelItem &other);
+ void operator = (const _ScopeModelItem &other);
+
+ QStringList _M_enumsDeclarations;
+};
+
+class _ClassModelItem: public _ScopeModelItem
+{
+public:
+ DECLARE_MODEL_NODE(Class)
+
+ static ClassModelItem create(CodeModel *model);
+
+public:
+ QStringList baseClasses() const;
+
+ void setBaseClasses(const QStringList &baseClasses);
+ void addBaseClass(const QString &baseClass);
+ void removeBaseClass(const QString &baseClass);
+
+ TemplateParameterList templateParameters() const;
+ void setTemplateParameters(const TemplateParameterList &templateParameters);
+
+ bool extendsClass(const QString &name) const;
+
+ void setClassType(CodeModel::ClassType type);
+ CodeModel::ClassType classType() const;
+
+ void addPropertyDeclaration(const QString &propertyDeclaration);
+ QStringList propertyDeclarations() const
+ {
+ return _M_propertyDeclarations;
+ }
+
+protected:
+ _ClassModelItem(CodeModel *model, int kind = __node_kind)
+ : _ScopeModelItem(model, kind), _M_classType(CodeModel::Class) {}
+
+private:
+ QStringList _M_baseClasses;
+ TemplateParameterList _M_templateParameters;
+ CodeModel::ClassType _M_classType;
+
+ QStringList _M_propertyDeclarations;
+
+private:
+ _ClassModelItem(const _ClassModelItem &other);
+ void operator = (const _ClassModelItem &other);
+};
+
+class _NamespaceModelItem: public _ScopeModelItem
+{
+public:
+ DECLARE_MODEL_NODE(Namespace)
+
+ static NamespaceModelItem create(CodeModel *model);
+
+public:
+ NamespaceList namespaces() const;
+
+ void addNamespace(NamespaceModelItem item);
+ void removeNamespace(NamespaceModelItem item);
+
+ NamespaceModelItem findNamespace(const QString &name) const;
+
+ inline QHash<QString, NamespaceModelItem> namespaceMap() const
+ {
+ return _M_namespaces;
+ };
+
+protected:
+ _NamespaceModelItem(CodeModel *model, int kind = __node_kind)
+ : _ScopeModelItem(model, kind) {}
+
+private:
+ QHash<QString, NamespaceModelItem> _M_namespaces;
+
+private:
+ _NamespaceModelItem(const _NamespaceModelItem &other);
+ void operator = (const _NamespaceModelItem &other);
+};
+
+class _FileModelItem: public _NamespaceModelItem
+{
+public:
+ DECLARE_MODEL_NODE(File)
+
+ static FileModelItem create(CodeModel *model);
+
+protected:
+ _FileModelItem(CodeModel *model, int kind = __node_kind)
+ : _NamespaceModelItem(model, kind) {}
+
+private:
+ _FileModelItem(const _FileModelItem &other);
+ void operator = (const _FileModelItem &other);
+};
+
+class _ArgumentModelItem: public _CodeModelItem
+{
+public:
+ DECLARE_MODEL_NODE(Argument)
+
+ static ArgumentModelItem create(CodeModel *model);
+
+public:
+ TypeInfo type() const;
+ void setType(const TypeInfo &type);
+
+ bool defaultValue() const;
+ void setDefaultValue(bool defaultValue);
+
+ QString defaultValueExpression() const
+ {
+ return _M_defaultValueExpression;
+ }
+
+ void setDefaultValueExpression(const QString &expr)
+ {
+ _M_defaultValueExpression = expr;
+ }
+
+protected:
+ _ArgumentModelItem(CodeModel *model, int kind = __node_kind)
+ : _CodeModelItem(model, kind), _M_defaultValue(false) {}
+
+private:
+ TypeInfo _M_type;
+ QString _M_defaultValueExpression;
+ bool _M_defaultValue;
+
+private:
+ _ArgumentModelItem(const _ArgumentModelItem &other);
+ void operator = (const _ArgumentModelItem &other);
+};
+
+class _MemberModelItem: public _CodeModelItem
+{
+public:
+ DECLARE_MODEL_NODE(Member)
+
+ bool isConstant() const;
+ void setConstant(bool isConstant);
+
+ bool isVolatile() const;
+ void setVolatile(bool isVolatile);
+
+ bool isStatic() const;
+ void setStatic(bool isStatic);
+
+ bool isAuto() const;
+ void setAuto(bool isAuto);
+
+ bool isFriend() const;
+ void setFriend(bool isFriend);
+
+ bool isRegister() const;
+ void setRegister(bool isRegister);
+
+ bool isExtern() const;
+ void setExtern(bool isExtern);
+
+ bool isMutable() const;
+ void setMutable(bool isMutable);
+
+ CodeModel::AccessPolicy accessPolicy() const;
+ void setAccessPolicy(CodeModel::AccessPolicy accessPolicy);
+
+ TemplateParameterList templateParameters() const
+ {
+ return _M_templateParameters;
+ }
+
+ void setTemplateParameters(const TemplateParameterList &templateParameters)
+ {
+ _M_templateParameters = templateParameters;
+ }
+
+ TypeInfo type() const;
+ void setType(const TypeInfo &type);
+
+protected:
+ _MemberModelItem(CodeModel *model, int kind)
+ : _CodeModelItem(model, kind),
+ _M_accessPolicy(CodeModel::Public),
+ _M_flags(0) {}
+
+private:
+ TemplateParameterList _M_templateParameters;
+ TypeInfo _M_type;
+ CodeModel::AccessPolicy _M_accessPolicy;
+ union {
+ struct {
+ uint _M_isConstant: 1;
+ uint _M_isVolatile: 1;
+ uint _M_isStatic: 1;
+ uint _M_isAuto: 1;
+ uint _M_isFriend: 1;
+ uint _M_isRegister: 1;
+ uint _M_isExtern: 1;
+ uint _M_isMutable: 1;
+ };
+ uint _M_flags;
+ };
+
+};
+
+class _FunctionModelItem: public _MemberModelItem
+{
+public:
+ DECLARE_MODEL_NODE(Function)
+
+ static FunctionModelItem create(CodeModel *model);
+
+public:
+ ArgumentList arguments() const;
+
+ void addArgument(ArgumentModelItem item);
+ void removeArgument(ArgumentModelItem item);
+
+ CodeModel::FunctionType functionType() const;
+ void setFunctionType(CodeModel::FunctionType functionType);
+
+ bool isVirtual() const;
+ void setVirtual(bool isVirtual);
+
+ bool isInline() const;
+ void setInline(bool isInline);
+
+ bool isExplicit() const;
+ void setExplicit(bool isExplicit);
+
+ bool isInvokable() const; // Qt
+ void setInvokable(bool isInvokable); // Qt
+
+ bool isAbstract() const;
+ void setAbstract(bool isAbstract);
+
+ bool isVariadics() const;
+ void setVariadics(bool isVariadics);
+
+ bool isSimilar(FunctionModelItem other) const;
+
+protected:
+ _FunctionModelItem(CodeModel *model, int kind = __node_kind)
+ : _MemberModelItem(model, kind),
+ _M_functionType(CodeModel::Normal),
+ _M_flags(0) {}
+
+private:
+ ArgumentList _M_arguments;
+ CodeModel::FunctionType _M_functionType;
+ union {
+ struct {
+ uint _M_isVirtual: 1;
+ uint _M_isInline: 1;
+ uint _M_isAbstract: 1;
+ uint _M_isExplicit: 1;
+ uint _M_isVariadics: 1;
+ uint _M_isInvokable : 1; // Qt
+ };
+ uint _M_flags;
+ };
+
+private:
+ _FunctionModelItem(const _FunctionModelItem &other);
+ void operator = (const _FunctionModelItem &other);
+};
+
+class _FunctionDefinitionModelItem: public _FunctionModelItem
+{
+public:
+ DECLARE_MODEL_NODE(FunctionDefinition)
+
+ static FunctionDefinitionModelItem create(CodeModel *model);
+
+protected:
+ _FunctionDefinitionModelItem(CodeModel *model, int kind = __node_kind)
+ : _FunctionModelItem(model, kind) {}
+
+private:
+ _FunctionDefinitionModelItem(const _FunctionDefinitionModelItem &other);
+ void operator = (const _FunctionDefinitionModelItem &other);
+};
+
+class _VariableModelItem: public _MemberModelItem
+{
+public:
+ DECLARE_MODEL_NODE(Variable)
+
+ static VariableModelItem create(CodeModel *model);
+
+protected:
+ _VariableModelItem(CodeModel *model, int kind = __node_kind)
+ : _MemberModelItem(model, kind) {}
+
+private:
+ _VariableModelItem(const _VariableModelItem &other);
+ void operator = (const _VariableModelItem &other);
+};
+
+class _TypeAliasModelItem: public _CodeModelItem
+{
+public:
+ DECLARE_MODEL_NODE(TypeAlias)
+
+ static TypeAliasModelItem create(CodeModel *model);
+
+public:
+ TypeInfo type() const;
+ void setType(const TypeInfo &type);
+
+protected:
+ _TypeAliasModelItem(CodeModel *model, int kind = __node_kind)
+ : _CodeModelItem(model, kind) {}
+
+private:
+ TypeInfo _M_type;
+
+private:
+ _TypeAliasModelItem(const _TypeAliasModelItem &other);
+ void operator = (const _TypeAliasModelItem &other);
+};
+
+class _EnumModelItem: public _CodeModelItem
+{
+public:
+ DECLARE_MODEL_NODE(Enum)
+
+ static EnumModelItem create(CodeModel *model);
+
+public:
+ CodeModel::AccessPolicy accessPolicy() const;
+ void setAccessPolicy(CodeModel::AccessPolicy accessPolicy);
+
+ EnumeratorList enumerators() const;
+ void addEnumerator(EnumeratorModelItem item);
+ void removeEnumerator(EnumeratorModelItem item);
+
+protected:
+ _EnumModelItem(CodeModel *model, int kind = __node_kind)
+ : _CodeModelItem(model, kind),
+ _M_accessPolicy(CodeModel::Public) {}
+
+private:
+ CodeModel::AccessPolicy _M_accessPolicy;
+ EnumeratorList _M_enumerators;
+
+private:
+ _EnumModelItem(const _EnumModelItem &other);
+ void operator = (const _EnumModelItem &other);
+};
+
+class _EnumeratorModelItem: public _CodeModelItem
+{
+public:
+ DECLARE_MODEL_NODE(Enumerator)
+
+ static EnumeratorModelItem create(CodeModel *model);
+
+public:
+ QString value() const;
+ void setValue(const QString &value);
+
+protected:
+ _EnumeratorModelItem(CodeModel *model, int kind = __node_kind)
+ : _CodeModelItem(model, kind) {}
+
+private:
+ QString _M_value;
+
+private:
+ _EnumeratorModelItem(const _EnumeratorModelItem &other);
+ void operator = (const _EnumeratorModelItem &other);
+};
+
+class _TemplateParameterModelItem: public _CodeModelItem
+{
+public:
+ DECLARE_MODEL_NODE(TemplateParameter)
+
+ static TemplateParameterModelItem create(CodeModel *model);
+
+public:
+ TypeInfo type() const;
+ void setType(const TypeInfo &type);
+
+ bool defaultValue() const;
+ void setDefaultValue(bool defaultValue);
+
+protected:
+ _TemplateParameterModelItem(CodeModel *model, int kind = __node_kind)
+ : _CodeModelItem(model, kind), _M_defaultValue(false) {}
+
+private:
+ TypeInfo _M_type;
+ bool _M_defaultValue;
+
+private:
+ _TemplateParameterModelItem(const _TemplateParameterModelItem &other);
+ void operator = (const _TemplateParameterModelItem &other);
+};
+
+template <class _Target, class _Source>
+_Target model_safe_cast(_Source item)
+{
+ typedef typename _Target::Type * _Target_pointer;
+ typedef typename _Source::Type * _Source_pointer;
+
+ _Source_pointer source = item.data();
+ if (source && source->kind() == _Target_pointer(0)->__node_kind) {
+ _Target ptr(static_cast<_Target_pointer>(source));
+ return ptr;
+ }
+
+ return _Target();
+}
+
+template <typename _Target, typename _Source>
+_Target model_dynamic_cast(_Source item)
+{
+ typedef typename _Target::Type * _Target_pointer;
+ typedef typename _Source::Type * _Source_pointer;
+
+ _Source_pointer source = item.data();
+ if (source && (source->kind() == _Target_pointer(0)->__node_kind
+ || (int(_Target_pointer(0)->__node_kind) <= int(_CodeModelItem::KindMask)
+ && ((source->kind() & _Target_pointer(0)->__node_kind)
+ == _Target_pointer(0)->__node_kind)))) {
+ _Target ptr(static_cast<_Target_pointer>(source));
+ return ptr;
+ }
+
+ return _Target();
+}
+#endif // CODEMODEL_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/codemodel_finder.cpp b/parser/codemodel_finder.cpp
new file mode 100644
index 00000000..866ea1cb
--- /dev/null
+++ b/parser/codemodel_finder.cpp
@@ -0,0 +1,98 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include "codemodel_finder.h"
+#include "codemodel.h"
+#include "binder.h"
+
+CodeModelFinder::CodeModelFinder(CodeModel *model, Binder *binder)
+ : _M_model(model),
+ _M_binder(binder),
+ _M_token_stream(binder->tokenStream()),
+ name_cc(_M_binder),
+ _M_resolve_policy(ResolveItem)
+{
+}
+
+CodeModelFinder::~CodeModelFinder()
+{
+}
+
+ScopeModelItem CodeModelFinder::resolveScope(NameAST *name, ScopeModelItem scope)
+{
+ Q_ASSERT(scope);
+
+ ResolvePolicy saved_resolve_policy = _M_resolve_policy;
+ _M_resolve_policy = ResolveScope;
+
+ ScopeModelItem old = changeCurrentScope(scope);
+
+ visit(name);
+ ScopeModelItem result = _M_current_scope;
+
+ changeCurrentScope(old); // restore
+
+ _M_resolve_policy = saved_resolve_policy;
+
+ return result;
+}
+
+ScopeModelItem CodeModelFinder::changeCurrentScope(ScopeModelItem scope)
+{
+ ScopeModelItem old = _M_current_scope;
+ _M_current_scope = scope;
+ return old;
+}
+
+void CodeModelFinder::visitName(NameAST *node)
+{
+ visitNodes(this, node->qualified_names);
+
+ if (_M_resolve_policy == ResolveItem)
+ visit(node->unqualified_name);
+}
+
+void CodeModelFinder::visitUnqualifiedName(UnqualifiedNameAST *node)
+{
+ if (!_M_current_scope) {
+ // nothing to do
+ return;
+ }
+
+ name_cc.run(node);
+ QString id = name_cc.name();
+
+ if (ClassModelItem klass = _M_current_scope->findClass(id)) {
+ _M_current_scope = klass;
+ } else if (NamespaceModelItem parentNamespace = model_safe_cast<NamespaceModelItem>(_M_current_scope)) {
+ NamespaceModelItem ns = parentNamespace->findNamespace(id);
+ _M_current_scope = model_static_cast<ScopeModelItem>(ns);
+ } else if (FileModelItem file = model_safe_cast<FileModelItem>(_M_current_scope)) {
+ NamespaceModelItem ns = file->findNamespace(id);
+ _M_current_scope = model_static_cast<ScopeModelItem>(ns);
+ }
+}
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
+
diff --git a/parser/codemodel_finder.h b/parser/codemodel_finder.h
new file mode 100644
index 00000000..ac1b5b0e
--- /dev/null
+++ b/parser/codemodel_finder.h
@@ -0,0 +1,70 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+
+#ifndef CODEMODEL_FINDER_H
+#define CODEMODEL_FINDER_H
+
+#include <default_visitor.h>
+#include <codemodel_fwd.h>
+#include <name_compiler.h>
+
+class TokenStream;
+class Binder;
+
+class CodeModelFinder: protected DefaultVisitor
+{
+ enum ResolvePolicy {
+ ResolveScope,
+ ResolveItem
+ };
+
+public:
+ CodeModelFinder(CodeModel *model, Binder *binder);
+ virtual ~CodeModelFinder();
+
+ ScopeModelItem resolveScope(NameAST *name, ScopeModelItem scope);
+
+ inline CodeModel *model() const
+ {
+ return _M_model;
+ }
+
+protected:
+ virtual void visitName(NameAST *node);
+ virtual void visitUnqualifiedName(UnqualifiedNameAST *node);
+
+ ScopeModelItem changeCurrentScope(ScopeModelItem scope);
+
+private:
+ CodeModel *_M_model;
+ Binder *_M_binder;
+ TokenStream *_M_token_stream;
+ NameCompiler name_cc;
+
+ ScopeModelItem _M_current_scope;
+ ResolvePolicy _M_resolve_policy;
+};
+
+#endif // CODEMODEL_FINDER_H
diff --git a/parser/codemodel_fwd.h b/parser/codemodel_fwd.h
new file mode 100644
index 00000000..96405909
--- /dev/null
+++ b/parser/codemodel_fwd.h
@@ -0,0 +1,80 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+
+#ifndef CODEMODEL_FWD_H
+#define CODEMODEL_FWD_H
+
+#include "codemodel_pointer.h"
+#include <QtCore/QList>
+
+// forward declarations
+class CodeModel;
+class _ArgumentModelItem;
+class _ClassModelItem;
+class _CodeModelItem;
+class _EnumModelItem;
+class _EnumeratorModelItem;
+class _FileModelItem;
+class _FunctionDefinitionModelItem;
+class _FunctionModelItem;
+class _NamespaceModelItem;
+class _ScopeModelItem;
+class _TemplateParameterModelItem;
+class _TypeAliasModelItem;
+class _VariableModelItem;
+class _MemberModelItem;
+class TypeInfo;
+
+typedef CodeModelPointer<_ArgumentModelItem> ArgumentModelItem;
+typedef CodeModelPointer<_ClassModelItem> ClassModelItem;
+typedef CodeModelPointer<_CodeModelItem> CodeModelItem;
+typedef CodeModelPointer<_EnumModelItem> EnumModelItem;
+typedef CodeModelPointer<_EnumeratorModelItem> EnumeratorModelItem;
+typedef CodeModelPointer<_FileModelItem> FileModelItem;
+typedef CodeModelPointer<_FunctionDefinitionModelItem> FunctionDefinitionModelItem;
+typedef CodeModelPointer<_FunctionModelItem> FunctionModelItem;
+typedef CodeModelPointer<_NamespaceModelItem> NamespaceModelItem;
+typedef CodeModelPointer<_ScopeModelItem> ScopeModelItem;
+typedef CodeModelPointer<_TemplateParameterModelItem> TemplateParameterModelItem;
+typedef CodeModelPointer<_TypeAliasModelItem> TypeAliasModelItem;
+typedef CodeModelPointer<_VariableModelItem> VariableModelItem;
+typedef CodeModelPointer<_MemberModelItem> MemberModelItem;
+
+typedef QList<ArgumentModelItem> ArgumentList;
+typedef QList<ClassModelItem> ClassList;
+typedef QList<CodeModelItem> ItemList;
+typedef QList<EnumModelItem> EnumList;
+typedef QList<EnumeratorModelItem> EnumeratorList;
+typedef QList<FileModelItem> FileList;
+typedef QList<FunctionDefinitionModelItem> FunctionDefinitionList;
+typedef QList<FunctionModelItem> FunctionList;
+typedef QList<NamespaceModelItem> NamespaceList;
+typedef QList<ScopeModelItem> ScopeList;
+typedef QList<TemplateParameterModelItem> TemplateParameterList;
+typedef QList<TypeAliasModelItem> TypeAliasList;
+typedef QList<VariableModelItem> VariableList;
+typedef QList<MemberModelItem> MemberList;
+
+#endif // CODEMODEL_FWD_H
diff --git a/parser/codemodel_pointer.h b/parser/codemodel_pointer.h
new file mode 100644
index 00000000..2c728f3c
--- /dev/null
+++ b/parser/codemodel_pointer.h
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2006 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef CODEMODEL_POINTER_H
+#define CODEMODEL_POINTER_H
+
+#include <QtCore/QSharedData>
+#include <QAtomicPointer>
+
+template <class T> class CodeModelPointer : public QAtomicPointer<T>
+{
+public:
+ typedef T Type;
+
+ inline CodeModelPointer(T *value = 0) : QAtomicPointer<T>(value) {}
+
+ inline CodeModelPointer &operator=(T *o)
+ {
+ QAtomicPointer<T>::operator=(o);
+ return *this;
+ }
+
+ inline T *data()
+ {
+ return (T *) *this;
+ }
+
+ inline const T *data() const
+ {
+ return (const T *) *this;
+ }
+
+ inline const T *constData() const
+ {
+ return (const T *) *this;
+ }
+};
+
+#endif // CODEMODEL_POINTER_H
diff --git a/parser/compiler_utils.cpp b/parser/compiler_utils.cpp
new file mode 100644
index 00000000..49624149
--- /dev/null
+++ b/parser/compiler_utils.cpp
@@ -0,0 +1,50 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+
+#include "compiler_utils.h"
+#include "type_compiler.h"
+#include "name_compiler.h"
+#include "declarator_compiler.h"
+#include "ast.h"
+#include "binder.h"
+
+TypeInfo CompilerUtils::typeDescription(TypeSpecifierAST *type_specifier, DeclaratorAST *declarator, Binder *binder)
+{
+ TypeCompiler type_cc(binder);
+ DeclaratorCompiler decl_cc(binder);
+
+ type_cc.run(type_specifier);
+ decl_cc.run(declarator);
+
+ TypeInfo typeInfo;
+ typeInfo.setQualifiedName(type_cc.qualifiedName());
+ typeInfo.setConstant(type_cc.isConstant());
+ typeInfo.setVolatile(type_cc.isVolatile());
+ typeInfo.setReference(decl_cc.isReference());
+ typeInfo.setIndirections(decl_cc.indirection());
+ typeInfo.setArrayElements(decl_cc.arrayElements());
+
+ return typeInfo;
+}
diff --git a/parser/compiler_utils.h b/parser/compiler_utils.h
new file mode 100644
index 00000000..fdd96f15
--- /dev/null
+++ b/parser/compiler_utils.h
@@ -0,0 +1,47 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+
+#ifndef COMPILER_UTILS_H
+#define COMPILER_UTILS_H
+
+#include <utility>
+
+#include "codemodel.h"
+
+class QString;
+class QStringList;
+struct TypeSpecifierAST;
+struct DeclaratorAST;
+class TokenStream;
+class Binder;
+
+namespace CompilerUtils
+{
+
+TypeInfo typeDescription(TypeSpecifierAST *type_specifier, DeclaratorAST *declarator, Binder *binder);
+
+} // namespace CompilerUtils
+
+#endif // COMPILER_UTILS_H
diff --git a/parser/control.cpp b/parser/control.cpp
new file mode 100644
index 00000000..9615debb
--- /dev/null
+++ b/parser/control.cpp
@@ -0,0 +1,130 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+
+#include "control.h"
+#include "lexer.h"
+
+Control::Control()
+ : current_context(0),
+ _M_skipFunctionBody(false),
+ _M_lexer(0),
+ _M_parser(0)
+{
+ pushContext();
+
+ declareTypedef(findOrInsertName("__builtin_va_list",
+ strlen("__builtin_va_list")), 0);
+}
+
+Control::~Control()
+{
+ popContext();
+
+ Q_ASSERT(current_context == 0);
+}
+
+Lexer *Control::changeLexer(Lexer *lexer)
+{
+ Lexer *old = _M_lexer;
+ _M_lexer = lexer;
+ return old;
+}
+
+Parser *Control::changeParser(Parser *parser)
+{
+ Parser *old = _M_parser;
+ _M_parser = parser;
+ return old;
+}
+
+Type *Control::lookupType(const NameSymbol *name) const
+{
+ Q_ASSERT(current_context != 0);
+
+ return current_context->resolve(name);
+}
+
+void Control::declare(const NameSymbol *name, Type *type)
+{
+ //printf("*** Declare:");
+ //printSymbol(name);
+ //putchar('\n');
+ Q_ASSERT(current_context != 0);
+
+ current_context->bind(name, type);
+}
+
+void Control::pushContext()
+{
+ // printf("+Context\n");
+ Context *new_context = new Context;
+ new_context->parent = current_context;
+ current_context = new_context;
+}
+
+void Control::popContext()
+{
+ // printf("-Context\n");
+ Q_ASSERT(current_context != 0);
+
+ Context *old_context = current_context;
+ current_context = current_context->parent;
+
+ delete old_context;
+}
+
+void Control::declareTypedef(const NameSymbol *name, Declarator *d)
+{
+ // printf("declared typedef:");
+ // printSymbol(name);
+ // printf("\n");
+ stl_typedef_table.insert(name, d);
+}
+
+bool Control::isTypedef(const NameSymbol *name) const
+{
+ // printf("is typedef:");
+ // printSymbol(name);
+ // printf("= %d\n", (stl_typedef_table.find(name) != stl_typedef_table.end()));
+
+ return stl_typedef_table.contains(name);
+}
+
+QList<Control::ErrorMessage> Control::errorMessages() const
+{
+ return _M_error_messages;
+}
+
+void Control::clearErrorMessages()
+{
+ _M_error_messages.clear();
+}
+
+void Control::reportError(const ErrorMessage &errmsg)
+{
+ _M_error_messages.append(errmsg);
+}
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/control.h b/parser/control.h
new file mode 100644
index 00000000..533db912
--- /dev/null
+++ b/parser/control.h
@@ -0,0 +1,160 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+
+#ifndef CONTROL_H
+#define CONTROL_H
+
+#include "symbol.h"
+#include "smallobject.h"
+
+#include <QtCore/QHash>
+
+struct Declarator;
+struct Type;
+class Lexer;
+class Parser;
+
+struct Context {
+ Context *parent;
+
+ inline void bind(const NameSymbol *name, Type *type) {
+ symbol_table.insert(name, type);
+ }
+
+ inline Type *resolve(const NameSymbol *name) const {
+ if (Type *type = symbol_table.value(name))
+ return type;
+ else if (parent)
+ return parent->resolve(name);
+
+ return 0;
+ }
+
+ typedef QHash<const NameSymbol*, Type*> symbol_table_t;
+
+ symbol_table_t symbol_table;
+};
+
+class Control
+{
+public:
+ class ErrorMessage
+ {
+ public:
+ ErrorMessage():
+ _M_line(0),
+ _M_column(0) {}
+
+ inline int line() const {
+ return _M_line;
+ }
+ inline void setLine(int line) {
+ _M_line = line;
+ }
+
+ inline int column() const {
+ return _M_column;
+ }
+ inline void setColumn(int column) {
+ _M_column = column;
+ }
+
+ inline QString fileName() const {
+ return _M_fileName;
+ }
+ inline void setFileName(const QString &fileName) {
+ _M_fileName = fileName;
+ }
+
+ inline QString message() const {
+ return _M_message;
+ }
+ inline void setMessage(const QString &message) {
+ _M_message = message;
+ }
+
+ private:
+ int _M_line;
+ int _M_column;
+ QString _M_fileName;
+ QString _M_message;
+ };
+
+ Control();
+ ~Control();
+
+ inline bool skipFunctionBody() const {
+ return _M_skipFunctionBody;
+ }
+ inline void setSkipFunctionBody(bool skip) {
+ _M_skipFunctionBody = skip;
+ }
+
+ Lexer *changeLexer(Lexer *lexer);
+ Parser *changeParser(Parser *parser);
+
+ Lexer *currentLexer() const {
+ return _M_lexer;
+ }
+ Parser *currentParser() const {
+ return _M_parser;
+ }
+
+ Context *current_context;
+
+ inline Context *currentContext() const {
+ return current_context;
+ }
+
+ void pushContext();
+ void popContext();
+
+ Type *lookupType(const NameSymbol *name) const;
+ void declare(const NameSymbol *name, Type *type);
+
+ inline const NameSymbol *findOrInsertName(const char *data, size_t count) {
+ return name_table.findOrInsert(data, count);
+ }
+
+ void declareTypedef(const NameSymbol *name, Declarator *d);
+ bool isTypedef(const NameSymbol *name) const;
+
+ void reportError(const ErrorMessage &errmsg);
+ QList<ErrorMessage> errorMessages() const;
+ void clearErrorMessages();
+
+private:
+ NameTable name_table;
+ QHash<const NameSymbol*, Declarator*> stl_typedef_table;
+ bool _M_skipFunctionBody;
+ Lexer *_M_lexer;
+ Parser *_M_parser;
+
+ QList<ErrorMessage> _M_error_messages;
+};
+
+#endif // CONTROL_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/declarator_compiler.cpp b/parser/declarator_compiler.cpp
new file mode 100644
index 00000000..255bfcdd
--- /dev/null
+++ b/parser/declarator_compiler.cpp
@@ -0,0 +1,147 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+
+#include "declarator_compiler.h"
+#include "name_compiler.h"
+#include "type_compiler.h"
+#include "compiler_utils.h"
+#include "lexer.h"
+#include "binder.h"
+#include "tokens.h"
+
+#include <qdebug.h>
+
+DeclaratorCompiler::DeclaratorCompiler(Binder *binder)
+ : _M_binder(binder), _M_token_stream(binder->tokenStream())
+{
+}
+
+void DeclaratorCompiler::run(DeclaratorAST *node)
+{
+ _M_id.clear();
+ _M_parameters.clear();
+ _M_array.clear();
+ _M_function = false;
+ _M_reference = false;
+ _M_variadics = false;
+ _M_indirection = 0;
+
+ if (node) {
+ NameCompiler name_cc(_M_binder);
+
+ DeclaratorAST *decl = node;
+ while (decl && decl->sub_declarator)
+ decl = decl->sub_declarator;
+
+ Q_ASSERT(decl != 0);
+
+ name_cc.run(decl->id);
+ _M_id = name_cc.name();
+ _M_function = (node->parameter_declaration_clause != 0);
+ if (node->parameter_declaration_clause && node->parameter_declaration_clause->ellipsis)
+ _M_variadics = true;
+
+ visitNodes(this, node->ptr_ops);
+ visit(node->parameter_declaration_clause);
+
+ if (const ListNode<ExpressionAST*> *it = node->array_dimensions) {
+ it->toFront();
+ const ListNode<ExpressionAST*> *end = it;
+
+ do {
+ QString elt;
+ if (ExpressionAST *expr = it->element) {
+ const Token &start_token = _M_token_stream->token((int) expr->start_token);
+ const Token &end_token = _M_token_stream->token((int) expr->end_token);
+
+ elt += QString::fromUtf8(&start_token.text[start_token.position],
+ (int)(end_token.position - start_token.position)).trimmed();
+ }
+
+ _M_array.append(elt);
+
+ it = it->next;
+ } while (it != end);
+ }
+ }
+}
+
+void DeclaratorCompiler::visitPtrOperator(PtrOperatorAST *node)
+{
+ std::size_t op = _M_token_stream->kind(node->op);
+
+ switch (op) {
+ case '&':
+ _M_reference = true;
+ break;
+ case '*':
+ ++_M_indirection;
+ break;
+
+ default:
+ break;
+ }
+
+ if (node->mem_ptr) {
+#if defined(__GNUC__)
+#warning "ptr to mem -- not implemented"
+#endif
+ }
+}
+
+void DeclaratorCompiler::visitParameterDeclaration(ParameterDeclarationAST *node)
+{
+ Parameter p;
+
+ TypeCompiler type_cc(_M_binder);
+ DeclaratorCompiler decl_cc(_M_binder);
+
+ decl_cc.run(node->declarator);
+
+ p.name = decl_cc.id();
+ p.type = CompilerUtils::typeDescription(node->type_specifier, node->declarator, _M_binder);
+ if (node->expression != 0) {
+ const Token &start = _M_token_stream->token((int) node->expression->start_token);
+ const Token &end = _M_token_stream->token((int) node->expression->end_token);
+ int length = (int)(end.position - start.position);
+
+ p.defaultValueExpression = QString();
+ QString source = QString::fromUtf8(&start.text[start.position], length).trimmed();
+ QStringList list = source.split("\n");
+
+
+ for (int i = 0; i < list.size(); ++i) {
+ if (!list.at(i).startsWith("#"))
+ p.defaultValueExpression += list.at(i).trimmed();
+ }
+
+ p.defaultValue = p.defaultValueExpression.size() > 0;
+
+ }
+
+ _M_parameters.append(p);
+}
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/declarator_compiler.h b/parser/declarator_compiler.h
new file mode 100644
index 00000000..70a65b05
--- /dev/null
+++ b/parser/declarator_compiler.h
@@ -0,0 +1,96 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+
+#ifndef DECLARATOR_COMPILER_H
+#define DECLARATOR_COMPILER_H
+
+#include "default_visitor.h"
+#include "codemodel.h"
+
+#include <QtCore/QString>
+#include <QtCore/QList>
+
+class TokenStream;
+class Binder;
+
+class DeclaratorCompiler: protected DefaultVisitor
+{
+public:
+ struct Parameter {
+ TypeInfo type;
+ QString name;
+ QString defaultValueExpression;
+ bool defaultValue;
+
+ Parameter(): defaultValue(false) {}
+ };
+
+public:
+ DeclaratorCompiler(Binder *binder);
+
+ void run(DeclaratorAST *node);
+
+ inline QString id() const {
+ return _M_id;
+ }
+ inline QStringList arrayElements() const {
+ return _M_array;
+ }
+ inline bool isFunction() const {
+ return _M_function;
+ }
+ inline bool isVariadics() const {
+ return _M_variadics;
+ }
+ inline bool isReference() const {
+ return _M_reference;
+ }
+ inline int indirection() const {
+ return _M_indirection;
+ }
+ inline QList<Parameter> parameters() const {
+ return _M_parameters;
+ }
+
+protected:
+ virtual void visitPtrOperator(PtrOperatorAST *node);
+ virtual void visitParameterDeclaration(ParameterDeclarationAST *node);
+
+private:
+ Binder *_M_binder;
+ TokenStream *_M_token_stream;
+
+ bool _M_function;
+ bool _M_reference;
+ bool _M_variadics;
+ int _M_indirection;
+ QString _M_id;
+ QStringList _M_array;
+ QList<Parameter> _M_parameters;
+};
+
+#endif // DECLARATOR_COMPILER_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/default_visitor.cpp b/parser/default_visitor.cpp
new file mode 100644
index 00000000..07ab968c
--- /dev/null
+++ b/parser/default_visitor.cpp
@@ -0,0 +1,459 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+
+#include "default_visitor.h"
+
+void DefaultVisitor::visitAccessSpecifier(AccessSpecifierAST *)
+{
+ // nothing to do
+}
+
+void DefaultVisitor::visitAsmDefinition(AsmDefinitionAST *)
+{
+ // nothing to do
+}
+
+void DefaultVisitor::visitBaseClause(BaseClauseAST *node)
+{
+ visitNodes(this, node->base_specifiers);
+}
+
+void DefaultVisitor::visitBaseSpecifier(BaseSpecifierAST *node)
+{
+ visit(node->name);
+}
+
+void DefaultVisitor::visitBinaryExpression(BinaryExpressionAST *node)
+{
+ visit(node->left_expression);
+ visit(node->right_expression);
+}
+
+void DefaultVisitor::visitCastExpression(CastExpressionAST *node)
+{
+ visit(node->type_id);
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitClassMemberAccess(ClassMemberAccessAST *node)
+{
+ visit(node->name);
+}
+
+void DefaultVisitor::visitClassSpecifier(ClassSpecifierAST *node)
+{
+ visit(node->win_decl_specifiers);
+ visit(node->name);
+ visit(node->base_clause);
+ visitNodes(this, node->member_specs);
+}
+
+void DefaultVisitor::visitCompoundStatement(CompoundStatementAST *node)
+{
+ visitNodes(this, node->statements);
+}
+
+void DefaultVisitor::visitCondition(ConditionAST *node)
+{
+ visit(node->type_specifier);
+ visit(node->declarator);
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitConditionalExpression(ConditionalExpressionAST *node)
+{
+ visit(node->condition);
+ visit(node->left_expression);
+ visit(node->right_expression);
+}
+
+void DefaultVisitor::visitCppCastExpression(CppCastExpressionAST *node)
+{
+ visit(node->type_id);
+ visit(node->expression);
+ visitNodes(this, node->sub_expressions);
+}
+
+void DefaultVisitor::visitCtorInitializer(CtorInitializerAST *node)
+{
+ visitNodes(this, node->member_initializers);
+}
+
+void DefaultVisitor::visitDeclarationStatement(DeclarationStatementAST *node)
+{
+ visit(node->declaration);
+}
+
+void DefaultVisitor::visitDeclarator(DeclaratorAST *node)
+{
+ visit(node->sub_declarator);
+ visitNodes(this, node->ptr_ops);
+ visit(node->id);
+ visit(node->bit_expression);
+ visitNodes(this, node->array_dimensions);
+ visit(node->parameter_declaration_clause);
+ visit(node->exception_spec);
+}
+
+void DefaultVisitor::visitDeleteExpression(DeleteExpressionAST *node)
+{
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitDoStatement(DoStatementAST *node)
+{
+ visit(node->statement);
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitElaboratedTypeSpecifier(ElaboratedTypeSpecifierAST *node)
+{
+ visit(node->name);
+}
+
+void DefaultVisitor::visitEnumSpecifier(EnumSpecifierAST *node)
+{
+ visit(node->name);
+ visitNodes(this, node->enumerators);
+}
+
+void DefaultVisitor::visitEnumerator(EnumeratorAST *node)
+{
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitExceptionSpecification(ExceptionSpecificationAST *node)
+{
+ visitNodes(this, node->type_ids);
+}
+
+void DefaultVisitor::visitExpressionOrDeclarationStatement(ExpressionOrDeclarationStatementAST *node)
+{
+ visit(node->expression);
+ visit(node->declaration);
+}
+
+void DefaultVisitor::visitExpressionStatement(ExpressionStatementAST *node)
+{
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitForStatement(ForStatementAST *node)
+{
+ visit(node->init_statement);
+ visit(node->condition);
+ visit(node->expression);
+ visit(node->statement);
+}
+
+void DefaultVisitor::visitFunctionCall(FunctionCallAST *node)
+{
+ visit(node->arguments);
+}
+
+void DefaultVisitor::visitFunctionDefinition(FunctionDefinitionAST *node)
+{
+ visit(node->type_specifier);
+ visit(node->init_declarator);
+ visit(node->function_body);
+ visit(node->win_decl_specifiers);
+}
+
+void DefaultVisitor::visitIfStatement(IfStatementAST *node)
+{
+ visit(node->condition);
+ visit(node->statement);
+ visit(node->else_statement);
+}
+
+void DefaultVisitor::visitIncrDecrExpression(IncrDecrExpressionAST *)
+{
+ // nothing to do
+}
+
+void DefaultVisitor::visitInitDeclarator(InitDeclaratorAST *node)
+{
+ visit(node->declarator);
+ visit(node->initializer);
+}
+
+void DefaultVisitor::visitInitializer(InitializerAST *node)
+{
+ visit(node->initializer_clause);
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitInitializerClause(InitializerClauseAST *node)
+{
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitLabeledStatement(LabeledStatementAST *)
+{
+ // nothing to do
+}
+
+void DefaultVisitor::visitLinkageBody(LinkageBodyAST *node)
+{
+ visitNodes(this, node->declarations);
+}
+
+void DefaultVisitor::visitLinkageSpecification(LinkageSpecificationAST *node)
+{
+ visit(node->linkage_body);
+ visit(node->declaration);
+}
+
+void DefaultVisitor::visitMemInitializer(MemInitializerAST *node)
+{
+ visit(node->initializer_id);
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitName(NameAST *node)
+{
+ visitNodes(this, node->qualified_names);
+ visit(node->unqualified_name);
+}
+
+void DefaultVisitor::visitNamespace(NamespaceAST *node)
+{
+ visit(node->linkage_body);
+}
+
+void DefaultVisitor::visitNamespaceAliasDefinition(NamespaceAliasDefinitionAST *node)
+{
+ visit(node->alias_name);
+}
+
+void DefaultVisitor::visitNewDeclarator(NewDeclaratorAST *node)
+{
+ visit(node->ptr_op);
+ visit(node->sub_declarator);
+ visitNodes(this, node->expressions);
+}
+
+void DefaultVisitor::visitNewExpression(NewExpressionAST *node)
+{
+ visit(node->expression);
+ visit(node->type_id);
+ visit(node->new_type_id);
+ visit(node->new_initializer);
+}
+
+void DefaultVisitor::visitNewInitializer(NewInitializerAST *node)
+{
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitNewTypeId(NewTypeIdAST *node)
+{
+ visit(node->type_specifier);
+ visit(node->new_initializer);
+ visit(node->new_declarator);
+}
+
+void DefaultVisitor::visitOperator(OperatorAST *)
+{
+ // nothing to do
+}
+
+void DefaultVisitor::visitOperatorFunctionId(OperatorFunctionIdAST *node)
+{
+ visit(node->op);
+ visit(node->type_specifier);
+ visitNodes(this, node->ptr_ops);
+}
+
+void DefaultVisitor::visitParameterDeclaration(ParameterDeclarationAST *node)
+{
+ visit(node->type_specifier);
+ visit(node->declarator);
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitParameterDeclarationClause(ParameterDeclarationClauseAST *node)
+{
+ visitNodes(this, node->parameter_declarations);
+}
+
+void DefaultVisitor::visitPostfixExpression(PostfixExpressionAST *node)
+{
+ visit(node->type_specifier);
+ visit(node->expression);
+ visitNodes(this, node->sub_expressions);
+}
+
+void DefaultVisitor::visitPrimaryExpression(PrimaryExpressionAST *node)
+{
+ visit(node->literal);
+ visit(node->expression_statement);
+ visit(node->sub_expression);
+ visit(node->name);
+}
+
+void DefaultVisitor::visitPtrOperator(PtrOperatorAST *node)
+{
+ visit(node->mem_ptr);
+}
+
+void DefaultVisitor::visitPtrToMember(PtrToMemberAST *)
+{
+ // nothing to do
+}
+
+void DefaultVisitor::visitReturnStatement(ReturnStatementAST *node)
+{
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitSimpleDeclaration(SimpleDeclarationAST *node)
+{
+ visit(node->type_specifier);
+ visitNodes(this, node->init_declarators);
+ visit(node->win_decl_specifiers);
+}
+
+void DefaultVisitor::visitSimpleTypeSpecifier(SimpleTypeSpecifierAST *node)
+{
+ visit(node->name);
+ visit(node->type_id);
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitSizeofExpression(SizeofExpressionAST *node)
+{
+ visit(node->type_id);
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitStringLiteral(StringLiteralAST *)
+{
+ // nothing to do
+}
+
+void DefaultVisitor::visitSubscriptExpression(SubscriptExpressionAST *node)
+{
+ visit(node->subscript);
+}
+
+void DefaultVisitor::visitSwitchStatement(SwitchStatementAST *node)
+{
+ visit(node->condition);
+ visit(node->statement);
+}
+
+void DefaultVisitor::visitTemplateArgument(TemplateArgumentAST *node)
+{
+ visit(node->type_id);
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitTemplateDeclaration(TemplateDeclarationAST *node)
+{
+ visitNodes(this, node->template_parameters);
+ visit(node->declaration);
+}
+
+void DefaultVisitor::visitTemplateParameter(TemplateParameterAST *node)
+{
+ visit(node->type_parameter);
+ visit(node->parameter_declaration);
+}
+
+void DefaultVisitor::visitThrowExpression(ThrowExpressionAST *node)
+{
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitTranslationUnit(TranslationUnitAST *node)
+{
+ visitNodes(this, node->declarations);
+}
+
+void DefaultVisitor::visitTryBlockStatement(TryBlockStatementAST *)
+{
+ // nothing to do
+}
+
+void DefaultVisitor::visitTypeId(TypeIdAST *node)
+{
+ visit(node->type_specifier);
+ visit(node->declarator);
+}
+
+void DefaultVisitor::visitTypeIdentification(TypeIdentificationAST *node)
+{
+ visit(node->name);
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitTypeParameter(TypeParameterAST *node)
+{
+ visit(node->name);
+ visit(node->type_id);
+ visitNodes(this, node->template_parameters);
+ visit(node->template_name);
+}
+
+void DefaultVisitor::visitTypedef(TypedefAST *node)
+{
+ visit(node->type_specifier);
+ visitNodes(this, node->init_declarators);
+}
+
+void DefaultVisitor::visitUnaryExpression(UnaryExpressionAST *node)
+{
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitUnqualifiedName(UnqualifiedNameAST *node)
+{
+ visit(node->operator_id);
+ visitNodes(this, node->template_arguments);
+}
+
+void DefaultVisitor::visitUsing(UsingAST *node)
+{
+ visit(node->name);
+}
+
+void DefaultVisitor::visitUsingDirective(UsingDirectiveAST *node)
+{
+ visit(node->name);
+}
+
+void DefaultVisitor::visitWhileStatement(WhileStatementAST *node)
+{
+ visit(node->condition);
+ visit(node->statement);
+}
+
+void DefaultVisitor::visitWinDeclSpec(WinDeclSpecAST *)
+{
+ // nothing to do
+}
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/default_visitor.h b/parser/default_visitor.h
new file mode 100644
index 00000000..ec1caf3b
--- /dev/null
+++ b/parser/default_visitor.h
@@ -0,0 +1,118 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+
+#ifndef DEFAULT_VISITOR_H
+#define DEFAULT_VISITOR_H
+
+#include "visitor.h"
+
+class DefaultVisitor: public Visitor
+{
+public:
+ DefaultVisitor() {}
+
+protected:
+ virtual void visitAccessSpecifier(AccessSpecifierAST *);
+ virtual void visitAsmDefinition(AsmDefinitionAST *);
+ virtual void visitBaseClause(BaseClauseAST *);
+ virtual void visitBaseSpecifier(BaseSpecifierAST *);
+ virtual void visitBinaryExpression(BinaryExpressionAST *);
+ virtual void visitCastExpression(CastExpressionAST *);
+ virtual void visitClassMemberAccess(ClassMemberAccessAST *);
+ virtual void visitClassSpecifier(ClassSpecifierAST *);
+ virtual void visitCompoundStatement(CompoundStatementAST *);
+ virtual void visitCondition(ConditionAST *);
+ virtual void visitConditionalExpression(ConditionalExpressionAST *);
+ virtual void visitCppCastExpression(CppCastExpressionAST *);
+ virtual void visitCtorInitializer(CtorInitializerAST *);
+ virtual void visitDeclarationStatement(DeclarationStatementAST *);
+ virtual void visitDeclarator(DeclaratorAST *);
+ virtual void visitDeleteExpression(DeleteExpressionAST *);
+ virtual void visitDoStatement(DoStatementAST *);
+ virtual void visitElaboratedTypeSpecifier(ElaboratedTypeSpecifierAST *);
+ virtual void visitEnumSpecifier(EnumSpecifierAST *);
+ virtual void visitEnumerator(EnumeratorAST *);
+ virtual void visitExceptionSpecification(ExceptionSpecificationAST *);
+ virtual void visitExpressionOrDeclarationStatement(ExpressionOrDeclarationStatementAST *);
+ virtual void visitExpressionStatement(ExpressionStatementAST *);
+ virtual void visitForStatement(ForStatementAST *);
+ virtual void visitFunctionCall(FunctionCallAST *);
+ virtual void visitFunctionDefinition(FunctionDefinitionAST *);
+ virtual void visitIfStatement(IfStatementAST *);
+ virtual void visitIncrDecrExpression(IncrDecrExpressionAST *);
+ virtual void visitInitDeclarator(InitDeclaratorAST *);
+ virtual void visitInitializer(InitializerAST *);
+ virtual void visitInitializerClause(InitializerClauseAST *);
+ virtual void visitLabeledStatement(LabeledStatementAST *);
+ virtual void visitLinkageBody(LinkageBodyAST *);
+ virtual void visitLinkageSpecification(LinkageSpecificationAST *);
+ virtual void visitMemInitializer(MemInitializerAST *);
+ virtual void visitName(NameAST *);
+ virtual void visitNamespace(NamespaceAST *);
+ virtual void visitNamespaceAliasDefinition(NamespaceAliasDefinitionAST *);
+ virtual void visitNewDeclarator(NewDeclaratorAST *);
+ virtual void visitNewExpression(NewExpressionAST *);
+ virtual void visitNewInitializer(NewInitializerAST *);
+ virtual void visitNewTypeId(NewTypeIdAST *);
+ virtual void visitOperator(OperatorAST *);
+ virtual void visitOperatorFunctionId(OperatorFunctionIdAST *);
+ virtual void visitParameterDeclaration(ParameterDeclarationAST *);
+ virtual void visitParameterDeclarationClause(ParameterDeclarationClauseAST *);
+ virtual void visitPostfixExpression(PostfixExpressionAST *);
+ virtual void visitPrimaryExpression(PrimaryExpressionAST *);
+ virtual void visitPtrOperator(PtrOperatorAST *);
+ virtual void visitPtrToMember(PtrToMemberAST *);
+ virtual void visitReturnStatement(ReturnStatementAST *);
+ virtual void visitSimpleDeclaration(SimpleDeclarationAST *);
+ virtual void visitSimpleTypeSpecifier(SimpleTypeSpecifierAST *);
+ virtual void visitSizeofExpression(SizeofExpressionAST *);
+ virtual void visitStringLiteral(StringLiteralAST *);
+ virtual void visitSubscriptExpression(SubscriptExpressionAST *);
+ virtual void visitSwitchStatement(SwitchStatementAST *);
+ virtual void visitTemplateArgument(TemplateArgumentAST *);
+ virtual void visitTemplateDeclaration(TemplateDeclarationAST *);
+ virtual void visitTemplateParameter(TemplateParameterAST *);
+ virtual void visitThrowExpression(ThrowExpressionAST *);
+ virtual void visitTranslationUnit(TranslationUnitAST *);
+ virtual void visitTryBlockStatement(TryBlockStatementAST *);
+ virtual void visitTypeId(TypeIdAST *);
+ virtual void visitTypeIdentification(TypeIdentificationAST *);
+ virtual void visitTypeParameter(TypeParameterAST *);
+ virtual void visitTypedef(TypedefAST *);
+ virtual void visitUnaryExpression(UnaryExpressionAST *);
+ virtual void visitUnqualifiedName(UnqualifiedNameAST *);
+ virtual void visitUsing(UsingAST *);
+ virtual void visitUsingDirective(UsingDirectiveAST *);
+ virtual void visitWhileStatement(WhileStatementAST *);
+ virtual void visitWinDeclSpec(WinDeclSpecAST *);
+
+private:
+ typedef void (Visitor::*visitor_fun_ptr)(AST *);
+ static visitor_fun_ptr _S_table[];
+};
+
+#endif // VISITOR_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/dumptree.cpp b/parser/dumptree.cpp
new file mode 100644
index 00000000..1514b0f6
--- /dev/null
+++ b/parser/dumptree.cpp
@@ -0,0 +1,125 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+
+#include "dumptree.h"
+
+#include <QtCore/QString>
+#include <QtCore/qdebug.h>
+
+static char const * const names[] = {
+ 0,
+ "AccessSpecifier",
+ "AsmDefinition",
+ "BaseClause",
+ "BaseSpecifier",
+ "BinaryExpression",
+ "CastExpression",
+ "ClassMemberAccess",
+ "ClassSpecifier",
+ "CompoundStatement",
+ "Condition",
+ "ConditionalExpression",
+ "CppCastExpression",
+ "CtorInitializer",
+ "DeclarationStatement",
+ "Declarator",
+ "DeleteExpression",
+ "DoStatement",
+ "ElaboratedTypeSpecifier",
+ "EnumSpecifier",
+ "Enumerator",
+ "ExceptionSpecification",
+ "ExpressionOrDeclarationStatement",
+ "ExpressionStatement",
+ "ForStatement",
+ "FunctionCall",
+ "FunctionDefinition",
+ "IfStatement",
+ "IncrDecrExpression",
+ "InitDeclarator",
+ "Initializer",
+ "InitializerClause",
+ "LabeledStatement",
+ "LinkageBody",
+ "LinkageSpecification",
+ "MemInitializer",
+ "Name",
+ "Namespace",
+ "NamespaceAliasDefinition",
+ "NewDeclarator",
+ "NewExpression",
+ "NewInitializer",
+ "NewTypeId",
+ "Operator",
+ "OperatorFunctionId",
+ "ParameterDeclaration",
+ "ParameterDeclarationClause",
+ "PostfixExpression",
+ "PrimaryExpression",
+ "PtrOperator",
+ "PtrToMember",
+ "ReturnStatement",
+ "SimpleDeclaration",
+ "SimpleTypeSpecifier",
+ "SizeofExpression",
+ "StringLiteral",
+ "SubscriptExpression",
+ "SwitchStatement",
+ "TemplateArgument",
+ "TemplateDeclaration",
+ "TemplateParameter",
+ "ThrowExpression",
+ "TranslationUnit",
+ "TryBlockStatement",
+ "TypeId",
+ "TypeIdentification",
+ "TypeParameter",
+ "Typedef",
+ "UnaryExpression",
+ "UnqualifiedName",
+ "Using",
+ "UsingDirective",
+ "WhileStatement",
+ "WinDeclSpec"
+};
+
+DumpTree::DumpTree()
+{
+}
+
+void DumpTree::visit(AST *node)
+{
+ static int indent = 0;
+
+ if (node)
+ qDebug() << QString(indent * 2, ' ').toLatin1().constData() << names[node->kind]
+ << '[' << node->start_token << ", " << node->end_token << ']';
+
+ ++indent;
+ DefaultVisitor::visit(node);
+ --indent;
+}
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/dumptree.h b/parser/dumptree.h
new file mode 100644
index 00000000..cfc55e2e
--- /dev/null
+++ b/parser/dumptree.h
@@ -0,0 +1,46 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+
+#ifndef DUMPTREE_H
+#define DUMPTREE_H
+
+#include "default_visitor.h"
+
+class DumpTree: protected DefaultVisitor
+{
+public:
+ DumpTree();
+
+ void dump(AST *node) {
+ visit(node);
+ }
+
+protected:
+ virtual void visit(AST *node);
+};
+
+#endif // DUMPTREE_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/lexer.cpp b/parser/lexer.cpp
new file mode 100644
index 00000000..2abb540d
--- /dev/null
+++ b/parser/lexer.cpp
@@ -0,0 +1,1695 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+
+#include "lexer.h"
+#include "tokens.h"
+#include "control.h"
+
+#include <cctype>
+#include <iostream>
+
+scan_fun_ptr Lexer::s_scan_keyword_table[] = {
+ &Lexer::scanKeyword0, &Lexer::scanKeyword0,
+ &Lexer::scanKeyword2, &Lexer::scanKeyword3,
+ &Lexer::scanKeyword4, &Lexer::scanKeyword5,
+ &Lexer::scanKeyword6, &Lexer::scanKeyword7,
+ &Lexer::scanKeyword8, &Lexer::scanKeyword9,
+ &Lexer::scanKeyword10, &Lexer::scanKeyword11,
+ &Lexer::scanKeyword12, &Lexer::scanKeyword13,
+ &Lexer::scanKeyword14, &Lexer::scanKeyword0,
+ &Lexer::scanKeyword16
+};
+
+void LocationManager::extract_line(int offset, int *line, QString *filename) const
+{
+ *line = 0;
+ if (token_stream.size() < 1)
+ return;
+
+ const unsigned char *begin_buffer = reinterpret_cast<const unsigned char *>(token_stream[0].text);
+ const unsigned char *cursor = begin_buffer + offset;
+
+ ++cursor; // skip '#'
+ if (std::isspace(*cursor) && std::isdigit(*(cursor + 1))) {
+ ++cursor;
+ char buffer[1024], *cp = buffer;
+ do {
+ *cp++ = *cursor++;
+ } while (std::isdigit(*cursor));
+ *cp = '\0';
+ int l = strtol(buffer, 0, 0);
+
+ Q_ASSERT(std::isspace(*cursor));
+ ++cursor;
+
+ Q_ASSERT(*cursor == '"');
+ ++cursor;
+
+ cp = buffer;
+ while (*cursor && *cursor != '"') {
+ *cp++ = *cursor++;
+ }
+ *cp = '\0';
+ Q_ASSERT(*cursor == '"');
+ ++cursor;
+
+ *filename = buffer;
+ *line = l;
+ // printf("filename: %s line: %d\n", buffer, line);
+ }
+}
+
+void LocationManager::positionAt(std::size_t offset, int *line, int *column,
+ QString *filename) const
+{
+ int ppline, ppcolumn;
+ line_table.positionAt(offset, &ppline, &ppcolumn);
+
+ int base_line;
+ extract_line((int) line_table[ppline-1], &base_line, filename);
+
+ int line2, column2;
+ location_table.positionAt((int) line_table[ppline-1], &line2, &column2);
+
+ location_table.positionAt(offset, line, column);
+ *line = base_line + *line - line2 - 1;
+}
+
+scan_fun_ptr Lexer::s_scan_table[256];
+bool Lexer::s_initialized = false;
+
+void Lexer::tokenize(const char *contents, std::size_t size)
+{
+ if (!s_initialized)
+ initialize_scan_table();
+
+ token_stream.resize(1024);
+ token_stream[0].kind = Token_EOF;
+ token_stream[0].text = contents;
+
+ index = 1;
+
+ cursor = (const unsigned char *) contents;
+ begin_buffer = (const unsigned char *) contents;
+ end_buffer = cursor + size;
+
+ location_table.resize(1024);
+ location_table[0] = 0;
+ location_table.current_line = 1;
+
+ line_table.resize(1024);
+ line_table[0] = 0;
+ line_table.current_line = 1;
+
+ do {
+ if (index == token_stream.size())
+ token_stream.resize(token_stream.size() * 2);
+
+ Token *current_token = &token_stream[(int) index];
+ current_token->text = reinterpret_cast<const char*>(begin_buffer);
+ current_token->position = cursor - begin_buffer;
+ (this->*s_scan_table[*cursor])();
+ current_token->size = cursor - begin_buffer - current_token->position;
+ } while (cursor < end_buffer);
+
+ if (index == token_stream.size())
+ token_stream.resize(token_stream.size() * 2);
+
+ Q_ASSERT(index < token_stream.size());
+ token_stream[(int) index].position = cursor - begin_buffer;
+ token_stream[(int) index].kind = Token_EOF;
+}
+
+void Lexer::reportError(const QString& msg)
+{
+ int line, column;
+ QString fileName;
+
+ std::size_t tok = token_stream.cursor();
+ _M_location.positionAt(token_stream.position(tok),
+ &line, &column, &fileName);
+
+ Control::ErrorMessage errmsg;
+ errmsg.setLine(line + 1);
+ errmsg.setColumn(column);
+ errmsg.setFileName(fileName);
+ errmsg.setMessage(QLatin1String("** LEXER ERROR ") + msg);
+ control->reportError(errmsg);
+}
+
+void Lexer::initialize_scan_table()
+{
+ s_initialized = true;
+
+ for (int i = 0; i < 256; ++i) {
+ if (isspace(i))
+ s_scan_table[i] = &Lexer::scan_white_spaces;
+ else if (isalpha(i) || i == '_')
+ s_scan_table[i] = &Lexer::scan_identifier_or_keyword;
+ else if (isdigit(i))
+ s_scan_table[i] = &Lexer::scan_int_constant;
+ else
+ s_scan_table[i] = &Lexer::scan_invalid_input;
+ }
+
+ s_scan_table[int('L')] = &Lexer::scan_identifier_or_literal;
+ s_scan_table[int('\n')] = &Lexer::scan_newline;
+ s_scan_table[int('#')] = &Lexer::scan_preprocessor;
+
+ s_scan_table[int('\'')] = &Lexer::scan_char_constant;
+ s_scan_table[int('"')] = &Lexer::scan_string_constant;
+
+ s_scan_table[int('.')] = &Lexer::scan_int_constant;
+
+ s_scan_table[int('!')] = &Lexer::scan_not;
+ s_scan_table[int('%')] = &Lexer::scan_remainder;
+ s_scan_table[int('&')] = &Lexer::scan_and;
+ s_scan_table[int('(')] = &Lexer::scan_left_paren;
+ s_scan_table[int(')')] = &Lexer::scan_right_paren;
+ s_scan_table[int('*')] = &Lexer::scan_star;
+ s_scan_table[int('+')] = &Lexer::scan_plus;
+ s_scan_table[int(',')] = &Lexer::scan_comma;
+ s_scan_table[int('-')] = &Lexer::scan_minus;
+ s_scan_table[int('/')] = &Lexer::scan_divide;
+ s_scan_table[int(':')] = &Lexer::scan_colon;
+ s_scan_table[int(';')] = &Lexer::scan_semicolon;
+ s_scan_table[int('<')] = &Lexer::scan_less;
+ s_scan_table[int('=')] = &Lexer::scan_equal;
+ s_scan_table[int('>')] = &Lexer::scan_greater;
+ s_scan_table[int('?')] = &Lexer::scan_question;
+ s_scan_table[int('[')] = &Lexer::scan_left_bracket;
+ s_scan_table[int(']')] = &Lexer::scan_right_bracket;
+ s_scan_table[int('^')] = &Lexer::scan_xor;
+ s_scan_table[int('{')] = &Lexer::scan_left_brace;
+ s_scan_table[int('|')] = &Lexer::scan_or;
+ s_scan_table[int('}')] = &Lexer::scan_right_brace;
+ s_scan_table[int('~')] = &Lexer::scan_tilde;
+
+ s_scan_table[0] = &Lexer::scan_EOF;
+}
+
+void Lexer::scan_preprocessor()
+{
+ if (line_table.current_line == line_table.size())
+ line_table.resize(line_table.current_line * 2);
+
+ line_table[(int) line_table.current_line++] = (cursor - begin_buffer);
+
+ while (*cursor && *cursor != '\n')
+ ++cursor;
+
+ if (*cursor != '\n')
+ reportError("expected newline");
+}
+
+void Lexer::scan_char_constant()
+{
+ const unsigned char *begin = cursor;
+
+ ++cursor;
+ while (*cursor && *cursor != '\'') {
+ if (*cursor == '\n')
+ reportError("did not expect newline");
+
+ if (*cursor == '\\')
+ ++cursor;
+ ++cursor;
+ }
+
+ if (*cursor != '\'')
+ reportError("expected \'");
+
+ ++cursor;
+
+ token_stream[(int) index].extra.symbol =
+ control->findOrInsertName((const char*) begin, cursor - begin);
+
+ token_stream[(int) index++].kind = Token_char_literal;
+}
+
+void Lexer::scan_string_constant()
+{
+ const unsigned char *begin = cursor;
+
+ ++cursor;
+ while (*cursor && *cursor != '"') {
+ if (*cursor == '\n')
+ reportError("did not expect newline");
+
+ if (*cursor == '\\')
+ ++cursor;
+ ++cursor;
+ }
+
+ if (*cursor != '"')
+ reportError("expected \"");
+
+ ++cursor;
+
+ token_stream[(int) index].extra.symbol =
+ control->findOrInsertName((const char*) begin, cursor - begin);
+
+ token_stream[(int) index++].kind = Token_string_literal;
+}
+
+void Lexer::scan_newline()
+{
+ if (location_table.current_line == location_table.size())
+ location_table.resize(location_table.current_line * 2);
+
+ location_table[(int) location_table.current_line++] = (cursor - begin_buffer);
+ ++cursor;
+}
+
+void Lexer::scan_white_spaces()
+{
+ while (isspace(*cursor)) {
+ if (*cursor == '\n')
+ scan_newline();
+ else
+ ++cursor;
+ }
+}
+
+void Lexer::scan_identifier_or_literal()
+{
+ switch (*(cursor + 1)) {
+ case '\'':
+ ++cursor;
+ scan_char_constant();
+ break;
+
+ case '\"':
+ ++cursor;
+ scan_string_constant();
+ break;
+
+ default:
+ scan_identifier_or_keyword();
+ break;
+ }
+}
+
+void Lexer::scan_identifier_or_keyword()
+{
+ const unsigned char *skip = cursor;
+ while (isalnum(*skip) || *skip == '_')
+ ++skip;
+
+ int n = skip - cursor;
+ Token *current_token = &token_stream[(int) index];
+ (this->*s_scan_keyword_table[n < 17 ? n : 0])();
+
+ if (current_token->kind == Token_identifier) {
+ current_token->extra.symbol =
+ control->findOrInsertName((const char*) cursor, n);
+ }
+
+ cursor = skip;
+}
+
+void Lexer::scan_int_constant()
+{
+ if (*cursor == '.' && !std::isdigit(*(cursor + 1))) {
+ scan_dot();
+ return;
+ }
+
+ const unsigned char *begin = cursor;
+
+ while (isalnum(*cursor) || *cursor == '.')
+ ++cursor;
+
+ token_stream[(int) index].extra.symbol =
+ control->findOrInsertName((const char*) begin, cursor - begin);
+
+ token_stream[(int) index++].kind = Token_number_literal;
+}
+
+void Lexer::scan_not()
+{
+ /*
+ '!' ::= not
+ '!=' ::= not_equal
+ */
+
+ ++cursor;
+
+ if (*cursor == '=') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_not_eq;
+ } else {
+ token_stream[(int) index++].kind = '!';
+ }
+}
+
+void Lexer::scan_remainder()
+{
+ /*
+ '%' ::= remainder
+ '%=' ::= remainder_equal
+ */
+
+ ++cursor;
+
+ if (*cursor == '=') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_assign;
+ } else {
+ token_stream[(int) index++].kind = '%';
+ }
+}
+
+void Lexer::scan_and()
+{
+ /*
+ '&&' ::= and_and
+ '&' ::= and
+ '&=' ::= and_equal
+ */
+
+ ++cursor;
+ if (*cursor == '=') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_assign;
+ } else if (*cursor == '&') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_and;
+ } else {
+ token_stream[(int) index++].kind = '&';
+ }
+}
+
+void Lexer::scan_left_paren()
+{
+ ++cursor;
+ token_stream[(int) index++].kind = '(';
+}
+
+void Lexer::scan_right_paren()
+{
+ ++cursor;
+ token_stream[(int) index++].kind = ')';
+}
+
+void Lexer::scan_star()
+{
+ /*
+ '*' ::= star
+ '*=' ::= star_equal
+ */
+
+ ++cursor;
+
+ if (*cursor == '=') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_assign;
+ } else {
+ token_stream[(int) index++].kind = '*';
+ }
+}
+
+void Lexer::scan_plus()
+{
+ /*
+ '+' ::= plus
+ '++' ::= incr
+ '+=' ::= plus_equal
+ */
+
+ ++cursor;
+ if (*cursor == '=') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_assign;
+ } else if (*cursor == '+') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_incr;
+ } else {
+ token_stream[(int) index++].kind = '+';
+ }
+}
+
+void Lexer::scan_comma()
+{
+ ++cursor;
+ token_stream[(int) index++].kind = ',';
+}
+
+void Lexer::scan_minus()
+{
+ /*
+ '-' ::= minus
+ '--' ::= decr
+ '-=' ::= minus_equal
+ '->' ::= left_arrow
+ */
+
+ ++cursor;
+ if (*cursor == '=') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_assign;
+ } else if (*cursor == '-') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_decr;
+ } else if (*cursor == '>') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_arrow;
+ if (*cursor == '*') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_ptrmem;
+ }
+ } else {
+ token_stream[(int) index++].kind = '-';
+ }
+}
+
+void Lexer::scan_dot()
+{
+ /*
+ '.' ::= dot
+ '...' ::= ellipsis
+ */
+
+ ++cursor;
+ if (*cursor == '.' && *(cursor + 1) == '.') {
+ cursor += 2;
+ token_stream[(int) index++].kind = Token_ellipsis;
+ } else if (*cursor == '.' && *(cursor + 1) == '*') {
+ cursor += 2;
+ token_stream[(int) index++].kind = Token_ptrmem;
+ } else
+ token_stream[(int) index++].kind = '.';
+}
+
+void Lexer::scan_divide()
+{
+ /*
+ '/' ::= divide
+ '/=' ::= divide_equal
+ */
+
+ ++cursor;
+
+ if (*cursor == '=') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_assign;
+ } else {
+ token_stream[(int) index++].kind = '/';
+ }
+}
+
+void Lexer::scan_colon()
+{
+ ++cursor;
+ if (*cursor == ':') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_scope;
+ } else {
+ token_stream[(int) index++].kind = ':';
+ }
+}
+
+void Lexer::scan_semicolon()
+{
+ ++cursor;
+ token_stream[(int) index++].kind = ';';
+}
+
+void Lexer::scan_less()
+{
+ /*
+ '<' ::= less
+ '<<' ::= left_shift
+ '<<=' ::= left_shift_equal
+ '<=' ::= less_equal
+ */
+
+ ++cursor;
+ if (*cursor == '=') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_leq;
+ } else if (*cursor == '<') {
+ ++cursor;
+ if (*cursor == '=') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_assign;
+ } else {
+ token_stream[(int) index++].kind = Token_shift;
+ }
+ } else {
+ token_stream[(int) index++].kind = '<';
+ }
+}
+
+void Lexer::scan_equal()
+{
+ /*
+ '=' ::= equal
+ '==' ::= equal_equal
+ */
+ ++cursor;
+
+ if (*cursor == '=') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_eq;
+ } else {
+ token_stream[(int) index++].kind = '=';
+ }
+}
+
+void Lexer::scan_greater()
+{
+ /*
+ '>' ::= greater
+ '>=' ::= greater_equal
+ '>>' ::= right_shift
+ '>>=' ::= right_shift_equal
+ */
+
+ ++cursor;
+ if (*cursor == '=') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_geq;
+ } else if (*cursor == '>') {
+ ++cursor;
+ if (*cursor == '=') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_assign;
+ } else {
+ token_stream[(int) index++].kind = Token_shift;
+ }
+ } else {
+ token_stream[(int) index++].kind = '>';
+ }
+}
+
+void Lexer::scan_question()
+{
+ ++cursor;
+ token_stream[(int) index++].kind = '?';
+}
+
+void Lexer::scan_left_bracket()
+{
+ ++cursor;
+ token_stream[(int) index++].kind = '[';
+}
+
+void Lexer::scan_right_bracket()
+{
+ ++cursor;
+ token_stream[(int) index++].kind = ']';
+}
+
+void Lexer::scan_xor()
+{
+ /*
+ '^' ::= xor
+ '^=' ::= xor_equal
+ */
+ ++cursor;
+
+ if (*cursor == '=') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_assign;
+ } else {
+ token_stream[(int) index++].kind = '^';
+ }
+}
+
+void Lexer::scan_left_brace()
+{
+ ++cursor;
+ token_stream[(int) index++].kind = '{';
+}
+
+void Lexer::scan_or()
+{
+ /*
+ '|' ::= or
+ '|=' ::= or_equal
+ '||' ::= or_or
+ */
+ ++cursor;
+ if (*cursor == '=') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_assign;
+ } else if (*cursor == '|') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_or;
+ } else {
+ token_stream[(int) index++].kind = '|';
+ }
+}
+
+void Lexer::scan_right_brace()
+{
+ ++cursor;
+ token_stream[(int) index++].kind = '}';
+}
+
+void Lexer::scan_tilde()
+{
+ ++cursor;
+ token_stream[(int) index++].kind = '~';
+}
+
+void Lexer::scan_EOF()
+{
+ ++cursor;
+ token_stream[(int) index++].kind = Token_EOF;
+}
+
+void Lexer::scan_invalid_input()
+{
+ QString errmsg("invalid input: %1");
+ errmsg.arg(int(*cursor));
+ reportError(errmsg);
+ ++cursor;
+}
+
+void LocationTable::positionAt(std::size_t offset, int max_line,
+ int *line, int *column) const
+{
+ if (!(line && column && max_line != 0))
+ return;
+
+ int first = 0;
+ int len = max_line;
+ int half;
+ int middle;
+
+ while (len > 0) {
+ half = len >> 1;
+ middle = first;
+
+ middle += half;
+
+ if (lines[middle] < offset) {
+ first = middle;
+ ++first;
+ len = len - half - 1;
+ } else
+ len = half;
+ }
+
+ *line = std::max(first, 1);
+ *column = (int)(offset - lines[*line - 1] - 1);
+
+ if (*column < 0) {
+ *column = 0;
+ }
+}
+
+void Lexer::scanKeyword0()
+{
+ token_stream[(int) index++].kind = Token_identifier;
+}
+
+void Lexer::scanKeyword2()
+{
+ switch (*cursor) {
+ case 'i':
+ if (*(cursor + 1) == 'f') {
+ token_stream[(int) index++].kind = Token_if;
+ return;
+ }
+ break;
+
+ case 'd':
+ if (*(cursor + 1) == 'o') {
+ token_stream[(int) index++].kind = Token_do;
+ return;
+ }
+ break;
+
+ case 'o':
+ if (*(cursor + 1) == 'r') {
+ token_stream[(int) index++].kind = Token_or;
+ return;
+ }
+ break;
+
+ }
+ token_stream[(int) index++].kind = Token_identifier;
+}
+
+void Lexer::scanKeyword3()
+{
+ switch (*cursor) {
+ case 'a':
+ if (*(cursor + 1) == 'n' &&
+ *(cursor + 2) == 'd') {
+ token_stream[(int) index++].kind = Token_and;
+ return;
+ }
+ if (*(cursor + 1) == 's' &&
+ *(cursor + 2) == 'm') {
+ token_stream[(int) index++].kind = Token_asm;
+ return;
+ }
+ break;
+
+ case 'f':
+ if (*(cursor + 1) == 'o' &&
+ *(cursor + 2) == 'r') {
+ token_stream[(int) index++].kind = Token_for;
+ return;
+ }
+ break;
+
+ case 'i':
+ if (*(cursor + 1) == 'n' &&
+ *(cursor + 2) == 't') {
+ token_stream[(int) index++].kind = Token_int;
+ return;
+ }
+ break;
+
+ case 'n':
+ if (*(cursor + 1) == 'e' &&
+ *(cursor + 2) == 'w') {
+ token_stream[(int) index++].kind = Token_new;
+ return;
+ }
+ if (*(cursor + 1) == 'o' &&
+ *(cursor + 2) == 't') {
+ token_stream[(int) index++].kind = Token_not;
+ return;
+ }
+ break;
+
+ case 't':
+ if (*(cursor + 1) == 'r' &&
+ *(cursor + 2) == 'y') {
+ token_stream[(int) index++].kind = Token_try;
+ return;
+ }
+ break;
+
+ case 'x':
+ if (*(cursor + 1) == 'o' &&
+ *(cursor + 2) == 'r') {
+ token_stream[(int) index++].kind = Token_xor;
+ return;
+ }
+ break;
+
+ }
+ token_stream[(int) index++].kind = Token_identifier;
+}
+
+void Lexer::scanKeyword4()
+{
+ switch (*cursor) {
+ case 'a':
+ if (*(cursor + 1) == 'u' &&
+ *(cursor + 2) == 't' &&
+ *(cursor + 3) == 'o') {
+ token_stream[(int) index++].kind = Token_auto;
+ return;
+ }
+ break;
+
+ case 'c':
+ if (*(cursor + 1) == 'a' &&
+ *(cursor + 2) == 's' &&
+ *(cursor + 3) == 'e') {
+ token_stream[(int) index++].kind = Token_case;
+ return;
+ }
+ if (*(cursor + 1) == 'h' &&
+ *(cursor + 2) == 'a' &&
+ *(cursor + 3) == 'r') {
+ token_stream[(int) index++].kind = Token_char;
+ return;
+ }
+ break;
+
+ case 'b':
+ if (*(cursor + 1) == 'o' &&
+ *(cursor + 2) == 'o' &&
+ *(cursor + 3) == 'l') {
+ token_stream[(int) index++].kind = Token_bool;
+ return;
+ }
+ break;
+
+ case 'e':
+ if (*(cursor + 1) == 'l' &&
+ *(cursor + 2) == 's' &&
+ *(cursor + 3) == 'e') {
+ token_stream[(int) index++].kind = Token_else;
+ return;
+ }
+ if (*(cursor + 1) == 'm' &&
+ *(cursor + 2) == 'i' &&
+ *(cursor + 3) == 't') {
+ token_stream[(int) index++].kind = Token_emit;
+ return;
+ }
+ if (*(cursor + 1) == 'n' &&
+ *(cursor + 2) == 'u' &&
+ *(cursor + 3) == 'm') {
+ token_stream[(int) index++].kind = Token_enum;
+ return;
+ }
+ break;
+
+ case 'g':
+ if (*(cursor + 1) == 'o' &&
+ *(cursor + 2) == 't' &&
+ *(cursor + 3) == 'o') {
+ token_stream[(int) index++].kind = Token_goto;
+ return;
+ }
+ break;
+
+ case 'l':
+ if (*(cursor + 1) == 'o' &&
+ *(cursor + 2) == 'n' &&
+ *(cursor + 3) == 'g') {
+ token_stream[(int) index++].kind = Token_long;
+ return;
+ }
+ break;
+
+ case 't':
+ if (*(cursor + 1) == 'h' &&
+ *(cursor + 2) == 'i' &&
+ *(cursor + 3) == 's') {
+ token_stream[(int) index++].kind = Token_this;
+ return;
+ }
+ break;
+
+ case 'v':
+ if (*(cursor + 1) == 'o' &&
+ *(cursor + 2) == 'i' &&
+ *(cursor + 3) == 'd') {
+ token_stream[(int) index++].kind = Token_void;
+ return;
+ }
+ break;
+
+ }
+ token_stream[(int) index++].kind = Token_identifier;
+}
+
+void Lexer::scanKeyword5()
+{
+ switch (*cursor) {
+ case 'c':
+ if (*(cursor + 1) == 'a' &&
+ *(cursor + 2) == 't' &&
+ *(cursor + 3) == 'c' &&
+ *(cursor + 4) == 'h') {
+ token_stream[(int) index++].kind = Token_catch;
+ return;
+ }
+ if (*(cursor + 1) == 'l' &&
+ *(cursor + 2) == 'a' &&
+ *(cursor + 3) == 's' &&
+ *(cursor + 4) == 's') {
+ token_stream[(int) index++].kind = Token_class;
+ return;
+ }
+ if (*(cursor + 1) == 'o' &&
+ *(cursor + 2) == 'm' &&
+ *(cursor + 3) == 'p' &&
+ *(cursor + 4) == 'l') {
+ token_stream[(int) index++].kind = Token_compl;
+ return;
+ }
+ if (*(cursor + 1) == 'o' &&
+ *(cursor + 2) == 'n' &&
+ *(cursor + 3) == 's' &&
+ *(cursor + 4) == 't') {
+ token_stream[(int) index++].kind = Token_const;
+ return;
+ }
+ break;
+
+ case 'b':
+ if (*(cursor + 1) == 'i' &&
+ *(cursor + 2) == 't' &&
+ *(cursor + 3) == 'o' &&
+ *(cursor + 4) == 'r') {
+ token_stream[(int) index++].kind = Token_bitor;
+ return;
+ }
+ if (*(cursor + 1) == 'r' &&
+ *(cursor + 2) == 'e' &&
+ *(cursor + 3) == 'a' &&
+ *(cursor + 4) == 'k') {
+ token_stream[(int) index++].kind = Token_break;
+ return;
+ }
+ break;
+
+ case 'f':
+ if (*(cursor + 1) == 'l' &&
+ *(cursor + 2) == 'o' &&
+ *(cursor + 3) == 'a' &&
+ *(cursor + 4) == 't') {
+ token_stream[(int) index++].kind = Token_float;
+ return;
+ }
+ break;
+
+ case 'o':
+ if (*(cursor + 1) == 'r' &&
+ *(cursor + 2) == '_' &&
+ *(cursor + 3) == 'e' &&
+ *(cursor + 4) == 'q') {
+ token_stream[(int) index++].kind = Token_or_eq;
+ return;
+ }
+ break;
+
+ case 's':
+ if (*(cursor + 1) == 'h' &&
+ *(cursor + 2) == 'o' &&
+ *(cursor + 3) == 'r' &&
+ *(cursor + 4) == 't') {
+ token_stream[(int) index++].kind = Token_short;
+ return;
+ }
+ if (*(cursor + 1) == 'l' &&
+ *(cursor + 2) == 'o' &&
+ *(cursor + 3) == 't' &&
+ *(cursor + 4) == 's') {
+ token_stream[(int) index++].kind = Token_slots;
+ return;
+ }
+ break;
+
+ case 'u':
+ if (*(cursor + 1) == 'n' &&
+ *(cursor + 2) == 'i' &&
+ *(cursor + 3) == 'o' &&
+ *(cursor + 4) == 'n') {
+ token_stream[(int) index++].kind = Token_union;
+ return;
+ }
+ if (*(cursor + 1) == 's' &&
+ *(cursor + 2) == 'i' &&
+ *(cursor + 3) == 'n' &&
+ *(cursor + 4) == 'g') {
+ token_stream[(int) index++].kind = Token_using;
+ return;
+ }
+ break;
+
+ case 't':
+ if (*(cursor + 1) == 'h' &&
+ *(cursor + 2) == 'r' &&
+ *(cursor + 3) == 'o' &&
+ *(cursor + 4) == 'w') {
+ token_stream[(int) index++].kind = Token_throw;
+ return;
+ }
+ break;
+
+ case 'w':
+ if (*(cursor + 1) == 'h' &&
+ *(cursor + 2) == 'i' &&
+ *(cursor + 3) == 'l' &&
+ *(cursor + 4) == 'e') {
+ token_stream[(int) index++].kind = Token_while;
+ return;
+ }
+ break;
+
+ }
+ token_stream[(int) index++].kind = Token_identifier;
+}
+
+void Lexer::scanKeyword6()
+{
+ switch (*cursor) {
+ case 'a':
+ if (*(cursor + 1) == 'n' &&
+ *(cursor + 2) == 'd' &&
+ *(cursor + 3) == '_' &&
+ *(cursor + 4) == 'e' &&
+ *(cursor + 5) == 'q') {
+ token_stream[(int) index++].kind = Token_and_eq;
+ return;
+ }
+ break;
+
+ case 'b':
+ if (*(cursor + 1) == 'i' &&
+ *(cursor + 2) == 't' &&
+ *(cursor + 3) == 'a' &&
+ *(cursor + 4) == 'n' &&
+ *(cursor + 5) == 'd') {
+ token_stream[(int) index++].kind = Token_bitand;
+ return;
+ }
+ break;
+
+ case 'e':
+ if (*(cursor + 1) == 'x' &&
+ *(cursor + 2) == 'p' &&
+ *(cursor + 3) == 'o' &&
+ *(cursor + 4) == 'r' &&
+ *(cursor + 5) == 't') {
+ token_stream[(int) index++].kind = Token_export;
+ return;
+ }
+ if (*(cursor + 1) == 'x' &&
+ *(cursor + 2) == 't' &&
+ *(cursor + 3) == 'e' &&
+ *(cursor + 4) == 'r' &&
+ *(cursor + 5) == 'n') {
+ token_stream[(int) index++].kind = Token_extern;
+ return;
+ }
+ break;
+
+ case 'd':
+ if (*(cursor + 1) == 'e' &&
+ *(cursor + 2) == 'l' &&
+ *(cursor + 3) == 'e' &&
+ *(cursor + 4) == 't' &&
+ *(cursor + 5) == 'e') {
+ token_stream[(int) index++].kind = Token_delete;
+ return;
+ }
+ if (*(cursor + 1) == 'o' &&
+ *(cursor + 2) == 'u' &&
+ *(cursor + 3) == 'b' &&
+ *(cursor + 4) == 'l' &&
+ *(cursor + 5) == 'e') {
+ token_stream[(int) index++].kind = Token_double;
+ return;
+ }
+ break;
+
+ case 'f':
+ if (*(cursor + 1) == 'r' &&
+ *(cursor + 2) == 'i' &&
+ *(cursor + 3) == 'e' &&
+ *(cursor + 4) == 'n' &&
+ *(cursor + 5) == 'd') {
+ token_stream[(int) index++].kind = Token_friend;
+ return;
+ }
+ break;
+
+ case 'i':
+ if (*(cursor + 1) == 'n' &&
+ *(cursor + 2) == 'l' &&
+ *(cursor + 3) == 'i' &&
+ *(cursor + 4) == 'n' &&
+ *(cursor + 5) == 'e') {
+ token_stream[(int) index++].kind = Token_inline;
+ return;
+ }
+ break;
+
+ case 'K':
+ if (*(cursor + 1) == '_' &&
+ *(cursor + 2) == 'D' &&
+ *(cursor + 3) == 'C' &&
+ *(cursor + 4) == 'O' &&
+ *(cursor + 5) == 'P') {
+ token_stream[(int) index++].kind = Token_K_DCOP;
+ return;
+ }
+ break;
+
+ case 'n':
+ if (*(cursor + 1) == 'o' &&
+ *(cursor + 2) == 't' &&
+ *(cursor + 3) == '_' &&
+ *(cursor + 4) == 'e' &&
+ *(cursor + 5) == 'q') {
+ token_stream[(int) index++].kind = Token_not_eq;
+ return;
+ }
+ break;
+
+ case 'p':
+ if (*(cursor + 1) == 'u' &&
+ *(cursor + 2) == 'b' &&
+ *(cursor + 3) == 'l' &&
+ *(cursor + 4) == 'i' &&
+ *(cursor + 5) == 'c') {
+ token_stream[(int) index++].kind = Token_public;
+ return;
+ }
+ break;
+
+ case 's':
+ if (*(cursor + 1) == 'i' &&
+ *(cursor + 2) == 'g' &&
+ *(cursor + 3) == 'n' &&
+ *(cursor + 4) == 'e' &&
+ *(cursor + 5) == 'd') {
+ token_stream[(int) index++].kind = Token_signed;
+ return;
+ }
+ if (*(cursor + 1) == 'i' &&
+ *(cursor + 2) == 'z' &&
+ *(cursor + 3) == 'e' &&
+ *(cursor + 4) == 'o' &&
+ *(cursor + 5) == 'f') {
+ token_stream[(int) index++].kind = Token_sizeof;
+ return;
+ }
+ if (*(cursor + 1) == 't' &&
+ *(cursor + 2) == 'a' &&
+ *(cursor + 3) == 't' &&
+ *(cursor + 4) == 'i' &&
+ *(cursor + 5) == 'c') {
+ token_stream[(int) index++].kind = Token_static;
+ return;
+ }
+ if (*(cursor + 1) == 't' &&
+ *(cursor + 2) == 'r' &&
+ *(cursor + 3) == 'u' &&
+ *(cursor + 4) == 'c' &&
+ *(cursor + 5) == 't') {
+ token_stream[(int) index++].kind = Token_struct;
+ return;
+ }
+ if (*(cursor + 1) == 'w' &&
+ *(cursor + 2) == 'i' &&
+ *(cursor + 3) == 't' &&
+ *(cursor + 4) == 'c' &&
+ *(cursor + 5) == 'h') {
+ token_stream[(int) index++].kind = Token_switch;
+ return;
+ }
+ break;
+
+ case 'r':
+ if (*(cursor + 1) == 'e' &&
+ *(cursor + 2) == 't' &&
+ *(cursor + 3) == 'u' &&
+ *(cursor + 4) == 'r' &&
+ *(cursor + 5) == 'n') {
+ token_stream[(int) index++].kind = Token_return;
+ return;
+ }
+ break;
+
+ case 't':
+ if (*(cursor + 1) == 'y' &&
+ *(cursor + 2) == 'p' &&
+ *(cursor + 3) == 'e' &&
+ *(cursor + 4) == 'i' &&
+ *(cursor + 5) == 'd') {
+ token_stream[(int) index++].kind = Token_typeid;
+ return;
+ }
+ break;
+
+ case 'x':
+ if (*(cursor + 1) == 'o' &&
+ *(cursor + 2) == 'r' &&
+ *(cursor + 3) == '_' &&
+ *(cursor + 4) == 'e' &&
+ *(cursor + 5) == 'q') {
+ token_stream[(int) index++].kind = Token_xor_eq;
+ return;
+ }
+ break;
+
+ case 'k':
+ if (*(cursor + 1) == '_' &&
+ *(cursor + 2) == 'd' &&
+ *(cursor + 3) == 'c' &&
+ *(cursor + 4) == 'o' &&
+ *(cursor + 5) == 'p') {
+ token_stream[(int) index++].kind = Token_k_dcop;
+ return;
+ }
+ break;
+
+ }
+ token_stream[(int) index++].kind = Token_identifier;
+}
+
+void Lexer::scanKeyword7()
+{
+ switch (*cursor) {
+ case 'd':
+ if (*(cursor + 1) == 'e' &&
+ *(cursor + 2) == 'f' &&
+ *(cursor + 3) == 'a' &&
+ *(cursor + 4) == 'u' &&
+ *(cursor + 5) == 'l' &&
+ *(cursor + 6) == 't') {
+ token_stream[(int) index++].kind = Token_default;
+ return;
+ }
+ break;
+
+ case 'm':
+ if (*(cursor + 1) == 'u' &&
+ *(cursor + 2) == 't' &&
+ *(cursor + 3) == 'a' &&
+ *(cursor + 4) == 'b' &&
+ *(cursor + 5) == 'l' &&
+ *(cursor + 6) == 'e') {
+ token_stream[(int) index++].kind = Token_mutable;
+ return;
+ }
+ break;
+
+ case 'p':
+ if (*(cursor + 1) == 'r' &&
+ *(cursor + 2) == 'i' &&
+ *(cursor + 3) == 'v' &&
+ *(cursor + 4) == 'a' &&
+ *(cursor + 5) == 't' &&
+ *(cursor + 6) == 'e') {
+ token_stream[(int) index++].kind = Token_private;
+ return;
+ }
+ break;
+ case 's':
+ if (*(cursor + 1) == 'i' &&
+ *(cursor + 2) == 'g' &&
+ *(cursor + 3) == 'n' &&
+ *(cursor + 4) == 'a' &&
+ *(cursor + 5) == 'l' &&
+ *(cursor + 6) == 's') {
+ token_stream[(int) index++].kind = Token_signals;
+ return;
+ }
+ break;
+ case 't':
+ if (*(cursor + 1) == 'y' &&
+ *(cursor + 2) == 'p' &&
+ *(cursor + 3) == 'e' &&
+ *(cursor + 4) == 'd' &&
+ *(cursor + 5) == 'e' &&
+ *(cursor + 6) == 'f') {
+ token_stream[(int) index++].kind = Token_typedef;
+ return;
+ }
+ break;
+
+ case 'v':
+ if (*(cursor + 1) == 'i' &&
+ *(cursor + 2) == 'r' &&
+ *(cursor + 3) == 't' &&
+ *(cursor + 4) == 'u' &&
+ *(cursor + 5) == 'a' &&
+ *(cursor + 6) == 'l') {
+ token_stream[(int) index++].kind = Token_virtual;
+ return;
+ }
+ break;
+
+ case 'Q':
+ if (*(cursor + 1) == '_' &&
+ *(cursor + 2) == 'E' &&
+ *(cursor + 3) == 'N' &&
+ *(cursor + 4) == 'U' &&
+ *(cursor + 5) == 'M' &&
+ *(cursor + 6) == 'S') {
+ token_stream[(int) index++].kind = Token_Q_ENUMS;
+ return;
+ }
+ break;
+
+ }
+ token_stream[(int) index++].kind = Token_identifier;
+}
+
+void Lexer::scanKeyword8()
+{
+ switch (*cursor) {
+ case '_':
+ if (*(cursor + 1) == '_' &&
+ *(cursor + 2) == 't' &&
+ *(cursor + 3) == 'y' &&
+ *(cursor + 4) == 'p' &&
+ *(cursor + 5) == 'e' &&
+ *(cursor + 6) == 'o' &&
+ *(cursor + 7) == 'f') {
+ token_stream[(int) index++].kind = Token___typeof;
+ return;
+ }
+ break;
+
+ case 'c':
+ if (*(cursor + 1) == 'o' &&
+ *(cursor + 2) == 'n' &&
+ *(cursor + 3) == 't' &&
+ *(cursor + 4) == 'i' &&
+ *(cursor + 5) == 'n' &&
+ *(cursor + 6) == 'u' &&
+ *(cursor + 7) == 'e') {
+ token_stream[(int) index++].kind = Token_continue;
+ return;
+ }
+ break;
+
+ case 'e':
+ if (*(cursor + 1) == 'x' &&
+ *(cursor + 2) == 'p' &&
+ *(cursor + 3) == 'l' &&
+ *(cursor + 4) == 'i' &&
+ *(cursor + 5) == 'c' &&
+ *(cursor + 6) == 'i' &&
+ *(cursor + 7) == 't') {
+ token_stream[(int) index++].kind = Token_explicit;
+ return;
+ }
+ break;
+
+ case 'o':
+ if (*(cursor + 1) == 'p' &&
+ *(cursor + 2) == 'e' &&
+ *(cursor + 3) == 'r' &&
+ *(cursor + 4) == 'a' &&
+ *(cursor + 5) == 't' &&
+ *(cursor + 6) == 'o' &&
+ *(cursor + 7) == 'r') {
+ token_stream[(int) index++].kind = Token_operator;
+ return;
+ }
+ break;
+
+ case 'Q':
+ if (*(cursor + 1) == '_' &&
+ *(cursor + 2) == 'O' &&
+ *(cursor + 3) == 'B' &&
+ *(cursor + 4) == 'J' &&
+ *(cursor + 5) == 'E' &&
+ *(cursor + 6) == 'C' &&
+ *(cursor + 7) == 'T') {
+ token_stream[(int) index++].kind = Token_Q_OBJECT;
+ return;
+ }
+ break;
+
+ case 'r':
+ if (*(cursor + 1) == 'e' &&
+ *(cursor + 2) == 'g' &&
+ *(cursor + 3) == 'i' &&
+ *(cursor + 4) == 's' &&
+ *(cursor + 5) == 't' &&
+ *(cursor + 6) == 'e' &&
+ *(cursor + 7) == 'r') {
+ token_stream[(int) index++].kind = Token_register;
+ return;
+ }
+ break;
+
+ case 'u':
+ if (*(cursor + 1) == 'n' &&
+ *(cursor + 2) == 's' &&
+ *(cursor + 3) == 'i' &&
+ *(cursor + 4) == 'g' &&
+ *(cursor + 5) == 'n' &&
+ *(cursor + 6) == 'e' &&
+ *(cursor + 7) == 'd') {
+ token_stream[(int) index++].kind = Token_unsigned;
+ return;
+ }
+ break;
+
+ case 't':
+ if (*(cursor + 1) == 'e' &&
+ *(cursor + 2) == 'm' &&
+ *(cursor + 3) == 'p' &&
+ *(cursor + 4) == 'l' &&
+ *(cursor + 5) == 'a' &&
+ *(cursor + 6) == 't' &&
+ *(cursor + 7) == 'e') {
+ token_stream[(int) index++].kind = Token_template;
+ return;
+ }
+ if (*(cursor + 1) == 'y' &&
+ *(cursor + 2) == 'p' &&
+ *(cursor + 3) == 'e' &&
+ *(cursor + 4) == 'n' &&
+ *(cursor + 5) == 'a' &&
+ *(cursor + 6) == 'm' &&
+ *(cursor + 7) == 'e') {
+ token_stream[(int) index++].kind = Token_typename;
+ return;
+ }
+ break;
+
+ case 'v':
+ if (*(cursor + 1) == 'o' &&
+ *(cursor + 2) == 'l' &&
+ *(cursor + 3) == 'a' &&
+ *(cursor + 4) == 't' &&
+ *(cursor + 5) == 'i' &&
+ *(cursor + 6) == 'l' &&
+ *(cursor + 7) == 'e') {
+ token_stream[(int) index++].kind = Token_volatile;
+ return;
+ }
+ break;
+
+ }
+ token_stream[(int) index++].kind = Token_identifier;
+}
+
+void Lexer::scanKeyword9()
+{
+ switch (*cursor) {
+ case 'p':
+ if (*(cursor + 1) == 'r' &&
+ *(cursor + 2) == 'o' &&
+ *(cursor + 3) == 't' &&
+ *(cursor + 4) == 'e' &&
+ *(cursor + 5) == 'c' &&
+ *(cursor + 6) == 't' &&
+ *(cursor + 7) == 'e' &&
+ *(cursor + 8) == 'd') {
+ token_stream[(int) index++].kind = Token_protected;
+ return;
+ }
+ break;
+
+ case 'n':
+ if (*(cursor + 1) == 'a' &&
+ *(cursor + 2) == 'm' &&
+ *(cursor + 3) == 'e' &&
+ *(cursor + 4) == 's' &&
+ *(cursor + 5) == 'p' &&
+ *(cursor + 6) == 'a' &&
+ *(cursor + 7) == 'c' &&
+ *(cursor + 8) == 'e') {
+ token_stream[(int) index++].kind = Token_namespace;
+ return;
+ }
+ break;
+
+ }
+ token_stream[(int) index++].kind = Token_identifier;
+}
+
+void Lexer::scanKeyword10()
+{
+ switch (*cursor) {
+ case 'c':
+ if (*(cursor + 1) == 'o' &&
+ *(cursor + 2) == 'n' &&
+ *(cursor + 3) == 's' &&
+ *(cursor + 4) == 't' &&
+ *(cursor + 5) == '_' &&
+ *(cursor + 6) == 'c' &&
+ *(cursor + 7) == 'a' &&
+ *(cursor + 8) == 's' &&
+ *(cursor + 9) == 't') {
+ token_stream[(int) index++].kind = Token_const_cast;
+ return;
+ }
+ break;
+
+ case 'Q':
+ if (*(cursor + 1) == '_' &&
+ *(cursor + 2) == 'P' &&
+ *(cursor + 3) == 'R' &&
+ *(cursor + 4) == 'O' &&
+ *(cursor + 5) == 'P' &&
+ *(cursor + 6) == 'E' &&
+ *(cursor + 7) == 'R' &&
+ *(cursor + 8) == 'T' &&
+ *(cursor + 9) == 'Y') {
+ token_stream[(int) index++].kind = Token_Q_PROPERTY;
+ return;
+ }
+
+ break;
+ }
+
+ token_stream[(int) index++].kind = Token_identifier;
+}
+
+void Lexer::scanKeyword11()
+{
+ switch (*cursor) {
+ case 'Q':
+ if (*(cursor + 1) == '_' &&
+ *(cursor + 2) == 'I' &&
+ *(cursor + 3) == 'N' &&
+ *(cursor + 4) == 'V' &&
+ *(cursor + 5) == 'O' &&
+ *(cursor + 6) == 'K' &&
+ *(cursor + 7) == 'A' &&
+ *(cursor + 8) == 'B' &&
+ *(cursor + 9) == 'L' &&
+ *(cursor + 10) == 'E') {
+ token_stream[(int) index++].kind = Token_Q_INVOKABLE;
+ return;
+ }
+ break;
+
+ case 's':
+ if (*(cursor + 1) == 't' &&
+ *(cursor + 2) == 'a' &&
+ *(cursor + 3) == 't' &&
+ *(cursor + 4) == 'i' &&
+ *(cursor + 5) == 'c' &&
+ *(cursor + 6) == '_' &&
+ *(cursor + 7) == 'c' &&
+ *(cursor + 8) == 'a' &&
+ *(cursor + 9) == 's' &&
+ *(cursor + 10) == 't') {
+ token_stream[(int) index++].kind = Token_static_cast;
+ return;
+ }
+ break;
+
+ }
+ token_stream[(int) index++].kind = Token_identifier;
+}
+
+void Lexer::scanKeyword12()
+{
+ switch (*cursor) {
+ case 'd':
+ if (*(cursor + 1) == 'y' &&
+ *(cursor + 2) == 'n' &&
+ *(cursor + 3) == 'a' &&
+ *(cursor + 4) == 'm' &&
+ *(cursor + 5) == 'i' &&
+ *(cursor + 6) == 'c' &&
+ *(cursor + 7) == '_' &&
+ *(cursor + 8) == 'c' &&
+ *(cursor + 9) == 'a' &&
+ *(cursor + 10) == 's' &&
+ *(cursor + 11) == 't') {
+ token_stream[(int) index++].kind = Token_dynamic_cast;
+ return;
+ }
+ break;
+
+ }
+ token_stream[(int) index++].kind = Token_identifier;
+}
+
+void Lexer::scanKeyword13()
+{
+ switch (*cursor) {
+ case '_':
+ if (*(cursor + 1) == '_' &&
+ *(cursor + 2) == 'a' &&
+ *(cursor + 3) == 't' &&
+ *(cursor + 4) == 't' &&
+ *(cursor + 5) == 'r' &&
+ *(cursor + 6) == 'i' &&
+ *(cursor + 7) == 'b' &&
+ *(cursor + 8) == 'u' &&
+ *(cursor + 9) == 't' &&
+ *(cursor + 10) == 'e' &&
+ *(cursor + 11) == '_' &&
+ *(cursor + 12) == '_') {
+ token_stream[(int) index++].kind = Token___attribute__;
+ return;
+ }
+ break;
+ }
+ token_stream[(int) index++].kind = Token_identifier;
+}
+
+void Lexer::scanKeyword14()
+{
+ switch (*cursor) {
+ case 'k':
+ if (*(cursor + 1) == '_' &&
+ *(cursor + 2) == 'd' &&
+ *(cursor + 3) == 'c' &&
+ *(cursor + 4) == 'o' &&
+ *(cursor + 5) == 'p' &&
+ *(cursor + 6) == '_' &&
+ *(cursor + 7) == 's' &&
+ *(cursor + 8) == 'i' &&
+ *(cursor + 9) == 'g' &&
+ *(cursor + 10) == 'n' &&
+ *(cursor + 11) == 'a' &&
+ *(cursor + 12) == 'l' &&
+ *(cursor + 13) == 's') {
+ token_stream[(int) index++].kind = Token_k_dcop_signals;
+ return;
+ }
+ break;
+ }
+ token_stream[(int) index++].kind = Token_identifier;
+}
+
+void Lexer::scanKeyword16()
+{
+ switch (*cursor) {
+ case 'r':
+ if (*(cursor + 1) == 'e' &&
+ *(cursor + 2) == 'i' &&
+ *(cursor + 3) == 'n' &&
+ *(cursor + 4) == 't' &&
+ *(cursor + 5) == 'e' &&
+ *(cursor + 6) == 'r' &&
+ *(cursor + 7) == 'p' &&
+ *(cursor + 8) == 'r' &&
+ *(cursor + 9) == 'e' &&
+ *(cursor + 10) == 't' &&
+ *(cursor + 11) == '_' &&
+ *(cursor + 12) == 'c' &&
+ *(cursor + 13) == 'a' &&
+ *(cursor + 14) == 's' &&
+ *(cursor + 15) == 't') {
+ token_stream[(int) index++].kind = Token_reinterpret_cast;
+ return;
+ }
+ break;
+ }
+
+ token_stream[(int) index++].kind = Token_identifier;
+}
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/lexer.h b/parser/lexer.h
new file mode 100644
index 00000000..87480532
--- /dev/null
+++ b/parser/lexer.h
@@ -0,0 +1,290 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+
+#ifndef LEXER_H
+#define LEXER_H
+
+#include "symbol.h"
+
+#include <QtCore/QString>
+#include <cstdlib>
+#include <cassert>
+
+struct NameSymbol;
+class Lexer;
+class Control;
+
+typedef void (Lexer::*scan_fun_ptr)();
+
+class Token
+{
+public:
+ int kind;
+ std::size_t position;
+ std::size_t size;
+ char const *text;
+
+ union {
+ const NameSymbol *symbol;
+ std::size_t right_brace;
+ } extra;
+};
+
+class LocationTable
+{
+private:
+ LocationTable(const LocationTable &source);
+ void operator = (const LocationTable &source);
+
+public:
+ inline LocationTable(std::size_t size = 1024)
+ : lines(0),
+ line_count(0),
+ current_line(0) {
+ resize(size);
+ }
+
+ inline ~LocationTable() {
+ free(lines);
+ }
+
+ inline std::size_t size() const {
+ return line_count;
+ }
+
+ void resize(std::size_t size) {
+ Q_ASSERT(size > 0);
+ lines = (std::size_t*) ::realloc(lines, sizeof(std::size_t) * size);
+ line_count = size;
+ }
+
+ void positionAt(std::size_t offset, int *line, int *column) const {
+ positionAt(offset, (int) current_line, line, column);
+ }
+
+ void positionAt(std::size_t offset, int max_line, int *line, int *column) const;
+
+ inline std::size_t &operator[](int index) {
+ return lines[index];
+ }
+
+private:
+ std::size_t *lines;
+ std::size_t line_count;
+ std::size_t current_line;
+
+ friend class Lexer;
+};
+
+class TokenStream
+{
+private:
+ TokenStream(const TokenStream &);
+ void operator = (const TokenStream &);
+
+public:
+ inline TokenStream(std::size_t size = 1024)
+ : tokens(0),
+ index(0),
+ token_count(0) {
+ resize(size);
+ }
+
+ inline ~TokenStream() {
+ ::free(tokens);
+ }
+
+ inline std::size_t size() const {
+ return token_count;
+ }
+
+ inline std::size_t cursor() const {
+ return index;
+ }
+
+ inline void rewind(int i) {
+ index = i;
+ }
+
+ void resize(std::size_t size) {
+ Q_ASSERT(size > 0);
+ tokens = (Token*) ::realloc(tokens, sizeof(Token) * size);
+ token_count = size;
+ }
+
+ inline std::size_t nextToken() {
+ return index++;
+ }
+
+ inline int lookAhead(std::size_t i = 0) const {
+ return tokens[index + i].kind;
+ }
+
+ inline int kind(std::size_t i) const {
+ return tokens[i].kind;
+ }
+
+ inline std::size_t position(std::size_t i) const {
+ return tokens[i].position;
+ }
+
+ inline const NameSymbol *symbol(std::size_t i) const {
+ return tokens[i].extra.symbol;
+ }
+
+ inline std::size_t matchingBrace(std::size_t i) const {
+ return tokens[i].extra.right_brace;
+ }
+
+ inline Token &operator[](int index) {
+ return tokens[index];
+ }
+
+ inline const Token &token(int index) const {
+ return tokens[index];
+ }
+
+private:
+ Token *tokens;
+ std::size_t index;
+ std::size_t token_count;
+
+private:
+ friend class Lexer;
+};
+
+class LocationManager
+{
+ LocationManager(LocationManager const &__other);
+ void operator = (LocationManager const &__other);
+
+public:
+ LocationManager(TokenStream &__token_stream,
+ LocationTable &__location_table,
+ LocationTable &__line_table):
+ token_stream(__token_stream),
+ location_table(__location_table),
+ line_table(__line_table) {}
+
+ void positionAt(std::size_t offset, int *line, int *column,
+ QString *filename) const;
+
+ void extract_line(int offset, int *line, QString *filename) const;
+
+ TokenStream &token_stream;
+ LocationTable &location_table;
+ LocationTable &line_table;
+};
+
+class Lexer
+{
+public:
+ Lexer(LocationManager &__location, Control *__control):
+ _M_location(__location),
+ token_stream(_M_location.token_stream),
+ location_table(_M_location.location_table),
+ line_table(_M_location.line_table),
+ control(__control) {}
+
+ void tokenize(const char *contents, std::size_t size);
+
+ LocationManager &_M_location;
+ TokenStream &token_stream;
+ LocationTable &location_table;
+ LocationTable &line_table;
+
+private:
+ void reportError(const QString& msg);
+
+ void initialize_scan_table();
+ void scan_newline();
+ void scan_white_spaces();
+ void scan_identifier_or_keyword();
+ void scan_identifier_or_literal();
+ void scan_int_constant();
+ void scan_char_constant();
+ void scan_string_constant();
+ void scan_invalid_input();
+ void scan_preprocessor();
+
+ // keywords
+ void scanKeyword0();
+ void scanKeyword2();
+ void scanKeyword3();
+ void scanKeyword4();
+ void scanKeyword5();
+ void scanKeyword6();
+ void scanKeyword7();
+ void scanKeyword8();
+ void scanKeyword9();
+ void scanKeyword10();
+ void scanKeyword11();
+ void scanKeyword12();
+ void scanKeyword13();
+ void scanKeyword14();
+ void scanKeyword16();
+
+ // operators
+ void scan_not();
+ void scan_remainder();
+ void scan_and();
+ void scan_left_paren();
+ void scan_right_paren();
+ void scan_star();
+ void scan_plus();
+ void scan_comma();
+ void scan_minus();
+ void scan_dot();
+ void scan_divide();
+ void scan_colon();
+ void scan_semicolon();
+ void scan_less();
+ void scan_equal();
+ void scan_greater();
+ void scan_question();
+ void scan_left_bracket();
+ void scan_right_bracket();
+ void scan_xor();
+ void scan_left_brace();
+ void scan_or();
+ void scan_right_brace();
+ void scan_tilde();
+ void scan_EOF();
+
+private:
+ Control *control;
+ const unsigned char *cursor;
+ const unsigned char *begin_buffer;
+ const unsigned char *end_buffer;
+ std::size_t index;
+
+ static scan_fun_ptr s_scan_table[];
+ static scan_fun_ptr s_scan_keyword_table[];
+ static bool s_initialized;
+};
+
+#endif // LEXER_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/list.cpp b/parser/list.cpp
new file mode 100644
index 00000000..7482b739
--- /dev/null
+++ b/parser/list.cpp
@@ -0,0 +1,28 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+
+#include "list.h"
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/list.h b/parser/list.h
new file mode 100644
index 00000000..64aef452
--- /dev/null
+++ b/parser/list.h
@@ -0,0 +1,100 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+
+#ifndef FASTLIST_H
+#define FASTLIST_H
+
+#include "smallobject.h"
+
+template <typename Tp>
+struct ListNode {
+ Tp element;
+ int index;
+ mutable const ListNode<Tp> *next;
+
+ static ListNode *create(const Tp &element, pool *p) {
+ ListNode<Tp> *node = new(p->allocate(sizeof(ListNode))) ListNode();
+ node->element = element;
+ node->index = 0;
+ node->next = node;
+
+ return node;
+ }
+
+ static ListNode *create(const ListNode *n1, const Tp &element, pool *p) {
+ ListNode<Tp> *n2 = ListNode::create(element, p);
+
+ n2->index = n1->index + 1;
+ n2->next = n1->next;
+ n1->next = n2;
+
+ return n2;
+ }
+
+ inline ListNode<Tp>() { }
+
+ inline const ListNode<Tp> *at(int index) const {
+ const ListNode<Tp> *node = this;
+ while (index != node->index)
+ node = node->next;
+
+ return node;
+ }
+
+ inline bool hasNext() const {
+ return index < next->index;
+ }
+
+ inline int count() const {
+ return 1 + toBack()->index;
+ }
+
+ inline const ListNode<Tp> *toFront() const {
+ return toBack()->next;
+ }
+
+ inline const ListNode<Tp> *toBack() const {
+ const ListNode<Tp> *node = this;
+ while (node->hasNext())
+ node = node->next;
+
+ return node;
+ }
+};
+
+template <class Tp>
+inline const ListNode<Tp> *snoc(const ListNode<Tp> *list,
+ const Tp &element, pool *p)
+{
+ if (!list)
+ return ListNode<Tp>::create(element, p);
+
+ return ListNode<Tp>::create(list->toBack(), element, p);
+}
+
+#endif // FASTLIST_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
+
diff --git a/parser/name_compiler.cpp b/parser/name_compiler.cpp
new file mode 100644
index 00000000..4dbd516d
--- /dev/null
+++ b/parser/name_compiler.cpp
@@ -0,0 +1,134 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+
+#include "name_compiler.h"
+#include "type_compiler.h"
+#include "declarator_compiler.h"
+#include "lexer.h"
+#include "symbol.h"
+#include "binder.h"
+
+#include <QtCore/qdebug.h>
+
+NameCompiler::NameCompiler(Binder *binder)
+ : _M_binder(binder), _M_token_stream(binder->tokenStream())
+{
+}
+
+QString NameCompiler::decode_operator(std::size_t index) const
+{
+ const Token &tk = _M_token_stream->token((int) index);
+ return QString::fromUtf8(&tk.text[tk.position], (int) tk.size);
+}
+
+QString NameCompiler::internal_run(AST *node)
+{
+ _M_name.clear();
+ visit(node);
+ return name();
+}
+
+void NameCompiler::visitUnqualifiedName(UnqualifiedNameAST *node)
+{
+ QString tmp_name;
+
+ if (node->tilde)
+ tmp_name += QLatin1String("~");
+
+ if (node->id)
+ tmp_name += _M_token_stream->symbol(node->id)->as_string();
+
+ if (OperatorFunctionIdAST *op_id = node->operator_id) {
+#if defined(__GNUC__)
+#warning "NameCompiler::visitUnqualifiedName() -- implement me"
+#endif
+
+ if (op_id->op && op_id->op->op) {
+ tmp_name += QLatin1String("operator");
+ tmp_name += decode_operator(op_id->op->op);
+ if (op_id->op->close)
+ tmp_name += decode_operator(op_id->op->close);
+ } else if (op_id->type_specifier) {
+#if defined(__GNUC__)
+#warning "don't use an hardcoded string as cast' name"
+#endif
+ Token const &tk = _M_token_stream->token((int) op_id->start_token);
+ Token const &end_tk = _M_token_stream->token((int) op_id->end_token);
+ tmp_name += QString::fromLatin1(&tk.text[tk.position],
+ (int)(end_tk.position - tk.position)).trimmed();
+ }
+ }
+
+ _M_name += tmp_name;
+ if (node->template_arguments) {
+ // ### cleanup
+ _M_name.last() += QLatin1String("<");
+ visitNodes(this, node->template_arguments);
+ _M_name.last().truncate(_M_name.last().count() - 1); // remove the last ','
+ _M_name.last() += QLatin1String(">");
+ }
+
+}
+
+void NameCompiler::visitTemplateArgument(TemplateArgumentAST *node)
+{
+ if (node->type_id && node->type_id->type_specifier) {
+ TypeCompiler type_cc(_M_binder);
+ type_cc.run(node->type_id->type_specifier);
+
+ DeclaratorCompiler decl_cc(_M_binder);
+ decl_cc.run(node->type_id->declarator);
+
+ if (type_cc.isConstant())
+ _M_name.last() += "const ";
+
+ QStringList q = type_cc.qualifiedName();
+
+ if (q.count() == 1) {
+#if defined (RXX_RESOLVE_TYPEDEF) // ### it'll break :(
+ TypeInfo tp;
+ tp.setQualifiedName(q);
+ tp = TypeInfo::resolveType(tp, _M_binder->currentScope()->toItem());
+ q = tp.qualifiedName();
+#endif
+
+ if (CodeModelItem item = _M_binder->model()->findItem(q, _M_binder->currentScope()->toItem())) {
+ if (item->name() == q.last())
+ q = item->qualifiedName();
+ }
+ }
+
+ _M_name.last() += q.join("::");
+
+ if (decl_cc.isReference())
+ _M_name.last() += "&";
+ if (decl_cc.indirection())
+ _M_name.last() += QString(decl_cc.indirection(), '*');
+
+ _M_name.last() += QLatin1String(",");
+ }
+}
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/name_compiler.h b/parser/name_compiler.h
new file mode 100644
index 00000000..66cabacc
--- /dev/null
+++ b/parser/name_compiler.h
@@ -0,0 +1,69 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+
+#ifndef NAME_COMPILER_H
+#define NAME_COMPILER_H
+
+#include "default_visitor.h"
+#include <QtCore/QStringList>
+
+class TokenStream;
+class Binder;
+
+class NameCompiler: protected DefaultVisitor
+{
+public:
+ NameCompiler(Binder *binder);
+
+ void run(NameAST *node) {
+ internal_run(node);
+ }
+ void run(UnqualifiedNameAST *node) {
+ internal_run(node);
+ }
+
+ QString name() const {
+ return _M_name.join("::");
+ }
+ QStringList qualifiedName() const {
+ return _M_name;
+ }
+
+protected:
+ virtual void visitUnqualifiedName(UnqualifiedNameAST *node);
+ virtual void visitTemplateArgument(TemplateArgumentAST *node);
+
+ QString internal_run(AST *node);
+ QString decode_operator(std::size_t index) const;
+
+private:
+ Binder *_M_binder;
+ TokenStream *_M_token_stream;
+ QStringList _M_name;
+};
+
+#endif // NAME_COMPILER_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/parser.cpp b/parser/parser.cpp
new file mode 100644
index 00000000..d65d5f3e
--- /dev/null
+++ b/parser/parser.cpp
@@ -0,0 +1,4056 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+
+
+// c++ support
+#include "parser.h"
+#include "tokens.h"
+#include "lexer.h"
+#include "control.h"
+
+#include <cstdlib>
+
+#define ADVANCE(tk, descr) \
+ { \
+ if (token_stream.lookAhead() != tk) { \
+ tokenRequiredError(tk); \
+ return false; \
+ } \
+ token_stream.nextToken(); \
+ }
+
+#define ADVANCE_NR(tk, descr) \
+ do { \
+ if (token_stream.lookAhead() != tk) { \
+ tokenRequiredError(tk); \
+ } \
+ else \
+ token_stream.nextToken(); \
+ } while (0)
+
+#define CHECK(tk) \
+ do { \
+ if (token_stream.lookAhead() != tk) { \
+ return false; \
+ } \
+ token_stream.nextToken(); \
+ } while (0)
+
+#define UPDATE_POS(_node, start, end) \
+ do { \
+ (_node)->start_token = start; \
+ (_node)->end_token = end; \
+ } while (0)
+
+Parser::Parser(Control *c)
+ : _M_location(token_stream, location_table, line_table),
+ control(c),
+ lexer(_M_location, control)
+{
+ _M_block_errors = false;
+}
+
+Parser::~Parser()
+{
+}
+
+void Parser::advance()
+{
+ token_stream.nextToken();
+}
+
+TranslationUnitAST *Parser::parse(const char *contents,
+ std::size_t size, pool *p)
+{
+ _M_block_errors = false;
+ _M_pool = p;
+ lexer.tokenize(contents, size);
+ token_stream.nextToken(); // skip the first token
+
+ Lexer *oldLexer = control->changeLexer(&lexer);
+ Parser *oldParser = control->changeParser(this);
+
+ TranslationUnitAST *ast = 0;
+ parseTranslationUnit(ast);
+
+ control->changeLexer(oldLexer);
+ control->changeParser(oldParser);
+
+ return ast;
+}
+
+bool Parser::parseWinDeclSpec(WinDeclSpecAST *&node)
+{
+ if (token_stream.lookAhead() != Token_identifier)
+ return false;
+
+ std::size_t start = token_stream.cursor();
+
+ const NameSymbol *name_symbol = token_stream.symbol(token_stream.cursor());
+ QString name = name_symbol->as_string();
+ if (name != QLatin1String("__declspec"))
+ return false;
+ std::size_t specifier = token_stream.cursor();
+
+ token_stream.nextToken();
+ if (token_stream.lookAhead() != '(')
+ return false;
+
+ token_stream.nextToken();
+ if (token_stream.lookAhead() != Token_identifier)
+ return false;
+ std::size_t modifier = token_stream.cursor();
+
+ token_stream.nextToken();
+ if (token_stream.lookAhead() != ')')
+ return false;
+
+ token_stream.nextToken();
+
+ node = CreateNode<WinDeclSpecAST>(_M_pool);
+ node->specifier = specifier;
+ node->modifier = modifier;
+
+ UPDATE_POS(node, start, token_stream.cursor());
+
+ return true;
+}
+
+void Parser::tokenRequiredError(int token)
+{
+ QString err;
+
+ err += "expected token ";
+ err += "``";
+ err += token_name(token);
+ err += "'' found ``";
+ err += token_name(token_stream.lookAhead());
+ err += "''";
+
+ reportError(err);
+}
+
+void Parser::syntaxError()
+{
+ QString err;
+
+ err += "unexpected token ";
+ err += "``";
+ err += token_name(token_stream.lookAhead());
+ err += "''";
+
+ reportError(err);
+}
+
+void Parser::reportError(const QString& msg)
+{
+ if (!_M_block_errors) {
+ int line, column;
+ QString fileName;
+
+ std::size_t tok = token_stream.cursor();
+ location().positionAt(token_stream.position(tok),
+ &line, &column, &fileName);
+
+ Control::ErrorMessage errmsg;
+ errmsg.setLine(line + 1);
+ errmsg.setColumn(column);
+ errmsg.setFileName(fileName);
+ errmsg.setMessage(QLatin1String("** PARSER ERROR ") + msg);
+ control->reportError(errmsg);
+ }
+}
+
+bool Parser::skipUntil(int token)
+{
+ while (token_stream.lookAhead()) {
+ if (token_stream.lookAhead() == token)
+ return true;
+
+ token_stream.nextToken();
+ }
+
+ return false;
+}
+
+bool Parser::skipUntilDeclaration()
+{
+ while (token_stream.lookAhead()) {
+
+ switch (token_stream.lookAhead()) {
+ case ';':
+ case '~':
+ case Token_scope:
+ case Token_identifier:
+ case Token_operator:
+ case Token_char:
+ case Token_wchar_t:
+ case Token_bool:
+ case Token_short:
+ case Token_int:
+ case Token_long:
+ case Token_signed:
+ case Token_unsigned:
+ case Token_float:
+ case Token_double:
+ case Token_void:
+ case Token_extern:
+ case Token_namespace:
+ case Token_using:
+ case Token_typedef:
+ case Token_asm:
+ case Token_template:
+ case Token_export:
+
+ case Token_const: // cv
+ case Token_volatile: // cv
+
+ case Token_public:
+ case Token_protected:
+ case Token_private:
+ case Token_signals: // Qt
+ case Token_slots: // Qt
+ return true;
+
+ default:
+ token_stream.nextToken();
+ }
+ }
+
+ return false;
+}
+
+bool Parser::skipUntilStatement()
+{
+ while (token_stream.lookAhead()) {
+ switch (token_stream.lookAhead()) {
+ case ';':
+ case '{':
+ case '}':
+ case Token_const:
+ case Token_volatile:
+ case Token_identifier:
+ case Token_case:
+ case Token_default:
+ case Token_if:
+ case Token_switch:
+ case Token_while:
+ case Token_do:
+ case Token_for:
+ case Token_break:
+ case Token_continue:
+ case Token_return:
+ case Token_goto:
+ case Token_try:
+ case Token_catch:
+ case Token_throw:
+ case Token_char:
+ case Token_wchar_t:
+ case Token_bool:
+ case Token_short:
+ case Token_int:
+ case Token_long:
+ case Token_signed:
+ case Token_unsigned:
+ case Token_float:
+ case Token_double:
+ case Token_void:
+ case Token_class:
+ case Token_struct:
+ case Token_union:
+ case Token_enum:
+ case Token_scope:
+ case Token_template:
+ case Token_using:
+ return true;
+
+ default:
+ token_stream.nextToken();
+ }
+ }
+
+ return false;
+}
+
+bool Parser::skip(int l, int r)
+{
+ int count = 0;
+ while (token_stream.lookAhead()) {
+ int tk = token_stream.lookAhead();
+
+ if (tk == l)
+ ++count;
+ else if (tk == r)
+ --count;
+ else if (l != '{' && (tk == '{' || tk == '}' || tk == ';'))
+ return false;
+
+ if (!count)
+ return true;
+
+ token_stream.nextToken();
+ }
+
+ return false;
+}
+
+bool Parser::parseName(NameAST *&node, bool acceptTemplateId)
+{
+ std::size_t start = token_stream.cursor();
+
+ WinDeclSpecAST *winDeclSpec = 0;
+ parseWinDeclSpec(winDeclSpec);
+
+ NameAST *ast = CreateNode<NameAST>(_M_pool);
+
+ if (token_stream.lookAhead() == Token_scope) {
+ ast->global = true;
+ token_stream.nextToken();
+ }
+
+ std::size_t idx = token_stream.cursor();
+
+ while (true) {
+ UnqualifiedNameAST *n = 0;
+ if (!parseUnqualifiedName(n))
+ return false;
+
+ if (token_stream.lookAhead() == Token_scope) {
+ token_stream.nextToken();
+
+ ast->qualified_names
+ = snoc(ast->qualified_names, n, _M_pool);
+
+ if (token_stream.lookAhead() == Token_template) {
+ /// skip optional template #### @todo CHECK
+ token_stream.nextToken();
+ }
+ } else {
+ Q_ASSERT(n);
+ if (!acceptTemplateId) {
+ token_stream.rewind((int) n->start_token);
+ parseUnqualifiedName(n, false);
+ }
+
+ ast->unqualified_name = n;
+ break;
+ }
+ }
+
+ if (idx == token_stream.cursor())
+ return false;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTranslationUnit(TranslationUnitAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+ TranslationUnitAST *ast = CreateNode<TranslationUnitAST>(_M_pool);
+
+ while (token_stream.lookAhead()) {
+ std::size_t startDecl = token_stream.cursor();
+
+ DeclarationAST *declaration = 0;
+ if (parseDeclaration(declaration)) {
+ ast->declarations =
+ snoc(ast->declarations, declaration, _M_pool);
+ } else {
+ // error recovery
+ if (startDecl == token_stream.cursor()) {
+ // skip at least one token
+ token_stream.nextToken();
+ }
+
+ skipUntilDeclaration();
+ }
+ }
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseDeclaration(DeclarationAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ switch (token_stream.lookAhead()) {
+ case ';':
+ token_stream.nextToken();
+ return true;
+
+ case Token_extern:
+ return parseLinkageSpecification(node);
+
+ case Token_namespace:
+ return parseNamespace(node);
+
+ case Token_using:
+ return parseUsing(node);
+
+ case Token_typedef:
+ return parseTypedef(node);
+
+ case Token_asm:
+ return parseAsmDefinition(node);
+
+ case Token_Q_ENUMS:
+ return parseQ_ENUMS(node);
+
+ case Token_template:
+ case Token_export:
+ return parseTemplateDeclaration(node);
+
+ default: {
+ const ListNode<std::size_t> *cv = 0;
+ parseCvQualify(cv);
+
+ const ListNode<std::size_t> *storageSpec = 0;
+ parseStorageClassSpecifier(storageSpec);
+
+ parseCvQualify(cv);
+
+ TypeSpecifierAST *spec = 0;
+ if (parseEnumSpecifier(spec)
+ || parseClassSpecifier(spec)
+ || parseForwardDeclarationSpecifier(spec)) {
+ parseCvQualify(cv);
+
+ spec->cv = cv;
+
+ const ListNode<InitDeclaratorAST*> *declarators = 0;
+ parseInitDeclaratorList(declarators);
+ ADVANCE(';', ";");
+
+ SimpleDeclarationAST *ast =
+ CreateNode<SimpleDeclarationAST>(_M_pool);
+
+ ast->storage_specifiers = storageSpec;
+ ast->type_specifier = spec;
+ ast->init_declarators = declarators;
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+ }
+ }
+ } // end switch
+
+ token_stream.rewind((int) start);
+ return parseDeclarationInternal(node);
+}
+
+bool Parser::parseLinkageSpecification(DeclarationAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ CHECK(Token_extern);
+
+ LinkageSpecificationAST *ast = CreateNode<LinkageSpecificationAST>(_M_pool);
+
+ if (token_stream.lookAhead() == Token_string_literal) {
+ ast->extern_type = token_stream.cursor();
+ token_stream.nextToken();
+ }
+
+ if (token_stream.lookAhead() == '{')
+ parseLinkageBody(ast->linkage_body);
+ else if (!parseDeclaration(ast->declaration))
+ reportError(("Declaration syntax error"));
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseLinkageBody(LinkageBodyAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ CHECK('{');
+
+ LinkageBodyAST *ast = CreateNode<LinkageBodyAST>(_M_pool);
+
+ while (token_stream.lookAhead()) {
+ int tk = token_stream.lookAhead();
+
+ if (tk == '}')
+ break;
+
+ std::size_t startDecl = token_stream.cursor();
+
+ DeclarationAST *declaration = 0;
+ if (parseDeclaration(declaration)) {
+ ast->declarations = snoc(ast->declarations, declaration, _M_pool);
+ } else {
+ // error recovery
+ if (startDecl == token_stream.cursor()) {
+ // skip at least one token
+ token_stream.nextToken();
+ }
+
+ skipUntilDeclaration();
+ }
+ }
+
+ if (token_stream.lookAhead() != '}')
+ reportError(("} expected"));
+ else
+ token_stream.nextToken();
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseNamespace(DeclarationAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ CHECK(Token_namespace);
+
+ std::size_t namespace_name = 0;
+ if (token_stream.lookAhead() == Token_identifier) {
+ namespace_name = token_stream.cursor();
+ token_stream.nextToken();
+ }
+
+ if (token_stream.lookAhead() == '=') {
+ // namespace alias
+ token_stream.nextToken();
+
+ NameAST *name = 0;
+ if (parseName(name)) {
+ ADVANCE(';', ";");
+
+ NamespaceAliasDefinitionAST *ast
+ = CreateNode<NamespaceAliasDefinitionAST>(_M_pool);
+ ast->namespace_name = namespace_name;
+ ast->alias_name = name;
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ return true;
+ } else {
+ reportError(("namespace expected"));
+ return false;
+ }
+ } else if (token_stream.lookAhead() != '{') {
+ reportError(("{ expected"));
+ return false;
+ }
+
+ NamespaceAST *ast = CreateNode<NamespaceAST>(_M_pool);
+ ast->namespace_name = namespace_name;
+ parseLinkageBody(ast->linkage_body);
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseUsing(DeclarationAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ CHECK(Token_using);
+
+ if (token_stream.lookAhead() == Token_namespace)
+ return parseUsingDirective(node);
+
+ UsingAST *ast = CreateNode<UsingAST>(_M_pool);
+
+ if (token_stream.lookAhead() == Token_typename) {
+ ast->type_name = token_stream.cursor();
+ token_stream.nextToken();
+ }
+
+ if (!parseName(ast->name))
+ return false;
+
+ ADVANCE(';', ";");
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseUsingDirective(DeclarationAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ CHECK(Token_namespace);
+
+ NameAST *name = 0;
+ if (!parseName(name)) {
+ reportError(("Namespace name expected"));
+ return false;
+ }
+
+ ADVANCE(';', ";");
+
+ UsingDirectiveAST *ast = CreateNode<UsingDirectiveAST>(_M_pool);
+ ast->name = name;
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+
+bool Parser::parseOperatorFunctionId(OperatorFunctionIdAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ CHECK(Token_operator);
+
+ OperatorFunctionIdAST *ast = CreateNode<OperatorFunctionIdAST>(_M_pool);
+
+ if (!parseOperator(ast->op)) {
+ ast->op = 0;
+
+ // parse cast operator
+ const ListNode<std::size_t> *cv = 0;
+ parseCvQualify(cv);
+
+ if (!parseSimpleTypeSpecifier(ast->type_specifier)) {
+ syntaxError();
+ return false;
+ }
+
+ parseCvQualify(cv);
+ ast->type_specifier->cv = cv;
+
+ PtrOperatorAST *ptr_op = 0;
+ while (parsePtrOperator(ptr_op))
+ ast->ptr_ops = snoc(ast->ptr_ops, ptr_op, _M_pool);
+ }
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ return true;
+}
+
+bool Parser::parseTemplateArgumentList(const ListNode<TemplateArgumentAST*> *&node,
+ bool reportError)
+{
+ TemplateArgumentAST *templArg = 0;
+ if (!parseTemplateArgument(templArg))
+ return false;
+
+ node = snoc(node, templArg, _M_pool);
+
+ while (token_stream.lookAhead() == ',') {
+ token_stream.nextToken();
+
+ if (!parseTemplateArgument(templArg)) {
+ if (reportError) {
+ syntaxError();
+ break;
+ }
+
+ node = 0;
+ return false;
+ }
+
+ node = snoc(node, templArg, _M_pool);
+ }
+
+ return true;
+}
+
+bool Parser::parseTypedef(DeclarationAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ CHECK(Token_typedef);
+
+ TypeSpecifierAST *spec = 0;
+ if (!parseTypeSpecifierOrClassSpec(spec)) {
+ reportError(("Need a type specifier to declare"));
+ return false;
+ }
+
+ const ListNode<InitDeclaratorAST*> *declarators = 0;
+ if (!parseInitDeclaratorList(declarators)) {
+ //reportError(("Need an identifier to declare"));
+ //return false;
+ }
+
+ ADVANCE(';', ";");
+
+ TypedefAST *ast = CreateNode<TypedefAST>(_M_pool);
+ ast->type_specifier = spec;
+ ast->init_declarators = declarators;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseAsmDefinition(DeclarationAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ ADVANCE(Token_asm, "asm");
+
+ const ListNode<std::size_t> *cv = 0;
+ parseCvQualify(cv);
+
+#if defined(__GNUC__)
+#warning "implement me"
+#endif
+ skip('(', ')');
+ token_stream.nextToken();
+ ADVANCE(';', ";");
+
+ AsmDefinitionAST *ast = CreateNode<AsmDefinitionAST>(_M_pool);
+ ast->cv = cv;
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTemplateDeclaration(DeclarationAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ std::size_t exported = 0;
+ if (token_stream.lookAhead() == Token_export) {
+ exported = token_stream.cursor();
+ token_stream.nextToken();
+ }
+
+ CHECK(Token_template);
+
+ const ListNode<TemplateParameterAST*> *params = 0;
+ if (token_stream.lookAhead() == '<') {
+ token_stream.nextToken();
+ parseTemplateParameterList(params);
+
+ ADVANCE('>', ">");
+ }
+
+ DeclarationAST *declaration = 0;
+ if (!parseDeclaration(declaration))
+ reportError(("expected a declaration"));
+
+ TemplateDeclarationAST *ast = CreateNode<TemplateDeclarationAST>(_M_pool);
+ ast->exported = exported;
+ ast->template_parameters = params;
+ ast->declaration = declaration;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseOperator(OperatorAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ OperatorAST *ast = CreateNode<OperatorAST>(_M_pool);
+
+ switch (token_stream.lookAhead()) {
+ case Token_new:
+ case Token_delete: {
+ ast->op = token_stream.cursor();
+ token_stream.nextToken();
+
+ if (token_stream.lookAhead() == '['
+ && token_stream.lookAhead(1) == ']') {
+ ast->open = token_stream.cursor();
+ token_stream.nextToken();
+
+ ast->close = token_stream.cursor();
+ token_stream.nextToken();
+ }
+ }
+ break;
+
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '%':
+ case '^':
+ case '&':
+ case '|':
+ case '~':
+ case '!':
+ case '=':
+ case '<':
+ case '>':
+ case ',':
+ case Token_assign:
+ case Token_shift:
+ case Token_eq:
+ case Token_not_eq:
+ case Token_leq:
+ case Token_geq:
+ case Token_and:
+ case Token_or:
+ case Token_incr:
+ case Token_decr:
+ case Token_ptrmem:
+ case Token_arrow:
+ ast->op = token_stream.cursor();
+ token_stream.nextToken();
+ break;
+
+ default:
+ if (token_stream.lookAhead() == '('
+ && token_stream.lookAhead(1) == ')') {
+ ast->op = ast->open = token_stream.cursor();
+ token_stream.nextToken();
+ ast->close = token_stream.cursor();
+ token_stream.nextToken();
+ } else if (token_stream.lookAhead() == '['
+ && token_stream.lookAhead(1) == ']') {
+ ast->op = ast->open = token_stream.cursor();
+ token_stream.nextToken();
+ ast->close = token_stream.cursor();
+ token_stream.nextToken();
+ } else {
+ return false;
+ }
+ }
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseCvQualify(const ListNode<std::size_t> *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ int tk;
+ while (0 != (tk = token_stream.lookAhead())
+ && (tk == Token_const || tk == Token_volatile)) {
+ node = snoc(node, token_stream.cursor(), _M_pool);
+ token_stream.nextToken();
+ }
+
+ return start != token_stream.cursor();
+}
+
+bool Parser::parseSimpleTypeSpecifier(TypeSpecifierAST *&node,
+ bool onlyIntegral)
+{
+ std::size_t start = token_stream.cursor();
+ bool isIntegral = false;
+ bool done = false;
+
+ const ListNode<std::size_t> *integrals = 0;
+
+ while (!done) {
+ switch (token_stream.lookAhead()) {
+ case Token_char:
+ case Token_wchar_t:
+ case Token_bool:
+ case Token_short:
+ case Token_int:
+ case Token_long:
+ case Token_signed:
+ case Token_unsigned:
+ case Token_float:
+ case Token_double:
+ case Token_void:
+ integrals = snoc(integrals, token_stream.cursor(), _M_pool);
+ isIntegral = true;
+ token_stream.nextToken();
+ break;
+
+ default:
+ done = true;
+ }
+ }
+
+ SimpleTypeSpecifierAST *ast = CreateNode<SimpleTypeSpecifierAST>(_M_pool);
+ if (isIntegral) {
+ ast->integrals = integrals;
+ } else if (token_stream.lookAhead() == Token___typeof) {
+ ast->type_of = token_stream.cursor();
+ token_stream.nextToken();
+
+ if (token_stream.lookAhead() == '(') {
+ token_stream.nextToken();
+
+ std::size_t saved = token_stream.cursor();
+ parseTypeId(ast->type_id);
+ if (token_stream.lookAhead() != ')') {
+ ast->type_id = 0;
+ token_stream.rewind((int) saved);
+ parseUnaryExpression(ast->expression);
+ }
+ ADVANCE(')', ")");
+ } else {
+ parseUnaryExpression(ast->expression);
+ }
+ } else if (onlyIntegral) {
+ token_stream.rewind((int) start);
+ return false;
+ } else {
+ if (!parseName(ast->name, true)) {
+ ast->name = 0;
+ token_stream.rewind((int) start);
+ return false;
+ }
+ }
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parsePtrOperator(PtrOperatorAST *&node)
+{
+ int tk = token_stream.lookAhead();
+
+ if (tk != '&' && tk != '*'
+ && tk != Token_scope && tk != Token_identifier) {
+ return false;
+ }
+
+ std::size_t start = token_stream.cursor();
+
+ PtrOperatorAST *ast = CreateNode<PtrOperatorAST>(_M_pool);
+
+ switch (token_stream.lookAhead()) {
+ case '&':
+ case '*':
+ ast->op = token_stream.cursor();
+ token_stream.nextToken();
+ break;
+
+ case Token_scope:
+ case Token_identifier: {
+ if (!parsePtrToMember(ast->mem_ptr)) {
+ token_stream.rewind((int) start);
+ return false;
+ }
+ }
+ break;
+
+ default:
+ Q_ASSERT(0);
+ break;
+ }
+
+ parseCvQualify(ast->cv);
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTemplateArgument(TemplateArgumentAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ TypeIdAST *typeId = 0;
+ ExpressionAST *expr = 0;
+
+ if (!parseTypeId(typeId) || (token_stream.lookAhead() != ','
+ && token_stream.lookAhead() != '>')) {
+ token_stream.rewind((int) start);
+
+ if (!parseLogicalOrExpression(expr, true))
+ return false;
+ }
+
+ TemplateArgumentAST *ast = CreateNode<TemplateArgumentAST>(_M_pool);
+ ast->type_id = typeId;
+ ast->expression = expr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTypeSpecifier(TypeSpecifierAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ const ListNode<std::size_t> *cv = 0;
+ parseCvQualify(cv);
+
+ TypeSpecifierAST *ast = 0;
+ if (!parseElaboratedTypeSpecifier(ast) && !parseSimpleTypeSpecifier(ast)) {
+ token_stream.rewind((int) start);
+ return false;
+ }
+
+ parseCvQualify(cv);
+ ast->cv = cv;
+
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseDeclarator(DeclaratorAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ DeclaratorAST *ast = CreateNode<DeclaratorAST>(_M_pool);
+
+ //fprintf(stderr, "[%s-%s] ast->ptr_ops: %p\n", __FILE__, __FUNCTION__, ast->ptr_ops);
+
+ DeclaratorAST *decl = 0;
+ NameAST *declId = 0;
+
+ PtrOperatorAST *ptrOp = 0;
+ while (parsePtrOperator(ptrOp))
+ ast->ptr_ops = snoc(ast->ptr_ops, ptrOp, _M_pool);
+
+ if (token_stream.lookAhead() == '(') {
+ token_stream.nextToken();
+
+ if (!parseDeclarator(decl))
+ return false;
+
+ ast->sub_declarator = decl;
+
+ CHECK(')');
+ } else {
+ if (token_stream.lookAhead() == ':') {
+ // unnamed bitfield
+ } else if (parseName(declId, true)) {
+ ast->id = declId;
+ } else {
+ token_stream.rewind((int) start);
+ return false;
+ }
+
+ if (token_stream.lookAhead() == ':') {
+ token_stream.nextToken();
+
+ if (!parseConstantExpression(ast->bit_expression))
+ reportError(("Constant expression expected"));
+
+ goto update_pos;
+ }
+ }
+
+ {
+ bool isVector = true;
+
+ while (token_stream.lookAhead() == '[') {
+ token_stream.nextToken();
+
+ ExpressionAST *expr = 0;
+ parseCommaExpression(expr);
+
+ ADVANCE(']', "]");
+
+ ast->array_dimensions = snoc(ast->array_dimensions, expr, _M_pool);
+ isVector = true;
+ }
+
+ bool skipParen = false;
+ if (token_stream.lookAhead() == Token_identifier
+ && token_stream.lookAhead(1) == '('
+ && token_stream.lookAhead(2) == '(') {
+ token_stream.nextToken();
+ token_stream.nextToken();
+ skipParen = true;
+ }
+
+ int tok = token_stream.lookAhead();
+ if (ast->sub_declarator
+ && !(isVector || tok == '(' || tok == ','
+ || tok == ';' || tok == '=')) {
+ token_stream.rewind((int) start);
+ return false;
+ }
+
+ std::size_t index = token_stream.cursor();
+ if (token_stream.lookAhead() == '(') {
+ token_stream.nextToken();
+
+ ParameterDeclarationClauseAST *params = 0;
+ if (!parseParameterDeclarationClause(params)) {
+ token_stream.rewind((int) index);
+ goto update_pos;
+ }
+
+ ast->parameter_declaration_clause = params;
+
+ if (token_stream.lookAhead() != ')') {
+ token_stream.rewind((int) index);
+ goto update_pos;
+ }
+
+ token_stream.nextToken(); // skip ')'
+
+ parseCvQualify(ast->fun_cv);
+ parseExceptionSpecification(ast->exception_spec);
+
+ if (token_stream.lookAhead() == Token___attribute__)
+ parse_Attribute__();
+ }
+
+ if (skipParen) {
+ if (token_stream.lookAhead() != ')')
+ reportError(("')' expected"));
+ else
+ token_stream.nextToken();
+ }
+ }
+
+update_pos:
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseAbstractDeclarator(DeclaratorAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ DeclaratorAST *ast = CreateNode<DeclaratorAST>(_M_pool);
+ DeclaratorAST *decl = 0;
+
+ PtrOperatorAST *ptrOp = 0;
+ while (parsePtrOperator(ptrOp))
+ ast->ptr_ops = snoc(ast->ptr_ops, ptrOp, _M_pool);
+
+ int index = (int) token_stream.cursor();
+ if (token_stream.lookAhead() == '(') {
+ token_stream.nextToken();
+
+ if (!parseAbstractDeclarator(decl)) {
+ token_stream.rewind((int) index);
+ goto label1;
+ }
+
+ ast->sub_declarator = decl;
+
+ if (token_stream.lookAhead() != ')') {
+ token_stream.rewind((int) start);
+ return false;
+ }
+ token_stream.nextToken();
+ } else if (token_stream.lookAhead() == ':') {
+ token_stream.nextToken();
+ if (!parseConstantExpression(ast->bit_expression)) {
+ ast->bit_expression = 0;
+ reportError(("Constant expression expected"));
+ }
+ goto update_pos;
+ }
+
+label1: {
+ bool isVector = true;
+
+ while (token_stream.lookAhead() == '[') {
+ token_stream.nextToken();
+
+ ExpressionAST *expr = 0;
+ parseCommaExpression(expr);
+
+ ADVANCE(']', "]");
+
+ ast->array_dimensions = snoc(ast->array_dimensions, expr, _M_pool);
+ isVector = true;
+ }
+
+ int tok = token_stream.lookAhead();
+ if (ast->sub_declarator
+ && !(isVector || tok == '(' || tok == ','
+ || tok == ';' || tok == '=')) {
+ token_stream.rewind((int) start);
+ return false;
+ }
+
+ int index = (int) token_stream.cursor();
+ if (token_stream.lookAhead() == '(') {
+ token_stream.nextToken();
+
+ ParameterDeclarationClauseAST *params = 0;
+ if (!parseParameterDeclarationClause(params)) {
+ token_stream.rewind((int) index);
+ goto update_pos;
+ }
+
+ ast->parameter_declaration_clause = params;
+
+ if (token_stream.lookAhead() != ')') {
+ token_stream.rewind((int) index);
+ goto update_pos;
+ }
+
+ token_stream.nextToken(); // skip ')'
+
+ parseCvQualify(ast->fun_cv);
+ parseExceptionSpecification(ast->exception_spec);
+ }
+ }
+
+update_pos:
+ if (token_stream.cursor() == start)
+ return false;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseEnumSpecifier(TypeSpecifierAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ CHECK(Token_enum);
+
+ NameAST *name = 0;
+ parseName(name);
+
+ if (token_stream.lookAhead() != '{') {
+ token_stream.rewind((int) start);
+ return false;
+ }
+ token_stream.nextToken();
+
+ EnumSpecifierAST *ast = CreateNode<EnumSpecifierAST>(_M_pool);
+ ast->name = name;
+
+ EnumeratorAST *enumerator = 0;
+ if (parseEnumerator(enumerator)) {
+ ast->enumerators = snoc(ast->enumerators, enumerator, _M_pool);
+
+ while (token_stream.lookAhead() == ',') {
+ token_stream.nextToken();
+
+ if (!parseEnumerator(enumerator)) {
+ //reportError(("Enumerator expected"));
+ break;
+ }
+
+ ast->enumerators = snoc(ast->enumerators, enumerator, _M_pool);
+ }
+ }
+
+ ADVANCE_NR('}', "}");
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTemplateParameterList(const ListNode<TemplateParameterAST*> *&node)
+{
+ TemplateParameterAST *param = 0;
+ if (!parseTemplateParameter(param))
+ return false;
+
+ node = snoc(node, param, _M_pool);
+
+ while (token_stream.lookAhead() == ',') {
+ token_stream.nextToken();
+
+ if (!parseTemplateParameter(param)) {
+ syntaxError();
+ break;
+ } else {
+ node = snoc(node, param, _M_pool);
+ }
+ }
+
+ return true;
+}
+
+bool Parser::parseTemplateParameter(TemplateParameterAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+ TemplateParameterAST *ast = CreateNode<TemplateParameterAST>(_M_pool);
+
+ int tk = token_stream.lookAhead();
+
+ if ((tk == Token_class || tk == Token_typename || tk == Token_template)
+ && parseTypeParameter(ast->type_parameter)) {
+ // nothing to do
+ } else if (!parseParameterDeclaration(ast->parameter_declaration))
+ return false;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTypeParameter(TypeParameterAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ TypeParameterAST *ast = CreateNode<TypeParameterAST>(_M_pool);
+ ast->type = start;
+
+ switch (token_stream.lookAhead()) {
+ case Token_class:
+ case Token_typename: {
+ token_stream.nextToken(); // skip class
+
+ // parse optional name
+ if (parseName(ast->name, true)) {
+ if (token_stream.lookAhead() == '=') {
+ token_stream.nextToken();
+
+ if (!parseTypeId(ast->type_id)) {
+ //syntaxError();
+ token_stream.rewind((int) start);
+ return false;
+ }
+ } else if (token_stream.lookAhead() != ','
+ && token_stream.lookAhead() != '>') {
+ token_stream.rewind((int) start);
+ return false;
+ }
+ }
+ }
+ break;
+
+ case Token_template: {
+ token_stream.nextToken(); // skip template
+ ADVANCE('<', "<");
+
+ if (!parseTemplateParameterList(ast->template_parameters))
+ return false;
+
+ ADVANCE('>', ">");
+
+ if (token_stream.lookAhead() == Token_class)
+ token_stream.nextToken();
+
+ // parse optional name
+ if (parseName(ast->name, true)) {
+ if (token_stream.lookAhead() == '=') {
+ token_stream.nextToken();
+
+ if (!parseTypeId(ast->type_id)) {
+ syntaxError();
+ return false;
+ }
+ }
+ }
+
+ if (token_stream.lookAhead() == '=') {
+ token_stream.nextToken();
+
+ parseName(ast->template_name, true);
+ }
+ }
+ break;
+
+ default:
+ return false;
+
+ } // end switch
+
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ return true;
+}
+
+bool Parser::parseStorageClassSpecifier(const ListNode<std::size_t> *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ int tk;
+ while (0 != (tk = token_stream.lookAhead())
+ && (tk == Token_friend || tk == Token_auto
+ || tk == Token_register || tk == Token_static
+ || tk == Token_extern || tk == Token_mutable)) {
+ node = snoc(node, token_stream.cursor(), _M_pool);
+ token_stream.nextToken();
+ }
+
+ return start != token_stream.cursor();
+}
+
+bool Parser::parseFunctionSpecifier(const ListNode<std::size_t> *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ int tk;
+ while (0 != (tk = token_stream.lookAhead())
+ && (tk == Token_inline || tk == Token_virtual
+ || tk == Token_explicit || tk == Token_Q_INVOKABLE)) {
+ node = snoc(node, token_stream.cursor(), _M_pool);
+ token_stream.nextToken();
+ }
+
+ return start != token_stream.cursor();
+}
+
+bool Parser::parseTypeId(TypeIdAST *&node)
+{
+ /// @todo implement the AST for typeId
+ std::size_t start = token_stream.cursor();
+
+ TypeSpecifierAST *spec = 0;
+ if (!parseTypeSpecifier(spec)) {
+ token_stream.rewind((int) start);
+ return false;
+ }
+
+ DeclaratorAST *decl = 0;
+ parseAbstractDeclarator(decl);
+
+ TypeIdAST *ast = CreateNode<TypeIdAST>(_M_pool);
+ ast->type_specifier = spec;
+ ast->declarator = decl;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseInitDeclaratorList(const ListNode<InitDeclaratorAST*> *&node)
+{
+ InitDeclaratorAST *decl = 0;
+ if (!parseInitDeclarator(decl))
+ return false;
+
+ node = snoc(node, decl, _M_pool);
+
+ while (token_stream.lookAhead() == ',') {
+ token_stream.nextToken();
+
+ if (!parseInitDeclarator(decl)) {
+ syntaxError();
+ break;
+ }
+ node = snoc(node, decl, _M_pool);
+ }
+
+ return true;
+}
+
+bool Parser::parseParameterDeclarationClause(ParameterDeclarationClauseAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ ParameterDeclarationClauseAST *ast
+ = CreateNode<ParameterDeclarationClauseAST>(_M_pool);
+
+ if (!parseParameterDeclarationList(ast->parameter_declarations)) {
+ if (token_stream.lookAhead() == ')')
+ goto good;
+
+ if (token_stream.lookAhead() == Token_ellipsis
+ && token_stream.lookAhead(1) == ')') {
+ ast->ellipsis = token_stream.cursor();
+ goto good;
+ }
+
+ return false;
+ }
+
+good:
+
+ if (token_stream.lookAhead() == Token_ellipsis) {
+ ast->ellipsis = token_stream.cursor();
+ token_stream.nextToken();
+ }
+
+ /// @todo add ellipsis
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseParameterDeclarationList(const ListNode<ParameterDeclarationAST*> *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ ParameterDeclarationAST *param = 0;
+ if (!parseParameterDeclaration(param)) {
+ token_stream.rewind((int) start);
+ return false;
+ }
+
+ node = snoc(node, param, _M_pool);
+
+ while (token_stream.lookAhead() == ',') {
+ token_stream.nextToken();
+
+ if (token_stream.lookAhead() == Token_ellipsis)
+ break;
+
+ if (!parseParameterDeclaration(param)) {
+ token_stream.rewind((int) start);
+ return false;
+ }
+ node = snoc(node, param, _M_pool);
+ }
+
+ return true;
+}
+
+bool Parser::parseParameterDeclaration(ParameterDeclarationAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ const ListNode<std::size_t> *storage = 0;
+ parseStorageClassSpecifier(storage);
+
+ // parse decl spec
+ TypeSpecifierAST *spec = 0;
+ if (!parseTypeSpecifier(spec)) {
+ token_stream.rewind((int) start);
+ return false;
+ }
+
+ int index = (int) token_stream.cursor();
+
+ DeclaratorAST *decl = 0;
+ if (!parseDeclarator(decl)) {
+ token_stream.rewind((int) index);
+
+ // try with abstract declarator
+ parseAbstractDeclarator(decl);
+ }
+
+ ExpressionAST *expr = 0;
+ if (token_stream.lookAhead() == '=') {
+ token_stream.nextToken();
+ if (!parseLogicalOrExpression(expr, true))
+ reportError(("Expression expected"));
+ }
+
+ ParameterDeclarationAST *ast = CreateNode<ParameterDeclarationAST>(_M_pool);
+ ast->type_specifier = spec;
+ ast->declarator = decl;
+ ast->expression = expr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parse_Attribute__()
+{
+ token_stream.nextToken();
+
+ ADVANCE('(', "(");
+
+ ExpressionAST *expr = 0;
+ parseExpression(expr);
+
+ if (token_stream.lookAhead() != ')') {
+ reportError(("')' expected"));
+ return false;
+ } else {
+ token_stream.nextToken();
+ }
+ return true;
+}
+
+QString Parser::tokenText(AST *ast) const
+{
+ if (!ast)
+ return QString();
+
+ int start_token = ast->start_token;
+ int end_token = ast->end_token;
+
+ Token const &tk = token_stream.token(start_token);
+ Token const &end_tk = token_stream.token(end_token);
+
+ return QString::fromLatin1(&tk.text[tk.position],
+ (int)(end_tk.position - tk.position)).trimmed();
+}
+
+bool Parser::parseForwardDeclarationSpecifier(TypeSpecifierAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ int kind = token_stream.lookAhead();
+ if (kind != Token_class && kind != Token_struct && kind != Token_union)
+ return false;
+
+ std::size_t class_key = token_stream.cursor();
+ token_stream.nextToken();
+
+ NameAST *name = 0;
+ if (!parseName(name, false)) {
+ token_stream.rewind((int) start);
+ return false;
+ }
+
+ BaseClauseAST *bases = 0;
+ if (token_stream.lookAhead() == ':') {
+ if (!parseBaseClause(bases)) {
+ token_stream.rewind((int) start);
+ return false;
+ }
+ }
+
+ if (token_stream.lookAhead() != ';') {
+ token_stream.rewind((int) start);
+ return false;
+ }
+
+ ForwardDeclarationSpecifierAST *ast = CreateNode<ForwardDeclarationSpecifierAST>(_M_pool);
+ ast->class_key = class_key;
+ ast->name = name;
+ ast->base_clause = bases;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseClassSpecifier(TypeSpecifierAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ int kind = token_stream.lookAhead();
+ if (kind != Token_class && kind != Token_struct && kind != Token_union)
+ return false;
+
+ std::size_t class_key = token_stream.cursor();
+ token_stream.nextToken();
+
+ WinDeclSpecAST *winDeclSpec = 0;
+ parseWinDeclSpec(winDeclSpec);
+
+ if (token_stream.lookAhead() == Token___attribute__)
+ parse_Attribute__();
+
+ while (token_stream.lookAhead() == Token_identifier
+ && token_stream.lookAhead(1) == Token_identifier)
+ token_stream.nextToken();
+
+ NameAST *name = 0;
+ parseName(name, true);
+
+ BaseClauseAST *bases = 0;
+
+ if (token_stream.lookAhead() == ':') {
+ if (!parseBaseClause(bases))
+ skipUntil('{');
+ }
+
+ if (token_stream.lookAhead() != '{') {
+
+ token_stream.rewind((int) start);
+ return false;
+ }
+
+ ADVANCE('{', "{");
+
+ ClassSpecifierAST *ast = CreateNode<ClassSpecifierAST>(_M_pool);
+ ast->win_decl_specifiers = winDeclSpec;
+ ast->class_key = class_key;
+ ast->name = name;
+ ast->base_clause = bases;
+
+ while (token_stream.lookAhead()) {
+ if (token_stream.lookAhead() == '}')
+ break;
+
+ std::size_t startDecl = token_stream.cursor();
+
+ DeclarationAST *memSpec = 0;
+ if (!parseMemberSpecification(memSpec)) {
+ if (startDecl == token_stream.cursor())
+ token_stream.nextToken(); // skip at least one token
+ skipUntilDeclaration();
+ } else
+ ast->member_specs = snoc(ast->member_specs, memSpec, _M_pool);
+ }
+
+ ADVANCE_NR('}', "}");
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseAccessSpecifier(DeclarationAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ const ListNode<std::size_t> *specs = 0;
+
+ bool done = false;
+ while (!done) {
+ switch (token_stream.lookAhead()) {
+ case Token_signals:
+ case Token_slots:
+ case Token_k_dcop:
+ case Token_k_dcop_signals:
+ case Token_public:
+ case Token_protected:
+ case Token_private:
+ specs = snoc(specs, token_stream.cursor(), _M_pool);
+ token_stream.nextToken();
+ break;
+
+ default:
+ done = true;
+ break;
+ }
+ }
+
+ if (!specs)
+ return false;
+
+ ADVANCE(':', ":");
+
+ AccessSpecifierAST *ast = CreateNode<AccessSpecifierAST>(_M_pool);
+ ast->specs = specs;
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseMemberSpecification(DeclarationAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ if (token_stream.lookAhead() == ';') {
+ token_stream.nextToken();
+ return true;
+ } else if (token_stream.lookAhead() == Token_Q_OBJECT
+ || token_stream.lookAhead() == Token_K_DCOP) {
+ token_stream.nextToken();
+ return true;
+ } else if (parseTypedef(node)) {
+ return true;
+ } else if (parseUsing(node)) {
+ return true;
+ } else if (parseTemplateDeclaration(node)) {
+ return true;
+ } else if (parseAccessSpecifier(node)) {
+ return true;
+ } else if (parseQ_PROPERTY(node)) {
+ return true;
+ } else if (parseQ_ENUMS(node)) {
+ return true;
+ }
+
+ token_stream.rewind((int) start);
+
+ const ListNode<std::size_t> *cv = 0;
+ parseCvQualify(cv);
+
+ const ListNode<std::size_t> *storageSpec = 0;
+ parseStorageClassSpecifier(storageSpec);
+
+ parseCvQualify(cv);
+
+ TypeSpecifierAST *spec = 0;
+ if (parseEnumSpecifier(spec) || parseClassSpecifier(spec)) {
+ parseCvQualify(cv);
+ spec->cv = cv;
+
+ const ListNode<InitDeclaratorAST*> *declarators = 0;
+ parseInitDeclaratorList(declarators);
+ ADVANCE(';', ";");
+
+ SimpleDeclarationAST *ast = CreateNode<SimpleDeclarationAST>(_M_pool);
+ ast->type_specifier = spec;
+ ast->init_declarators = declarators;
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+ }
+
+ token_stream.rewind((int) start);
+ return parseDeclarationInternal(node);
+}
+
+bool Parser::parseCtorInitializer(CtorInitializerAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ CHECK(':');
+
+ CtorInitializerAST *ast = CreateNode<CtorInitializerAST>(_M_pool);
+ ast->colon = start;
+
+ if (!parseMemInitializerList(ast->member_initializers))
+ reportError(("Member initializers expected"));
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseElaboratedTypeSpecifier(TypeSpecifierAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ int tk = token_stream.lookAhead();
+ if (tk == Token_class
+ || tk == Token_struct
+ || tk == Token_union
+ || tk == Token_enum
+ || tk == Token_typename) {
+ std::size_t type = token_stream.cursor();
+ token_stream.nextToken();
+
+ NameAST *name = 0;
+ if (parseName(name, true)) {
+ ElaboratedTypeSpecifierAST *ast
+ = CreateNode<ElaboratedTypeSpecifierAST>(_M_pool);
+
+ ast->type = type;
+ ast->name = name;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+ }
+ }
+
+ token_stream.rewind((int) start);
+ return false;
+}
+
+bool Parser::parseExceptionSpecification(ExceptionSpecificationAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ CHECK(Token_throw);
+ ADVANCE('(', "(");
+
+ ExceptionSpecificationAST *ast = CreateNode<ExceptionSpecificationAST>(_M_pool);
+
+ if (token_stream.lookAhead() == Token_ellipsis) {
+ ast->ellipsis = token_stream.cursor();
+ token_stream.nextToken();
+ } else {
+ parseTypeIdList(ast->type_ids);
+ }
+
+ ADVANCE(')', ")");
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseEnumerator(EnumeratorAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ CHECK(Token_identifier);
+ std::size_t id = token_stream.cursor() - 1;
+
+ EnumeratorAST *ast = CreateNode<EnumeratorAST>(_M_pool);
+ ast->id = id;
+
+ if (token_stream.lookAhead() == '=') {
+ token_stream.nextToken();
+
+ if (!parseConstantExpression(ast->expression))
+ reportError(("Constant expression expected"));
+ }
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseInitDeclarator(InitDeclaratorAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ DeclaratorAST *decl = 0;
+ if (!parseDeclarator(decl))
+ return false;
+
+ if (token_stream.lookAhead(0) == Token_asm) {
+ token_stream.nextToken();
+ skip('(', ')');
+ token_stream.nextToken();
+ }
+
+ InitializerAST *init = 0;
+ parseInitializer(init);
+
+ InitDeclaratorAST *ast = CreateNode<InitDeclaratorAST>(_M_pool);
+ ast->declarator = decl;
+ ast->initializer = init;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseBaseClause(BaseClauseAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ CHECK(':');
+
+ BaseSpecifierAST *baseSpec = 0;
+ if (!parseBaseSpecifier(baseSpec))
+ return false;
+
+ BaseClauseAST *ast = CreateNode<BaseClauseAST>(_M_pool);
+ ast->base_specifiers = snoc(ast->base_specifiers, baseSpec, _M_pool);
+
+ while (token_stream.lookAhead() == ',') {
+ token_stream.nextToken();
+
+ if (!parseBaseSpecifier(baseSpec)) {
+ reportError(("Base class specifier expected"));
+ break;
+ }
+ ast->base_specifiers = snoc(ast->base_specifiers, baseSpec, _M_pool);
+ }
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseInitializer(InitializerAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ int tk = token_stream.lookAhead();
+ if (tk != '=' && tk != '(')
+ return false;
+
+ InitializerAST *ast = CreateNode<InitializerAST>(_M_pool);
+
+ if (tk == '=') {
+ token_stream.nextToken();
+
+ if (!parseInitializerClause(ast->initializer_clause))
+ reportError(("Initializer clause expected"));
+
+ } else if (tk == '(') {
+ token_stream.nextToken();
+ parseCommaExpression(ast->expression);
+ CHECK(')');
+ }
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseMemInitializerList(const ListNode<MemInitializerAST*> *&node)
+{
+ MemInitializerAST *init = 0;
+
+ if (!parseMemInitializer(init))
+ return false;
+
+ node = snoc(node, init, _M_pool);
+
+ while (token_stream.lookAhead() == ',') {
+ token_stream.nextToken();
+
+ if (!parseMemInitializer(init))
+ break;
+
+ node = snoc(node, init, _M_pool);
+ }
+
+ return true;
+}
+
+bool Parser::parseMemInitializer(MemInitializerAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ NameAST *initId = 0;
+ if (!parseName(initId, true)) {
+ reportError(("Identifier expected"));
+ return false;
+ }
+
+ ADVANCE('(', "(");
+ ExpressionAST *expr = 0;
+ parseCommaExpression(expr);
+ ADVANCE(')', ")");
+
+ MemInitializerAST *ast = CreateNode<MemInitializerAST>(_M_pool);
+ ast->initializer_id = initId;
+ ast->expression = expr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTypeIdList(const ListNode<TypeIdAST*> *&node)
+{
+ TypeIdAST *typeId = 0;
+ if (!parseTypeId(typeId))
+ return false;
+
+ node = snoc(node, typeId, _M_pool);
+
+ while (token_stream.lookAhead() == ',') {
+ token_stream.nextToken();
+ if (parseTypeId(typeId)) {
+ node = snoc(node, typeId, _M_pool);
+ } else {
+ reportError(("Type id expected"));
+ break;
+ }
+ }
+
+ return true;
+}
+
+bool Parser::parseBaseSpecifier(BaseSpecifierAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ BaseSpecifierAST *ast = CreateNode<BaseSpecifierAST>(_M_pool);
+
+ if (token_stream.lookAhead() == Token_virtual) {
+ ast->virt = token_stream.cursor();
+ token_stream.nextToken();
+
+ int tk = token_stream.lookAhead();
+ if (tk == Token_public || tk == Token_protected
+ || tk == Token_private) {
+ ast->access_specifier = token_stream.cursor();
+ token_stream.nextToken();
+ }
+ } else {
+ int tk = token_stream.lookAhead();
+ if (tk == Token_public || tk == Token_protected
+ || tk == Token_private) {
+ ast->access_specifier = token_stream.cursor();
+ token_stream.nextToken();
+ }
+
+ if (token_stream.lookAhead() == Token_virtual) {
+ ast->virt = token_stream.cursor();
+ token_stream.nextToken();
+ }
+ }
+
+ if (!parseName(ast->name, true))
+ reportError(("Class name expected"));
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseInitializerClause(InitializerClauseAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ InitializerClauseAST *ast = CreateNode<InitializerClauseAST>(_M_pool);
+
+ if (token_stream.lookAhead() == '{') {
+#if defined(__GNUC__)
+#warning "implement me"
+#endif
+ if (skip('{', '}'))
+ token_stream.nextToken();
+ else
+ reportError(("} missing"));
+ } else {
+ if (!parseAssignmentExpression(ast->expression))
+ reportError(("Expression expected"));
+ }
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parsePtrToMember(PtrToMemberAST *&node)
+{
+#if defined(__GNUC__)
+#warning "implemente me (AST)"
+#endif
+
+ std::size_t start = token_stream.cursor();
+
+ std::size_t global_scope = 0;
+ if (token_stream.lookAhead() == Token_scope) {
+ global_scope = token_stream.cursor();
+ token_stream.nextToken();
+ }
+
+ UnqualifiedNameAST *name = 0;
+ while (token_stream.lookAhead() == Token_identifier) {
+ if (!parseUnqualifiedName(name))
+ break;
+
+ if (token_stream.lookAhead() == Token_scope
+ && token_stream.lookAhead(1) == '*') {
+ token_stream.nextToken();
+ token_stream.nextToken();
+
+ PtrToMemberAST *ast = CreateNode<PtrToMemberAST>(_M_pool);
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+ }
+
+ if (token_stream.lookAhead() == Token_scope)
+ token_stream.nextToken();
+ }
+
+ token_stream.rewind((int) start);
+ return false;
+}
+
+bool Parser::parseUnqualifiedName(UnqualifiedNameAST *&node,
+ bool parseTemplateId)
+{
+ std::size_t start = token_stream.cursor();
+
+ std::size_t tilde = 0;
+ std::size_t id = 0;
+ OperatorFunctionIdAST *operator_id = 0;
+
+ if (token_stream.lookAhead() == Token_identifier) {
+ id = token_stream.cursor();
+ token_stream.nextToken();
+ } else if (token_stream.lookAhead() == '~'
+ && token_stream.lookAhead(1) == Token_identifier) {
+ tilde = token_stream.cursor();
+ token_stream.nextToken(); // skip ~
+
+ id = token_stream.cursor();
+ token_stream.nextToken(); // skip classname
+ } else if (token_stream.lookAhead() == Token_operator) {
+ if (!parseOperatorFunctionId(operator_id))
+ return false;
+ } else {
+ return false;
+ }
+
+ UnqualifiedNameAST *ast = CreateNode<UnqualifiedNameAST>(_M_pool);
+ ast->tilde = tilde;
+ ast->id = id;
+ ast->operator_id = operator_id;
+
+ if (parseTemplateId && !tilde) {
+ std::size_t index = token_stream.cursor();
+
+ if (token_stream.lookAhead() == '<') {
+ token_stream.nextToken();
+
+ // optional template arguments
+ parseTemplateArgumentList(ast->template_arguments);
+
+ if (token_stream.lookAhead() == '>') {
+ token_stream.nextToken();
+ } else {
+ ast->template_arguments = 0;
+ token_stream.rewind((int) index);
+ }
+ }
+ }
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseStringLiteral(StringLiteralAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ if (token_stream.lookAhead() != Token_string_literal)
+ return false;
+
+ StringLiteralAST *ast = CreateNode<StringLiteralAST>(_M_pool);
+
+ while (token_stream.lookAhead() == Token_string_literal) {
+ ast->literals = snoc(ast->literals, token_stream.cursor(), _M_pool);
+ token_stream.nextToken();
+ }
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseExpressionStatement(StatementAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ ExpressionAST *expr = 0;
+ parseCommaExpression(expr);
+
+ ADVANCE(';', ";");
+
+ ExpressionStatementAST *ast = CreateNode<ExpressionStatementAST>(_M_pool);
+ ast->expression = expr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseStatement(StatementAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ switch (token_stream.lookAhead()) {
+ case Token_while:
+ return parseWhileStatement(node);
+
+ case Token_do:
+ return parseDoStatement(node);
+
+ case Token_for:
+ return parseForStatement(node);
+
+ case Token_if:
+ return parseIfStatement(node);
+
+ case Token_switch:
+ return parseSwitchStatement(node);
+
+ case Token_try:
+ return parseTryBlockStatement(node);
+
+ case Token_case:
+ case Token_default:
+ return parseLabeledStatement(node);
+
+ case Token_break:
+ case Token_continue:
+#if defined(__GNUC__)
+#warning "implement me"
+#endif
+ token_stream.nextToken();
+ ADVANCE(';', ";");
+ return true;
+
+ case Token_goto:
+#if defined(__GNUC__)
+#warning "implement me"
+#endif
+ token_stream.nextToken();
+ ADVANCE(Token_identifier, "identifier");
+ ADVANCE(';', ";");
+ return true;
+
+ case Token_return: {
+ token_stream.nextToken();
+ ExpressionAST *expr = 0;
+ parseCommaExpression(expr);
+
+ ADVANCE(';', ";");
+
+ ReturnStatementAST *ast = CreateNode<ReturnStatementAST>(_M_pool);
+ ast->expression = expr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+ return true;
+
+ case '{':
+ return parseCompoundStatement(node);
+
+ case Token_identifier:
+ if (parseLabeledStatement(node))
+ return true;
+ break;
+ }
+
+ return parseExpressionOrDeclarationStatement(node);
+}
+
+bool Parser::parseExpressionOrDeclarationStatement(StatementAST *&node)
+{
+ bool blocked = block_errors(true);
+
+ std::size_t start = token_stream.cursor();
+
+ StatementAST *decl_ast = 0;
+ bool maybe_amb = parseDeclarationStatement(decl_ast);
+ maybe_amb &= token_stream.kind(token_stream.cursor() - 1) == ';';
+
+ std::size_t end = token_stream.cursor();
+
+ token_stream.rewind((int) start);
+ StatementAST *expr_ast = 0;
+ maybe_amb &= parseExpressionStatement(expr_ast);
+ maybe_amb &= token_stream.kind(token_stream.cursor() - 1) == ';';
+
+ if (maybe_amb) {
+ Q_ASSERT(decl_ast && expr_ast);
+ ExpressionOrDeclarationStatementAST *ast =
+ CreateNode<ExpressionOrDeclarationStatementAST>(_M_pool);
+ ast->declaration = decl_ast;
+ ast->expression = expr_ast;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ } else {
+ token_stream.rewind((int) std::max(end, token_stream.cursor()));
+
+ node = decl_ast;
+ if (!node)
+ node = expr_ast;
+ }
+
+ block_errors(blocked);
+
+ if (!node)
+ syntaxError();
+
+ return node != 0;
+}
+
+bool Parser::parseCondition(ConditionAST *&node, bool initRequired)
+{
+ std::size_t start = token_stream.cursor();
+
+ ConditionAST *ast = CreateNode<ConditionAST>(_M_pool);
+ TypeSpecifierAST *spec = 0;
+
+ if (parseTypeSpecifier(spec)) {
+ ast->type_specifier = spec;
+
+ std::size_t declarator_start = token_stream.cursor();
+
+ DeclaratorAST *decl = 0;
+ if (!parseDeclarator(decl)) {
+ token_stream.rewind((int) declarator_start);
+ if (!initRequired && !parseAbstractDeclarator(decl))
+ decl = 0;
+ }
+
+ if (decl && (!initRequired || token_stream.lookAhead() == '=')) {
+ ast->declarator = decl;
+
+ if (token_stream.lookAhead() == '=') {
+ token_stream.nextToken();
+
+ parseExpression(ast->expression);
+ }
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+ }
+ }
+
+ token_stream.rewind((int) start);
+
+ if (!parseCommaExpression(ast->expression))
+ return false;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+
+bool Parser::parseWhileStatement(StatementAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ ADVANCE(Token_while, "while");
+ ADVANCE('(' , "(");
+
+ ConditionAST *cond = 0;
+ if (!parseCondition(cond)) {
+ reportError(("condition expected"));
+ return false;
+ }
+ ADVANCE(')', ")");
+
+ StatementAST *body = 0;
+ if (!parseStatement(body)) {
+ reportError(("statement expected"));
+ return false;
+ }
+
+ WhileStatementAST *ast = CreateNode<WhileStatementAST>(_M_pool);
+ ast->condition = cond;
+ ast->statement = body;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseDoStatement(StatementAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ ADVANCE(Token_do, "do");
+
+ StatementAST *body = 0;
+ if (!parseStatement(body)) {
+ reportError(("statement expected"));
+ //return false;
+ }
+
+ ADVANCE_NR(Token_while, "while");
+ ADVANCE_NR('(' , "(");
+
+ ExpressionAST *expr = 0;
+ if (!parseCommaExpression(expr)) {
+ reportError(("expression expected"));
+ //return false;
+ }
+
+ ADVANCE_NR(')', ")");
+ ADVANCE_NR(';', ";");
+
+ DoStatementAST *ast = CreateNode<DoStatementAST>(_M_pool);
+ ast->statement = body;
+ ast->expression = expr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseForStatement(StatementAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ ADVANCE(Token_for, "for");
+ ADVANCE('(', "(");
+
+ StatementAST *init = 0;
+ if (!parseForInitStatement(init)) {
+ reportError(("for initialization expected"));
+ return false;
+ }
+
+ ConditionAST *cond = 0;
+ parseCondition(cond);
+ ADVANCE(';', ";");
+
+ ExpressionAST *expr = 0;
+ parseCommaExpression(expr);
+ ADVANCE(')', ")");
+
+ StatementAST *body = 0;
+ if (!parseStatement(body))
+ return false;
+
+ ForStatementAST *ast = CreateNode<ForStatementAST>(_M_pool);
+ ast->init_statement = init;
+ ast->condition = cond;
+ ast->expression = expr;
+ ast->statement = body;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseForInitStatement(StatementAST *&node)
+{
+ if (parseDeclarationStatement(node))
+ return true;
+
+ return parseExpressionStatement(node);
+}
+
+bool Parser::parseCompoundStatement(StatementAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ CHECK('{');
+
+ CompoundStatementAST *ast = CreateNode<CompoundStatementAST>(_M_pool);
+
+ while (token_stream.lookAhead()) {
+ if (token_stream.lookAhead() == '}')
+ break;
+
+ std::size_t startStmt = token_stream.cursor();
+
+ StatementAST *stmt = 0;
+ if (!parseStatement(stmt)) {
+ if (startStmt == token_stream.cursor())
+ token_stream.nextToken();
+
+ skipUntilStatement();
+ } else {
+ ast->statements = snoc(ast->statements, stmt, _M_pool);
+ }
+ }
+
+ ADVANCE_NR('}', "}");
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseIfStatement(StatementAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ ADVANCE(Token_if, "if");
+
+ ADVANCE('(' , "(");
+
+ IfStatementAST *ast = CreateNode<IfStatementAST>(_M_pool);
+
+ ConditionAST *cond = 0;
+ if (!parseCondition(cond)) {
+ reportError(("condition expected"));
+ return false;
+ }
+ ADVANCE(')', ")");
+
+ StatementAST *stmt = 0;
+ if (!parseStatement(stmt)) {
+ reportError(("statement expected"));
+ return false;
+ }
+
+ ast->condition = cond;
+ ast->statement = stmt;
+
+ if (token_stream.lookAhead() == Token_else) {
+ token_stream.nextToken();
+
+ if (!parseStatement(ast->else_statement)) {
+ reportError(("statement expected"));
+ return false;
+ }
+ }
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseSwitchStatement(StatementAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+ ADVANCE(Token_switch, "switch");
+
+ ADVANCE('(' , "(");
+
+ ConditionAST *cond = 0;
+ if (!parseCondition(cond)) {
+ reportError(("condition expected"));
+ return false;
+ }
+ ADVANCE(')', ")");
+
+ StatementAST *stmt = 0;
+ if (!parseCompoundStatement(stmt)) {
+ syntaxError();
+ return false;
+ }
+
+ SwitchStatementAST *ast = CreateNode<SwitchStatementAST>(_M_pool);
+ ast->condition = cond;
+ ast->statement = stmt;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseLabeledStatement(StatementAST *&node)
+{
+ switch (token_stream.lookAhead()) {
+ case Token_identifier:
+ case Token_default:
+ if (token_stream.lookAhead(1) == ':') {
+ token_stream.nextToken();
+ token_stream.nextToken();
+
+ StatementAST *stmt = 0;
+ if (parseStatement(stmt)) {
+ node = stmt;
+ return true;
+ }
+ }
+ break;
+
+ case Token_case: {
+ token_stream.nextToken();
+ ExpressionAST *expr = 0;
+ if (!parseConstantExpression(expr)) {
+ reportError(("expression expected"));
+ } else if (token_stream.lookAhead() == Token_ellipsis) {
+ token_stream.nextToken();
+
+ ExpressionAST *expr2 = 0;
+ if (!parseConstantExpression(expr2))
+ reportError(("expression expected"));
+ }
+ ADVANCE(':', ":");
+
+ StatementAST *stmt = 0;
+ if (parseStatement(stmt)) {
+ node = stmt;
+ return true;
+ }
+ }
+ break;
+
+ }
+
+ return false;
+}
+
+bool Parser::parseBlockDeclaration(DeclarationAST *&node)
+{
+ switch (token_stream.lookAhead()) {
+ case Token_typedef:
+ return parseTypedef(node);
+ case Token_using:
+ return parseUsing(node);
+ case Token_asm:
+ return parseAsmDefinition(node);
+ case Token_namespace:
+ return parseNamespaceAliasDefinition(node);
+ }
+
+ std::size_t start = token_stream.cursor();
+
+ const ListNode<std::size_t> *cv = 0;
+ parseCvQualify(cv);
+
+ const ListNode<std::size_t> *storageSpec = 0;
+ parseStorageClassSpecifier(storageSpec);
+
+ parseCvQualify(cv);
+
+ TypeSpecifierAST *spec = 0;
+ if (!parseTypeSpecifierOrClassSpec(spec)) { // replace with simpleTypeSpecifier?!?!
+ token_stream.rewind((int) start);
+ return false;
+ }
+
+ parseCvQualify(cv);
+ spec->cv = cv;
+
+ const ListNode<InitDeclaratorAST*> *declarators = 0;
+ parseInitDeclaratorList(declarators);
+
+ if (token_stream.lookAhead() != ';') {
+ token_stream.rewind((int) start);
+ return false;
+ }
+ token_stream.nextToken();
+
+ SimpleDeclarationAST *ast = CreateNode<SimpleDeclarationAST>(_M_pool);
+ ast->type_specifier = spec;
+ ast->init_declarators = declarators;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseNamespaceAliasDefinition(DeclarationAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ CHECK(Token_namespace);
+
+ NamespaceAliasDefinitionAST *ast
+ = CreateNode<NamespaceAliasDefinitionAST>(_M_pool);
+
+ ADVANCE(Token_identifier, "identifier");
+ ast->namespace_name = token_stream.cursor() - 1;
+
+ ADVANCE('=', "=");
+
+ if (!parseName(ast->alias_name))
+ reportError(("Namespace name expected"));
+
+ ADVANCE(';', ";");
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseDeclarationStatement(StatementAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ DeclarationAST *decl = 0;
+ if (!parseBlockDeclaration(decl))
+ return false;
+
+ DeclarationStatementAST *ast = CreateNode<DeclarationStatementAST>(_M_pool);
+ ast->declaration = decl;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseDeclarationInternal(DeclarationAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ // that is for the case '__declspec(dllexport) int ...' or
+ // '__declspec(dllexport) inline int ...', etc.
+ WinDeclSpecAST *winDeclSpec = 0;
+ parseWinDeclSpec(winDeclSpec);
+
+ const ListNode<std::size_t> *funSpec = 0;
+ bool hasFunSpec = parseFunctionSpecifier(funSpec);
+
+ const ListNode<std::size_t> *cv = 0;
+ parseCvQualify(cv);
+
+ const ListNode<std::size_t> *storageSpec = 0;
+ bool hasStorageSpec = parseStorageClassSpecifier(storageSpec);
+
+ if (hasStorageSpec && !hasFunSpec)
+ hasFunSpec = parseFunctionSpecifier(funSpec);
+
+ // that is for the case 'friend __declspec(dllexport) ....'
+ parseWinDeclSpec(winDeclSpec);
+
+ if (!cv)
+ parseCvQualify(cv);
+
+ int index = (int) token_stream.cursor();
+ NameAST *name = 0;
+ if (parseName(name, true) && token_stream.lookAhead() == '(') {
+ // no type specifier, maybe a constructor or a cast operator??
+
+ token_stream.rewind((int) index);
+
+ InitDeclaratorAST *declarator = 0;
+ if (parseInitDeclarator(declarator)) {
+ switch (token_stream.lookAhead()) {
+ case ';': {
+ token_stream.nextToken();
+
+ SimpleDeclarationAST *ast
+ = CreateNode<SimpleDeclarationAST>(_M_pool);
+
+ ast->storage_specifiers = storageSpec;
+ ast->function_specifiers = funSpec;
+ ast->init_declarators = snoc(ast->init_declarators,
+ declarator, _M_pool);
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+ return true;
+
+ case ':': {
+ CtorInitializerAST *ctorInit = 0;
+ StatementAST *funBody = 0;
+
+ if (parseCtorInitializer(ctorInit)
+ && parseFunctionBody(funBody)) {
+ FunctionDefinitionAST *ast
+ = CreateNode<FunctionDefinitionAST>(_M_pool);
+
+ ast->storage_specifiers = storageSpec;
+ ast->function_specifiers = funSpec;
+ ast->init_declarator = declarator;
+ ast->function_body = funBody;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+ }
+ }
+ break;
+
+ case '{': {
+ StatementAST *funBody = 0;
+ if (parseFunctionBody(funBody)) {
+ FunctionDefinitionAST *ast
+ = CreateNode<FunctionDefinitionAST>(_M_pool);
+
+ ast->storage_specifiers = storageSpec;
+ ast->function_specifiers = funSpec;
+ ast->init_declarator = declarator;
+ ast->function_body = funBody;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+ }
+ }
+ break;
+
+ case '(':
+ case '[':
+ // ops!! it seems a declarator
+ goto start_decl;
+ break;
+ }
+
+ }
+ }
+
+start_decl:
+ token_stream.rewind((int) index);
+
+ if (token_stream.lookAhead() == Token_const
+ && token_stream.lookAhead(1) == Token_identifier
+ && token_stream.lookAhead(2) == '=') {
+ // constant definition
+ token_stream.nextToken(); // skip const
+
+ const ListNode<InitDeclaratorAST*> *declarators = 0;
+ if (!parseInitDeclaratorList(declarators)) {
+ syntaxError();
+ return false;
+ }
+
+ ADVANCE(';', ";");
+
+#if defined(__GNUC__)
+#warning "mark the ast as constant"
+#endif
+ SimpleDeclarationAST *ast = CreateNode<SimpleDeclarationAST>(_M_pool);
+ ast->init_declarators = declarators;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+ }
+
+ TypeSpecifierAST *spec = 0;
+ if (parseTypeSpecifier(spec)) {
+ Q_ASSERT(spec);
+
+ if (!hasFunSpec)
+ parseFunctionSpecifier(funSpec); // e.g. "void inline"
+
+ spec->cv = cv;
+
+ const ListNode<InitDeclaratorAST*> *declarators = 0;
+ InitDeclaratorAST *decl = 0;
+ int startDeclarator = (int) token_stream.cursor();
+ bool maybeFunctionDefinition = false;
+
+ if (token_stream.lookAhead() != ';') {
+ if (parseInitDeclarator(decl) && token_stream.lookAhead() == '{') {
+ // function definition
+ maybeFunctionDefinition = true;
+ } else {
+ token_stream.rewind((int) startDeclarator);
+ if (!parseInitDeclaratorList(declarators)) {
+ syntaxError();
+ return false;
+ }
+ }
+ }
+
+ switch (token_stream.lookAhead()) {
+ case ';': {
+ token_stream.nextToken();
+ SimpleDeclarationAST *ast
+ = CreateNode<SimpleDeclarationAST>(_M_pool);
+
+ ast->storage_specifiers = storageSpec;
+ ast->function_specifiers = funSpec;
+ ast->type_specifier = spec;
+ ast->win_decl_specifiers = winDeclSpec;
+ ast->init_declarators = declarators;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+ return true;
+
+ case '{': {
+ if (!maybeFunctionDefinition) {
+ syntaxError();
+ return false;
+ }
+
+ StatementAST *funBody = 0;
+ if (parseFunctionBody(funBody)) {
+ FunctionDefinitionAST *ast
+ = CreateNode<FunctionDefinitionAST>(_M_pool);
+
+ ast->win_decl_specifiers = winDeclSpec;
+ ast->storage_specifiers = storageSpec;
+ ast->function_specifiers = funSpec;
+ ast->type_specifier = spec;
+ ast->init_declarator = decl;
+ ast->function_body = funBody;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+ }
+ }
+ break;
+ } // end switch
+ }
+
+ syntaxError();
+ return false;
+}
+
+bool Parser::skipFunctionBody(StatementAST *&)
+{
+#if defined(__GNUC__)
+#warning "Parser::skipFunctionBody() -- implement me"
+#endif
+ Q_ASSERT(0); // ### not implemented
+ return 0;
+}
+
+bool Parser::parseFunctionBody(StatementAST *&node)
+{
+ if (control->skipFunctionBody())
+ return skipFunctionBody(node);
+
+ return parseCompoundStatement(node);
+}
+
+bool Parser::parseTypeSpecifierOrClassSpec(TypeSpecifierAST *&node)
+{
+ if (parseClassSpecifier(node))
+ return true;
+ else if (parseEnumSpecifier(node))
+ return true;
+ else if (parseTypeSpecifier(node))
+ return true;
+
+ return false;
+}
+
+bool Parser::parseTryBlockStatement(StatementAST *&node)
+{
+#if defined(__GNUC__)
+#warning "implement me"
+#endif
+ CHECK(Token_try);
+
+ StatementAST *stmt = 0;
+ if (!parseCompoundStatement(stmt)) {
+ syntaxError();
+ return false;
+ }
+
+ if (token_stream.lookAhead() != Token_catch) {
+ reportError(("catch expected"));
+ return false;
+ }
+
+ while (token_stream.lookAhead() == Token_catch) {
+ token_stream.nextToken();
+ ADVANCE('(', "(");
+ ConditionAST *cond = 0;
+ if (token_stream.lookAhead() == Token_ellipsis) {
+ token_stream.nextToken();
+ } else if (!parseCondition(cond, false)) {
+ reportError(("condition expected"));
+ return false;
+ }
+ ADVANCE(')', ")");
+
+ StatementAST *body = 0;
+ if (!parseCompoundStatement(body)) {
+ syntaxError();
+ return false;
+ }
+ }
+
+ node = stmt;
+ return true;
+}
+
+bool Parser::parsePrimaryExpression(ExpressionAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ PrimaryExpressionAST *ast = CreateNode<PrimaryExpressionAST>(_M_pool);
+
+ switch (token_stream.lookAhead()) {
+ case Token_string_literal:
+ parseStringLiteral(ast->literal);
+ break;
+
+ case Token_number_literal:
+ case Token_char_literal:
+ case Token_true:
+ case Token_false:
+ case Token_this:
+ ast->token = token_stream.cursor();
+ token_stream.nextToken();
+ break;
+
+ case '(':
+ token_stream.nextToken();
+
+ if (token_stream.lookAhead() == '{') {
+ if (!parseCompoundStatement(ast->expression_statement))
+ return false;
+ } else {
+ if (!parseExpression(ast->sub_expression))
+ return false;
+ }
+
+ CHECK(')');
+ break;
+
+ default:
+ if (!parseName(ast->name))
+ return false;
+
+ break;
+ }
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+
+/*
+ postfix-expression-internal:
+ [ expression ]
+ ( expression-list [opt] )
+ (.|->) template [opt] id-expression
+ (.|->) pseudo-destructor-name
+ ++
+ --
+*/
+bool Parser::parsePostfixExpressionInternal(ExpressionAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ switch (token_stream.lookAhead()) {
+ case '[': {
+ token_stream.nextToken();
+ ExpressionAST *expr = 0;
+ parseExpression(expr);
+ CHECK(']');
+
+ SubscriptExpressionAST *ast
+ = CreateNode<SubscriptExpressionAST>(_M_pool);
+
+ ast->subscript = expr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+ return true;
+
+ case '(': {
+ token_stream.nextToken();
+ ExpressionAST *expr = 0;
+ parseExpression(expr);
+ CHECK(')');
+
+ FunctionCallAST *ast = CreateNode<FunctionCallAST>(_M_pool);
+ ast->arguments = expr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+ return true;
+
+ case '.':
+ case Token_arrow: {
+ std::size_t op = token_stream.cursor();
+ token_stream.nextToken();
+
+ std::size_t templ = 0;
+ if (token_stream.lookAhead() == Token_template) {
+ templ = token_stream.cursor();
+ token_stream.nextToken();
+ }
+
+ int saved = int(token_stream.cursor());
+ NameAST *name = 0;
+
+ if (parseName(name, true) && name->unqualified_name
+ && name->unqualified_name->template_arguments
+ && token_stream.lookAhead() == '(') {
+ // a template method call
+ // ### reverse the logic
+ } else {
+ token_stream.rewind(saved);
+ name = 0;
+
+ if (!parseName(name, templ != 0))
+ return false;
+ }
+
+ ClassMemberAccessAST *ast = CreateNode<ClassMemberAccessAST>(_M_pool);
+ ast->op = op;
+ ast->name = name;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+ return true;
+
+ case Token_incr:
+ case Token_decr: {
+ std::size_t op = token_stream.cursor();
+ token_stream.nextToken();
+
+ IncrDecrExpressionAST *ast = CreateNode<IncrDecrExpressionAST>(_M_pool);
+ ast->op = op;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+/*
+ postfix-expression:
+ simple-type-specifier ( expression-list [opt] )
+ primary-expression postfix-expression-internal*
+*/
+bool Parser::parsePostfixExpression(ExpressionAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ switch (token_stream.lookAhead()) {
+ case Token_dynamic_cast:
+ case Token_static_cast:
+ case Token_reinterpret_cast:
+ case Token_const_cast: {
+ std::size_t castOp = token_stream.cursor();
+ token_stream.nextToken();
+
+ CHECK('<');
+ TypeIdAST *typeId = 0;
+ parseTypeId(typeId);
+ CHECK('>');
+
+ CHECK('(');
+ ExpressionAST *expr = 0;
+ parseCommaExpression(expr);
+ CHECK(')');
+
+ CppCastExpressionAST *ast = CreateNode<CppCastExpressionAST>(_M_pool);
+ ast->op = castOp;
+ ast->type_id = typeId;
+ ast->expression = expr;
+
+ ExpressionAST *e = 0;
+ while (parsePostfixExpressionInternal(e))
+ ast->sub_expressions = snoc(ast->sub_expressions, e, _M_pool);
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+ return true;
+
+ case Token_typename: {
+ std::size_t token = token_stream.cursor();
+ token_stream.nextToken();
+
+ NameAST* name = 0;
+ if (!parseName(name, true))
+ return false;
+
+ CHECK('(');
+ ExpressionAST *expr = 0;
+ parseCommaExpression(expr);
+ CHECK(')');
+
+ TypeIdentificationAST *ast = CreateNode<TypeIdentificationAST>(_M_pool);
+ ast->typename_token = token;
+ ast->name = name;
+ ast->expression = expr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+ return true;
+
+ case Token_typeid: {
+ token_stream.nextToken();
+
+ CHECK('(');
+ TypeIdAST *typeId = 0;
+ parseTypeId(typeId);
+ CHECK(')');
+
+ TypeIdentificationAST *ast = CreateNode<TypeIdentificationAST>(_M_pool);
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+ return true;
+
+ default:
+ break;
+ }
+
+ std::size_t saved_pos = token_stream.cursor();
+
+ TypeSpecifierAST *typeSpec = 0;
+ ExpressionAST *expr = 0;
+
+ // let's try to parse a type
+ NameAST *name = 0;
+ if (parseName(name, true)) {
+ Q_ASSERT(name->unqualified_name);
+
+ bool has_template_args = name->unqualified_name->template_arguments != 0;
+
+ if (has_template_args && token_stream.lookAhead() == '(') {
+ ExpressionAST *cast_expr = 0;
+ if (parseCastExpression(cast_expr)
+ && cast_expr->kind == AST::Kind_CastExpression) {
+ token_stream.rewind((int) saved_pos);
+ parsePrimaryExpression(expr);
+ goto L_no_rewind;
+ }
+ }
+ }
+
+ token_stream.rewind((int) saved_pos);
+
+L_no_rewind:
+ if (!expr && parseSimpleTypeSpecifier(typeSpec)
+ && token_stream.lookAhead() == '(') {
+ token_stream.nextToken(); // skip '('
+ parseCommaExpression(expr);
+ CHECK(')');
+ } else if (expr) {
+ typeSpec = 0;
+ } else {
+ typeSpec = 0;
+ token_stream.rewind((int) start);
+
+ if (!parsePrimaryExpression(expr))
+ return false;
+ }
+
+ const ListNode<ExpressionAST*> *sub_expressions = 0;
+ ExpressionAST *sub_expression = 0;
+
+ while (parsePostfixExpressionInternal(sub_expression))
+ sub_expressions = snoc(sub_expressions, sub_expression, _M_pool);
+
+ if (sub_expressions || !expr || (typeSpec && expr)) {
+ PostfixExpressionAST *ast = CreateNode<PostfixExpressionAST>(_M_pool);
+ ast->type_specifier = typeSpec;
+ ast->expression = expr;
+ ast->sub_expressions = sub_expressions;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ } else
+ node = expr;
+
+ return true;
+}
+
+bool Parser::parseUnaryExpression(ExpressionAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ switch (token_stream.lookAhead()) {
+ case Token_incr:
+ case Token_decr:
+ case '*':
+ case '&':
+ case '+':
+ case '-':
+ case '!':
+ case '~': {
+ std::size_t op = token_stream.cursor();
+ token_stream.nextToken();
+
+ ExpressionAST *expr = 0;
+ if (!parseCastExpression(expr))
+ return false;
+
+ UnaryExpressionAST *ast = CreateNode<UnaryExpressionAST>(_M_pool);
+ ast->op = op;
+ ast->expression = expr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+ return true;
+
+ case Token_sizeof: {
+ std::size_t sizeof_token = token_stream.cursor();
+ token_stream.nextToken();
+
+ SizeofExpressionAST *ast = CreateNode<SizeofExpressionAST>(_M_pool);
+ ast->sizeof_token = sizeof_token;
+
+ std::size_t index = token_stream.cursor();
+ if (token_stream.lookAhead() == '(') {
+ token_stream.nextToken();
+ if (parseTypeId(ast->type_id) && token_stream.lookAhead() == ')') {
+ token_stream.nextToken(); // skip )
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ return true;
+ }
+
+ ast->type_id = 0;
+ token_stream.rewind((int) index);
+ }
+
+ if (!parseUnaryExpression(ast->expression))
+ return false;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ return true;
+ }
+
+ default:
+ break;
+ }
+
+ int token = token_stream.lookAhead();
+
+ if (token == Token_new
+ || (token == Token_scope && token_stream.lookAhead(1) == Token_new))
+ return parseNewExpression(node);
+
+ if (token == Token_delete
+ || (token == Token_scope && token_stream.lookAhead(1) == Token_delete))
+ return parseDeleteExpression(node);
+
+ return parsePostfixExpression(node);
+}
+
+bool Parser::parseNewExpression(ExpressionAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ NewExpressionAST *ast = CreateNode<NewExpressionAST>(_M_pool);
+
+ if (token_stream.lookAhead() == Token_scope
+ && token_stream.lookAhead(1) == Token_new) {
+ ast->scope_token = token_stream.cursor();
+ token_stream.nextToken();
+ }
+
+ CHECK(Token_new);
+ ast->new_token = token_stream.cursor() - 1;
+
+ if (token_stream.lookAhead() == '(') {
+ token_stream.nextToken();
+ parseCommaExpression(ast->expression);
+ CHECK(')');
+ }
+
+ if (token_stream.lookAhead() == '(') {
+ token_stream.nextToken();
+ parseTypeId(ast->type_id);
+ CHECK(')');
+ } else {
+ parseNewTypeId(ast->new_type_id);
+ }
+
+ parseNewInitializer(ast->new_initializer);
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseNewTypeId(NewTypeIdAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ TypeSpecifierAST *typeSpec = 0;
+ if (!parseTypeSpecifier(typeSpec))
+ return false;
+
+ NewTypeIdAST *ast = CreateNode<NewTypeIdAST>(_M_pool);
+ ast->type_specifier = typeSpec;
+
+ parseNewDeclarator(ast->new_declarator);
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseNewDeclarator(NewDeclaratorAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ NewDeclaratorAST *ast = CreateNode<NewDeclaratorAST>(_M_pool);
+
+ PtrOperatorAST *ptrOp = 0;
+ if (parsePtrOperator(ptrOp)) {
+ ast->ptr_op = ptrOp;
+ parseNewDeclarator(ast->sub_declarator);
+ }
+
+ while (token_stream.lookAhead() == '[') {
+ token_stream.nextToken();
+ ExpressionAST *expr = 0;
+ parseExpression(expr);
+ ast->expressions = snoc(ast->expressions, expr, _M_pool);
+ ADVANCE(']', "]");
+ }
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseNewInitializer(NewInitializerAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ CHECK('(');
+
+ NewInitializerAST *ast = CreateNode<NewInitializerAST>(_M_pool);
+
+ parseCommaExpression(ast->expression);
+
+ CHECK(')');
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseDeleteExpression(ExpressionAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ DeleteExpressionAST *ast = CreateNode<DeleteExpressionAST>(_M_pool);
+
+ if (token_stream.lookAhead() == Token_scope
+ && token_stream.lookAhead(1) == Token_delete) {
+ ast->scope_token = token_stream.cursor();
+ token_stream.nextToken();
+ }
+
+ CHECK(Token_delete);
+ ast->delete_token = token_stream.cursor() - 1;
+
+ if (token_stream.lookAhead() == '[') {
+ ast->lbracket_token = token_stream.cursor();
+ token_stream.nextToken();
+ CHECK(']');
+ ast->rbracket_token = token_stream.cursor() - 1;
+ }
+
+ if (!parseCastExpression(ast->expression))
+ return false;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseCastExpression(ExpressionAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ if (token_stream.lookAhead() == '(') {
+ token_stream.nextToken();
+
+ CastExpressionAST *ast = CreateNode<CastExpressionAST>(_M_pool);
+
+ if (parseTypeId(ast->type_id)) {
+ if (token_stream.lookAhead() == ')') {
+ token_stream.nextToken();
+
+ if (parseCastExpression(ast->expression)) {
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+ }
+ }
+ }
+ }
+
+ token_stream.rewind((int) start);
+ return parseUnaryExpression(node);
+}
+
+bool Parser::parsePmExpression(ExpressionAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ if (!parseCastExpression(node) || !node) // ### fixme
+ return false;
+
+ while (token_stream.lookAhead() == Token_ptrmem) {
+ std::size_t op = token_stream.cursor();
+ token_stream.nextToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (!parseCastExpression(rightExpr))
+ return false;
+
+ BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+ ast->op = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+
+ return true;
+}
+
+bool Parser::parseMultiplicativeExpression(ExpressionAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ if (!parsePmExpression(node))
+ return false;
+
+ while (token_stream.lookAhead() == '*'
+ || token_stream.lookAhead() == '/'
+ || token_stream.lookAhead() == '%') {
+ std::size_t op = token_stream.cursor();
+ token_stream.nextToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (!parsePmExpression(rightExpr))
+ return false;
+
+ BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+ ast->op = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+
+ return true;
+}
+
+
+bool Parser::parseAdditiveExpression(ExpressionAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ if (!parseMultiplicativeExpression(node))
+ return false;
+
+ while (token_stream.lookAhead() == '+' || token_stream.lookAhead() == '-') {
+ std::size_t op = token_stream.cursor();
+ token_stream.nextToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (!parseMultiplicativeExpression(rightExpr))
+ return false;
+
+ BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+ ast->op = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+
+ return true;
+}
+
+bool Parser::parseShiftExpression(ExpressionAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ if (!parseAdditiveExpression(node))
+ return false;
+
+ while (token_stream.lookAhead() == Token_shift) {
+ std::size_t op = token_stream.cursor();
+ token_stream.nextToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (!parseAdditiveExpression(rightExpr))
+ return false;
+
+ BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+ ast->op = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+
+ return true;
+}
+
+bool Parser::parseRelationalExpression(ExpressionAST *&node, bool templArgs)
+{
+ std::size_t start = token_stream.cursor();
+
+ if (!parseShiftExpression(node))
+ return false;
+
+ while (token_stream.lookAhead() == '<'
+ || (token_stream.lookAhead() == '>' && !templArgs)
+ || token_stream.lookAhead() == Token_leq
+ || token_stream.lookAhead() == Token_geq) {
+ std::size_t op = token_stream.cursor();
+ token_stream.nextToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (!parseShiftExpression(rightExpr))
+ return false;
+
+ BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+ ast->op = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+
+ return true;
+}
+
+bool Parser::parseEqualityExpression(ExpressionAST *&node, bool templArgs)
+{
+ std::size_t start = token_stream.cursor();
+
+ if (!parseRelationalExpression(node, templArgs))
+ return false;
+
+ while (token_stream.lookAhead() == Token_eq
+ || token_stream.lookAhead() == Token_not_eq) {
+ std::size_t op = token_stream.cursor();
+ token_stream.nextToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (!parseRelationalExpression(rightExpr, templArgs))
+ return false;
+
+ BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+ ast->op = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+
+ return true;
+}
+
+bool Parser::parseAndExpression(ExpressionAST *&node, bool templArgs)
+{
+ std::size_t start = token_stream.cursor();
+
+ if (!parseEqualityExpression(node, templArgs))
+ return false;
+
+ while (token_stream.lookAhead() == '&') {
+ std::size_t op = token_stream.cursor();
+ token_stream.nextToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (!parseEqualityExpression(rightExpr, templArgs))
+ return false;
+
+ BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+ ast->op = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+
+ return true;
+}
+
+bool Parser::parseExclusiveOrExpression(ExpressionAST *&node, bool templArgs)
+{
+ std::size_t start = token_stream.cursor();
+
+ if (!parseAndExpression(node, templArgs))
+ return false;
+
+ while (token_stream.lookAhead() == '^') {
+ std::size_t op = token_stream.cursor();
+ token_stream.nextToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (!parseAndExpression(rightExpr, templArgs))
+ return false;
+
+ BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+ ast->op = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+
+ return true;
+}
+
+bool Parser::parseInclusiveOrExpression(ExpressionAST *&node, bool templArgs)
+{
+ std::size_t start = token_stream.cursor();
+
+ if (!parseExclusiveOrExpression(node, templArgs))
+ return false;
+
+ while (token_stream.lookAhead() == '|') {
+ std::size_t op = token_stream.cursor();
+ token_stream.nextToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (!parseExclusiveOrExpression(rightExpr, templArgs))
+ return false;
+
+ BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+ ast->op = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+
+ return true;
+}
+
+bool Parser::parseLogicalAndExpression(ExpressionAST *&node, bool templArgs)
+{
+ std::size_t start = token_stream.cursor();
+
+ if (!parseInclusiveOrExpression(node, templArgs))
+ return false;
+
+ while (token_stream.lookAhead() == Token_and) {
+ std::size_t op = token_stream.cursor();
+ token_stream.nextToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (!parseInclusiveOrExpression(rightExpr, templArgs))
+ return false;
+
+ BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+ ast->op = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+
+ return true;
+}
+
+bool Parser::parseLogicalOrExpression(ExpressionAST *&node, bool templArgs)
+{
+ std::size_t start = token_stream.cursor();
+
+ if (!parseLogicalAndExpression(node, templArgs))
+ return false;
+
+ while (token_stream.lookAhead() == Token_or) {
+ std::size_t op = token_stream.cursor();
+ token_stream.nextToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (!parseLogicalAndExpression(rightExpr, templArgs))
+ return false;
+
+ BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+ ast->op = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+
+ return true;
+}
+
+bool Parser::parseConditionalExpression(ExpressionAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ if (!parseLogicalOrExpression(node))
+ return false;
+
+ if (token_stream.lookAhead() == '?') {
+ token_stream.nextToken();
+
+ ExpressionAST *leftExpr = 0;
+ if (!parseExpression(leftExpr))
+ return false;
+
+ CHECK(':');
+
+ ExpressionAST *rightExpr = 0;
+ if (!parseAssignmentExpression(rightExpr))
+ return false;
+
+ ConditionalExpressionAST *ast
+ = CreateNode<ConditionalExpressionAST>(_M_pool);
+
+ ast->condition = node;
+ ast->left_expression = leftExpr;
+ ast->right_expression = rightExpr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+
+ return true;
+}
+
+bool Parser::parseAssignmentExpression(ExpressionAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ if (token_stream.lookAhead() == Token_throw && !parseThrowExpression(node))
+ return false;
+ else if (!parseConditionalExpression(node))
+ return false;
+
+ while (token_stream.lookAhead() == Token_assign
+ || token_stream.lookAhead() == '=') {
+ std::size_t op = token_stream.cursor();
+ token_stream.nextToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (!parseConditionalExpression(rightExpr))
+ return false;
+
+ BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+ ast->op = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+
+ return true;
+}
+
+bool Parser::parseConstantExpression(ExpressionAST *&node)
+{
+ return parseConditionalExpression(node);
+}
+
+bool Parser::parseExpression(ExpressionAST *&node)
+{
+ return parseCommaExpression(node);
+}
+
+bool Parser::parseCommaExpression(ExpressionAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ if (!parseAssignmentExpression(node))
+ return false;
+
+ while (token_stream.lookAhead() == ',') {
+ std::size_t op = token_stream.cursor();
+ token_stream.nextToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (!parseAssignmentExpression(rightExpr))
+ return false;
+
+ BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+ ast->op = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+
+ return true;
+}
+
+bool Parser::parseThrowExpression(ExpressionAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ CHECK(Token_throw);
+
+ ThrowExpressionAST *ast = CreateNode<ThrowExpressionAST>(_M_pool);
+ ast->throw_token = token_stream.cursor() - 1;
+
+ parseAssignmentExpression(ast->expression);
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseQ_ENUMS(DeclarationAST *&node)
+{
+ if (token_stream.lookAhead() != Token_Q_ENUMS)
+ return false;
+
+ if (token_stream.lookAhead(1) != '(')
+ return false;
+
+ token_stream.nextToken();
+ token_stream.nextToken();
+
+ int firstToken = token_stream.cursor();
+ while (token_stream.lookAhead() != ')')
+ token_stream.nextToken();
+
+ QEnumsAST *ast = CreateNode<QEnumsAST>(_M_pool);
+ UPDATE_POS(ast, firstToken, token_stream.cursor());
+ node = ast;
+
+ token_stream.nextToken();
+
+ return true;
+}
+
+bool Parser::parseQ_PROPERTY(DeclarationAST *&node)
+{
+ if (token_stream.lookAhead() != Token_Q_PROPERTY)
+ return false;
+
+ if (token_stream.lookAhead(1) != '(')
+ return false;
+
+ token_stream.nextToken();
+ token_stream.nextToken();
+
+ int firstToken = token_stream.cursor();
+ while (token_stream.lookAhead() != ')')
+ token_stream.nextToken();
+
+ QPropertyAST *ast = CreateNode<QPropertyAST>(_M_pool);
+ UPDATE_POS(ast, firstToken, token_stream.cursor());
+ node = ast;
+
+// const Token &t1 = token_stream[firstToken];
+// const Token &t2 = token_stream[token_stream.cursor()];
+// printf("property: %s\n",
+// qPrintable(QString::fromLatin1(t1.text + t1.position, t2.position - t1.position)));
+
+ token_stream.nextToken();
+
+ return true;
+}
+
+bool Parser::block_errors(bool block)
+{
+ bool current = _M_block_errors;
+ _M_block_errors = block;
+ return current;
+}
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
+
diff --git a/parser/parser.h b/parser/parser.h
new file mode 100644
index 00000000..4b0c76c8
--- /dev/null
+++ b/parser/parser.h
@@ -0,0 +1,198 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+
+#ifndef PARSER_H
+#define PARSER_H
+
+#include "ast.h"
+#include "lexer.h"
+
+#include <QtCore/QString>
+
+class FileSymbol;
+class Control;
+
+class Parser
+{
+public:
+ Parser(Control *control);
+ ~Parser();
+
+ LocationManager &location() { return _M_location; }
+
+ TranslationUnitAST *parse(const char *contents, std::size_t size, pool *p);
+
+private:
+ void reportError(const QString& msg);
+ void syntaxError();
+ void tokenRequiredError(int expected);
+
+public:
+ bool skipFunctionBody(StatementAST *&node);
+
+public:
+ bool parse_Attribute__();
+ bool parseAbstractDeclarator(DeclaratorAST *&node);
+ bool parseAccessSpecifier(DeclarationAST *&node);
+ bool parseAdditiveExpression(ExpressionAST *&node);
+ bool parseAndExpression(ExpressionAST *&node, bool templArgs = false);
+ bool parseAsmDefinition(DeclarationAST *&node);
+ bool parseAssignmentExpression(ExpressionAST *&node);
+ bool parseBaseClause(BaseClauseAST *&node);
+ bool parseBaseSpecifier(BaseSpecifierAST *&node);
+ bool parseBlockDeclaration(DeclarationAST *&node);
+ bool parseCastExpression(ExpressionAST *&node);
+ bool parseClassSpecifier(TypeSpecifierAST *&node);
+ bool parseForwardDeclarationSpecifier(TypeSpecifierAST *&node);
+ bool parseCommaExpression(ExpressionAST *&node);
+ bool parseCompoundStatement(StatementAST *&node);
+ bool parseCondition(ConditionAST *&node, bool initRequired = true);
+ bool parseConditionalExpression(ExpressionAST *&node);
+ bool parseConstantExpression(ExpressionAST *&node);
+ bool parseCtorInitializer(CtorInitializerAST *&node);
+ bool parseCvQualify(const ListNode<std::size_t> *&node);
+ bool parseDeclaration(DeclarationAST *&node);
+ bool parseDeclarationInternal(DeclarationAST *&node);
+ bool parseDeclarationStatement(StatementAST *&node);
+ bool parseDeclarator(DeclaratorAST *&node);
+ bool parseDeleteExpression(ExpressionAST *&node);
+ bool parseDoStatement(StatementAST *&node);
+ bool parseElaboratedTypeSpecifier(TypeSpecifierAST *&node);
+ bool parseEnumSpecifier(TypeSpecifierAST *&node);
+ bool parseEnumerator(EnumeratorAST *&node);
+ bool parseEqualityExpression(ExpressionAST *&node,
+ bool templArgs = false);
+ bool parseExceptionSpecification(ExceptionSpecificationAST *&node);
+ bool parseExclusiveOrExpression(ExpressionAST *&node,
+ bool templArgs = false);
+ 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 parseFunctionSpecifier(const ListNode<std::size_t> *&node);
+ bool parseIfStatement(StatementAST *&node);
+ bool parseInclusiveOrExpression(ExpressionAST *&node,
+ bool templArgs = false);
+ bool parseInitDeclarator(InitDeclaratorAST *&node);
+ bool parseInitDeclaratorList(const ListNode<InitDeclaratorAST*> *&node);
+ bool parseInitializer(InitializerAST *&node);
+ bool parseInitializerClause(InitializerClauseAST *&node);
+ bool parseLabeledStatement(StatementAST *&node);
+ bool parseLinkageBody(LinkageBodyAST *&node);
+ bool parseLinkageSpecification(DeclarationAST *&node);
+ bool parseLogicalAndExpression(ExpressionAST *&node,
+ bool templArgs = false);
+ bool parseLogicalOrExpression(ExpressionAST *&node,
+ bool templArgs = false);
+ bool parseMemInitializer(MemInitializerAST *&node);
+ bool parseMemInitializerList(const ListNode<MemInitializerAST*> *&node);
+ bool parseMemberSpecification(DeclarationAST *&node);
+ bool parseMultiplicativeExpression(ExpressionAST *&node);
+ bool parseName(NameAST *&node, bool acceptTemplateId = false);
+ 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 parseOperatorFunctionId(OperatorFunctionIdAST *&node);
+ bool parseParameterDeclaration(ParameterDeclarationAST *&node);
+ bool parseParameterDeclarationClause(ParameterDeclarationClauseAST *&node);
+ bool parseParameterDeclarationList(const ListNode<ParameterDeclarationAST*> *&node);
+ bool parsePmExpression(ExpressionAST *&node);
+ bool parsePostfixExpression(ExpressionAST *&node);
+ bool parsePostfixExpressionInternal(ExpressionAST *&node);
+ bool parsePrimaryExpression(ExpressionAST *&node);
+ bool parsePtrOperator(PtrOperatorAST *&node);
+ bool parsePtrToMember(PtrToMemberAST *&node);
+ bool parseRelationalExpression(ExpressionAST *&node,
+ bool templArgs = false);
+ bool parseShiftExpression(ExpressionAST *&node);
+ bool parseSimpleTypeSpecifier(TypeSpecifierAST *&node,
+ bool onlyIntegral = false);
+ bool parseStatement(StatementAST *&node);
+ bool parseStorageClassSpecifier(const ListNode<std::size_t> *&node);
+ bool parseStringLiteral(StringLiteralAST *&node);
+ bool parseSwitchStatement(StatementAST *&node);
+ bool parseTemplateArgument(TemplateArgumentAST *&node);
+ bool parseTemplateArgumentList(const ListNode<TemplateArgumentAST*> *&node,
+ bool reportError = true);
+ bool parseTemplateDeclaration(DeclarationAST *&node);
+ bool parseTemplateParameter(TemplateParameterAST *&node);
+ bool parseTemplateParameterList(const ListNode<TemplateParameterAST*> *&node);
+ bool parseThrowExpression(ExpressionAST *&node);
+ bool parseTranslationUnit(TranslationUnitAST *&node);
+ bool parseTryBlockStatement(StatementAST *&node);
+ bool parseTypeId(TypeIdAST *&node);
+ bool parseTypeIdList(const ListNode<TypeIdAST*> *&node);
+ bool parseTypeParameter(TypeParameterAST *&node);
+ bool parseTypeSpecifier(TypeSpecifierAST *&node);
+ bool parseTypeSpecifierOrClassSpec(TypeSpecifierAST *&node);
+ bool parseTypedef(DeclarationAST *&node);
+ bool parseUnaryExpression(ExpressionAST *&node);
+ bool parseUnqualifiedName(UnqualifiedNameAST *&node,
+ bool parseTemplateId = true);
+ bool parseUsing(DeclarationAST *&node);
+ bool parseUsingDirective(DeclarationAST *&node);
+ bool parseWhileStatement(StatementAST *&node);
+ bool parseWinDeclSpec(WinDeclSpecAST *&node);
+
+ bool parseQ_PROPERTY(DeclarationAST *&node);
+ bool parseQ_ENUMS(DeclarationAST *&node);
+
+ bool skipUntil(int token);
+ bool skipUntilDeclaration();
+ bool skipUntilStatement();
+ bool skip(int l, int r);
+
+ void advance();
+
+ // private:
+ TokenStream token_stream;
+ LocationTable location_table;
+ LocationTable line_table;
+
+ bool block_errors(bool block);
+
+private:
+ QString tokenText(AST *) const;
+
+ LocationManager _M_location;
+ Control *control;
+ Lexer lexer;
+ pool *_M_pool;
+ bool _M_block_errors;
+
+private:
+ Parser(const Parser& source);
+ void operator = (const Parser& source);
+};
+
+#endif
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/r++.macros b/parser/r++.macros
new file mode 100644
index 00000000..455276c8
--- /dev/null
+++ b/parser/r++.macros
@@ -0,0 +1,28 @@
+
+#define __attribute__(a...)
+#define __typeof__ __typeof
+
+#define __extension
+#define __extension__
+
+#define __restrict
+#define __restrict__
+
+#define __volatile volatile
+#define __volatile__ volatile
+
+#define __inline inline
+#define __inline__ inline
+
+#define __const const
+#define __const__ const
+
+#define __asm asm
+#define __asm__ asm
+
+#define __GNUC__ 3
+//#define __GNUC_MINOR__ 4
+
+#define __ROBC__ 0
+#define __ROBC_MINOR__ 1
+
diff --git a/parser/rpp-allocator.h b/parser/rpp-allocator.h
new file mode 100644
index 00000000..313895f0
--- /dev/null
+++ b/parser/rpp-allocator.h
@@ -0,0 +1,24 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include "parser/rxx_allocator.h"
diff --git a/parser/rpp/builtin-macros.cpp b/parser/rpp/builtin-macros.cpp
new file mode 100644
index 00000000..1b0fc06a
--- /dev/null
+++ b/parser/rpp/builtin-macros.cpp
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
diff --git a/parser/rpp/pp-cctype.h b/parser/rpp/pp-cctype.h
new file mode 100644
index 00000000..5b0bf477
--- /dev/null
+++ b/parser/rpp/pp-cctype.h
@@ -0,0 +1,57 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright 2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef PP_CCTYPE_H
+#define PP_CCTYPE_H
+
+#include <cctype>
+
+namespace rpp
+{
+
+inline bool pp_isalpha(int __ch)
+{
+ return std::isalpha((unsigned char) __ch) != 0;
+}
+
+inline bool pp_isalnum(int __ch)
+{
+ return std::isalnum((unsigned char) __ch) != 0;
+}
+
+inline bool pp_isdigit(int __ch)
+{
+ return std::isdigit((unsigned char) __ch) != 0;
+}
+
+inline bool pp_isspace(int __ch)
+{
+ return std::isspace((unsigned char) __ch) != 0;
+}
+
+} // namespace rpp
+
+#endif // PP_CCTYPE_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/rpp/pp-configuration b/parser/rpp/pp-configuration
new file mode 100644
index 00000000..15586dd8
--- /dev/null
+++ b/parser/rpp/pp-configuration
@@ -0,0 +1,86 @@
+#define __DBL_MIN_EXP__ (-1021)
+#define __FLT_MIN__ 1.17549435e-38F
+#define __CHAR_BIT__ 8
+#define __WCHAR_MAX__ 2147483647
+#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
+#define __FLT_EVAL_METHOD__ 2
+#define __DBL_MIN_10_EXP__ (-307)
+#define __FINITE_MATH_ONLY__ 0
+#define __GNUC_PATCHLEVEL__ 2
+#define __SHRT_MAX__ 32767
+#define __LDBL_MAX__ 1.18973149535723176502e+4932L
+#define __UINTMAX_TYPE__ long long unsigned int
+#define __linux 1
+#define __unix 1
+#define __LDBL_MAX_EXP__ 16384
+#define __linux__ 1
+#define __SCHAR_MAX__ 127
+#define __USER_LABEL_PREFIX__
+#define __STDC_HOSTED__ 1
+#define __LDBL_HAS_INFINITY__ 1
+#define __DBL_DIG__ 15
+#define __FLT_EPSILON__ 1.19209290e-7F
+#define __GXX_WEAK__ 1
+#define __LDBL_MIN__ 3.36210314311209350626e-4932L
+#define __unix__ 1
+#define __DECIMAL_DIG__ 21
+#define __gnu_linux__ 1
+#define __LDBL_HAS_QUIET_NAN__ 1
+#define __GNUC__ 4
+#define __DBL_MAX__ 1.7976931348623157e+308
+#define __DBL_HAS_INFINITY__ 1
+#define __cplusplus 1
+#define __DEPRECATED 1
+#define __DBL_MAX_EXP__ 1024
+#define __GNUG__ 4
+#define __LONG_LONG_MAX__ 9223372036854775807LL
+#define __GXX_ABI_VERSION 1002
+#define __FLT_MIN_EXP__ (-125)
+#define __DBL_MIN__ 2.2250738585072014e-308
+#define __FLT_MIN_10_EXP__ (-37)
+#define __DBL_HAS_QUIET_NAN__ 1
+#define __REGISTER_PREFIX__
+#define __NO_INLINE__ 1
+#define __i386 1
+#define __FLT_MANT_DIG__ 24
+#define __VERSION__ "4.0.2 20050808 (prerelease) (Ubuntu 4.0.1-4ubuntu9)"
+#define i386 1
+#define __i486__ 1
+#define unix 1
+#define __i386__ 1
+#define __SIZE_TYPE__ unsigned int
+#define __ELF__ 1
+#define __FLT_RADIX__ 2
+#define __LDBL_EPSILON__ 1.08420217248550443401e-19L
+#define __FLT_HAS_QUIET_NAN__ 1
+#define __FLT_MAX_10_EXP__ 38
+#define __LONG_MAX__ 2147483647L
+#define __FLT_HAS_INFINITY__ 1
+#define linux 1
+#define __EXCEPTIONS 1
+#define __LDBL_MANT_DIG__ 64
+#define __WCHAR_TYPE__ int
+#define __FLT_DIG__ 6
+#define __INT_MAX__ 2147483647
+#define __i486 1
+#define __FLT_MAX_EXP__ 128
+#define __DBL_MANT_DIG__ 53
+#define __WINT_TYPE__ unsigned int
+#define __LDBL_MIN_EXP__ (-16381)
+#define __LDBL_MAX_10_EXP__ 4932
+#define __DBL_EPSILON__ 2.2204460492503131e-16
+#define __tune_i486__ 1
+#define __INTMAX_MAX__ 9223372036854775807LL
+#define __FLT_DENORM_MIN__ 1.40129846e-45F
+#define __FLT_MAX__ 3.40282347e+38F
+#define __INTMAX_TYPE__ long long int
+#define __GNUC_MINOR__ 0
+#define __DBL_MAX_10_EXP__ 308
+#define __LDBL_DENORM_MIN__ 3.64519953188247460253e-4951L
+#define __PTRDIFF_TYPE__ int
+#define __LDBL_MIN_10_EXP__ (-4931)
+#define __LDBL_DIG__ 18
+#define _GNU_SOURCE 1
+
+
+#define __STDC__
diff --git a/parser/rpp/pp-engine-bits.h b/parser/rpp/pp-engine-bits.h
new file mode 100644
index 00000000..7594ab79
--- /dev/null
+++ b/parser/rpp/pp-engine-bits.h
@@ -0,0 +1,1252 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright 2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef PP_ENGINE_BITS_H
+#define PP_ENGINE_BITS_H
+
+#include "pp.h"
+#include <sys/stat.h>
+#include <cstdio>
+#include <iostream>
+
+namespace rpp
+{
+
+inline std::string pp::fix_file_path(std::string const &filename) const
+{
+#if defined (PP_OS_WIN)
+ std::string s = filename;
+ for (std::string::iterator it = s.begin(); it != s.end(); ++it) {
+ if (*it == '/')
+ *it = '\\';
+ }
+ return s;
+#else
+ return filename;
+#endif
+}
+
+inline bool pp::is_absolute(std::string const &filename) const
+{
+#if defined(PP_OS_WIN)
+ return filename.length() >= 3
+ && filename.at(1) == ':'
+ && (filename.at(2) == '\\' || filename.at(2) == '/');
+#else
+ return filename.length() >= 1
+ && filename.at(0) == '/';
+#endif
+}
+
+template <typename _OutputIterator>
+void pp::file(std::string const &filename, _OutputIterator __result)
+{
+ FILE *fp = std::fopen(filename.c_str(), "rb");
+ if (fp != 0) {
+ std::string was = env.current_file;
+ env.current_file = filename;
+ file(fp, __result);
+ env.current_file = was;
+ }
+ //else
+ //std::cerr << "** WARNING file ``" << filename << " not found!" << std::endl;
+}
+
+template <typename _OutputIterator>
+void pp::file(FILE *fp, _OutputIterator __result)
+{
+ assert(fp != 0);
+
+#if defined (HAVE_MMAP)
+ struct stat st;
+ fstat(FILENO(fp), &st);
+ std::size_t size = st.st_size;
+ char *buffer = 0;
+ buffer = (char *) ::mmap(0, size, PROT_READ, MAP_SHARED, FILENO(fp), 0);
+ fclose(fp);
+ if (!buffer || buffer == (char*) - 1)
+ return;
+ this->operator()(buffer, buffer + size, __result);
+ ::munmap(buffer, size);
+#else
+ std::string buffer;
+ while (!feof(fp)) {
+ char tmp[1024];
+ int read = (int) fread(tmp, sizeof(char), 1023, fp);
+ tmp[read] = '\0';
+ buffer += tmp;
+ }
+ fclose(fp);
+ this->operator()(buffer.c_str(), buffer.c_str() + buffer.size(), __result);
+#endif
+}
+
+template <typename _InputIterator>
+bool pp::find_header_protection(_InputIterator __first, _InputIterator __last, std::string *__prot)
+{
+ int was = env.current_line;
+
+ while (__first != __last) {
+ if (pp_isspace(*__first)) {
+ if (*__first == '\n')
+ ++env.current_line;
+
+ ++__first;
+ } else if (_PP_internal::comment_p(__first, __last)) {
+ __first = skip_comment_or_divop(__first, __last);
+ env.current_line += skip_comment_or_divop.lines;
+ } else if (*__first == '#') {
+ __first = skip_blanks(++__first, __last);
+ env.current_line += skip_blanks.lines;
+
+ if (__first != __last && *__first == 'i') {
+ _InputIterator __begin = __first;
+ __first = skip_identifier(__begin, __last);
+ env.current_line += skip_identifier.lines;
+
+ std::string __directive(__begin, __first);
+
+ if (__directive == "ifndef") {
+ __first = skip_blanks(__first, __last);
+ env.current_line += skip_blanks.lines;
+
+ __begin = __first;
+ __first = skip_identifier(__first, __last);
+ env.current_line += skip_identifier.lines;
+
+ if (__begin != __first && __first != __last) {
+ __prot->assign(__begin, __first);
+ return true;
+ }
+ }
+ }
+ break;
+ } else
+ break;
+ }
+
+ env.current_line = was;
+ return false;
+}
+
+inline pp::PP_DIRECTIVE_TYPE pp::find_directive(char const *__directive, std::size_t __size) const
+{
+ switch (__size) {
+ case 2:
+ if (__directive[0] == 'i'
+ && __directive[1] == 'f')
+ return PP_IF;
+ break;
+
+ case 4:
+ if (__directive[0] == 'e' && !strcmp(__directive, "elif"))
+ return PP_ELIF;
+ else if (__directive[0] == 'e' && !strcmp(__directive, "else"))
+ return PP_ELSE;
+ break;
+
+ case 5:
+ if (__directive[0] == 'i' && !strcmp(__directive, "ifdef"))
+ return PP_IFDEF;
+ else if (__directive[0] == 'u' && !strcmp(__directive, "undef"))
+ return PP_UNDEF;
+ else if (__directive[0] == 'e') {
+ if (!strcmp(__directive, "endif"))
+ return PP_ENDIF;
+ else if (!strcmp(__directive, "error"))
+ return PP_ERROR;
+ }
+ break;
+
+ case 6:
+ if (__directive[0] == 'i' && !strcmp(__directive, "ifndef"))
+ return PP_IFNDEF;
+ else if (__directive[0] == 'd' && !strcmp(__directive, "define"))
+ return PP_DEFINE;
+ else if (__directive[0] == 'p' && !strcmp(__directive, "pragma"))
+ return PP_PRAGMA;
+ break;
+
+ case 7:
+ if (__directive[0] == 'i' && !strcmp(__directive, "include"))
+ return PP_INCLUDE;
+ else if (!strcmp(__directive, "warning"))
+ return PP_WARNING;
+ break;
+
+ case 12:
+ if (__directive[0] == 'i' && !strcmp(__directive, "include_next"))
+ return PP_INCLUDE_NEXT;
+ break;
+
+ default:
+ break;
+ }
+ std::cerr << "** WARNING unknown directive '#" << __directive << "' at " << env.current_file << ":" << env.current_line << std::endl;
+ return PP_UNKNOWN_DIRECTIVE;
+}
+
+inline bool pp::file_isdir(std::string const &__filename) const
+{
+ struct stat __st;
+#if defined(PP_OS_WIN)
+ if (stat(__filename.c_str(), &__st) == 0)
+ return (__st.st_mode & _S_IFDIR) == _S_IFDIR;
+ else
+ return false;
+#else
+ if (lstat(__filename.c_str(), &__st) == 0)
+ return (__st.st_mode & S_IFDIR) == S_IFDIR;
+ else
+ return false;
+#endif
+}
+
+inline bool pp::file_exists(std::string const &__filename) const
+{
+ struct stat __st;
+#if defined(PP_OS_WIN)
+ return stat(__filename.c_str(), &__st) == 0;
+#else
+ return lstat(__filename.c_str(), &__st) == 0;
+#endif
+}
+
+inline FILE *pp::find_include_file(std::string const &__input_filename, std::string *__filepath,
+ INCLUDE_POLICY __include_policy, bool __skip_current_path) const
+{
+ assert(__filepath != 0);
+ assert(! __input_filename.empty());
+
+ __filepath->assign(__input_filename);
+
+ if (is_absolute(*__filepath))
+ return std::fopen(__filepath->c_str(), "r");
+
+ if (! env.current_file.empty())
+ _PP_internal::extract_file_path(env.current_file, __filepath);
+
+ if (__include_policy == INCLUDE_LOCAL && ! __skip_current_path) {
+ std::string __tmp(*__filepath);
+ __tmp += __input_filename;
+
+ if (file_exists(__tmp) && !file_isdir(__tmp)) {
+ __filepath->append(__input_filename);
+ return std::fopen(__filepath->c_str(), "r");
+ }
+ }
+
+ std::vector<std::string>::const_iterator it = include_paths.begin();
+
+ if (__skip_current_path) {
+ it = std::find(include_paths.begin(), include_paths.end(), *__filepath);
+
+ if (it != include_paths.end())
+ ++it;
+
+ else
+ it = include_paths.begin();
+ }
+
+ for (; it != include_paths.end(); ++it) {
+ if (__skip_current_path && it == include_paths.begin())
+ continue;
+
+ __filepath->assign(*it);
+ __filepath->append(__input_filename);
+
+ if (file_exists(*__filepath) && !file_isdir(*__filepath))
+ return std::fopen(__filepath->c_str(), "r");
+
+#ifdef Q_OS_MAC
+ // try in Framework path on Mac, if there is a path in front
+ // ### what about escaped slashes?
+ size_t slashPos = __input_filename.find('/');
+ if (slashPos != std::string::npos) {
+ __filepath->assign(*it);
+ __filepath->append(__input_filename.substr(0, slashPos));
+ __filepath->append(".framework/Headers/");
+ __filepath->append(__input_filename.substr(slashPos + 1, std::string::npos));
+ std::cerr << *__filepath << "\n";
+
+ if (file_exists(*__filepath) && !file_isdir(*__filepath))
+ return fopen(__filepath->c_str(), "r");
+ }
+#endif // Q_OS_MAC
+ }
+
+ return 0;
+}
+
+template <typename _InputIterator, typename _OutputIterator>
+_InputIterator pp::handle_directive(char const *__directive, std::size_t __size,
+ _InputIterator __first, _InputIterator __last, _OutputIterator __result)
+{
+ __first = skip_blanks(__first, __last);
+
+ PP_DIRECTIVE_TYPE d = find_directive(__directive, __size);
+ switch (d) {
+ case PP_DEFINE:
+ if (! skipping())
+ return handle_define(__first, __last);
+ break;
+
+ case PP_INCLUDE:
+ case PP_INCLUDE_NEXT:
+ if (! skipping())
+ return handle_include(d == PP_INCLUDE_NEXT, __first, __last, __result);
+ break;
+
+ case PP_UNDEF:
+ if (! skipping())
+ return handle_undef(__first, __last);
+ break;
+
+ case PP_ELIF:
+ return handle_elif(__first, __last);
+
+ case PP_ELSE:
+ return handle_else(__first, __last);
+
+ case PP_ENDIF:
+ return handle_endif(__first, __last);
+
+ case PP_IF:
+ return handle_if(__first, __last);
+
+ case PP_IFDEF:
+ return handle_ifdef(false, __first, __last);
+
+ case PP_IFNDEF:
+ return handle_ifdef(true, __first, __last);
+
+ default:
+ break;
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator, typename _OutputIterator>
+_InputIterator pp::handle_include(bool __skip_current_path, _InputIterator __first, _InputIterator __last,
+ _OutputIterator __result)
+{
+ if (pp_isalpha(*__first) || *__first == '_') {
+ pp_macro_expander expand_include(env);
+ std::string name;
+ name.reserve(255);
+ expand_include(__first, __last, std::back_inserter(name));
+ std::string::iterator it = skip_blanks(name.begin(), name.end());
+ assert(it != name.end() && (*it == '<' || *it == '"'));
+ handle_include(__skip_current_path, it, name.end(), __result);
+ return __first;
+ }
+
+ assert(*__first == '<' || *__first == '"');
+ int quote = (*__first == '"') ? '"' : '>';
+ ++__first;
+
+ _InputIterator end_name = __first;
+ for (; end_name != __last; ++end_name) {
+ assert(*end_name != '\n');
+
+ if (*end_name == quote)
+ break;
+ }
+
+ std::string filename(__first, end_name);
+
+#ifdef PP_OS_WIN
+ std::replace(filename.begin(), filename.end(), '/', '\\');
+#endif
+
+ std::string filepath;
+ FILE *fp = find_include_file(filename, &filepath, quote == '>' ? INCLUDE_GLOBAL : INCLUDE_LOCAL, __skip_current_path);
+
+#if defined (PP_HOOK_ON_FILE_INCLUDED)
+ PP_HOOK_ON_FILE_INCLUDED(env.current_file, fp ? filepath : filename, fp);
+#endif
+
+ if (fp != 0) {
+ std::string old_file = env.current_file;
+ env.current_file = filepath;
+ int __saved_lines = env.current_line;
+
+ env.current_line = 1;
+ //output_line (env.current_file, 1, __result);
+
+ file(fp, __result);
+
+ // restore the file name and the line position
+ env.current_file = old_file;
+ env.current_line = __saved_lines;
+
+ // sync the buffer
+ _PP_internal::output_line(env.current_file, env.current_line, __result);
+ }
+#ifndef RPP_JAMBI
+// else
+// std::cerr << "*** WARNING " << filename << ": No such file or directory" << std::endl;
+#endif
+
+ return __first;
+}
+
+template <typename _InputIterator, typename _OutputIterator>
+void pp::operator()(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
+{
+#ifndef PP_NO_SMART_HEADER_PROTECTION
+ std::string __prot;
+ __prot.reserve(255);
+ pp_fast_string __tmp(__prot.c_str(), __prot.size());
+
+ if (find_header_protection(__first, __last, &__prot)
+ && env.resolve(&__tmp) != 0) {
+ // std::cerr << "** DEBUG found header protection:" << __prot << std::endl;
+ return;
+ }
+#endif
+
+ env.current_line = 1;
+ char __buffer[512];
+
+ while (true) {
+ __first = skip_blanks(__first, __last);
+ env.current_line += skip_blanks.lines;
+
+ if (__first == __last)
+ break;
+ else if (*__first == '#') {
+ assert(*__first == '#');
+ __first = skip_blanks(++__first, __last);
+ env.current_line += skip_blanks.lines;
+
+ _InputIterator end_id = skip_identifier(__first, __last);
+ env.current_line += skip_identifier.lines;
+ std::size_t __size = end_id - __first;
+
+ assert(__size < 512);
+ char *__cp = __buffer;
+ std::copy(__first, end_id, __cp);
+ __cp[__size] = '\0';
+
+ end_id = skip_blanks(end_id, __last);
+ __first = skip(end_id, __last);
+
+ int was = env.current_line;
+ (void) handle_directive(__buffer, __size, end_id, __first, __result);
+
+ if (env.current_line != was) {
+ env.current_line = was;
+ _PP_internal::output_line(env.current_file, env.current_line, __result);
+ }
+ } else if (*__first == '\n') {
+ // ### compress the line
+ *__result++ = *__first++;
+ ++env.current_line;
+ } else if (skipping())
+ __first = skip(__first, __last);
+ else {
+ _PP_internal::output_line(env.current_file, env.current_line, __result);
+ __first = expand(__first, __last, __result);
+ env.current_line += expand.lines;
+
+ if (expand.generated_lines)
+ _PP_internal::output_line(env.current_file, env.current_line, __result);
+ }
+ }
+}
+
+inline pp::pp(pp_environment &__env):
+ env(__env), expand(env)
+{
+ iflevel = 0;
+ _M_skipping[iflevel] = 0;
+ _M_true_test[iflevel] = 0;
+}
+
+inline std::back_insert_iterator<std::vector<std::string> > pp::include_paths_inserter()
+{
+ return std::back_inserter(include_paths);
+}
+
+inline std::vector<std::string>::iterator pp::include_paths_begin()
+{
+ return include_paths.begin();
+}
+
+inline std::vector<std::string>::iterator pp::include_paths_end()
+{
+ return include_paths.end();
+}
+
+inline std::vector<std::string>::const_iterator pp::include_paths_begin() const
+{
+ return include_paths.begin();
+}
+
+inline std::vector<std::string>::const_iterator pp::include_paths_end() const
+{
+ return include_paths.end();
+}
+
+inline void pp::push_include_path(std::string const &__path)
+{
+ if (__path.empty() || __path [__path.size() - 1] != PATH_SEPARATOR) {
+ std::string __tmp(__path);
+ __tmp += PATH_SEPARATOR;
+ include_paths.push_back(__tmp);
+ }
+
+ else
+ include_paths.push_back(__path);
+}
+
+template <typename _InputIterator>
+_InputIterator pp::handle_define(_InputIterator __first, _InputIterator __last)
+{
+ pp_macro macro;
+#if defined (PP_WITH_MACRO_POSITION)
+ macro.file = pp_symbol::get(env.current_file);
+#endif
+ std::string definition;
+
+ __first = skip_blanks(__first, __last);
+ _InputIterator end_macro_name = skip_identifier(__first, __last);
+ pp_fast_string const *macro_name = pp_symbol::get(__first, end_macro_name);
+ __first = end_macro_name;
+
+ if (__first != __last && *__first == '(') {
+ macro.function_like = true;
+ macro.formals.reserve(5);
+
+ __first = skip_blanks(++__first, __last); // skip '('
+ _InputIterator arg_end = skip_identifier(__first, __last);
+ if (__first != arg_end)
+ macro.formals.push_back(pp_symbol::get(__first, arg_end));
+
+ __first = skip_blanks(arg_end, __last);
+
+ if (*__first == '.') {
+ macro.variadics = true;
+ while (*__first == '.')
+ ++__first;
+ }
+
+ while (__first != __last && *__first == ',') {
+ __first = skip_blanks(++__first, __last);
+
+ arg_end = skip_identifier(__first, __last);
+ if (__first != arg_end)
+ macro.formals.push_back(pp_symbol::get(__first, arg_end));
+
+ __first = skip_blanks(arg_end, __last);
+
+ if (*__first == '.') {
+ macro.variadics = true;
+ while (*__first == '.')
+ ++__first;
+ }
+ }
+
+ assert(*__first == ')');
+ ++__first;
+ }
+
+ __first = skip_blanks(__first, __last);
+
+ while (__first != __last && *__first != '\n') {
+ if (*__first == '/') {
+ __first = skip_comment_or_divop(__first, __last);
+ env.current_line += skip_comment_or_divop.lines;
+ }
+
+ if (*__first == '\\') {
+ _InputIterator __begin = __first;
+ __begin = skip_blanks(++__begin, __last);
+
+ if (__begin != __last && *__begin == '\n') {
+ ++macro.lines;
+ __first = skip_blanks(++__begin, __last);
+ definition += ' ';
+ continue;
+ }
+ }
+
+ definition += *__first++;
+ }
+
+ macro.definition = pp_symbol::get(definition);
+ env.bind(macro_name, macro);
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::skip(_InputIterator __first, _InputIterator __last)
+{
+ pp_skip_string_literal skip_string_literal;
+ pp_skip_char_literal skip_char_literal;
+
+ while (__first != __last && *__first != '\n') {
+ if (*__first == '/') {
+ __first = skip_comment_or_divop(__first, __last);
+ env.current_line += skip_comment_or_divop.lines;
+ } else if (*__first == '"') {
+ __first = skip_string_literal(__first, __last);
+ env.current_line += skip_string_literal.lines;
+ } else if (*__first == '\'') {
+ __first = skip_char_literal(__first, __last);
+ env.current_line += skip_char_literal.lines;
+ } else if (*__first == '\\') {
+ __first = skip_blanks(++__first, __last);
+ env.current_line += skip_blanks.lines;
+
+ if (__first != __last && *__first == '\n') {
+ ++__first;
+ ++env.current_line;
+ }
+ } else
+ ++__first;
+ }
+
+ return __first;
+}
+
+inline bool pp::test_if_level()
+{
+ bool result = !_M_skipping[iflevel++];
+ _M_skipping[iflevel] = _M_skipping[iflevel - 1];
+ _M_true_test[iflevel] = false;
+ return result;
+}
+
+inline int pp::skipping() const
+{
+ return _M_skipping[iflevel];
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_primary(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ bool expect_paren = false;
+ int token;
+ __first = next_token(__first, __last, &token);
+
+ switch (token) {
+ case TOKEN_NUMBER:
+ result->set_long(token_value);
+ break;
+
+ case TOKEN_UNUMBER:
+ result->set_ulong(token_uvalue);
+ break;
+
+ case TOKEN_DEFINED:
+ __first = next_token(__first, __last, &token);
+
+ if (token == '(') {
+ expect_paren = true;
+ __first = next_token(__first, __last, &token);
+ }
+
+ if (token != TOKEN_IDENTIFIER) {
+ std::cerr << "** WARNING expected ``identifier'' found:" << char(token) << std::endl;
+ result->set_long(0);
+ break;
+ }
+
+ result->set_long(env.resolve(token_text->c_str(), token_text->size()) != 0);
+
+ next_token(__first, __last, &token); // skip '('
+
+ if (expect_paren) {
+ _InputIterator next = next_token(__first, __last, &token);
+ if (token != ')')
+ std::cerr << "** WARNING expected ``)''" << std::endl;
+ else
+ __first = next;
+ }
+ break;
+
+ case TOKEN_IDENTIFIER:
+ result->set_long(0);
+ break;
+
+ case '-':
+ __first = eval_primary(__first, __last, result);
+ result->set_long(- result->l);
+ return __first;
+
+ case '+':
+ __first = eval_primary(__first, __last, result);
+ return __first;
+
+ case '!':
+ __first = eval_primary(__first, __last, result);
+ result->set_long(result->is_zero());
+ return __first;
+
+ case '(':
+ __first = eval_constant_expression(__first, __last, result);
+ next_token(__first, __last, &token);
+
+ if (token != ')')
+ std::cerr << "** WARNING expected ``)'' = " << token << std::endl;
+ else
+ __first = next_token(__first, __last, &token);
+ break;
+
+ default:
+ result->set_long(0);
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_multiplicative(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ __first = eval_primary(__first, __last, result);
+
+ int token;
+ _InputIterator next = next_token(__first, __last, &token);
+
+ while (token == '*' || token == '/' || token == '%') {
+ Value value;
+ __first = eval_primary(next, __last, &value);
+
+ if (token == '*')
+ result->op_mult(value);
+ else if (token == '/') {
+ if (value.is_zero()) {
+ std::cerr << "** WARNING division by zero" << std::endl;
+ result->set_long(0);
+ } else
+ result->op_div(value);
+ } else {
+ if (value.is_zero()) {
+ std::cerr << "** WARNING division by zero" << std::endl;
+ result->set_long(0);
+ } else
+ result->op_mod(value);
+ }
+ next = next_token(__first, __last, &token);
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_additive(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ __first = eval_multiplicative(__first, __last, result);
+
+ int token;
+ _InputIterator next = next_token(__first, __last, &token);
+
+ while (token == '+' || token == '-') {
+ Value value;
+ __first = eval_multiplicative(next, __last, &value);
+
+ if (token == '+')
+ result->op_add(value);
+ else
+ result->op_sub(value);
+ next = next_token(__first, __last, &token);
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_shift(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ __first = eval_additive(__first, __last, result);
+
+ int token;
+ _InputIterator next = next_token(__first, __last, &token);
+
+ while (token == TOKEN_LT_LT || token == TOKEN_GT_GT) {
+ Value value;
+ __first = eval_additive(next, __last, &value);
+
+ if (token == TOKEN_LT_LT)
+ result->op_lhs(value);
+ else
+ result->op_rhs(value);
+ next = next_token(__first, __last, &token);
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_relational(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ __first = eval_shift(__first, __last, result);
+
+ int token;
+ _InputIterator next = next_token(__first, __last, &token);
+
+ while (token == '<'
+ || token == '>'
+ || token == TOKEN_LT_EQ
+ || token == TOKEN_GT_EQ) {
+ Value value;
+ __first = eval_shift(next, __last, &value);
+
+ switch (token) {
+ default:
+ assert(0);
+ break;
+
+ case '<':
+ result->op_lt(value);
+ break;
+
+ case '>':
+ result->op_gt(value);
+ break;
+
+ case TOKEN_LT_EQ:
+ result->op_le(value);
+ break;
+
+ case TOKEN_GT_EQ:
+ result->op_ge(value);
+ break;
+ }
+ next = next_token(__first, __last, &token);
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_equality(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ __first = eval_relational(__first, __last, result);
+
+ int token;
+ _InputIterator next = next_token(__first, __last, &token);
+
+ while (token == TOKEN_EQ_EQ || token == TOKEN_NOT_EQ) {
+ Value value;
+ __first = eval_relational(next, __last, &value);
+
+ if (token == TOKEN_EQ_EQ)
+ result->op_eq(value);
+ else
+ result->op_ne(value);
+ next = next_token(__first, __last, &token);
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_and(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ __first = eval_equality(__first, __last, result);
+
+ int token;
+ _InputIterator next = next_token(__first, __last, &token);
+
+ while (token == '&') {
+ Value value;
+ __first = eval_equality(next, __last, &value);
+ result->op_bit_and(value);
+ next = next_token(__first, __last, &token);
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_xor(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ __first = eval_and(__first, __last, result);
+
+ int token;
+ _InputIterator next = next_token(__first, __last, &token);
+
+ while (token == '^') {
+ Value value;
+ __first = eval_and(next, __last, &value);
+ result->op_bit_xor(value);
+ next = next_token(__first, __last, &token);
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_or(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ __first = eval_xor(__first, __last, result);
+
+ int token;
+ _InputIterator next = next_token(__first, __last, &token);
+
+ while (token == '|') {
+ Value value;
+ __first = eval_xor(next, __last, &value);
+ result->op_bit_or(value);
+ next = next_token(__first, __last, &token);
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_logical_and(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ __first = eval_or(__first, __last, result);
+
+ int token;
+ _InputIterator next = next_token(__first, __last, &token);
+
+ while (token == TOKEN_AND_AND) {
+ Value value;
+ __first = eval_or(next, __last, &value);
+ result->op_and(value);
+ next = next_token(__first, __last, &token);
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_logical_or(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ __first = eval_logical_and(__first, __last, result);
+
+ int token;
+ _InputIterator next = next_token(__first, __last, &token);
+
+ while (token == TOKEN_OR_OR) {
+ Value value;
+ __first = eval_logical_and(next, __last, &value);
+ result->op_or(value);
+ next = next_token(__first, __last, &token);
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_constant_expression(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ __first = eval_logical_or(__first, __last, result);
+
+ int token;
+ _InputIterator next = next_token(__first, __last, &token);
+
+ if (token == '?') {
+ Value left_value;
+ __first = eval_constant_expression(next, __last, &left_value);
+ __first = skip_blanks(__first, __last);
+
+ __first = next_token(__first, __last, &token);
+ if (token == ':') {
+ Value right_value;
+ __first = eval_constant_expression(__first, __last, &right_value);
+
+ *result = !result->is_zero() ? left_value : right_value;
+ } else {
+ std::cerr << "** WARNING expected ``:'' = " << int (token) << std::endl;
+ *result = left_value;
+ }
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_expression(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ return __first = eval_constant_expression(skip_blanks(__first, __last), __last, result);
+}
+
+template <typename _InputIterator>
+_InputIterator pp::handle_if(_InputIterator __first, _InputIterator __last)
+{
+ if (test_if_level()) {
+ pp_macro_expander expand_condition(env);
+ std::string condition;
+ condition.reserve(255);
+ expand_condition(skip_blanks(__first, __last), __last, std::back_inserter(condition));
+
+ Value result;
+ result.set_long(0);
+ eval_expression(condition.c_str(), condition.c_str() + condition.size(), &result);
+
+ _M_true_test[iflevel] = !result.is_zero();
+ _M_skipping[iflevel] = result.is_zero();
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::handle_else(_InputIterator __first, _InputIterator /*__last*/)
+{
+ if (iflevel == 0 && !skipping()) {
+ std::cerr << "** WARNING #else without #if" << std::endl;
+ } else if (iflevel > 0 && _M_skipping[iflevel - 1]) {
+ _M_skipping[iflevel] = true;
+ } else {
+ _M_skipping[iflevel] = _M_true_test[iflevel];
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::handle_elif(_InputIterator __first, _InputIterator __last)
+{
+ assert(iflevel > 0);
+
+ if (iflevel == 0 && !skipping()) {
+ std::cerr << "** WARNING #else without #if" << std::endl;
+ } else if (!_M_true_test[iflevel] && !_M_skipping[iflevel - 1]) {
+ Value result;
+ __first = eval_expression(__first, __last, &result);
+ _M_true_test[iflevel] = !result.is_zero();
+ _M_skipping[iflevel] = result.is_zero();
+ } else {
+ _M_skipping[iflevel] = true;
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::handle_endif(_InputIterator __first, _InputIterator /*__last*/)
+{
+ if (iflevel == 0 && !skipping()) {
+ std::cerr << "** WARNING #endif without #if" << std::endl;
+ } else {
+ _M_skipping[iflevel] = 0;
+ _M_true_test[iflevel] = 0;
+
+ --iflevel;
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::handle_ifdef(bool check_undefined, _InputIterator __first, _InputIterator __last)
+{
+ if (test_if_level()) {
+ _InputIterator end_macro_name = skip_identifier(__first, __last);
+
+ std::size_t __size;
+#if defined(__SUNPRO_CC)
+ std::distance(__first, end_macro_name, __size);
+#else
+ __size = std::distance(__first, end_macro_name);
+#endif
+ assert(__size < 256);
+
+ char __buffer [256];
+ std::copy(__first, end_macro_name, __buffer);
+
+ bool value = env.resolve(__buffer, __size) != 0;
+
+ __first = end_macro_name;
+
+ if (check_undefined)
+ value = !value;
+
+ _M_true_test[iflevel] = value;
+ _M_skipping[iflevel] = !value;
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::handle_undef(_InputIterator __first, _InputIterator __last)
+{
+ __first = skip_blanks(__first, __last);
+ _InputIterator end_macro_name = skip_identifier(__first, __last);
+ assert(end_macro_name != __first);
+
+ std::size_t __size;
+#if defined(__SUNPRO_CC)
+ std::distance(__first, end_macro_name, __size);
+#else
+ __size = std::distance(__first, end_macro_name);
+#endif
+
+ assert(__size < 256);
+
+ char __buffer [256];
+ std::copy(__first, end_macro_name, __buffer);
+
+ pp_fast_string const __tmp(__buffer, __size);
+ env.unbind(&__tmp);
+
+ __first = end_macro_name;
+
+ return __first;
+}
+
+template <typename _InputIterator>
+char pp::peek_char(_InputIterator __first, _InputIterator __last)
+{
+ if (__first == __last)
+ return 0;
+
+ return *++__first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::next_token(_InputIterator __first, _InputIterator __last, int *kind)
+{
+ __first = skip_blanks(__first, __last);
+
+ if (__first == __last) {
+ *kind = 0;
+ return __first;
+ }
+
+ char ch = *__first;
+ char ch2 = peek_char(__first, __last);
+
+ switch (ch) {
+ case '/':
+ if (ch2 == '/' || ch2 == '*') {
+ __first = skip_comment_or_divop(__first, __last);
+ return next_token(__first, __last, kind);
+ }
+ ++__first;
+ *kind = '/';
+ break;
+
+ case '<':
+ ++__first;
+ if (ch2 == '<') {
+ ++__first;
+ *kind = TOKEN_LT_LT;
+ } else if (ch2 == '=') {
+ ++__first;
+ *kind = TOKEN_LT_EQ;
+ } else
+ *kind = '<';
+
+ return __first;
+
+ case '>':
+ ++__first;
+ if (ch2 == '>') {
+ ++__first;
+ *kind = TOKEN_GT_GT;
+ } else if (ch2 == '=') {
+ ++__first;
+ *kind = TOKEN_GT_EQ;
+ } else
+ *kind = '>';
+
+ return __first;
+
+ case '!':
+ ++__first;
+ if (ch2 == '=') {
+ ++__first;
+ *kind = TOKEN_NOT_EQ;
+ } else
+ *kind = '!';
+
+ return __first;
+
+ case '=':
+ ++__first;
+ if (ch2 == '=') {
+ ++__first;
+ *kind = TOKEN_EQ_EQ;
+ } else
+ *kind = '=';
+
+ return __first;
+
+ case '|':
+ ++__first;
+ if (ch2 == '|') {
+ ++__first;
+ *kind = TOKEN_OR_OR;
+ } else
+ *kind = '|';
+
+ return __first;
+
+ case '&':
+ ++__first;
+ if (ch2 == '&') {
+ ++__first;
+ *kind = TOKEN_AND_AND;
+ } else
+ *kind = '&';
+
+ return __first;
+
+ default:
+ if (pp_isalpha(ch) || ch == '_') {
+ _InputIterator end = skip_identifier(__first, __last);
+ _M_current_text.assign(__first, end);
+
+ token_text = &_M_current_text;
+ __first = end;
+
+ if (*token_text == "defined")
+ *kind = TOKEN_DEFINED;
+ else
+ *kind = TOKEN_IDENTIFIER;
+ } else if (pp_isdigit(ch)) {
+ _InputIterator end = skip_number(__first, __last);
+ std::string __str(__first, __last);
+ char ch = __str [__str.size() - 1];
+ if (ch == 'u' || ch == 'U') {
+ token_uvalue = strtoul(__str.c_str(), 0, 0);
+ *kind = TOKEN_UNUMBER;
+ } else {
+ token_value = strtol(__str.c_str(), 0, 0);
+ *kind = TOKEN_NUMBER;
+ }
+ __first = end;
+ } else
+ *kind = *__first++;
+ }
+
+ return __first;
+}
+
+} // namespace rpp
+
+#endif // PP_ENGINE_BITS_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/rpp/pp-engine.h b/parser/rpp/pp-engine.h
new file mode 100644
index 00000000..79e74c1a
--- /dev/null
+++ b/parser/rpp/pp-engine.h
@@ -0,0 +1,274 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright 2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef PP_ENGINE_H
+#define PP_ENGINE_H
+
+namespace rpp
+{
+
+struct Value {
+ enum Kind {
+ Kind_Long,
+ Kind_ULong,
+ };
+
+ Kind kind;
+
+ union {
+ long l;
+ unsigned long ul;
+ };
+
+ inline bool is_ulong() const {
+ return kind == Kind_ULong;
+ }
+
+ inline void set_ulong(unsigned long v) {
+ ul = v;
+ kind = Kind_ULong;
+ }
+
+ inline void set_long(long v) {
+ l = v;
+ kind = Kind_Long;
+ }
+
+ inline bool is_zero() const {
+ return l == 0;
+ }
+
+#define PP_DEFINE_BIN_OP(name, op) \
+ inline Value &name (const Value &other) \
+ { \
+ if (is_ulong () || other.is_ulong ()) \
+ set_ulong (ul op other.ul); \
+ else \
+ set_long (l op other.l); \
+ return *this; \
+ }
+
+ PP_DEFINE_BIN_OP(op_add, +)
+ PP_DEFINE_BIN_OP(op_sub, -)
+ PP_DEFINE_BIN_OP(op_mult, *)
+ PP_DEFINE_BIN_OP(op_div, /)
+ PP_DEFINE_BIN_OP(op_mod, %)
+ PP_DEFINE_BIN_OP(op_lhs, <<)
+ PP_DEFINE_BIN_OP(op_rhs, >>)
+ PP_DEFINE_BIN_OP(op_lt, <)
+ PP_DEFINE_BIN_OP(op_gt, >)
+ PP_DEFINE_BIN_OP(op_le, <=)
+ PP_DEFINE_BIN_OP(op_ge, >=)
+ PP_DEFINE_BIN_OP(op_eq, ==)
+ PP_DEFINE_BIN_OP(op_ne, !=)
+ PP_DEFINE_BIN_OP(op_bit_and, &)
+ PP_DEFINE_BIN_OP(op_bit_or, |)
+ PP_DEFINE_BIN_OP(op_bit_xor, ^)
+ PP_DEFINE_BIN_OP(op_and, &&)
+ PP_DEFINE_BIN_OP(op_or, ||)
+
+#undef PP_DEFINE_BIN_OP
+};
+
+class pp
+{
+ pp_environment &env;
+ pp_macro_expander expand;
+ pp_skip_identifier skip_identifier;
+ pp_skip_comment_or_divop skip_comment_or_divop;
+ pp_skip_blanks skip_blanks;
+ pp_skip_number skip_number;
+ std::vector<std::string> include_paths;
+ std::string _M_current_text;
+
+ enum { MAX_LEVEL = 512 };
+ int _M_skipping[MAX_LEVEL];
+ int _M_true_test[MAX_LEVEL];
+ int iflevel;
+
+ union {
+ long token_value;
+ unsigned long token_uvalue;
+ std::string *token_text;
+ };
+
+ enum INCLUDE_POLICY {
+ INCLUDE_GLOBAL,
+ INCLUDE_LOCAL
+ };
+
+ enum TOKEN_TYPE {
+ TOKEN_NUMBER = 1000,
+ TOKEN_UNUMBER,
+ TOKEN_IDENTIFIER,
+ TOKEN_DEFINED,
+ TOKEN_LT_LT,
+ TOKEN_LT_EQ,
+ TOKEN_GT_GT,
+ TOKEN_GT_EQ,
+ TOKEN_EQ_EQ,
+ TOKEN_NOT_EQ,
+ TOKEN_OR_OR,
+ TOKEN_AND_AND,
+ };
+
+ enum PP_DIRECTIVE_TYPE {
+ PP_UNKNOWN_DIRECTIVE,
+ PP_DEFINE,
+ PP_INCLUDE,
+ PP_INCLUDE_NEXT,
+ PP_ELIF,
+ PP_ELSE,
+ PP_ENDIF,
+ PP_IF,
+ PP_IFDEF,
+ PP_IFNDEF,
+ PP_UNDEF,
+ PP_PRAGMA,
+ PP_ERROR,
+ PP_WARNING
+ };
+
+public:
+ pp(pp_environment &__env);
+
+ inline std::back_insert_iterator<std::vector<std::string> > include_paths_inserter();
+
+ inline void push_include_path(std::string const &__path);
+
+ inline std::vector<std::string>::iterator include_paths_begin();
+ inline std::vector<std::string>::iterator include_paths_end();
+
+ inline std::vector<std::string>::const_iterator include_paths_begin() const;
+ inline std::vector<std::string>::const_iterator include_paths_end() const;
+
+ template <typename _InputIterator>
+ inline _InputIterator eval_expression(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _OutputIterator>
+ void file(std::string const &filename, _OutputIterator __result);
+
+ template <typename _OutputIterator>
+ void file(FILE *fp, _OutputIterator __result);
+
+ template <typename _InputIterator, typename _OutputIterator>
+ void operator()(_InputIterator __first, _InputIterator __last, _OutputIterator __result);
+
+private:
+ inline bool file_isdir(std::string const &__filename) const;
+ inline bool file_exists(std::string const &__filename) const;
+ FILE *find_include_file(std::string const &__filename, std::string *__filepath,
+ INCLUDE_POLICY __include_policy, bool __skip_current_path = false) const;
+
+ inline int skipping() const;
+ bool test_if_level();
+
+ inline std::string fix_file_path(std::string const &filename) const;
+ inline bool is_absolute(std::string const &filename) const;
+
+ PP_DIRECTIVE_TYPE find_directive(char const *__directive, std::size_t __size) const;
+
+ template <typename _InputIterator>
+ bool find_header_protection(_InputIterator __first, _InputIterator __last, std::string *__prot);
+
+ template <typename _InputIterator>
+ _InputIterator skip(_InputIterator __first, _InputIterator __last);
+
+ template <typename _InputIterator>
+ _InputIterator eval_primary(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator>
+ _InputIterator eval_multiplicative(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator>
+ _InputIterator eval_additive(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator>
+ _InputIterator eval_shift(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator>
+ _InputIterator eval_relational(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator>
+ _InputIterator eval_equality(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator>
+ _InputIterator eval_and(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator>
+ _InputIterator eval_xor(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator>
+ _InputIterator eval_or(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator>
+ _InputIterator eval_logical_and(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator>
+ _InputIterator eval_logical_or(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator>
+ _InputIterator eval_constant_expression(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator, typename _OutputIterator>
+ _InputIterator handle_directive(char const *__directive, std::size_t __size,
+ _InputIterator __first, _InputIterator __last, _OutputIterator __result);
+
+ template <typename _InputIterator, typename _OutputIterator>
+ _InputIterator handle_include(bool skip_current_path, _InputIterator __first, _InputIterator __last,
+ _OutputIterator __result);
+
+ template <typename _InputIterator>
+ _InputIterator handle_define(_InputIterator __first, _InputIterator __last);
+
+ template <typename _InputIterator>
+ _InputIterator handle_if(_InputIterator __first, _InputIterator __last);
+
+ template <typename _InputIterator>
+ _InputIterator handle_else(_InputIterator __first, _InputIterator __last);
+
+ template <typename _InputIterator>
+ _InputIterator handle_elif(_InputIterator __first, _InputIterator __last);
+
+ template <typename _InputIterator>
+ _InputIterator handle_endif(_InputIterator __first, _InputIterator __last);
+
+ template <typename _InputIterator>
+ _InputIterator handle_ifdef(bool check_undefined, _InputIterator __first, _InputIterator __last);
+
+ template <typename _InputIterator>
+ _InputIterator handle_undef(_InputIterator __first, _InputIterator __last);
+
+ template <typename _InputIterator>
+ inline char peek_char(_InputIterator __first, _InputIterator __last);
+
+ template <typename _InputIterator>
+ _InputIterator next_token(_InputIterator __first, _InputIterator __last, int *kind);
+};
+
+} // namespace rpp
+
+#endif // PP_ENGINE_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/rpp/pp-environment.h b/parser/rpp/pp-environment.h
new file mode 100644
index 00000000..6003c082
--- /dev/null
+++ b/parser/rpp/pp-environment.h
@@ -0,0 +1,137 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright 2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef PP_ENVIRONMENT_H
+#define PP_ENVIRONMENT_H
+
+#include <vector>
+#include <cstring>
+
+namespace rpp
+{
+
+class pp_environment
+{
+public:
+ typedef std::vector<pp_macro*>::const_iterator const_iterator;
+
+public:
+ pp_environment():
+ current_line(0),
+ _M_hash_size(4093) {
+ _M_base = (pp_macro **) memset(new pp_macro* [_M_hash_size], 0, _M_hash_size * sizeof(pp_macro*));
+ }
+
+ ~pp_environment() {
+ for (std::size_t i = 0; i < _M_macros.size(); ++i)
+ delete _M_macros [i];
+
+ delete [] _M_base;
+ }
+
+ const_iterator first_macro() const {
+ return _M_macros.begin();
+ }
+ const_iterator last_macro() const {
+ return _M_macros.end();
+ }
+
+ inline void bind(pp_fast_string const *__name, pp_macro const &__macro) {
+ std::size_t h = hash_code(*__name) % _M_hash_size;
+ pp_macro *m = new pp_macro(__macro);
+ m->name = __name;
+ m->next = _M_base [h];
+ m->hash_code = h;
+ _M_base [h] = m;
+
+ _M_macros.push_back(m);
+
+ if (_M_macros.size() == _M_hash_size)
+ rehash();
+ }
+
+ inline void unbind(pp_fast_string const *__name) {
+ if (pp_macro *m = resolve(__name))
+ m->hidden = true;
+ }
+
+ inline void unbind(char const *__s, std::size_t __size) {
+ pp_fast_string __tmp(__s, __size);
+ unbind(&__tmp);
+ }
+
+ inline pp_macro *resolve(pp_fast_string const *__name) const {
+ std::size_t h = hash_code(*__name) % _M_hash_size;
+ pp_macro *it = _M_base [h];
+
+ while (it && it->name && it->hash_code == h && (*it->name != *__name || it->hidden))
+ it = it->next;
+
+ return it;
+ }
+
+ inline pp_macro *resolve(char const *__data, std::size_t __size) const {
+ pp_fast_string const __tmp(__data, __size);
+ return resolve(&__tmp);
+ }
+
+ std::string current_file;
+ int current_line;
+
+private:
+ inline std::size_t hash_code(pp_fast_string const &s) const {
+ std::size_t hash_value = 0;
+
+ for (std::size_t i = 0; i < s.size(); ++i)
+ hash_value = (hash_value << 5) - hash_value + s.at(i);
+
+ return hash_value;
+ }
+
+ void rehash() {
+ delete[] _M_base;
+
+ _M_hash_size <<= 1;
+
+ _M_base = (pp_macro **) memset(new pp_macro* [_M_hash_size], 0, _M_hash_size * sizeof(pp_macro*));
+ for (std::size_t index = 0; index < _M_macros.size(); ++index) {
+ pp_macro *elt = _M_macros [index];
+ std::size_t h = hash_code(*elt->name) % _M_hash_size;
+ elt->next = _M_base [h];
+ elt->hash_code = h;
+ _M_base [h] = elt;
+ }
+ }
+
+private:
+ std::vector<pp_macro*> _M_macros;
+ pp_macro **_M_base;
+ std::size_t _M_hash_size;
+};
+
+} // namespace rpp
+
+#endif // PP_ENVIRONMENT_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/rpp/pp-fwd.h b/parser/rpp/pp-fwd.h
new file mode 100644
index 00000000..5b1c792f
--- /dev/null
+++ b/parser/rpp/pp-fwd.h
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright 2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef PP_FWD_H
+#define PP_FWD_H
+
+namespace rpp
+{
+
+template <typename _CharT> class pp_string;
+
+typedef pp_string<char> pp_fast_string;
+
+} // namespace rpp
+
+#endif // PP_FWD_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/rpp/pp-internal.h b/parser/rpp/pp-internal.h
new file mode 100644
index 00000000..7e708101
--- /dev/null
+++ b/parser/rpp/pp-internal.h
@@ -0,0 +1,117 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright 2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef PP_INTERNAL_H
+#define PP_INTERNAL_H
+
+#include <algorithm>
+#include <string>
+#include "pp.h"
+
+namespace rpp
+{
+
+namespace _PP_internal
+{
+
+inline void extract_file_path(const std::string &__filename, std::string *__filepath)
+{
+ std::size_t __index = __filename.rfind(PATH_SEPARATOR);
+
+ if (__index == std::string::npos)
+ *__filepath = "/";
+
+ else
+ __filepath->assign(__filename, 0, __index + 1);
+}
+
+template <typename _OutputIterator>
+void output_line(const std::string &__filename, int __line, _OutputIterator __result)
+{
+ std::string __msg;
+
+ __msg += "# ";
+
+ char __line_descr[16];
+ pp_snprintf(__line_descr, 16, "%d", __line);
+ __msg += __line_descr;
+
+ __msg += " \"";
+
+ if (__filename.empty())
+ __msg += "<internal>";
+ else
+ __msg += __filename;
+
+ __msg += "\"\n";
+ std::copy(__msg.begin(), __msg.end(), __result);
+}
+
+template <typename _InputIterator>
+inline bool comment_p(_InputIterator __first, _InputIterator __last) /*const*/
+{
+ if (__first == __last)
+ return false;
+
+ if (*__first != '/')
+ return false;
+
+ if (++__first == __last)
+ return false;
+
+ return (*__first == '/' || *__first == '*');
+}
+
+struct _Compare_string: public std::binary_function<bool, pp_fast_string const *, pp_fast_string const *> {
+ inline bool operator()(pp_fast_string const *__lhs, pp_fast_string const *__rhs) const {
+ return *__lhs < *__rhs;
+ }
+};
+
+struct _Equal_to_string: public std::binary_function<bool, pp_fast_string const *, pp_fast_string const *> {
+ inline bool operator()(pp_fast_string const *__lhs, pp_fast_string const *__rhs) const {
+ return *__lhs == *__rhs;
+ }
+};
+
+struct _Hash_string: public std::unary_function<std::size_t, pp_fast_string const *> {
+ inline std::size_t operator()(pp_fast_string const *__s) const {
+ char const *__ptr = __s->begin();
+ std::size_t __size = __s->size();
+ std::size_t __h = 0;
+
+ for (std::size_t i = 0; i < __size; ++i)
+ __h = (__h << 5) - __h + __ptr [i];
+
+ return __h;
+ }
+};
+
+} // _PP_internal
+
+} // namespace rpp
+
+#endif // PP_INTERNAL_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/rpp/pp-iterator.h b/parser/rpp/pp-iterator.h
new file mode 100644
index 00000000..fe846bd2
--- /dev/null
+++ b/parser/rpp/pp-iterator.h
@@ -0,0 +1,88 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright 2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef PP_ITERATOR_H
+#define PP_ITERATOR_H
+
+#include <iterator>
+
+namespace rpp
+{
+
+class pp_null_output_iterator
+ : public std::iterator<std::output_iterator_tag, void, void, void, void>
+{
+public:
+ pp_null_output_iterator() {}
+
+ template <typename _Tp>
+ pp_null_output_iterator &operator=(_Tp const &) {
+ return *this;
+ }
+
+ inline pp_null_output_iterator &operator *() {
+ return *this;
+ }
+ inline pp_null_output_iterator &operator ++ () {
+ return *this;
+ }
+ inline pp_null_output_iterator operator ++ (int) {
+ return *this;
+ }
+};
+
+template <typename _Container>
+class pp_output_iterator
+ : public std::iterator<std::output_iterator_tag, void, void, void, void>
+{
+ std::string &_M_result;
+
+public:
+ explicit pp_output_iterator(std::string &__result):
+ _M_result(__result) {}
+
+ inline pp_output_iterator &operator=(typename _Container::const_reference __v) {
+ if (_M_result.capacity() == _M_result.size())
+ _M_result.reserve(_M_result.capacity() << 2);
+
+ _M_result.push_back(__v);
+ return *this;
+ }
+
+ inline pp_output_iterator &operator *() {
+ return *this;
+ }
+ inline pp_output_iterator &operator ++ () {
+ return *this;
+ }
+ inline pp_output_iterator operator ++ (int) {
+ return *this;
+ }
+};
+
+} // namespace rpp
+
+#endif // PP_ITERATOR_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/rpp/pp-macro-expander.h b/parser/rpp/pp-macro-expander.h
new file mode 100644
index 00000000..fd875d98
--- /dev/null
+++ b/parser/rpp/pp-macro-expander.h
@@ -0,0 +1,351 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright 2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef PP_MACRO_EXPANDER_H
+#define PP_MACRO_EXPANDER_H
+
+namespace rpp
+{
+
+struct pp_frame {
+ pp_macro *expanding_macro;
+ std::vector<std::string> *actuals;
+
+ pp_frame(pp_macro *__expanding_macro, std::vector<std::string> *__actuals):
+ expanding_macro(__expanding_macro), actuals(__actuals) {}
+};
+
+class pp_macro_expander
+{
+ pp_environment &env;
+ pp_frame *frame;
+
+ pp_skip_number skip_number;
+ pp_skip_identifier skip_identifier;
+ pp_skip_string_literal skip_string_literal;
+ pp_skip_char_literal skip_char_literal;
+ pp_skip_argument skip_argument;
+ pp_skip_comment_or_divop skip_comment_or_divop;
+ pp_skip_blanks skip_blanks;
+ pp_skip_whitespaces skip_whitespaces;
+
+ std::string const *resolve_formal(pp_fast_string const *__name) {
+ assert(__name != 0);
+
+ if (! frame)
+ return 0;
+
+ assert(frame->expanding_macro != 0);
+
+ std::vector<pp_fast_string const *> const formals = frame->expanding_macro->formals;
+ for (std::size_t index = 0; index < formals.size(); ++index) {
+ pp_fast_string const *formal = formals[index];
+
+ if (*formal != *__name)
+ continue;
+
+ else if (frame->actuals && index < frame->actuals->size())
+ return &(*frame->actuals)[index];
+
+ else
+ assert(0); // internal error?
+ }
+
+ return 0;
+ }
+
+public: // attributes
+ int lines;
+ int generated_lines;
+
+public:
+ pp_macro_expander(pp_environment &__env, pp_frame *__frame = 0):
+ env(__env), frame(__frame), lines(0), generated_lines(0) {}
+
+ template <typename _InputIterator, typename _OutputIterator>
+ _InputIterator operator()(_InputIterator __first, _InputIterator __last, _OutputIterator __result) {
+ generated_lines = 0;
+ __first = skip_blanks(__first, __last);
+ lines = skip_blanks.lines;
+
+ while (__first != __last) {
+ if (*__first == '\n') {
+ *__result++ = *__first;
+ ++lines;
+
+ __first = skip_blanks(++__first, __last);
+ lines += skip_blanks.lines;
+
+ if (__first != __last && *__first == '#')
+ break;
+ } else if (*__first == '#') {
+ __first = skip_blanks(++__first, __last);
+ lines += skip_blanks.lines;
+
+ _InputIterator end_id = skip_identifier(__first, __last);
+
+ // ### rewrite: not safe
+ char name_buffer[512], *cp = name_buffer;
+ std::copy(__first, end_id, cp);
+ std::size_t name_size = end_id - __first;
+ name_buffer[name_size] = '\0';
+
+ pp_fast_string fast_name(name_buffer, name_size);
+
+ if (std::string const *actual = resolve_formal(&fast_name)) {
+ *__result++ = '\"';
+
+ for (std::string::const_iterator it = skip_whitespaces(actual->begin(), actual->end());
+ it != actual->end(); ++it) {
+ if (*it == '"') {
+ *__result++ = '\\';
+ *__result++ = *it;
+ }
+
+ else if (*it == '\n') {
+ *__result++ = '"';
+ *__result++ = '\n';
+ *__result++ = '"';
+ }
+
+ else
+ *__result++ = *it;
+ }
+
+ *__result++ = '\"';
+ __first = end_id;
+ } else
+ *__result++ = '#'; // ### warning message?
+ } else if (*__first == '\"') {
+ _InputIterator next_pos = skip_string_literal(__first, __last);
+ lines += skip_string_literal.lines;
+ std::copy(__first, next_pos, __result);
+ __first = next_pos;
+ } else if (*__first == '\'') {
+ _InputIterator next_pos = skip_char_literal(__first, __last);
+ lines += skip_char_literal.lines;
+ std::copy(__first, next_pos, __result);
+ __first = next_pos;
+ } else if (_PP_internal::comment_p(__first, __last)) {
+ __first = skip_comment_or_divop(__first, __last);
+ int n = skip_comment_or_divop.lines;
+ lines += n;
+
+ while (n-- > 0)
+ *__result++ = '\n';
+ } else if (pp_isspace(*__first)) {
+ for (; __first != __last; ++__first) {
+ if (*__first == '\n' || !pp_isspace(*__first))
+ break;
+ }
+
+ *__result = ' ';
+ } else if (pp_isdigit(*__first)) {
+ _InputIterator next_pos = skip_number(__first, __last);
+ lines += skip_number.lines;
+ std::copy(__first, next_pos, __result);
+ __first = next_pos;
+ } else if (pp_isalpha(*__first) || *__first == '_') {
+ _InputIterator name_begin = __first;
+ _InputIterator name_end = skip_identifier(__first, __last);
+ __first = name_end; // advance
+
+ // search for the paste token
+ _InputIterator next = skip_blanks(__first, __last);
+ if (next != __last && *next == '#') {
+ ++next;
+ if (next != __last && *next == '#')
+ __first = skip_blanks(++next, __last);
+ }
+
+ // ### rewrite: not safe
+
+ std::ptrdiff_t name_size;
+#if defined(__SUNPRO_CC)
+ std::distance(name_begin, name_end, name_size);
+#else
+ name_size = std::distance(name_begin, name_end);
+#endif
+ assert(name_size >= 0 && name_size < 512);
+
+ char name_buffer[512], *cp = name_buffer;
+ std::size_t __size = name_end - name_begin;
+ std::copy(name_begin, name_end, cp);
+ name_buffer[__size] = '\0';
+
+ pp_fast_string fast_name(name_buffer, name_size);
+
+ if (std::string const *actual = resolve_formal(&fast_name)) {
+ std::copy(actual->begin(), actual->end(), __result);
+ continue;
+ }
+
+ static bool hide_next = false; // ### remove me
+
+ pp_macro *macro = env.resolve(name_buffer, name_size);
+ if (! macro || macro->hidden || hide_next) {
+ hide_next = ! strcmp(name_buffer, "defined");
+
+ if (__size == 8 && name_buffer [0] == '_' && name_buffer [1] == '_') {
+ if (! strcmp(name_buffer, "__LINE__")) {
+ char buf [16];
+ char *end = buf + pp_snprintf(buf, 16, "%d", env.current_line + lines);
+
+ std::copy(&buf [0], end, __result);
+ continue;
+ }
+
+ else if (! strcmp(name_buffer, "__FILE__")) {
+ __result++ = '"';
+ std::copy(env.current_file.begin(), env.current_file.end(), __result); // ### quote
+ __result++ = '"';
+ continue;
+ }
+ }
+
+ std::copy(name_begin, name_end, __result);
+ continue;
+ }
+
+ if (! macro->function_like) {
+ pp_macro *m = 0;
+
+ if (macro->definition) {
+ macro->hidden = true;
+
+ std::string __tmp;
+ __tmp.reserve(256);
+
+ pp_macro_expander expand_macro(env);
+ expand_macro(macro->definition->begin(), macro->definition->end(), std::back_inserter(__tmp));
+ generated_lines += expand_macro.lines;
+
+ if (! __tmp.empty()) {
+ std::string::iterator __begin_id = skip_whitespaces(__tmp.begin(), __tmp.end());
+ std::string::iterator __end_id = skip_identifier(__begin_id, __tmp.end());
+
+ if (__end_id == __tmp.end()) {
+ std::string __id;
+ __id.assign(__begin_id, __end_id);
+
+ std::size_t x;
+#if defined(__SUNPRO_CC)
+ std::distance(__begin_id, __end_id, x);
+#else
+ x = std::distance(__begin_id, __end_id);
+#endif
+ m = env.resolve(__id.c_str(), x);
+ }
+
+ if (! m)
+ std::copy(__tmp.begin(), __tmp.end(), __result);
+ }
+
+ macro->hidden = false;
+ }
+
+ if (! m)
+ continue;
+
+ macro = m;
+ }
+
+ // function like macro
+ _InputIterator arg_it = skip_whitespaces(__first, __last);
+
+ if (arg_it == __last || *arg_it != '(') {
+ std::copy(name_begin, name_end, __result);
+ lines += skip_whitespaces.lines;
+ __first = arg_it;
+ continue;
+ }
+
+ std::vector<std::string> actuals;
+ actuals.reserve(5);
+ ++arg_it; // skip '('
+
+ pp_macro_expander expand_actual(env, frame);
+
+ _InputIterator arg_end = skip_argument_variadics(actuals, macro, arg_it, __last);
+ if (arg_it != arg_end) {
+ std::string actual(arg_it, arg_end);
+ actuals.resize(actuals.size() + 1);
+ actuals.back().reserve(255);
+ expand_actual(actual.begin(), actual.end(), std::back_inserter(actuals.back()));
+ arg_it = arg_end;
+ }
+
+ while (arg_it != __last && *arg_end == ',') {
+ ++arg_it; // skip ','
+
+ arg_end = skip_argument_variadics(actuals, macro, arg_it, __last);
+ std::string actual(arg_it, arg_end);
+ actuals.resize(actuals.size() + 1);
+ actuals.back().reserve(255);
+ expand_actual(actual.begin(), actual.end(), std::back_inserter(actuals.back()));
+ arg_it = arg_end;
+ }
+
+ assert(arg_it != __last && *arg_it == ')');
+
+ ++arg_it; // skip ')'
+ __first = arg_it;
+
+#if 0 // ### enable me
+ assert((macro->variadics && macro->formals.size() >= actuals.size())
+ || macro->formals.size() == actuals.size());
+#endif
+
+ pp_frame frame(macro, &actuals);
+ pp_macro_expander expand_macro(env, &frame);
+ macro->hidden = true;
+ expand_macro(macro->definition->begin(), macro->definition->end(), __result);
+ macro->hidden = false;
+ generated_lines += expand_macro.lines;
+ } else
+ *__result++ = *__first++;
+ }
+
+ return __first;
+ }
+
+ template <typename _InputIterator>
+ _InputIterator skip_argument_variadics(std::vector<std::string> const &__actuals, pp_macro *__macro,
+ _InputIterator __first, _InputIterator __last) {
+ _InputIterator arg_end = skip_argument(__first, __last);
+
+ while (__macro->variadics && __first != arg_end && arg_end != __last && *arg_end == ','
+ && (__actuals.size() + 1) == __macro->formals.size()) {
+ arg_end = skip_argument(++arg_end, __last);
+ }
+
+ return arg_end;
+ }
+};
+
+} // namespace rpp
+
+#endif // PP_MACRO_EXPANDER_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/rpp/pp-macro.h b/parser/rpp/pp-macro.h
new file mode 100644
index 00000000..e633834b
--- /dev/null
+++ b/parser/rpp/pp-macro.h
@@ -0,0 +1,72 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright 2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef PP_MACRO_H
+#define PP_MACRO_H
+
+#include <vector>
+#include "pp-fwd.h"
+
+namespace rpp
+{
+
+struct pp_macro {
+#if defined (PP_WITH_MACRO_POSITION)
+ pp_fast_string const *file;
+#endif
+ pp_fast_string const *name;
+ pp_fast_string const *definition;
+ std::vector<pp_fast_string const *> formals;
+
+ union {
+ int unsigned state;
+
+ struct {
+ int unsigned hidden: 1;
+ int unsigned function_like: 1;
+ int unsigned variadics: 1;
+ };
+ };
+
+ int lines;
+ pp_macro *next;
+ std::size_t hash_code;
+
+ inline pp_macro():
+#if defined (PP_WITH_MACRO_POSITION)
+ file(0),
+#endif
+ name(0),
+ definition(0),
+ state(0),
+ lines(0),
+ next(0),
+ hash_code(0) {}
+};
+
+} // namespace rpp
+
+#endif // PP_MACRO_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/rpp/pp-main.cpp b/parser/rpp/pp-main.cpp
new file mode 100644
index 00000000..4c37e754
--- /dev/null
+++ b/parser/rpp/pp-main.cpp
@@ -0,0 +1,295 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright 2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <fstream>
+#include "pp.h"
+
+using namespace rpp;
+
+#ifndef GCC_MACHINE
+# define GCC_MACHINE "i386-redhat-linux"
+#endif
+
+#ifndef GCC_VERSION
+# define GCC_VERSION "4.1.1"
+#endif
+
+void usage()
+{
+ std::cerr << "usage: rpp file.cpp" << std::endl;
+ ::exit(EXIT_FAILURE);
+}
+
+void dump_macros(pp_environment &env, pp &, std::ostream &__out)
+{
+ for (pp_environment::const_iterator it = env.first_macro(); it != env.last_macro(); ++it) {
+ pp_macro const *m = *it;
+
+ if (m->hidden)
+ continue;
+
+ std::string id(m->name->begin(), m->name->end());
+ __out << "#define " << id;
+
+ if (m->function_like) {
+ __out << "(";
+
+ for (std::size_t i = 0; i < m->formals.size(); ++i) {
+ if (i != 0)
+ __out << ", ";
+
+ pp_fast_string const *f = m->formals [i];
+ std::string name(f->begin(), f->end());
+ __out << name;
+ }
+
+ if (m->variadics)
+ __out << "...";
+
+ __out << ")";
+ }
+
+ __out << "\t";
+ if (m->definition) {
+ std::string def(m->definition->begin(), m->definition->end());
+ __out << def;
+ }
+
+ __out << std::endl;
+ }
+}
+#if 0
+int main(int, char *argv [])
+{
+ char const *input_file = 0;
+ char const *output_file = 0;
+ char const *include_pch_file = 0;
+ bool opt_help = false;
+ bool opt_dump_macros = false;
+ bool opt_pch = false;
+
+ pp_environment env;
+ pp preprocess(env);
+
+ std::string result;
+ result.reserve(20 * 1024); // 20K
+
+ pp_output_iterator<std::string> out(result);
+ pp_null_output_iterator null_out;
+
+ preprocess.push_include_path("/usr/include");
+ preprocess.push_include_path("/usr/lib/gcc/" GCC_MACHINE "/" GCC_VERSION "/include");
+
+ preprocess.push_include_path("/usr/include/c++/" GCC_VERSION);
+ preprocess.push_include_path("/usr/include/c++/" GCC_VERSION "/" GCC_MACHINE);
+
+ std::string extra_args;
+
+ while (const char *arg = *++argv) {
+ if (arg [0] != '-')
+ input_file = arg;
+
+ else if (! strcmp(arg, "-help"))
+ opt_help = true;
+
+ else if (! strcmp(arg, "-dM"))
+ opt_dump_macros = true;
+
+ else if (! strcmp(arg, "-pch"))
+ opt_pch = true;
+
+ else if (! strcmp(arg, "-msse")) {
+ pp_macro __macro;
+ __macro.name = pp_symbol::get("__SSE__", 7);
+ env.bind(__macro.name, __macro);
+
+ __macro.name = pp_symbol::get("__MMX__", 7);
+ env.bind(__macro.name, __macro);
+ }
+
+ else if (! strcmp(arg, "-include")) {
+ if (argv [1])
+ include_pch_file = *++argv;
+ }
+
+ else if (! strncmp(arg, "-o", 2)) {
+ arg += 2;
+
+ if (! arg [0] && argv [1])
+ arg = *++argv;
+
+ if (arg)
+ output_file = arg;
+ }
+
+ else if (! strncmp(arg, "-conf", 8)) {
+ if (argv [1])
+ preprocess.file(*++argv, null_out);
+ }
+
+ else if (! strncmp(arg, "-I", 2)) {
+ arg += 2;
+
+ if (! arg [0] && argv [1])
+ arg = *++argv;
+
+ if (arg)
+ preprocess.push_include_path(arg);
+ }
+
+ else if (! strncmp(arg, "-U", 2)) {
+ arg += 2;
+
+ if (! arg [0] && argv [1])
+ arg = *++argv;
+
+ if (arg) {
+ env.unbind(arg, strlen(arg));
+ }
+ }
+
+ else if (! strncmp(arg, "-D", 2)) {
+ arg += 2;
+
+ if (! arg [0] && argv [1])
+ arg = *++argv;
+
+ if (arg) {
+ pp_macro __macro;
+
+ char const *end = arg;
+ char const *eq = 0;
+
+ for (; *end; ++end) {
+ if (*end == '=')
+ eq = end;
+ }
+
+ if (eq != 0) {
+ __macro.name = pp_symbol::get(arg, eq - arg);
+ __macro.definition = pp_symbol::get(eq + 1, end - (eq + 1));
+ }
+
+ else {
+ __macro.name = pp_symbol::get(arg, end - arg);
+ __macro.definition = 0;
+ }
+
+ env.bind(__macro.name, __macro);
+ }
+ } else {
+ extra_args += " ";
+ extra_args += arg;
+ }
+ }
+
+ if (! input_file || opt_help) {
+ usage();
+ return EXIT_FAILURE;
+ }
+
+ std::string __ifile(input_file);
+ bool is_c_file = false;
+ if (__ifile.size() > 2 && __ifile [__ifile.size() - 1] == 'c' && __ifile [__ifile.size() - 2] == '.') {
+ is_c_file = true;
+ env.unbind("__cplusplus", 11);
+
+ pp_macro __macro;
+ __macro.name = pp_symbol::get("__null");
+ __macro.definition = pp_symbol::get("((void*) 0)");
+ env.bind(__macro.name, __macro);
+
+ // turn off the pch
+ include_pch_file = 0;
+ } else if (include_pch_file) {
+ std::string __pch(include_pch_file);
+ __pch += ".gch/c++.conf";
+
+ //std::cerr << "*** pch file " << __pch << std::endl;
+ preprocess.file(__pch, null_out);
+ }
+
+ if (opt_dump_macros) {
+ preprocess.file(input_file, null_out);
+ dump_macros(env, preprocess, std::cout);
+ return EXIT_SUCCESS;
+ }
+
+ preprocess.file(input_file, out);
+
+ if (opt_pch) {
+ if (! output_file) {
+ std::cerr << "*** WARNING expected a file name" << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ std::string __conf_file(output_file);
+ __conf_file += ".conf";
+
+ std::ofstream __out;
+ __out.open(__conf_file.c_str());
+ dump_macros(env, preprocess, __out);
+ __out.close();
+
+ std::string __pp_file(output_file);
+ __pp_file += ".i";
+
+ __out.open(__pp_file.c_str());
+ __out.write(result.c_str(), result.size());
+ __out.close();
+ return EXIT_SUCCESS;
+ }
+
+ std::ostream *__out = &std::cout;
+ std::ofstream __ofile;
+
+ if (output_file) {
+ std::string __output_file_name(output_file);
+ __ofile.open(output_file);
+ __out = &__ofile;
+ }
+
+ if (include_pch_file) {
+ std::string __pch(include_pch_file);
+ __pch += ".gch/c++.i";
+
+ std::ifstream __in(__pch.c_str());
+
+ char buffer [1024];
+ while (__in.read(buffer, 1024))
+ __out->write(buffer, 1024);
+
+ __in.close();
+ }
+
+ __out->write(result.c_str(), result.size());
+
+ if (output_file)
+ __ofile.close();
+
+ return EXIT_SUCCESS;
+}
+#endif
+// kate: space-indent on; indent-width 2; replace-tabs on;
+
diff --git a/parser/rpp/pp-qt-configuration b/parser/rpp/pp-qt-configuration
new file mode 100644
index 00000000..206c3d64
--- /dev/null
+++ b/parser/rpp/pp-qt-configuration
@@ -0,0 +1,24 @@
+#define __cplusplus 1
+
+#define __STDC__
+
+// Qt
+#define QOBJECTDEFS_H
+
+// not yet supported
+#define Q_SLOTS slots
+#define Q_SIGNALS signals
+#define Q_FLAGS(a)
+#define Q_PRIVATE_SLOT(a, b)
+#define Q_DECLARE_INTERFACE(a,b)
+#define Q_INTERFACES(a)
+#define Q_GADGET
+#define Q_OVERRIDE(a)
+#define Q_OS_OS2
+#define Q_NO_USING_KEYWORD
+#define QT_NO_QOBJECT_CHECK
+#define QT_NO_MEMBER_TEMPLATES
+// There are symbols in Qt that exist in Debug but
+// not in release
+#define QT_NO_DEBUG
+
diff --git a/parser/rpp/pp-scanner.h b/parser/rpp/pp-scanner.h
new file mode 100644
index 00000000..e97b1584
--- /dev/null
+++ b/parser/rpp/pp-scanner.h
@@ -0,0 +1,313 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright 2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef PP_SCANNER_H
+#define PP_SCANNER_H
+
+#include "pp-cctype.h"
+#include <cassert>
+
+namespace rpp
+{
+
+struct pp_skip_blanks {
+ int lines;
+
+ template <typename _InputIterator>
+ _InputIterator operator()(_InputIterator __first, _InputIterator __last) {
+ lines = 0;
+
+ for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) {
+ if (*__first == '\\') {
+ _InputIterator __begin = __first;
+ ++__begin;
+
+ if (__begin != __last && *__begin == '\n')
+ ++__first;
+ else
+ break;
+ } else if (*__first == '\n' || !pp_isspace(*__first))
+ break;
+ }
+
+ return __first;
+ }
+};
+
+struct pp_skip_whitespaces {
+ int lines;
+
+ template <typename _InputIterator>
+ _InputIterator operator()(_InputIterator __first, _InputIterator __last) {
+ lines = 0;
+
+ for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) {
+ if (! pp_isspace(*__first))
+ break;
+ }
+
+ return __first;
+ }
+};
+
+struct pp_skip_comment_or_divop {
+ int lines;
+
+ template <typename _InputIterator>
+ _InputIterator operator()(_InputIterator __first, _InputIterator __last) {
+ enum {
+ MAYBE_BEGIN,
+ BEGIN,
+ MAYBE_END,
+ END,
+ IN_COMMENT,
+ IN_CXX_COMMENT
+ } state(MAYBE_BEGIN);
+
+ lines = 0;
+
+ for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) {
+ switch (state) {
+ default:
+ assert(0);
+ break;
+
+ case MAYBE_BEGIN:
+ if (*__first != '/')
+ return __first;
+
+ state = BEGIN;
+ break;
+
+ case BEGIN:
+ if (*__first == '*')
+ state = IN_COMMENT;
+ else if (*__first == '/')
+ state = IN_CXX_COMMENT;
+ else
+ return __first;
+ break;
+
+ case IN_COMMENT:
+ if (*__first == '*')
+ state = MAYBE_END;
+ break;
+
+ case IN_CXX_COMMENT:
+ if (*__first == '\n')
+ return __first;
+ break;
+
+ case MAYBE_END:
+ if (*__first == '/')
+ state = END;
+ else if (*__first != '*')
+ state = IN_COMMENT;
+ break;
+
+ case END:
+ return __first;
+ }
+ }
+
+ return __first;
+ }
+};
+
+struct pp_skip_identifier {
+ int lines;
+
+ template <typename _InputIterator>
+ _InputIterator operator()(_InputIterator __first, _InputIterator __last) {
+ lines = 0;
+
+ for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) {
+ if (! pp_isalnum(*__first) && *__first != '_')
+ break;
+ }
+
+ return __first;
+ }
+};
+
+struct pp_skip_number {
+ int lines;
+
+ template <typename _InputIterator>
+ _InputIterator operator()(_InputIterator __first, _InputIterator __last) {
+ lines = 0;
+
+ for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) {
+ if (! pp_isalnum(*__first) && *__first != '.')
+ break;
+ }
+
+ return __first;
+ }
+};
+
+struct pp_skip_string_literal {
+ int lines;
+
+ template <typename _InputIterator>
+ _InputIterator operator()(_InputIterator __first, _InputIterator __last) {
+ enum {
+ BEGIN,
+ IN_STRING,
+ QUOTE,
+ END
+ } state(BEGIN);
+
+ lines = 0;
+
+ for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) {
+ switch (state) {
+ default:
+ assert(0);
+ break;
+
+ case BEGIN:
+ if (*__first != '\"')
+ return __first;
+ state = IN_STRING;
+ break;
+
+ case IN_STRING:
+ assert(*__first != '\n');
+
+ if (*__first == '\"')
+ state = END;
+ else if (*__first == '\\')
+ state = QUOTE;
+ break;
+
+ case QUOTE:
+ state = IN_STRING;
+ break;
+
+ case END:
+ return __first;
+ }
+ }
+
+ return __first;
+ }
+};
+
+struct pp_skip_char_literal {
+ int lines;
+
+ template <typename _InputIterator>
+ _InputIterator operator()(_InputIterator __first, _InputIterator __last) {
+ enum {
+ BEGIN,
+ IN_STRING,
+ QUOTE,
+ END
+ } state(BEGIN);
+
+ lines = 0;
+
+ for (; state != END && __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) {
+ switch (state) {
+ default:
+ assert(0);
+ break;
+
+ case BEGIN:
+ if (*__first != '\'')
+ return __first;
+ state = IN_STRING;
+ break;
+
+ case IN_STRING:
+ assert(*__first != '\n');
+
+ if (*__first == '\'')
+ state = END;
+ else if (*__first == '\\')
+ state = QUOTE;
+ break;
+
+ case QUOTE:
+ state = IN_STRING;
+ break;
+ }
+ }
+
+ return __first;
+ }
+};
+
+struct pp_skip_argument {
+ pp_skip_identifier skip_number;
+ pp_skip_identifier skip_identifier;
+ pp_skip_string_literal skip_string_literal;
+ pp_skip_char_literal skip_char_literal;
+ pp_skip_comment_or_divop skip_comment_or_divop;
+ int lines;
+
+ template <typename _InputIterator>
+ _InputIterator operator()(_InputIterator __first, _InputIterator __last) {
+ int depth = 0;
+ lines = 0;
+
+ while (__first != __last) {
+ if (!depth && (*__first == ')' || *__first == ','))
+ break;
+ else if (*__first == '(')
+ ++depth, ++__first;
+ else if (*__first == ')')
+ --depth, ++__first;
+ else if (*__first == '\"') {
+ __first = skip_string_literal(__first, __last);
+ lines += skip_string_literal.lines;
+ } else if (*__first == '\'') {
+ __first = skip_char_literal(__first, __last);
+ lines += skip_char_literal.lines;
+ } else if (*__first == '/') {
+ __first = skip_comment_or_divop(__first, __last);
+ lines += skip_comment_or_divop.lines;
+ } else if (pp_isalpha(*__first) || *__first == '_') {
+ __first = skip_identifier(__first, __last);
+ lines += skip_identifier.lines;
+ } else if (pp_isdigit(*__first)) {
+ __first = skip_number(__first, __last);
+ lines += skip_number.lines;
+ } else if (*__first == '\n') {
+ ++__first;
+ ++lines;
+ } else
+ ++__first;
+ }
+
+ return __first;
+ }
+};
+
+} // namespace rpp
+
+#endif // PP_SCANNER_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/rpp/pp-string.h b/parser/rpp/pp-string.h
new file mode 100644
index 00000000..31bca4f7
--- /dev/null
+++ b/parser/rpp/pp-string.h
@@ -0,0 +1,107 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright 2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef PP_STRING_H
+#define PP_STRING_H
+
+namespace rpp
+{
+
+template <typename _CharT>
+class pp_string
+{
+ typedef std::char_traits<_CharT> traits_type;
+ typedef std::size_t size_type;
+
+ _CharT const *_M_begin;
+ std::size_t _M_size;
+
+public:
+ inline pp_string():
+ _M_begin(0), _M_size(0) {}
+
+ explicit pp_string(std::string const &__s):
+ _M_begin(__s.c_str()), _M_size(__s.size()) {}
+
+ inline pp_string(_CharT const *__begin, std::size_t __size):
+ _M_begin(__begin), _M_size(__size) {}
+
+ inline _CharT const *begin() const {
+ return _M_begin;
+ }
+ inline _CharT const *end() const {
+ return _M_begin + _M_size;
+ }
+
+ inline _CharT at(std::size_t index) const {
+ return _M_begin [index];
+ }
+
+ inline std::size_t size() const {
+ return _M_size;
+ }
+
+ inline int compare(pp_string const &__other) const {
+ size_type const __size = this->size();
+ size_type const __osize = __other.size();
+ size_type const __len = std::min(__size, __osize);
+
+ int __r = traits_type::compare(_M_begin, __other._M_begin, __len);
+ if (!__r)
+ __r = (int)(__size - __osize);
+
+ return __r;
+ }
+
+ inline bool operator == (pp_string const &__other) const {
+ return compare(__other) == 0;
+ }
+
+ inline bool operator != (pp_string const &__other) const {
+ return compare(__other) != 0;
+ }
+
+ inline bool operator < (pp_string const &__other) const {
+ return compare(__other) < 0;
+ }
+
+ inline bool operator == (char const *s) const {
+ std::size_t n = strlen(s);
+
+ if (n != _M_size)
+ return false;
+
+ return ! strncmp(_M_begin, s, n);
+ }
+
+ inline bool operator != (char const *s) const {
+ return ! operator == (s);
+ }
+};
+
+} // namespace rpp
+
+#endif // PP_STRING_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/rpp/pp-symbol.h b/parser/rpp/pp-symbol.h
new file mode 100644
index 00000000..eef66837
--- /dev/null
+++ b/parser/rpp/pp-symbol.h
@@ -0,0 +1,87 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright 2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef PP_SYMBOL_H
+#define PP_SYMBOL_H
+
+#include <cassert>
+#include <iterator>
+#include "pp-fwd.h"
+#include "parser/rxx_allocator.h"
+
+namespace rpp
+{
+
+class pp_symbol
+{
+ static rxx_allocator<char> &allocator_instance() {
+ static rxx_allocator<char>__allocator;
+ return __allocator;
+ }
+
+public:
+ static int &N() {
+ static int __N;
+ return __N;
+ }
+
+ static pp_fast_string const *get(char const *__data, std::size_t __size) {
+ ++N();
+ char *data = allocator_instance().allocate(__size + 1);
+ memcpy(data, __data, __size);
+ data[__size] = '\0';
+
+ char *where = allocator_instance().allocate(sizeof(pp_fast_string));
+ return new(where) pp_fast_string(data, __size);
+ }
+
+ template <typename _InputIterator>
+ static pp_fast_string const *get(_InputIterator __first, _InputIterator __last) {
+ ++N();
+ std::ptrdiff_t __size;
+#if defined(__SUNPRO_CC)
+ std::distance(__first, __last, __size);
+#else
+ __size = std::distance(__first, __last);
+#endif
+ assert(__size >= 0 && __size < 512);
+
+ char *data = allocator_instance().allocate(__size + 1);
+ std::copy(__first, __last, data);
+ data[__size] = '\0';
+
+ char *where = allocator_instance().allocate(sizeof(pp_fast_string));
+ return new(where) pp_fast_string(data, __size);
+ }
+
+ static pp_fast_string const *get(std::string const &__s) {
+ return get(__s.c_str(), __s.size());
+ }
+};
+
+} // namespace rpp
+
+#endif // PP_SYMBOL_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/rpp/pp.h b/parser/rpp/pp.h
new file mode 100644
index 00000000..3ff38c0d
--- /dev/null
+++ b/parser/rpp/pp.h
@@ -0,0 +1,91 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright 2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef PP_H
+#define PP_H
+
+#if defined(_WIN64) || defined(WIN64) || defined(__WIN64__) \
+ || defined(_WIN32) || defined(WIN32) || defined(__WIN32__)
+# define PP_OS_WIN
+#endif
+
+#include <set>
+#include <map>
+#include <vector>
+#include <string>
+#include <iterator>
+#include <iostream>
+#include <cassert>
+#include <cctype>
+#include <cstdio>
+
+#include <fcntl.h>
+
+#ifdef HAVE_MMAP
+# include <sys/mman.h>
+#endif
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#if (_MSC_VER >= 1400)
+# define FILENO _fileno
+#else
+# define FILENO fileno
+#endif
+
+#if defined (PP_OS_WIN)
+# define PATH_SEPARATOR '\\'
+#else
+# define PATH_SEPARATOR '/'
+#endif
+
+#if defined (RPP_JAMBI)
+# include "parser/rxx_allocator.h"
+#else
+# include "parser/rpp-allocator.h"
+#endif
+
+#if defined (_MSC_VER)
+# define pp_snprintf _snprintf
+#else
+# define pp_snprintf snprintf
+#endif
+
+#include "pp-fwd.h"
+#include "pp-cctype.h"
+#include "pp-string.h"
+#include "pp-symbol.h"
+#include "pp-internal.h"
+#include "pp-iterator.h"
+#include "pp-macro.h"
+#include "pp-environment.h"
+#include "pp-scanner.h"
+#include "pp-macro-expander.h"
+#include "pp-engine.h"
+#include "pp-engine-bits.h"
+
+#endif // PP_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/rpp/preprocessor.cpp b/parser/rpp/preprocessor.cpp
new file mode 100644
index 00000000..be6a8518
--- /dev/null
+++ b/parser/rpp/preprocessor.cpp
@@ -0,0 +1,158 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright 2005 Harald Fernengel <harry@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include "preprocessor.h"
+
+#include <string>
+
+// register callback for include hooks
+static void includeFileHook(const std::string &, const std::string &, FILE *);
+
+#define PP_HOOK_ON_FILE_INCLUDED(A, B, C) includeFileHook(A, B, C)
+#include "pp.h"
+
+using namespace rpp;
+
+#include <QtCore/QtCore>
+
+class PreprocessorPrivate
+{
+public:
+ QByteArray result;
+ pp_environment env;
+ QStringList includePaths;
+
+ void initPP(pp &proc) {
+ foreach(QString path, includePaths)
+ proc.push_include_path(path.toStdString());
+ }
+};
+
+QHash<QString, QStringList> includedFiles;
+
+void includeFileHook(const std::string &fileName, const std::string &filePath, FILE *)
+{
+ includedFiles[QString::fromStdString(fileName)].append(QString::fromStdString(filePath));
+}
+
+Preprocessor::Preprocessor()
+{
+ d = new PreprocessorPrivate;
+ includedFiles.clear();
+}
+
+Preprocessor::~Preprocessor()
+{
+ delete d;
+}
+
+void Preprocessor::processFile(const QString &fileName)
+{
+ pp proc(d->env);
+ d->initPP(proc);
+
+ d->result.reserve(d->result.size() + 20 * 1024);
+
+ d->result += "# 1 \"" + fileName.toLatin1() + "\"\n"; // ### REMOVE ME
+ proc.file(fileName.toLocal8Bit().constData(), std::back_inserter(d->result));
+}
+
+void Preprocessor::processString(const QByteArray &str)
+{
+ pp proc(d->env);
+ d->initPP(proc);
+
+ proc(str.begin(), str.end(), std::back_inserter(d->result));
+}
+
+QByteArray Preprocessor::result() const
+{
+ return d->result;
+}
+
+void Preprocessor::addIncludePaths(const QStringList &includePaths)
+{
+ d->includePaths += includePaths;
+}
+
+QStringList Preprocessor::macroNames() const
+{
+ QStringList macros;
+
+ pp_environment::const_iterator it = d->env.first_macro();
+ while (it != d->env.last_macro()) {
+ const pp_macro *m = *it;
+ macros += QString::fromLatin1(m->name->begin(), m->name->size());
+ ++it;
+ }
+
+ return macros;
+}
+
+QList<Preprocessor::MacroItem> Preprocessor::macros() const
+{
+ QList<MacroItem> items;
+
+ pp_environment::const_iterator it = d->env.first_macro();
+ while (it != d->env.last_macro()) {
+ const pp_macro *m = *it;
+ MacroItem item;
+ item.name = QString::fromLatin1(m->name->begin(), m->name->size());
+ item.definition = QString::fromLatin1(m->definition->begin(),
+ m->definition->size());
+ for (size_t i = 0; i < m->formals.size(); ++i) {
+ item.parameters += QString::fromLatin1(m->formals[i]->begin(),
+ m->formals[i]->size());
+ }
+ item.isFunctionLike = m->function_like;
+
+#ifdef PP_WITH_MACRO_POSITION
+ item.fileName = QString::fromLatin1(m->file->begin(), m->file->size());
+#endif
+ items += item;
+
+ ++it;
+ }
+
+ return items;
+}
+
+/*
+int main()
+{
+ Preprocessor pp;
+
+ QStringList paths;
+ paths << "/usr/include";
+ pp.addIncludePaths(paths);
+
+ pp.processFile("pp-configuration");
+ pp.processFile("/usr/include/stdio.h");
+
+ qDebug() << pp.result();
+
+ return 0;
+}
+*/
+
diff --git a/parser/rpp/preprocessor.h b/parser/rpp/preprocessor.h
new file mode 100644
index 00000000..c363ea7c
--- /dev/null
+++ b/parser/rpp/preprocessor.h
@@ -0,0 +1,66 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright 2005 Harald Fernengel <harry@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef PREPROCESSOR_H
+#define PREPROCESSOR_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qstringlist.h>
+
+class QByteArray;
+class PreprocessorPrivate;
+
+class Preprocessor
+{
+public:
+ Preprocessor();
+ ~Preprocessor();
+
+ void processFile(const QString &fileName);
+ void processString(const QByteArray &str);
+
+ void addIncludePaths(const QStringList &includePaths);
+
+ QByteArray result() const;
+
+ QStringList macroNames() const;
+
+ struct MacroItem {
+ QString name;
+ QStringList parameters;
+ QString definition;
+ bool isFunctionLike;
+#ifdef PP_WITH_MACRO_POSITION
+ QString fileName;
+#endif
+ };
+ QList<MacroItem> macros() const;
+
+private:
+ Q_DISABLE_COPY(Preprocessor)
+ PreprocessorPrivate *d;
+};
+
+#endif
diff --git a/parser/rxx_allocator.h b/parser/rxx_allocator.h
new file mode 100644
index 00000000..e4a38755
--- /dev/null
+++ b/parser/rxx_allocator.h
@@ -0,0 +1,130 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+
+#ifndef RXX_ALLOCATOR_H
+#define RXX_ALLOCATOR_H
+
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+#include <memory>
+
+template <class _Tp> class rxx_allocator
+{
+public:
+ typedef _Tp value_type;
+ typedef _Tp* pointer;
+ typedef const _Tp* const_pointer;
+ typedef _Tp& reference;
+ typedef const _Tp& const_reference;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+
+ static const size_type max_block_count = size_type(-1);
+ static const size_type _S_block_size = 1 << 16; // 64K
+
+ rxx_allocator()
+ {
+ _M_block_index = max_block_count;
+ _M_current_index = 0;
+ _M_storage = 0;
+ _M_current_block = 0;
+ }
+
+ ~rxx_allocator()
+ {
+ for (size_type index = 0; index < _M_block_index + 1; ++index)
+ delete[] _M_storage[index];
+
+ ::free(_M_storage);
+ }
+
+ pointer address(reference __val) { return &__val; }
+ const_pointer address(const_reference __val) const { return &__val; }
+
+ pointer allocate(size_type __n, const void* = 0)
+ {
+ const size_type bytes = __n * sizeof(_Tp);
+
+ if (_M_current_block == 0
+ || _S_block_size < _M_current_index + bytes) {
+ ++_M_block_index;
+
+ _M_storage = reinterpret_cast<char**>
+ (::realloc(_M_storage, sizeof(char*) * (1 + _M_block_index)));
+
+ _M_current_block = _M_storage[_M_block_index] = reinterpret_cast<char*>
+ (new char[_S_block_size]);
+
+#if defined(RXX_ALLOCATOR_INIT_0) // ### make it a policy
+ ::memset(_M_current_block, 0, _S_block_size);
+#endif
+ _M_current_index = 0;
+ }
+
+ pointer p = reinterpret_cast<pointer>
+ (_M_current_block + _M_current_index);
+
+ _M_current_index += bytes;
+
+ return p;
+ }
+
+ void deallocate(pointer __p, size_type __n) {}
+
+ size_type max_size() const
+ {
+ return size_type(-1) / sizeof(_Tp);
+ }
+
+ void contruct(pointer __p, const_reference __val)
+ {
+ new(__p) _Tp(__val);
+ }
+ void destruct(pointer __p)
+ {
+ __p->~_Tp();
+ }
+
+private:
+ template <class _Tp1>
+ struct rebind
+ {
+ typedef rxx_allocator<_Tp1> other;
+ };
+
+ template <class _Tp1> rxx_allocator(const rxx_allocator<_Tp1> &__o) {}
+
+private:
+ size_type _M_block_index;
+ size_type _M_current_index;
+ char *_M_current_block;
+ char **_M_storage;
+};
+
+#endif // RXX_ALLOCATOR_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
+
diff --git a/parser/smallobject.cpp b/parser/smallobject.cpp
new file mode 100644
index 00000000..e96d417c
--- /dev/null
+++ b/parser/smallobject.cpp
@@ -0,0 +1,28 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+
+#include "smallobject.h"
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/smallobject.h b/parser/smallobject.h
new file mode 100644
index 00000000..52cdc232
--- /dev/null
+++ b/parser/smallobject.h
@@ -0,0 +1,47 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+
+#ifndef SMALLOBJECT_H
+#define SMALLOBJECT_H
+
+#include "rxx_allocator.h"
+#include <cstring>
+
+class pool
+{
+ rxx_allocator<char> __alloc;
+
+public:
+ inline void *allocate(std::size_t __size);
+};
+
+inline void *pool::allocate(std::size_t __size)
+{
+ return __alloc.allocate(__size);
+}
+
+#endif
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/symbol.h b/parser/symbol.h
new file mode 100644
index 00000000..8e393cdd
--- /dev/null
+++ b/parser/symbol.h
@@ -0,0 +1,122 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+
+#ifndef SYMBOL_H
+#define SYMBOL_H
+
+#include <QtCore/QString>
+#include <cstring>
+
+#include <QtCore/QHash>
+#include <QtCore/QPair>
+
+struct NameSymbol
+{
+ const char *data;
+ std::size_t count;
+
+ inline QString as_string() const
+ {
+ return QString::fromUtf8(data, (int) count);
+ }
+
+ inline bool operator == (const NameSymbol &other) const
+ {
+ return count == other.count
+ && !std::strncmp(data, other.data, count);
+ }
+
+protected:
+ inline NameSymbol() {}
+ inline NameSymbol(const char *d, std::size_t c)
+ : data(d), count(c) {}
+
+private:
+ void operator = (const NameSymbol &);
+
+ friend class NameTable;
+};
+
+inline uint qHash(const NameSymbol &r)
+{
+ uint hash_value = 0;
+
+ for (std::size_t i = 0; i < r.count; ++i)
+ hash_value = (hash_value << 5) - hash_value + r.data[i];
+
+ return hash_value;
+}
+
+inline uint qHash(const QPair<const char*, std::size_t> &r)
+{
+ uint hash_value = 0;
+
+ for (std::size_t i = 0; i < r.second; ++i)
+ hash_value = (hash_value << 5) - hash_value + r.first[i];
+
+ return hash_value;
+}
+
+class NameTable
+{
+public:
+ typedef QPair<const char *, std::size_t> KeyType;
+ typedef QHash<KeyType, NameSymbol*> ContainerType;
+
+public:
+ NameTable() {}
+
+ ~NameTable()
+ {
+ qDeleteAll(_M_storage);
+ }
+
+ inline const NameSymbol *findOrInsert(const char *str, std::size_t len)
+ {
+ KeyType key(str, len);
+
+ NameSymbol *name = _M_storage.value(key);
+ if (!name) {
+ name = new NameSymbol(str, len);
+ _M_storage.insert(key, name);
+ }
+
+ return name;
+ }
+
+ inline std::size_t count() const { return _M_storage.size(); }
+
+private:
+ ContainerType _M_storage;
+
+private:
+ NameTable(const NameTable &other);
+ void operator=(const NameTable &other);
+};
+
+#endif // SYMBOL_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
+
diff --git a/parser/tokens.cpp b/parser/tokens.cpp
new file mode 100644
index 00000000..2e054d89
--- /dev/null
+++ b/parser/tokens.cpp
@@ -0,0 +1,249 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+
+#include <QtCore/qglobal.h>
+
+#include "tokens.h"
+
+static char const * const _S_token_names[] = {
+ "K_DCOP",
+ "Q_OBJECT",
+ "Q_PROPERTY",
+ "__attribute__",
+ "__typeof",
+ "and",
+ "and_eq",
+ "arrow",
+ "asm",
+ "assign",
+ "auto",
+ "bitand",
+ "bitor",
+ "bool",
+ "break",
+ "case",
+ "catch",
+ "char",
+ "char_literal",
+ "class",
+ "comment",
+ "compl",
+ "concat",
+ "const",
+ "const_cast",
+ "continue",
+ "decr",
+ "default",
+ "delete",
+ "do",
+ "double",
+ "dynamic_cast",
+ "ellipsis",
+ "else",
+ "emit",
+ "enum",
+ "eq",
+ "explicit",
+ "export",
+ "extern",
+ "false",
+ "float",
+ "for",
+ "friend",
+ "geq",
+ "goto",
+ "identifier",
+ "if",
+ "incr",
+ "inline",
+ "int",
+ "k_dcop",
+ "k_dcop_signals",
+ "leq",
+ "long",
+ "mutable",
+ "namespace",
+ "new",
+ "not",
+ "not_eq",
+ "number_literal",
+ "operator",
+ "or",
+ "or_eq",
+ "preproc",
+ "private",
+ "protected",
+ "ptrmem",
+ "public",
+ "register",
+ "reinterpret_cast",
+ "return",
+ "scope",
+ "shift",
+ "short",
+ "signals",
+ "signed",
+ "sizeof",
+ "slots",
+ "static",
+ "static_cast",
+ "string_literal",
+ "struct",
+ "switch",
+ "template",
+ "this",
+ "throw",
+ "true",
+ "try",
+ "typedef",
+ "typeid",
+ "typename",
+ "union",
+ "unsigned",
+ "using",
+ "virtual",
+ "void",
+ "volatile",
+ "wchar_t",
+ "while",
+ "whitespaces",
+ "xor",
+ "xor_eq",
+ "Q_ENUMS"
+};
+
+static char _S_printable[][2] = {
+ { char(32), '\0' },
+ { char(33), '\0' },
+ { char(34), '\0' },
+ { char(35), '\0' },
+ { char(36), '\0' },
+ { char(37), '\0' },
+ { char(38), '\0' },
+ { char(39), '\0' },
+ { char(40), '\0' },
+ { char(41), '\0' },
+ { char(42), '\0' },
+ { char(43), '\0' },
+ { char(44), '\0' },
+ { char(45), '\0' },
+ { char(46), '\0' },
+ { char(47), '\0' },
+ { char(48), '\0' },
+ { char(49), '\0' },
+ { char(50), '\0' },
+ { char(51), '\0' },
+ { char(52), '\0' },
+ { char(53), '\0' },
+ { char(54), '\0' },
+ { char(55), '\0' },
+ { char(56), '\0' },
+ { char(57), '\0' },
+ { char(58), '\0' },
+ { char(59), '\0' },
+ { char(60), '\0' },
+ { char(61), '\0' },
+ { char(62), '\0' },
+ { char(63), '\0' },
+ { char(64), '\0' },
+ { char(65), '\0' },
+ { char(66), '\0' },
+ { char(67), '\0' },
+ { char(68), '\0' },
+ { char(69), '\0' },
+ { char(70), '\0' },
+ { char(71), '\0' },
+ { char(72), '\0' },
+ { char(73), '\0' },
+ { char(74), '\0' },
+ { char(75), '\0' },
+ { char(76), '\0' },
+ { char(77), '\0' },
+ { char(78), '\0' },
+ { char(79), '\0' },
+ { char(80), '\0' },
+ { char(81), '\0' },
+ { char(82), '\0' },
+ { char(83), '\0' },
+ { char(84), '\0' },
+ { char(85), '\0' },
+ { char(86), '\0' },
+ { char(87), '\0' },
+ { char(88), '\0' },
+ { char(89), '\0' },
+ { char(90), '\0' },
+ { char(91), '\0' },
+ { char(92), '\0' },
+ { char(93), '\0' },
+ { char(94), '\0' },
+ { char(95), '\0' },
+ { char(96), '\0' },
+ { char(97), '\0' },
+ { char(98), '\0' },
+ { char(99), '\0' },
+ { char(100), '\0' },
+ { char(101), '\0' },
+ { char(102), '\0' },
+ { char(103), '\0' },
+ { char(104), '\0' },
+ { char(105), '\0' },
+ { char(106), '\0' },
+ { char(107), '\0' },
+ { char(108), '\0' },
+ { char(109), '\0' },
+ { char(110), '\0' },
+ { char(111), '\0' },
+ { char(112), '\0' },
+ { char(113), '\0' },
+ { char(114), '\0' },
+ { char(115), '\0' },
+ { char(116), '\0' },
+ { char(117), '\0' },
+ { char(118), '\0' },
+ { char(119), '\0' },
+ { char(120), '\0' },
+ { char(121), '\0' },
+ { char(122), '\0' },
+ { char(123), '\0' },
+ { char(124), '\0' },
+ { char(125), '\0' },
+ { char(126), '\0' },
+ { char(127), '\0' },
+};
+
+char const *token_name(int token)
+{
+ if (token == 0)
+ return "eof";
+ else if (token >= 32 && token <= 127)
+ return _S_printable[token - 32];
+ else if (token >= 1000)
+ return _S_token_names[token - 1000];
+
+ Q_ASSERT(0);
+ return 0;
+}
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/tokens.h b/parser/tokens.h
new file mode 100644
index 00000000..257ff099
--- /dev/null
+++ b/parser/tokens.h
@@ -0,0 +1,145 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+
+#ifndef TOKENS_H
+#define TOKENS_H
+
+enum TOKEN_KIND {
+ Token_EOF = 0,
+
+ Token_K_DCOP = 1000,
+ Token_Q_OBJECT,
+ Token_Q_PROPERTY,
+ Token___attribute__,
+ Token___typeof,
+ Token_and,
+ Token_and_eq,
+ Token_arrow,
+ Token_asm,
+ Token_assign,
+ Token_auto,
+ Token_bitand,
+ Token_bitor,
+ Token_bool,
+ Token_break,
+ Token_case,
+ Token_catch,
+ Token_char,
+ Token_char_literal,
+ Token_class,
+ Token_comment,
+ Token_compl,
+ Token_concat,
+ Token_const,
+ Token_const_cast,
+ Token_continue,
+ Token_decr,
+ Token_default,
+ Token_delete,
+ Token_do,
+ Token_double,
+ Token_dynamic_cast,
+ Token_ellipsis,
+ Token_else,
+ Token_emit,
+ Token_enum,
+ Token_eq,
+ Token_explicit,
+ Token_export,
+ Token_extern,
+ Token_false,
+ Token_float,
+ Token_for,
+ Token_friend,
+ Token_geq,
+ Token_goto,
+ Token_identifier,
+ Token_if,
+ Token_incr,
+ Token_inline,
+ Token_int,
+ Token_k_dcop,
+ Token_k_dcop_signals,
+ Token_leq,
+ Token_long,
+ Token_mutable,
+ Token_namespace,
+ Token_new,
+ Token_not,
+ Token_not_eq,
+ Token_number_literal,
+ Token_operator,
+ Token_or,
+ Token_or_eq,
+ Token_preproc,
+ Token_private,
+ Token_protected,
+ Token_ptrmem,
+ Token_public,
+ Token_register,
+ Token_reinterpret_cast,
+ Token_return,
+ Token_scope,
+ Token_shift,
+ Token_short,
+ Token_signals,
+ Token_signed,
+ Token_sizeof,
+ Token_slots,
+ Token_static,
+ Token_static_cast,
+ Token_string_literal,
+ Token_struct,
+ Token_switch,
+ Token_template,
+ Token_this,
+ Token_throw,
+ Token_true,
+ Token_try,
+ Token_typedef,
+ Token_typeid,
+ Token_typename,
+ Token_union,
+ Token_unsigned,
+ Token_using,
+ Token_virtual,
+ Token_void,
+ Token_volatile,
+ Token_wchar_t,
+ Token_while,
+ Token_whitespaces,
+ Token_xor,
+ Token_xor_eq,
+ Token_Q_ENUMS,
+ Token_Q_INVOKABLE,
+
+ TOKEN_KIND_COUNT
+};
+
+char const *token_name(int token);
+
+#endif
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/type_compiler.cpp b/parser/type_compiler.cpp
new file mode 100644
index 00000000..4bcdb277
--- /dev/null
+++ b/parser/type_compiler.cpp
@@ -0,0 +1,129 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+
+
+#include "type_compiler.h"
+#include "name_compiler.h"
+#include "lexer.h"
+#include "symbol.h"
+#include "tokens.h"
+#include "binder.h"
+
+#include <QtCore/QString>
+
+TypeCompiler::TypeCompiler(Binder *binder)
+ : _M_binder(binder), _M_token_stream(binder->tokenStream())
+{
+}
+
+void TypeCompiler::run(TypeSpecifierAST *node)
+{
+ _M_type.clear();
+ _M_cv.clear();
+
+ visit(node);
+
+ if (node && node->cv) {
+ const ListNode<std::size_t> *it = node->cv->toFront();
+ const ListNode<std::size_t> *end = it;
+ do {
+ int kind = _M_token_stream->kind(it->element);
+ if (!_M_cv.contains(kind))
+ _M_cv.append(kind);
+
+ it = it->next;
+ } while (it != end);
+ }
+}
+
+void TypeCompiler::visitClassSpecifier(ClassSpecifierAST *node)
+{
+ visit(node->name);
+}
+
+void TypeCompiler::visitEnumSpecifier(EnumSpecifierAST *node)
+{
+ visit(node->name);
+}
+
+void TypeCompiler::visitElaboratedTypeSpecifier(ElaboratedTypeSpecifierAST *node)
+{
+ visit(node->name);
+}
+
+void TypeCompiler::visitSimpleTypeSpecifier(SimpleTypeSpecifierAST *node)
+{
+ if (const ListNode<std::size_t> *it = node->integrals) {
+ it = it->toFront();
+ const ListNode<std::size_t> *end = it;
+ QString current_item;
+ do {
+ std::size_t token = it->element;
+ current_item += token_name(_M_token_stream->kind(token));
+ current_item += " ";
+ it = it->next;
+ } while (it != end);
+ _M_type += current_item.trimmed();
+ } else if (node->type_of) {
+ // ### implement me
+ _M_type += QLatin1String("typeof<...>");
+ }
+
+ visit(node->name);
+}
+
+void TypeCompiler::visitName(NameAST *node)
+{
+ NameCompiler name_cc(_M_binder);
+ name_cc.run(node);
+ _M_type = name_cc.qualifiedName();
+}
+
+QStringList TypeCompiler::cvString() const
+{
+ QStringList lst;
+
+ foreach (int q, cv()) {
+ if (q == Token_const)
+ lst.append(QLatin1String("const"));
+ else if (q == Token_volatile)
+ lst.append(QLatin1String("volatile"));
+ }
+
+ return lst;
+}
+
+bool TypeCompiler::isConstant() const
+{
+ return _M_cv.contains(Token_const);
+}
+
+bool TypeCompiler::isVolatile() const
+{
+ return _M_cv.contains(Token_volatile);
+}
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/type_compiler.h b/parser/type_compiler.h
new file mode 100644
index 00000000..985cc8e2
--- /dev/null
+++ b/parser/type_compiler.h
@@ -0,0 +1,71 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+
+#ifndef TYPE_COMPILER_H
+#define TYPE_COMPILER_H
+
+#include "default_visitor.h"
+
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QList>
+
+class TokenStream;
+class Binder;
+
+class TypeCompiler: protected DefaultVisitor
+{
+public:
+ TypeCompiler(Binder *binder);
+
+ inline QStringList qualifiedName() const { return _M_type; }
+ inline QList<int> cv() const { return _M_cv; }
+
+ bool isConstant() const;
+ bool isVolatile() const;
+
+ QStringList cvString() const;
+
+ void run(TypeSpecifierAST *node);
+
+protected:
+ virtual void visitClassSpecifier(ClassSpecifierAST *node);
+ virtual void visitEnumSpecifier(EnumSpecifierAST *node);
+ virtual void visitElaboratedTypeSpecifier(ElaboratedTypeSpecifierAST *node);
+ virtual void visitSimpleTypeSpecifier(SimpleTypeSpecifierAST *node);
+
+ virtual void visitName(NameAST *node);
+
+private:
+ Binder *_M_binder;
+ TokenStream *_M_token_stream;
+ QStringList _M_type;
+ QList<int> _M_cv;
+};
+
+#endif // TYPE_COMPILER_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
+
diff --git a/parser/visitor.cpp b/parser/visitor.cpp
new file mode 100644
index 00000000..74298141
--- /dev/null
+++ b/parser/visitor.cpp
@@ -0,0 +1,122 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+
+#include "visitor.h"
+
+Visitor::visitor_fun_ptr Visitor::_S_table[AST::NODE_KIND_COUNT] = {
+ 0,
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitAccessSpecifier),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitAsmDefinition),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitBaseClause),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitBaseSpecifier),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitBinaryExpression),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitCastExpression),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitClassMemberAccess),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitClassSpecifier),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitCompoundStatement),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitCondition),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitConditionalExpression),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitCppCastExpression),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitCtorInitializer),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitDeclarationStatement),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitDeclarator),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitDeleteExpression),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitDoStatement),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitElaboratedTypeSpecifier),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitEnumSpecifier),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitEnumerator),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitExceptionSpecification),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitExpressionOrDeclarationStatement),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitExpressionStatement),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitForStatement),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitFunctionCall),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitFunctionDefinition),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitIfStatement),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitIncrDecrExpression),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitInitDeclarator),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitInitializer),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitInitializerClause),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitLabeledStatement),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitLinkageBody),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitLinkageSpecification),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitMemInitializer),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitName),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitNamespace),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitNamespaceAliasDefinition),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitNewDeclarator),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitNewExpression),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitNewInitializer),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitNewTypeId),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitOperator),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitOperatorFunctionId),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitParameterDeclaration),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitParameterDeclarationClause),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitPostfixExpression),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitPrimaryExpression),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitPtrOperator),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitPtrToMember),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitReturnStatement),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitSimpleDeclaration),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitSimpleTypeSpecifier),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitSizeofExpression),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitStringLiteral),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitSubscriptExpression),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitSwitchStatement),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitTemplateArgument),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitTemplateDeclaration),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitTemplateParameter),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitThrowExpression),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitTranslationUnit),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitTryBlockStatement),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitTypeId),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitTypeIdentification),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitTypeParameter),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitTypedef),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitUnaryExpression),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitUnqualifiedName),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitUsing),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitUsingDirective),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitWhileStatement),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitWinDeclSpec),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitQProperty),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitForwardDeclarationSpecifier),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitQEnums)
+};
+
+Visitor::Visitor()
+{
+}
+
+Visitor::~Visitor()
+{
+}
+
+void Visitor::visit(AST *node)
+{
+ if (node)
+ (this->*_S_table[node->kind])(node);
+}
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/visitor.h b/parser/visitor.h
new file mode 100644
index 00000000..74edcca8
--- /dev/null
+++ b/parser/visitor.h
@@ -0,0 +1,140 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+
+#ifndef VISITOR_H
+#define VISITOR_H
+
+#include "ast.h"
+
+class Visitor
+{
+public:
+ Visitor();
+ virtual ~Visitor();
+
+ virtual void visit(AST *node);
+
+protected:
+ virtual void visitAccessSpecifier(AccessSpecifierAST *) {}
+ virtual void visitAsmDefinition(AsmDefinitionAST *) {}
+ virtual void visitBaseClause(BaseClauseAST *) {}
+ virtual void visitBaseSpecifier(BaseSpecifierAST *) {}
+ virtual void visitBinaryExpression(BinaryExpressionAST *) {}
+ virtual void visitCastExpression(CastExpressionAST *) {}
+ virtual void visitClassMemberAccess(ClassMemberAccessAST *) {}
+ virtual void visitClassSpecifier(ClassSpecifierAST *) {}
+ virtual void visitCompoundStatement(CompoundStatementAST *) {}
+ virtual void visitCondition(ConditionAST *) {}
+ virtual void visitConditionalExpression(ConditionalExpressionAST *) {}
+ virtual void visitCppCastExpression(CppCastExpressionAST *) {}
+ virtual void visitCtorInitializer(CtorInitializerAST *) {}
+ virtual void visitDeclarationStatement(DeclarationStatementAST *) {}
+ virtual void visitDeclarator(DeclaratorAST *) {}
+ virtual void visitDeleteExpression(DeleteExpressionAST *) {}
+ virtual void visitDoStatement(DoStatementAST *) {}
+ virtual void visitElaboratedTypeSpecifier(ElaboratedTypeSpecifierAST *) {}
+ virtual void visitEnumSpecifier(EnumSpecifierAST *) {}
+ virtual void visitEnumerator(EnumeratorAST *) {}
+ virtual void visitExceptionSpecification(ExceptionSpecificationAST *) {}
+ virtual void visitExpressionOrDeclarationStatement(ExpressionOrDeclarationStatementAST *) {}
+ virtual void visitExpressionStatement(ExpressionStatementAST *) {}
+ virtual void visitForStatement(ForStatementAST *) {}
+ virtual void visitFunctionCall(FunctionCallAST *) {}
+ virtual void visitFunctionDefinition(FunctionDefinitionAST *) {}
+ virtual void visitIfStatement(IfStatementAST *) {}
+ virtual void visitIncrDecrExpression(IncrDecrExpressionAST *) {}
+ virtual void visitInitDeclarator(InitDeclaratorAST *) {}
+ virtual void visitInitializer(InitializerAST *) {}
+ virtual void visitInitializerClause(InitializerClauseAST *) {}
+ virtual void visitLabeledStatement(LabeledStatementAST *) {}
+ virtual void visitLinkageBody(LinkageBodyAST *) {}
+ virtual void visitLinkageSpecification(LinkageSpecificationAST *) {}
+ virtual void visitMemInitializer(MemInitializerAST *) {}
+ virtual void visitName(NameAST *) {}
+ virtual void visitNamespace(NamespaceAST *) {}
+ virtual void visitNamespaceAliasDefinition(NamespaceAliasDefinitionAST *) {}
+ virtual void visitNewDeclarator(NewDeclaratorAST *) {}
+ virtual void visitNewExpression(NewExpressionAST *) {}
+ virtual void visitNewInitializer(NewInitializerAST *) {}
+ virtual void visitNewTypeId(NewTypeIdAST *) {}
+ virtual void visitOperator(OperatorAST *) {}
+ virtual void visitOperatorFunctionId(OperatorFunctionIdAST *) {}
+ virtual void visitParameterDeclaration(ParameterDeclarationAST *) {}
+ virtual void visitParameterDeclarationClause(ParameterDeclarationClauseAST *) {}
+ virtual void visitPostfixExpression(PostfixExpressionAST *) {}
+ virtual void visitPrimaryExpression(PrimaryExpressionAST *) {}
+ virtual void visitPtrOperator(PtrOperatorAST *) {}
+ virtual void visitPtrToMember(PtrToMemberAST *) {}
+ virtual void visitReturnStatement(ReturnStatementAST *) {}
+ virtual void visitSimpleDeclaration(SimpleDeclarationAST *) {}
+ virtual void visitSimpleTypeSpecifier(SimpleTypeSpecifierAST *) {}
+ virtual void visitSizeofExpression(SizeofExpressionAST *) {}
+ virtual void visitStringLiteral(StringLiteralAST *) {}
+ virtual void visitSubscriptExpression(SubscriptExpressionAST *) {}
+ virtual void visitSwitchStatement(SwitchStatementAST *) {}
+ virtual void visitTemplateArgument(TemplateArgumentAST *) {}
+ virtual void visitTemplateDeclaration(TemplateDeclarationAST *) {}
+ virtual void visitTemplateParameter(TemplateParameterAST *) {}
+ virtual void visitThrowExpression(ThrowExpressionAST *) {}
+ virtual void visitTranslationUnit(TranslationUnitAST *) {}
+ virtual void visitTryBlockStatement(TryBlockStatementAST *) {}
+ virtual void visitTypeId(TypeIdAST *) {}
+ virtual void visitTypeIdentification(TypeIdentificationAST *) {}
+ virtual void visitTypeParameter(TypeParameterAST *) {}
+ virtual void visitTypedef(TypedefAST *) {}
+ virtual void visitUnaryExpression(UnaryExpressionAST *) {}
+ virtual void visitUnqualifiedName(UnqualifiedNameAST *) {}
+ virtual void visitUsing(UsingAST *) {}
+ virtual void visitUsingDirective(UsingDirectiveAST *) {}
+ virtual void visitWhileStatement(WhileStatementAST *) {}
+ virtual void visitWinDeclSpec(WinDeclSpecAST *) {}
+ virtual void visitQProperty(QPropertyAST *) {}
+ virtual void visitForwardDeclarationSpecifier(ForwardDeclarationSpecifierAST *) {}
+ virtual void visitQEnums(QEnumsAST *) {}
+
+private:
+ typedef void (Visitor::*visitor_fun_ptr)(AST *);
+ static visitor_fun_ptr _S_table[];
+};
+
+template <class _Tp>
+void visitNodes(Visitor *v, const ListNode<_Tp> *nodes)
+{
+ if (!nodes)
+ return;
+
+ const ListNode<_Tp>
+ *it = nodes->toFront(),
+ *end = it;
+
+ do {
+ v->visit(it->element);
+ it = it->next;
+ } while (it != end);
+}
+
+#endif // VISITOR_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;