summaryrefslogtreecommitdiffstats
path: root/umbrello/umbrello/codeimport/kdevcppparser
diff options
context:
space:
mode:
Diffstat (limited to 'umbrello/umbrello/codeimport/kdevcppparser')
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/Makefile.am5
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/README56
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/ast.cpp1183
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/ast.h1449
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/ast_utils.cpp176
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/ast_utils.h29
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/cpptree2uml.cpp640
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/cpptree2uml.h98
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/driver.cpp435
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/driver.h230
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/errors.cpp25
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/errors.h45
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/keywords.lut.h123
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/lexer.cpp1002
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/lexer.h791
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/lookup.cpp113
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/lookup.h119
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/parser.cpp4238
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/parser.h221
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/tree_parser.cpp207
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/tree_parser.h59
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/urlutil.cpp310
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/urlutil.h132
23 files changed, 11686 insertions, 0 deletions
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/Makefile.am b/umbrello/umbrello/codeimport/kdevcppparser/Makefile.am
new file mode 100644
index 00000000..b8325478
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/Makefile.am
@@ -0,0 +1,5 @@
+INCLUDES = $(all_includes)
+
+noinst_LTLIBRARIES = libkdevcppparser.la
+libkdevcppparser_la_SOURCES = ast.cpp driver.cpp errors.cpp lexer.cpp lookup.cpp parser.cpp tree_parser.cpp urlutil.cpp ast_utils.cpp cpptree2uml.cpp
+
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/README b/umbrello/umbrello/codeimport/kdevcppparser/README
new file mode 100644
index 00000000..3ed39eba
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/README
@@ -0,0 +1,56 @@
+This directory contains the C++ parser from Kdevelop-3.0.
+
+Following files are copies from the directory kdevelop/lib/cppparser:
+ ast.{h,cpp} driver.{h,cpp} errors.{h,cpp} keywords.lut.h lexer.{h,cpp}
+ lookup.{h,cpp} parser.{h,cpp} tree_parser.{h,cpp}
+
+Following files are copies from the directory kdevelop/languages/cpp:
+ ast_utils.{h,cpp}
+
+Following files are copies from the directory kdevelop/lib/util:
+ urlutil.{h,cpp}
+
+The source files cpptree2uml.{h,cpp} are based on kdevelop/languages/cpp/
+store_walker.{h,cpp}. The class CppTree2Uml inherits from class TreeParser
+and overrides certain methods from that class.
+
+CppTree2Uml visits the nodes of the abstract syntax tree constructed by the
+CppParser, and constructs UML objects on the way.
+
+The import_utils.h (in the parent directory) is the interface between the
+CppTree2Uml and Umbrello.
+import_utils implements the construction of the UML objects. CppTree2Uml calls
+the create/insert methods in the import_utils while traversing the syntax
+tree.
+
+The one and only method that Umbrello uses for accessing the C++ parser,
+and any other parser for that matter, is ClassImport::importFiles().
+The class CppImport (in the parent directory) implements that operation.
+Thus we have these classes:
+
+ +-------------------+
+ | <<interface>> |
+ | ClassImport |
+ +===================+
+Umbrello ------>| importFiles() = 0 |
+ +-------------------+
+ A
+ | <<realize>>
+ |
+ +-------------------+ +-------------------+
+ | CppImport | | CppTree2Uml |
+ +===================+ <<invoke>> +===================+
+ | importFiles() |-------------->| |
+ +-------------------+ | |
+ +-------------------+
+ |
+ +-------------------+ |
+ | <<utility>> | |
+ | Import_Utils | |
+ +===================+ |
+ | createUMLObject() | <<invoke>> |
+ | insertMethod() |<-----------------------+
+ | insertAttribute() |
+ +-------------------+
+ |
+Umbrello <--------------+
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/ast.cpp b/umbrello/umbrello/codeimport/kdevcppparser/ast.cpp
new file mode 100644
index 00000000..6baca685
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/ast.cpp
@@ -0,0 +1,1183 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "ast.h"
+#include <qstringlist.h>
+#include <kdebug.h>
+
+QString nodeTypeToString( int type )
+{
+ switch( type )
+ {
+ case NodeType_Generic:
+ return "Generic";
+ case NodeType_TemplateArgumentList:
+ return "TemplateArgumentList";
+ case NodeType_ClassOrNamespaceName:
+ return "ClassOrNamespaceName";
+ case NodeType_Name:
+ return "Name";
+ case NodeType_Declaration:
+ return "Declaration";
+ case NodeType_TypeSpecifier:
+ return "TypeSpecifier";
+ case NodeType_BaseSpecifier:
+ return "BaseSpecifier";
+ case NodeType_BaseClause:
+ return "BaseClause";
+ case NodeType_ClassSpecifier:
+ return "ClassSpecifier";
+ case NodeType_Enumerator:
+ return "Enumerator";
+ case NodeType_EnumSpecifier:
+ return "EnumSpecifier";
+ case NodeType_ElaboratedTypeSpecifier:
+ return "ElaboratedTypeSpecifier";
+ case NodeType_LinkageBody:
+ return "LinkageBody";
+ case NodeType_LinkageSpecification:
+ return "LinkageSpecification";
+ case NodeType_Namespace:
+ return "Namespace";
+ case NodeType_NamespaceAlias:
+ return "NamespaceAlias";
+ case NodeType_Using:
+ return "Using";
+ case NodeType_UsingDirective:
+ return "UsingDirective";
+ case NodeType_InitDeclaratorList:
+ return "InitDeclaratorList";
+ case NodeType_Typedef:
+ return "Typedef";
+ case NodeType_Declarator:
+ return "Declarator";
+ case NodeType_InitDeclarator:
+ return "InitDeclarator";
+ case NodeType_TemplateDeclaration:
+ return "TemplateDeclaration";
+ case NodeType_SimpleDeclaration:
+ return "SimpleDeclaration";
+ case NodeType_Statement:
+ return "Statement";
+ case NodeType_IfStatement:
+ return "IfStatement";
+ case NodeType_WhileStatement:
+ return "WhileStatement";
+ case NodeType_DoStatement:
+ return "DoStatement";
+ case NodeType_ForStatement:
+ return "ForStatement";
+ case NodeType_SwitchStatement:
+ return "SwitchStatement";
+ case NodeType_DeclarationStatement:
+ return "DeclarationStatement";
+ case NodeType_StatementList:
+ return "StatementList";
+ case NodeType_TranslationUnit:
+ return "TranslationUnit";
+ case NodeType_FunctionDefinition:
+ return "FunctionDefinition";
+ case NodeType_ExpressionStatement:
+ return "ExpressionStatement";
+ case NodeType_ParameterDeclaration:
+ return "ParameterDeclaration";
+ case NodeType_ParameterDeclarationList:
+ return "ParameterDeclarationList";
+ case NodeType_ParameterDeclarationClause:
+ return "ParameterDeclarationClause";
+ case NodeType_Group:
+ return "Group";
+ case NodeType_AccessDeclaration:
+ return "AccessDeclaration";
+ case NodeType_TypeParameter:
+ return "TypeParameter";
+ case NodeType_TemplateParameter:
+ return "TemplateParameter";
+ case NodeType_TemplateParameterList:
+ return "TemplateParameterList";
+ case NodeType_Condition:
+ return "Condition";
+ case NodeType_Custom:
+ return "Custom";
+ }
+
+ return QString::null;
+}
+
+
+// ------------------------------------------------------------------------
+AST::AST()
+ : m_nodeType( NodeType_Generic ), m_parent( 0 ),
+ m_startLine( 0 ), m_startColumn( 0 ),
+ m_endLine( 0 ), m_endColumn( 0 )
+{
+#ifndef CPPPARSER_NO_CHILDREN
+ m_children.setAutoDelete( false );
+#endif
+}
+
+AST::~AST()
+{
+#ifndef CPPPARSER_NO_CHILDREN
+ if( m_parent )
+ m_parent->removeChild( this );
+#endif
+}
+
+void AST::setStartPosition( int line, int col )
+{
+ m_startLine = line;
+ m_startColumn = col;
+}
+
+void AST::getStartPosition( int* line, int* col ) const
+{
+ if( line )
+ *line = m_startLine;
+
+ if( col )
+ * col = m_startColumn;
+}
+
+void AST::setEndPosition( int line, int col )
+{
+ m_endLine = line;
+ m_endColumn = col;
+}
+
+void AST::getEndPosition( int* line, int* col ) const
+{
+ if( line )
+ *line = m_endLine;
+
+ if( col )
+ * col = m_endColumn;
+}
+
+void AST::setParent( AST* parent )
+{
+#ifndef CPPPARSER_NO_CHILDREN
+ if( m_parent )
+ m_parent->removeChild( this );
+#endif
+
+ m_parent = parent;
+
+#ifndef CPPPARSER_NO_CHILDREN
+ if( m_parent )
+ m_parent->appendChild( this );
+#endif
+}
+
+#ifndef CPPPARSER_NO_CHILDREN
+void AST::appendChild( AST* child )
+{
+ m_children.append( child );
+}
+
+void AST::removeChild( AST* child )
+{
+ m_children.remove( child );
+}
+#endif
+
+// ------------------------------------------------------------------------
+NameAST::NameAST()
+ : m_global( false )
+{
+ m_classOrNamespaceNameList.setAutoDelete( true );
+}
+
+void NameAST::setGlobal( bool b )
+{
+ m_global = b;
+}
+
+void NameAST::setUnqualifiedName( ClassOrNamespaceNameAST::Node& unqualifiedName )
+{
+ m_unqualifiedName = unqualifiedName;
+ if( m_unqualifiedName.get() ) m_unqualifiedName->setParent( this );
+}
+
+void NameAST::addClassOrNamespaceName( ClassOrNamespaceNameAST::Node& classOrNamespaceName )
+{
+ if( !classOrNamespaceName.get() )
+ return;
+
+ classOrNamespaceName->setParent( this );
+ m_classOrNamespaceNameList.append( classOrNamespaceName.release() );
+}
+
+QString NameAST::text() const
+{
+ if( !m_unqualifiedName.get() )
+ return QString::null;
+
+ QString str;
+
+ if( m_global )
+ str += "::";
+
+ QStringList l;
+ QPtrListIterator<ClassOrNamespaceNameAST> it( m_classOrNamespaceNameList );
+ while( it.current() ){
+ str += it.current()->text() + "::";
+ ++it;
+ }
+
+ if( m_unqualifiedName.get() )
+ str += m_unqualifiedName->text();
+
+ return str;
+}
+
+// ------------------------------------------------------------------------
+DeclarationAST::DeclarationAST()
+{
+}
+
+// ------------------------------------------------------------------------
+LinkageBodyAST::LinkageBodyAST()
+{
+ m_declarationList.setAutoDelete( true );
+}
+
+void LinkageBodyAST::addDeclaration( DeclarationAST::Node& ast )
+{
+ if( !ast.get() )
+ return;
+
+ ast->setParent( this );
+ m_declarationList.append( ast.release() );
+}
+
+// ------------------------------------------------------------------------
+LinkageSpecificationAST::LinkageSpecificationAST()
+{
+}
+
+void LinkageSpecificationAST::setExternType( AST::Node& externType )
+{
+ m_externType = externType;
+ if( m_externType.get() ) m_externType->setParent( this );
+}
+
+void LinkageSpecificationAST::setLinkageBody( LinkageBodyAST::Node& linkageBody )
+{
+ m_linkageBody = linkageBody;
+ if( m_linkageBody.get() ) m_linkageBody->setParent( this );
+}
+
+void LinkageSpecificationAST::setDeclaration( DeclarationAST::Node& decl )
+{
+ m_declaration = decl;
+ if( m_declaration.get() ) m_declaration->setParent( this );
+}
+
+// ------------------------------------------------------------------------
+TranslationUnitAST::TranslationUnitAST()
+{
+ //kdDebug(9007) << "++ TranslationUnitAST::TranslationUnitAST()" << endl;
+ m_declarationList.setAutoDelete( true );
+}
+
+void TranslationUnitAST::addDeclaration( DeclarationAST::Node& ast )
+{
+ if( !ast.get() )
+ return;
+
+ ast->setParent( this );
+ m_declarationList.append( ast.release() );
+}
+
+// ------------------------------------------------------------------------
+NamespaceAST::NamespaceAST()
+{
+}
+
+void NamespaceAST::setNamespaceName( AST::Node& namespaceName )
+{
+ m_namespaceName = namespaceName;
+ if( m_namespaceName.get() ) m_namespaceName->setParent( this );
+}
+
+void NamespaceAST::setLinkageBody( LinkageBodyAST::Node& linkageBody )
+{
+ m_linkageBody = linkageBody;
+ if( m_linkageBody.get() ) m_linkageBody->setParent( this );
+}
+
+
+// ------------------------------------------------------------------------
+NamespaceAliasAST::NamespaceAliasAST()
+{
+}
+
+void NamespaceAliasAST::setNamespaceName( AST::Node& namespaceName )
+{
+ m_namespaceName = namespaceName;
+ if( m_namespaceName.get() ) m_namespaceName->setParent( this );
+}
+
+void NamespaceAliasAST::setAliasName( NameAST::Node& name )
+{
+ m_aliasName = name;
+ if( m_aliasName.get() ) m_aliasName->setParent( this );
+}
+
+// ------------------------------------------------------------------------
+UsingAST::UsingAST()
+{
+}
+
+void UsingAST::setTypeName( AST::Node& typeName )
+{
+ m_typeName = typeName;
+ if( m_typeName.get() ) m_typeName->setParent( this );
+}
+
+void UsingAST::setName( NameAST::Node& name )
+{
+ m_name = name;
+ if( m_name.get() ) m_name->setParent( this );
+}
+
+// ------------------------------------------------------------------------
+UsingDirectiveAST::UsingDirectiveAST()
+{
+}
+
+void UsingDirectiveAST::setName( NameAST::Node& name )
+{
+ m_name = name;
+ if( m_name.get() ) m_name->setParent( this );
+}
+
+TypedefAST::TypedefAST()
+{
+}
+
+void TypeSpecifierAST::setName( NameAST::Node& name )
+{
+ m_name = name;
+ if( m_name.get() ) m_name->setParent( this );
+}
+
+void TypedefAST::setTypeSpec( TypeSpecifierAST::Node& typeSpec )
+{
+ m_typeSpec = typeSpec;
+ if( m_typeSpec.get() ) m_typeSpec->setParent( this );
+}
+
+void TypedefAST::setInitDeclaratorList( InitDeclaratorListAST::Node& initDeclaratorList )
+{
+ m_initDeclaratorList = initDeclaratorList;
+ if( m_initDeclaratorList.get() ) m_initDeclaratorList->setParent( this );
+}
+
+// ------------------------------------------------------------------------
+TemplateArgumentListAST::TemplateArgumentListAST()
+{
+ m_argumentList.setAutoDelete( true );
+}
+
+void TemplateArgumentListAST::addArgument( AST::Node& arg )
+{
+ if( !arg.get() )
+ return;
+
+ arg->setParent( this );
+ m_argumentList.append( arg.release() );
+}
+
+QString TemplateArgumentListAST::text() const
+{
+ QStringList l;
+
+ QPtrListIterator<AST> it( m_argumentList );
+ while( it.current() ){
+ l.append( it.current()->text() );
+ ++it;
+ }
+
+ return l.join( ", " );
+}
+
+// ------------------------------------------------------------------------
+TemplateDeclarationAST::TemplateDeclarationAST()
+{
+}
+
+void TemplateDeclarationAST::setExported( AST::Node& exported )
+{
+ m_exported = exported;
+ if( m_exported.get() ) m_exported->setParent( this );
+}
+
+void TemplateDeclarationAST::setTemplateParameterList( TemplateParameterListAST::Node& templateParameterList )
+{
+ m_templateParameterList = templateParameterList;
+ if( m_templateParameterList.get() ) m_templateParameterList->setParent( this );
+}
+
+void TemplateDeclarationAST::setDeclaration( DeclarationAST::Node& declaration )
+{
+ m_declaration = declaration;
+ if( m_declaration.get() ) m_declaration->setParent( this );
+}
+
+// ------------------------------------------------------------------------
+ClassOrNamespaceNameAST::ClassOrNamespaceNameAST()
+{
+}
+
+void ClassOrNamespaceNameAST::setName( AST::Node& name )
+{
+ m_name = name;
+ if( m_name.get() ) m_name->setParent( this );
+}
+
+void ClassOrNamespaceNameAST::setTemplateArgumentList( TemplateArgumentListAST::Node& templateArgumentList )
+{
+ m_templateArgumentList = templateArgumentList;
+ if( m_templateArgumentList.get() ) m_templateArgumentList->setParent( this );
+}
+
+QString ClassOrNamespaceNameAST::text() const
+{
+ if( !m_name.get() )
+ return QString::null;
+
+ QString str = m_name->text();
+ if( m_templateArgumentList.get() )
+ str += QString::fromLatin1("< ") + m_templateArgumentList->text() + QString::fromLatin1(" >");
+
+ return str;
+}
+
+// ------------------------------------------------------------------------
+TypeSpecifierAST::TypeSpecifierAST()
+{
+}
+
+void TypeSpecifierAST::setCvQualify( GroupAST::Node& cvQualify )
+{
+ m_cvQualify = cvQualify;
+ if( m_cvQualify.get() ) m_cvQualify->setParent( this );
+}
+
+void TypeSpecifierAST::setCv2Qualify( GroupAST::Node& cv2Qualify )
+{
+ m_cv2Qualify = cv2Qualify;
+ if( m_cv2Qualify.get() ) m_cv2Qualify->setParent( this );
+}
+
+QString TypeSpecifierAST::text() const
+{
+ QString str;
+
+ if( m_cvQualify.get() )
+ str += m_cvQualify->text() + ' ';
+
+ if( m_name.get() )
+ str += m_name->text();
+
+ if( m_cv2Qualify.get() )
+ str += QString(" ") + m_cv2Qualify->text();
+
+ return str;
+}
+
+// ------------------------------------------------------------------------
+ClassSpecifierAST::ClassSpecifierAST()
+{
+ m_declarationList.setAutoDelete( true );
+}
+
+void ClassSpecifierAST::setClassKey( AST::Node& classKey )
+{
+ m_classKey = classKey;
+ if( m_classKey.get() ) m_classKey->setParent( this );
+}
+
+void ClassSpecifierAST::addDeclaration( DeclarationAST::Node& declaration )
+{
+ if( !declaration.get() )
+ return;
+
+ declaration->setParent( this );
+ m_declarationList.append( declaration.release() );
+}
+
+void ClassSpecifierAST::setBaseClause( BaseClauseAST::Node& baseClause )
+{
+ m_baseClause = baseClause;
+ if( m_baseClause.get() ) m_baseClause->setParent( this );
+}
+
+// ------------------------------------------------------------------------
+EnumSpecifierAST::EnumSpecifierAST()
+{
+ m_enumeratorList.setAutoDelete( true );
+}
+
+void EnumSpecifierAST::addEnumerator( EnumeratorAST::Node& enumerator )
+{
+ if( !enumerator.get() )
+ return;
+
+ enumerator->setParent( this );
+ m_enumeratorList.append( enumerator.release() );
+}
+
+
+// ------------------------------------------------------------------------
+ElaboratedTypeSpecifierAST::ElaboratedTypeSpecifierAST()
+{
+}
+
+void ElaboratedTypeSpecifierAST::setKind( AST::Node& kind )
+{
+ m_kind = kind;
+ if( m_kind.get() ) m_kind->setParent( this );
+}
+
+QString ElaboratedTypeSpecifierAST::text() const
+{
+ if( m_kind.get() )
+ return m_kind->text() + ' ' + TypeSpecifierAST::text();
+
+ return TypeSpecifierAST::text();
+}
+
+// ------------------------------------------------------------------------
+StatementAST::StatementAST()
+{
+}
+
+// ------------------------------------------------------------------------
+EnumeratorAST::EnumeratorAST()
+{
+}
+
+void EnumeratorAST::setId( AST::Node& id )
+{
+ m_id = id;
+ if( m_id.get() ) m_id->setParent( this );
+}
+
+void EnumeratorAST::setExpr( AST::Node& expr )
+{
+ m_expr = expr;
+ if( m_expr.get() ) m_expr->setParent( this );
+}
+
+// ------------------------------------------------------------------------
+BaseClauseAST::BaseClauseAST()
+{
+ m_baseSpecifierList.setAutoDelete( true );
+}
+
+void BaseClauseAST::addBaseSpecifier( BaseSpecifierAST::Node& baseSpecifier )
+{
+ if( !baseSpecifier.get() )
+ return;
+
+ baseSpecifier->setParent( this );
+ m_baseSpecifierList.append( baseSpecifier.release() );
+}
+
+// ------------------------------------------------------------------------
+BaseSpecifierAST::BaseSpecifierAST()
+{
+}
+
+void BaseSpecifierAST::setIsVirtual( AST::Node& isVirtual )
+{
+ m_isVirtual = isVirtual;
+ if( m_isVirtual.get() ) m_isVirtual->setParent( this );
+}
+
+void BaseSpecifierAST::setAccess( AST::Node& access )
+{
+ m_access = access;
+ if( m_access.get() ) m_access->setParent( this );
+}
+
+void BaseSpecifierAST::setName( NameAST::Node& name )
+{
+ m_name = name;
+ if( m_name.get() ) m_name->setParent( this );
+}
+
+// ------------------------------------------------------------------------
+SimpleDeclarationAST::SimpleDeclarationAST()
+{
+}
+
+void SimpleDeclarationAST::setFunctionSpecifier( GroupAST::Node& functionSpecifier )
+{
+ m_functionSpecifier = functionSpecifier;
+ if( m_functionSpecifier.get() ) m_functionSpecifier->setParent( this );
+}
+
+void SimpleDeclarationAST::setStorageSpecifier( GroupAST::Node& storageSpecifier )
+{
+ m_storageSpecifier = storageSpecifier;
+ if( m_storageSpecifier.get() ) m_storageSpecifier->setParent( this );
+}
+
+void SimpleDeclarationAST::setTypeSpec( TypeSpecifierAST::Node& typeSpec )
+{
+ m_typeSpec = typeSpec;
+ if( m_typeSpec.get() ) m_typeSpec->setParent( this );
+}
+
+void SimpleDeclarationAST::setInitDeclaratorList( InitDeclaratorListAST::Node& initDeclaratorList )
+{
+ m_initDeclaratorList = initDeclaratorList;
+ if( m_initDeclaratorList.get() ) m_initDeclaratorList->setParent( this );
+}
+
+void SimpleDeclarationAST::setWinDeclSpec( GroupAST::Node& winDeclSpec )
+{
+ m_winDeclSpec = winDeclSpec;
+ if( m_winDeclSpec.get() ) m_winDeclSpec->setParent( this );
+}
+
+
+// ------------------------------------------------------------------------
+InitDeclaratorListAST::InitDeclaratorListAST()
+{
+ m_initDeclaratorList.setAutoDelete( true );
+}
+
+void InitDeclaratorListAST::addInitDeclarator( InitDeclaratorAST::Node& decl )
+{
+ if( !decl.get() )
+ return;
+
+ decl->setParent( this );
+ m_initDeclaratorList.append( decl.release() );
+}
+
+// ------------------------------------------------------------------------
+DeclaratorAST::DeclaratorAST()
+{
+ m_ptrOpList.setAutoDelete( true );
+ m_arrayDimensionList.setAutoDelete( true );
+}
+
+void DeclaratorAST::setSubDeclarator( DeclaratorAST::Node& subDeclarator )
+{
+ m_subDeclarator = subDeclarator;
+ if( m_subDeclarator.get() ) m_subDeclarator->setParent( this );
+}
+
+void DeclaratorAST::setDeclaratorId( NameAST::Node& declaratorId )
+{
+ m_declaratorId = declaratorId;
+ if( m_declaratorId.get() ) m_declaratorId->setParent( this );
+}
+
+void DeclaratorAST::setBitfieldInitialization( AST::Node& bitfieldInitialization )
+{
+ m_bitfieldInitialization = bitfieldInitialization;
+ if( m_bitfieldInitialization.get() ) m_bitfieldInitialization->setParent( this );
+}
+
+void DeclaratorAST::addArrayDimension( AST::Node& arrayDimension )
+{
+ if( !arrayDimension.get() )
+ return;
+
+ arrayDimension->setParent( this );
+ m_arrayDimensionList.append( arrayDimension.release() );
+}
+
+void DeclaratorAST::setParameterDeclarationClause( AUTO_PTR<class ParameterDeclarationClauseAST>& parameterDeclarationClause )
+{
+ m_parameterDeclarationClause = parameterDeclarationClause;
+ if( m_parameterDeclarationClause.get() ) m_parameterDeclarationClause->setParent( this );
+}
+
+void DeclaratorAST::setConstant( AST::Node& constant )
+{
+ m_constant = constant;
+ if( m_constant.get() ) m_constant->setParent( this );
+}
+
+void DeclaratorAST::setExceptionSpecification( GroupAST::Node& exceptionSpecification )
+{
+ m_exceptionSpecification = exceptionSpecification;
+ if( m_exceptionSpecification.get() ) m_exceptionSpecification->setParent( this );
+}
+
+void DeclaratorAST::addPtrOp( AST::Node& ptrOp )
+{
+ if( !ptrOp.get() )
+ return;
+
+ ptrOp->setParent( this );
+ m_ptrOpList.append( ptrOp.release() );
+}
+
+// --------------------------------------------------------------------------
+InitDeclaratorAST::InitDeclaratorAST()
+{
+}
+
+void InitDeclaratorAST::setDeclarator( DeclaratorAST::Node& declarator )
+{
+ m_declarator = declarator;
+ if( m_declarator.get() ) m_declarator->setParent( this );
+}
+
+void InitDeclaratorAST::setInitializer( AST::Node& initializer )
+{
+ m_initializer = initializer;
+ if( m_initializer.get() ) m_initializer->setParent( this );
+}
+
+// --------------------------------------------------------------------------
+FunctionDefinitionAST::FunctionDefinitionAST()
+{
+}
+
+void FunctionDefinitionAST::setFunctionSpecifier( GroupAST::Node& functionSpecifier )
+{
+ m_functionSpecifier = functionSpecifier;
+ if( m_functionSpecifier.get() ) m_functionSpecifier->setParent( this );
+}
+
+void FunctionDefinitionAST::setStorageSpecifier( GroupAST::Node& storageSpecifier )
+{
+ m_storageSpecifier = storageSpecifier;
+ if( m_storageSpecifier.get() ) m_storageSpecifier->setParent( this );
+}
+
+void FunctionDefinitionAST::setTypeSpec( TypeSpecifierAST::Node& typeSpec )
+{
+ m_typeSpec = typeSpec;
+ if( m_typeSpec.get() ) m_typeSpec->setParent( this );
+}
+
+void FunctionDefinitionAST::setInitDeclarator( InitDeclaratorAST::Node& initDeclarator )
+{
+ m_initDeclarator = initDeclarator;
+ if( m_initDeclarator.get() ) m_initDeclarator->setParent( this );
+}
+
+void FunctionDefinitionAST::setFunctionBody( StatementListAST::Node& functionBody )
+{
+ m_functionBody = functionBody;
+ if( m_functionBody.get() ) m_functionBody->setParent( this );
+}
+
+void FunctionDefinitionAST::setWinDeclSpec( GroupAST::Node& winDeclSpec )
+{
+ m_winDeclSpec = winDeclSpec;
+ if( m_winDeclSpec.get() ) m_winDeclSpec->setParent( this );
+}
+
+// --------------------------------------------------------------------------
+StatementListAST::StatementListAST()
+{
+ m_statementList.setAutoDelete( true );
+}
+
+void StatementListAST::addStatement( StatementAST::Node& statement )
+{
+ if( !statement.get() )
+ return;
+
+ statement->setParent( this );
+ m_statementList.append( statement.release() );
+}
+
+// --------------------------------------------------------------------------
+IfStatementAST::IfStatementAST()
+{
+}
+
+void IfStatementAST::setCondition( ConditionAST::Node& condition )
+{
+ m_condition = condition;
+ if( m_condition.get() ) m_condition->setParent( this );
+}
+
+void IfStatementAST::setStatement( StatementAST::Node& statement )
+{
+ m_statement = statement;
+ if( m_statement.get() ) m_statement->setParent( this );
+}
+
+void IfStatementAST::setElseStatement( StatementAST::Node& elseStatement )
+{
+ m_elseStatement = elseStatement;
+ if( m_elseStatement.get() ) m_elseStatement->setParent( this );
+}
+
+// --------------------------------------------------------------------------
+WhileStatementAST::WhileStatementAST()
+{
+}
+
+void WhileStatementAST::setCondition( ConditionAST::Node& condition )
+{
+ m_condition = condition;
+ if( m_condition.get() ) m_condition->setParent( this );
+}
+
+void WhileStatementAST::setStatement( StatementAST::Node& statement )
+{
+ m_statement = statement;
+ if( m_statement.get() ) m_statement->setParent( this );
+}
+
+// --------------------------------------------------------------------------
+DoStatementAST::DoStatementAST()
+{
+}
+
+void DoStatementAST::setCondition( ConditionAST::Node& condition )
+{
+ m_condition = condition;
+ if( m_condition.get() ) m_condition->setParent( this );
+}
+
+void DoStatementAST::setStatement( StatementAST::Node& statement )
+{
+ m_statement = statement;
+ if( m_statement.get() ) m_statement->setParent( this );
+}
+
+// --------------------------------------------------------------------------
+ForStatementAST::ForStatementAST()
+{
+}
+
+void ForStatementAST::setCondition( ConditionAST::Node& condition )
+{
+ m_condition = condition;
+ if( m_condition.get() ) m_condition->setParent( this );
+}
+
+void ForStatementAST::setExpression( AST::Node& expression )
+{
+ m_expression = expression;
+ if( m_expression.get() ) m_expression->setParent( this );
+}
+
+void ForStatementAST::setStatement( StatementAST::Node& statement )
+{
+ m_statement = statement;
+ if( m_statement.get() ) m_statement->setParent( this );
+}
+
+void ForStatementAST::setInitStatement( StatementAST::Node& initStatement )
+{
+ m_initStatement = initStatement;
+ if( m_initStatement.get() ) m_initStatement->setParent( this );
+}
+
+// --------------------------------------------------------------------------
+SwitchStatementAST::SwitchStatementAST()
+{
+}
+
+void SwitchStatementAST::setCondition( ConditionAST::Node& condition )
+{
+ m_condition = condition;
+ if( m_condition.get() ) m_condition->setParent( this );
+}
+
+void SwitchStatementAST::setStatement( StatementAST::Node& statement )
+{
+ m_statement = statement;
+ if( m_statement.get() ) m_statement->setParent( this );
+}
+
+// --------------------------------------------------------------------------
+DeclarationStatementAST::DeclarationStatementAST()
+{
+}
+
+void DeclarationStatementAST::setDeclaration( DeclarationAST::Node& declaration )
+{
+ m_declaration = declaration;
+ if( m_declaration.get() ) m_declaration->setParent( this );
+}
+
+// --------------------------------------------------------------------------
+ExpressionStatementAST::ExpressionStatementAST()
+{
+}
+
+void ExpressionStatementAST::setExpression( AST::Node& expression )
+{
+ m_expression = expression;
+ if( m_expression.get() ) m_expression->setParent( this );
+}
+
+
+// --------------------------------------------------------------------------
+ParameterDeclarationAST::ParameterDeclarationAST()
+{
+}
+
+void ParameterDeclarationAST::setTypeSpec( TypeSpecifierAST::Node& typeSpec )
+{
+ m_typeSpec = typeSpec;
+ if( m_typeSpec.get() ) m_typeSpec->setParent( this );
+}
+
+void ParameterDeclarationAST::setDeclarator( DeclaratorAST::Node& declarator )
+{
+ m_declarator = declarator;
+ if( m_declarator.get() ) m_declarator->setParent( this );
+}
+
+void ParameterDeclarationAST::setExpression( AST::Node& expression )
+{
+ m_expression = expression;
+ if( m_expression.get() ) m_expression->setParent( this );
+}
+
+QString ParameterDeclarationAST::text() const
+{
+ QString str;
+ if( m_typeSpec.get() )
+ str += m_typeSpec->text() + ' ';
+
+ if( m_declarator.get() )
+ str += m_declarator->text();
+
+ if( m_expression.get() )
+ str += QString( " = " ) + m_expression->text();
+
+ return str;
+}
+
+// --------------------------------------------------------------------------
+ParameterDeclarationListAST::ParameterDeclarationListAST()
+{
+ m_parameterList.setAutoDelete( true );
+}
+
+void ParameterDeclarationListAST::addParameter( ParameterDeclarationAST::Node& parameter )
+{
+ if( !parameter.get() )
+ return;
+
+ parameter->setParent( this );
+ m_parameterList.append( parameter.release() );
+}
+
+QString ParameterDeclarationListAST::text() const
+{
+ QStringList l;
+
+ QPtrListIterator<ParameterDeclarationAST> it( m_parameterList );
+ while( it.current() ){
+ l.append( it.current()->text() );
+ ++it;
+ }
+
+ return l.join( ", " );
+}
+
+
+// --------------------------------------------------------------------------
+ParameterDeclarationClauseAST::ParameterDeclarationClauseAST()
+{
+}
+
+void ParameterDeclarationClauseAST::setParameterDeclarationList( ParameterDeclarationListAST::Node& parameterDeclarationList )
+{
+ m_parameterDeclarationList = parameterDeclarationList;
+ if( m_parameterDeclarationList.get() ) m_parameterDeclarationList->setParent( this );
+}
+
+void ParameterDeclarationClauseAST::setEllipsis( AST::Node& ellipsis )
+{
+ m_ellipsis = ellipsis;
+ if( m_ellipsis.get() ) m_ellipsis->setParent( this );
+}
+
+QString ParameterDeclarationClauseAST::text() const
+{
+ QString str;
+
+ if( m_parameterDeclarationList.get() )
+ str += m_parameterDeclarationList->text();
+
+ if( m_ellipsis.get() )
+ str += " ...";
+
+ return str;
+}
+
+
+// --------------------------------------------------------------------------
+GroupAST::GroupAST()
+{
+ m_nodeList.setAutoDelete( true );
+}
+
+void GroupAST::addNode( AST::Node& node )
+{
+ if( !node.get() )
+ return;
+
+ node->setParent( this );
+ m_nodeList.append( node.release() );
+}
+
+QString GroupAST::text() const
+{
+ QStringList l;
+
+ QPtrListIterator<AST> it( m_nodeList );
+ while( it.current() ){
+ l.append( it.current()->text() );
+ ++it;
+ }
+
+ return l.join( " " );
+}
+
+// --------------------------------------------------------------------------
+AccessDeclarationAST::AccessDeclarationAST()
+{
+ m_accessList.setAutoDelete( true );
+}
+
+void AccessDeclarationAST::addAccess( AST::Node& access )
+{
+ if( !access.get() )
+ return;
+
+ access->setParent( this );
+ m_accessList.append( access.release() );
+}
+
+QString AccessDeclarationAST::text() const
+{
+ QStringList l;
+
+ QPtrListIterator<AST> it( m_accessList );
+ while( it.current() ){
+ l.append( it.current()->text() );
+ ++it;
+ }
+
+ return l.join( " " );
+}
+
+// --------------------------------------------------------------------------
+TypeParameterAST::TypeParameterAST()
+{
+}
+
+void TypeParameterAST::setKind( AST::Node& kind )
+{
+ m_kind = kind;
+ if( m_kind.get() ) m_kind->setParent( this );
+}
+
+void TypeParameterAST::setTemplateParameterList( AUTO_PTR<class TemplateParameterListAST>& templateParameterList )
+{
+ m_templateParameterList = templateParameterList;
+ if( m_templateParameterList.get() ) m_templateParameterList->setParent( this );
+}
+
+void TypeParameterAST::setName( NameAST::Node& name )
+{
+ m_name = name;
+ if( m_name.get() ) m_name->setParent( this );
+}
+
+void TypeParameterAST::setTypeId( AST::Node& typeId )
+{
+ m_typeId = typeId;
+ if( m_typeId.get() ) m_typeId->setParent( this );
+}
+
+// --------------------------------------------------------------------------
+TemplateParameterAST::TemplateParameterAST()
+{
+}
+
+void TemplateParameterAST::setTypeParameter( TypeParameterAST::Node& typeParameter )
+{
+ m_typeParameter = typeParameter;
+ if( m_typeParameter.get() ) m_typeParameter->setParent( this );
+}
+
+void TemplateParameterAST::setTypeValueParameter( ParameterDeclarationAST::Node& typeValueParameter )
+{
+ m_typeValueParameter = typeValueParameter;
+ if( m_typeValueParameter.get() ) m_typeValueParameter->setParent( this );
+}
+
+// --------------------------------------------------------------------------
+TemplateParameterListAST::TemplateParameterListAST()
+{
+ m_templateParameterList.setAutoDelete( true );
+}
+
+void TemplateParameterListAST::addTemplateParameter( TemplateParameterAST::Node& templateParameter )
+{
+ if( !templateParameter.get() )
+ return;
+
+ templateParameter->setParent( this );
+ m_templateParameterList.append( templateParameter.release() );
+}
+
+// --------------------------------------------------------------------------
+ConditionAST::ConditionAST()
+{
+}
+
+void ConditionAST::setTypeSpec( TypeSpecifierAST::Node& typeSpec )
+{
+ m_typeSpec = typeSpec;
+ if( m_typeSpec.get() ) m_typeSpec->setParent( this );
+}
+
+void ConditionAST::setDeclarator( DeclaratorAST::Node& declarator )
+{
+ m_declarator = declarator;
+ if( m_declarator.get() ) m_declarator->setParent( this );
+}
+
+void ConditionAST::setExpression( AST::Node& expression )
+{
+ m_expression = expression;
+ if( m_expression.get() ) m_expression->setParent( this );
+}
+
+void ClassSpecifierAST::setWinDeclSpec( GroupAST::Node & winDeclSpec )
+{
+ m_winDeclSpec = winDeclSpec;
+ if( m_winDeclSpec.get() ) m_winDeclSpec->setParent( this );
+}
+
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/ast.h b/umbrello/umbrello/codeimport/kdevcppparser/ast.h
new file mode 100644
index 00000000..9b7b5aac
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/ast.h
@@ -0,0 +1,1449 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __ast_h
+#define __ast_h
+
+#include <memory>
+#include <qstring.h>
+#include <qptrlist.h>
+
+#if defined( Q_OS_WIN32 ) || defined( Q_CC_SUN )
+
+#ifndef _THROW0
+# define _THROW0()
+#endif
+
+template <class _Tp> class AUTO_PTR {
+private:
+ _Tp* _M_ptr;
+
+public:
+ typedef _Tp element_type;
+
+ explicit AUTO_PTR(_Tp* __p = 0) _THROW0() : _M_ptr(__p) {}
+
+ template <class _Tp1> AUTO_PTR(AUTO_PTR<_Tp1>& __a) _THROW0()
+ : _M_ptr(__a.release()) {}
+
+ AUTO_PTR(AUTO_PTR& __a) _THROW0() : _M_ptr(__a.release()) {}
+
+
+
+ template <class _Tp1>
+ AUTO_PTR& operator=(AUTO_PTR<_Tp1>& __a) _THROW0() {
+ if (__a.get() != this->get()) {
+ delete _M_ptr;
+ _M_ptr = __a.release();
+ }
+ return *this;
+ }
+
+ AUTO_PTR& operator=(AUTO_PTR& __a) _THROW0() {
+ if (&__a != this) {
+ delete _M_ptr;
+ _M_ptr = __a.release();
+ }
+ return *this;
+ }
+
+ ~AUTO_PTR() _THROW0() { delete _M_ptr; }
+
+ _Tp& operator*() const _THROW0() {
+ return *_M_ptr;
+ }
+ _Tp* operator->() const _THROW0() {
+ return _M_ptr;
+ }
+ _Tp* get() const _THROW0() {
+ return _M_ptr;
+ }
+ _Tp* release() _THROW0() {
+ _Tp* __tmp = _M_ptr;
+ _M_ptr = 0;
+ return __tmp;
+ }
+ void reset(_Tp* __p = 0) _THROW0() {
+ delete _M_ptr;
+ _M_ptr = __p;
+ }
+
+ // According to the C++ standard, these conversions are required. Most
+ // present-day compilers, however, do not enforce that requirement---and,
+ // in fact, most present-day compilers do not support the language
+ // features that these conversions rely on.
+
+
+private:
+ template<class _Tp1> struct AUTO_PTR_ref {
+ _Tp1* _M_ptr;
+ AUTO_PTR_ref(_Tp1* __p) : _M_ptr(__p) {}
+ };
+
+public:
+ AUTO_PTR(AUTO_PTR_ref<_Tp> __ref) _THROW0()
+ : _M_ptr(__ref._M_ptr) {}
+ template <class _Tp1> operator AUTO_PTR_ref<_Tp1>() _THROW0()
+ { return AUTO_PTR_ref<_Tp>(this->release()); }
+ template <class _Tp1> operator AUTO_PTR<_Tp1>() _THROW0()
+ { return AUTO_PTR<_Tp1>(this->release()) }
+
+};
+
+#else
+#define AUTO_PTR std::auto_ptr
+#endif
+
+template <class T> typename T::Node CreateNode()
+{
+ typename T::Node node( new T );
+ node->setNodeType( T::Type );
+ return node;
+}
+
+template <class T> typename T::Node NullNode()
+{
+ typename T::Node node;
+ return node;
+}
+
+enum NodeType
+{
+ NodeType_Generic = 0,
+
+ NodeType_TemplateArgumentList = 1000,
+ NodeType_ClassOrNamespaceName,
+ NodeType_Name,
+ NodeType_Declaration,
+ NodeType_TypeSpecifier,
+ NodeType_BaseSpecifier,
+ NodeType_BaseClause,
+ NodeType_ClassSpecifier,
+ NodeType_Enumerator,
+ NodeType_EnumSpecifier,
+ NodeType_ElaboratedTypeSpecifier,
+ NodeType_LinkageBody,
+ NodeType_LinkageSpecification,
+ NodeType_Namespace,
+ NodeType_NamespaceAlias,
+ NodeType_Using,
+ NodeType_UsingDirective,
+ NodeType_InitDeclaratorList,
+ NodeType_Typedef,
+ NodeType_Declarator,
+ NodeType_InitDeclarator,
+ NodeType_TemplateDeclaration,
+ NodeType_SimpleDeclaration,
+ NodeType_Statement,
+ NodeType_StatementList,
+ NodeType_IfStatement,
+ NodeType_WhileStatement,
+ NodeType_DoStatement,
+ NodeType_ForStatement,
+ NodeType_SwitchStatement,
+ NodeType_DeclarationStatement,
+ NodeType_TranslationUnit,
+ NodeType_FunctionDefinition,
+ NodeType_ExpressionStatement,
+ NodeType_ParameterDeclaration,
+ NodeType_ParameterDeclarationList,
+ NodeType_ParameterDeclarationClause,
+ NodeType_Group,
+ NodeType_AccessDeclaration,
+ NodeType_TypeParameter,
+ NodeType_TemplateParameter,
+ NodeType_TemplateParameterList,
+ NodeType_Condition,
+
+ NodeType_Custom = 2000
+};
+
+QString nodeTypeToString( int type );
+
+
+#if defined(CPPPARSER_QUICK_ALLOCATOR)
+
+#include <quick_allocator.h>
+
+#define DECLARE_ALLOC(tp) \
+ void * operator new(std::size_t) \
+ { \
+ return quick_allocator< tp >::alloc(); \
+ } \
+ \
+ void operator delete(void * p) \
+ { \
+ quick_allocator< tp >::dealloc(p); \
+ }
+#else
+
+#define DECLARE_ALLOC(tp)
+
+#endif
+
+struct Slice
+{
+ QString source;
+ int position;
+ int length;
+
+ inline Slice()
+ : position(0), length(0) {}
+};
+
+class AST
+{
+public:
+ typedef AUTO_PTR<AST> Node;
+ enum { Type=NodeType_Generic };
+
+ DECLARE_ALLOC( AST )
+
+public:
+ AST();
+ virtual ~AST();
+
+ int nodeType() const { return m_nodeType; }
+ void setNodeType( int nodeType ) { m_nodeType = nodeType; }
+
+ AST* parent() { return m_parent; }
+ void setParent( AST* parent );
+
+ void setStartPosition( int line, int col );
+ void getStartPosition( int* line, int* col ) const;
+
+ void setEndPosition( int line, int col );
+ void getEndPosition( int* line, int* col ) const;
+
+#ifndef CPPPARSER_NO_CHILDREN
+ QPtrList<AST> children() { return m_children; }
+ void appendChild( AST* child );
+ void removeChild( AST* child );
+#endif
+
+ virtual inline QString text() const
+ { return m_slice.source.mid(m_slice.position, m_slice.length); }
+
+ QString comment() const
+ { return m_comment; }
+
+ inline void setSlice( const Slice& slice )
+ { m_slice = slice; }
+
+ inline void setSlice( const QString &text, int position, int length )
+ {
+ m_slice.source = text;
+ m_slice.position = position;
+ m_slice.length = length;
+ }
+
+ inline void setText(const QString &text)
+ { setSlice(text, 0, text.length()); }
+
+ void setComment( const QString &comment )
+ { m_comment = comment; }
+
+private:
+ int m_nodeType;
+ AST* m_parent;
+ int m_startLine, m_startColumn;
+ int m_endLine, m_endColumn;
+ Slice m_slice;
+#ifndef CPPPARSER_NO_CHILDREN
+ QPtrList<AST> m_children;
+#endif
+ QString m_comment;
+
+private:
+ AST( const AST& source );
+ void operator = ( const AST& source );
+};
+
+class GroupAST: public AST
+{
+public:
+ typedef AUTO_PTR<GroupAST> Node;
+ enum { Type = NodeType_Group };
+
+ DECLARE_ALLOC( GroupAST )
+
+public:
+ GroupAST();
+
+ QPtrList<AST> nodeList() { return m_nodeList; }
+ void addNode( AST::Node& node );
+
+ virtual QString text() const;
+
+private:
+ QPtrList<AST> m_nodeList;
+
+private:
+ GroupAST( const GroupAST& source );
+ void operator = ( const GroupAST& source );
+};
+
+
+class TemplateArgumentListAST: public AST
+{
+public:
+ typedef AUTO_PTR<TemplateArgumentListAST> Node;
+ enum { Type = NodeType_TemplateArgumentList };
+
+ DECLARE_ALLOC( TemplateArgumentListAST )
+
+public:
+ TemplateArgumentListAST();
+
+ void addArgument( AST::Node& arg );
+ QPtrList<AST> argumentList() { return m_argumentList; }
+
+ virtual QString text() const;
+
+private:
+ QPtrList<AST> m_argumentList;
+
+private:
+ TemplateArgumentListAST( const TemplateArgumentListAST& source );
+ void operator = ( const TemplateArgumentListAST& source );
+};
+
+class ClassOrNamespaceNameAST: public AST
+{
+public:
+ typedef AUTO_PTR<ClassOrNamespaceNameAST> Node;
+ enum { Type = NodeType_ClassOrNamespaceName };
+
+ DECLARE_ALLOC( ClassOrNamespaceNameAST )
+
+public:
+ ClassOrNamespaceNameAST();
+
+ AST* name() { return m_name.get(); }
+ void setName( AST::Node& name );
+
+ TemplateArgumentListAST* templateArgumentList() { return m_templateArgumentList.get(); }
+ void setTemplateArgumentList( TemplateArgumentListAST::Node& templateArgumentList );
+
+ virtual QString text() const;
+
+private:
+ AST::Node m_name;
+ TemplateArgumentListAST::Node m_templateArgumentList;
+
+private:
+ ClassOrNamespaceNameAST( const ClassOrNamespaceNameAST& source );
+ void operator = ( const ClassOrNamespaceNameAST& source );
+};
+
+class NameAST: public AST
+{
+public:
+ typedef AUTO_PTR<NameAST> Node;
+ enum { Type = NodeType_Name };
+
+ DECLARE_ALLOC( NameAST )
+
+public:
+ NameAST();
+
+ bool isGlobal() const { return m_global; }
+ void setGlobal( bool b );
+
+ void addClassOrNamespaceName( ClassOrNamespaceNameAST::Node& classOrNamespaceName );
+ QPtrList<ClassOrNamespaceNameAST> classOrNamespaceNameList() { return m_classOrNamespaceNameList; }
+
+ ClassOrNamespaceNameAST* unqualifiedName() { return m_unqualifiedName.get(); }
+ void setUnqualifiedName( ClassOrNamespaceNameAST::Node& unqualifiedName );
+
+ virtual QString text() const;
+
+private:
+ bool m_global;
+ ClassOrNamespaceNameAST::Node m_unqualifiedName;
+ QPtrList<ClassOrNamespaceNameAST> m_classOrNamespaceNameList;
+
+private:
+ NameAST( const NameAST& source );
+ void operator = ( const NameAST& source );
+};
+
+class TypeParameterAST: public AST
+{
+public:
+ typedef AUTO_PTR<TypeParameterAST> Node;
+ enum { Type = NodeType_TypeParameter };
+
+ DECLARE_ALLOC( TypeParameterAST )
+
+public:
+ TypeParameterAST();
+
+ AST* kind() { return m_kind.get(); }
+ void setKind( AST::Node& kind );
+
+ class TemplateParameterListAST* templateParameterList() { return m_templateParameterList.get(); }
+ void setTemplateParameterList( AUTO_PTR<class TemplateParameterListAST>& templateParameterList );
+
+ NameAST* name() { return m_name.get(); }
+ void setName( NameAST::Node& name );
+
+ AST* typeId() { return m_typeId.get(); }
+ void setTypeId( AST::Node& typeId );
+
+private:
+ AST::Node m_kind;
+ AUTO_PTR<class TemplateParameterListAST> m_templateParameterList;
+ NameAST::Node m_name;
+ AST::Node m_typeId;
+
+private:
+ TypeParameterAST( const TypeParameterAST& source );
+ void operator = ( const TypeParameterAST& source );
+};
+
+class DeclarationAST: public AST
+{
+public:
+ typedef AUTO_PTR<DeclarationAST> Node;
+ enum { Type = NodeType_Declaration };
+
+ DECLARE_ALLOC( DeclarationAST )
+
+public:
+ DeclarationAST();
+
+private:
+ DeclarationAST( const DeclarationAST& source );
+ void operator = ( const DeclarationAST& source );
+};
+
+class AccessDeclarationAST: public DeclarationAST
+{
+public:
+ typedef AUTO_PTR<AccessDeclarationAST> Node;
+ enum { Type = NodeType_AccessDeclaration };
+
+ DECLARE_ALLOC( AccessDeclarationAST )
+
+public:
+ AccessDeclarationAST();
+
+ QPtrList<AST> accessList() { return m_accessList; }
+ void addAccess( AST::Node& access );
+
+ virtual QString text() const;
+
+private:
+ QPtrList<AST> m_accessList;
+
+private:
+ AccessDeclarationAST( const AccessDeclarationAST& source );
+ void operator = ( const AccessDeclarationAST& source );
+};
+
+class TypeSpecifierAST: public AST
+{
+public:
+ typedef AUTO_PTR<TypeSpecifierAST> Node;
+ enum { Type = NodeType_TypeSpecifier };
+
+ DECLARE_ALLOC( TypeSpecifierAST )
+
+public:
+ TypeSpecifierAST();
+
+ virtual NameAST* name() { return m_name.get(); }
+ virtual void setName( NameAST::Node& name );
+
+ GroupAST* cvQualify() { return m_cvQualify.get(); }
+ void setCvQualify( GroupAST::Node& cvQualify );
+
+ GroupAST* cv2Qualify() { return m_cv2Qualify.get(); }
+ void setCv2Qualify( GroupAST::Node& cv2Qualify );
+
+ virtual QString text() const;
+
+private:
+ NameAST::Node m_name;
+ GroupAST::Node m_cvQualify;
+ GroupAST::Node m_cv2Qualify;
+
+private:
+ TypeSpecifierAST( const TypeSpecifierAST& source );
+ void operator = ( const TypeSpecifierAST& source );
+};
+
+class BaseSpecifierAST: public AST
+{
+public:
+ typedef AUTO_PTR<BaseSpecifierAST> Node;
+ enum { Type = NodeType_BaseSpecifier };
+
+ DECLARE_ALLOC( BaseSpecifierAST )
+
+public:
+ BaseSpecifierAST();
+
+ AST* isVirtual() { return m_isVirtual.get(); }
+ void setIsVirtual( AST::Node& isVirtual );
+
+ AST* access() { return m_access.get(); }
+ void setAccess( AST::Node& access );
+
+ NameAST* name() { return m_name.get(); }
+ void setName( NameAST::Node& name );
+
+private:
+ AST::Node m_isVirtual;
+ AST::Node m_access;
+ NameAST::Node m_name;
+
+private:
+ BaseSpecifierAST( const BaseSpecifierAST& source );
+ void operator = ( const BaseSpecifierAST& source );
+};
+
+class BaseClauseAST: public AST
+{
+public:
+ typedef AUTO_PTR<BaseClauseAST> Node;
+ enum { Type = NodeType_BaseClause };
+
+ DECLARE_ALLOC( BaseClauseAST )
+
+public:
+ BaseClauseAST();
+
+ void addBaseSpecifier( BaseSpecifierAST::Node& baseSpecifier );
+ QPtrList<BaseSpecifierAST> baseSpecifierList() { return m_baseSpecifierList; }
+
+private:
+ QPtrList<BaseSpecifierAST> m_baseSpecifierList;
+
+private:
+ BaseClauseAST( const BaseClauseAST& source );
+ void operator = ( const BaseClauseAST& source );
+};
+
+class ClassSpecifierAST: public TypeSpecifierAST
+{
+public:
+ typedef AUTO_PTR<ClassSpecifierAST> Node;
+ enum { Type = NodeType_ClassSpecifier };
+
+ DECLARE_ALLOC( ClassSpecifierAST )
+
+public:
+ ClassSpecifierAST();
+
+ GroupAST* winDeclSpec() { return m_winDeclSpec.get(); }
+ void setWinDeclSpec( GroupAST::Node& winDeclSpec );
+
+ AST* classKey() { return m_classKey.get(); }
+ void setClassKey( AST::Node& classKey );
+
+ BaseClauseAST* baseClause() { return m_baseClause.get(); }
+ void setBaseClause( BaseClauseAST::Node& baseClause );
+
+ QPtrList<DeclarationAST> declarationList() { return m_declarationList; }
+ void addDeclaration( DeclarationAST::Node& declaration );
+
+private:
+ GroupAST::Node m_winDeclSpec;
+ AST::Node m_classKey;
+ BaseClauseAST::Node m_baseClause;
+ QPtrList<DeclarationAST> m_declarationList;
+
+private:
+ ClassSpecifierAST( const ClassSpecifierAST& source );
+ void operator = ( const ClassSpecifierAST& source );
+};
+
+class EnumeratorAST: public AST
+{
+public:
+ typedef AUTO_PTR<EnumeratorAST> Node;
+ enum { Type = NodeType_Enumerator };
+
+ DECLARE_ALLOC( EnumeratorAST )
+
+public:
+ EnumeratorAST();
+
+ AST* id() { return m_id.get(); }
+ void setId( AST::Node& id );
+
+ AST* expr() { return m_expr.get(); }
+ void setExpr( AST::Node& expr );
+
+private:
+ AST::Node m_id;
+ AST::Node m_expr;
+
+private:
+ EnumeratorAST( const EnumeratorAST& source );
+ void operator = ( const EnumeratorAST& source );
+};
+
+class EnumSpecifierAST: public TypeSpecifierAST
+{
+public:
+ typedef AUTO_PTR<EnumSpecifierAST> Node;
+ enum { Type = NodeType_EnumSpecifier };
+
+ DECLARE_ALLOC( EnumSpecifierAST )
+
+public:
+ EnumSpecifierAST();
+
+ void addEnumerator( EnumeratorAST::Node& enumerator );
+ QPtrList<EnumeratorAST> enumeratorList() { return m_enumeratorList; }
+
+private:
+ QPtrList<EnumeratorAST> m_enumeratorList;
+
+private:
+ EnumSpecifierAST( const EnumSpecifierAST& source );
+ void operator = ( const EnumSpecifierAST& source );
+};
+
+class ElaboratedTypeSpecifierAST: public TypeSpecifierAST
+{
+public:
+ typedef AUTO_PTR<ElaboratedTypeSpecifierAST> Node;
+ enum { Type = NodeType_ElaboratedTypeSpecifier };
+
+ DECLARE_ALLOC( ElaboratedTypeSpecifierAST )
+
+public:
+ ElaboratedTypeSpecifierAST();
+
+ AST* kind() { return m_kind.get(); }
+ void setKind( AST::Node& kind );
+
+ virtual QString text() const;
+
+private:
+ AST::Node m_kind;
+
+private:
+ ElaboratedTypeSpecifierAST( const ElaboratedTypeSpecifierAST& source );
+ void operator = ( const ElaboratedTypeSpecifierAST& source );
+};
+
+
+class LinkageBodyAST: public AST
+{
+public:
+ typedef AUTO_PTR<LinkageBodyAST> Node;
+ enum { Type = NodeType_LinkageBody };
+
+ DECLARE_ALLOC( LinkageBodyAST )
+
+public:
+ LinkageBodyAST();
+
+ void addDeclaration( DeclarationAST::Node& ast );
+ QPtrList<DeclarationAST> declarationList() { return m_declarationList; }
+
+private:
+ QPtrList<DeclarationAST> m_declarationList;
+
+private:
+ LinkageBodyAST( const LinkageBodyAST& source );
+ void operator = ( const LinkageBodyAST& source );
+};
+
+class LinkageSpecificationAST: public DeclarationAST
+{
+public:
+ typedef AUTO_PTR<LinkageSpecificationAST> Node;
+ enum { Type = NodeType_LinkageSpecification };
+
+ DECLARE_ALLOC( LinkageSpecificationAST )
+
+public:
+ LinkageSpecificationAST();
+
+ AST* externType() { return m_externType.get(); }
+ void setExternType( AST::Node& externType );
+
+ LinkageBodyAST* linkageBody() { return m_linkageBody.get(); }
+ void setLinkageBody( LinkageBodyAST::Node& linkageBody );
+
+ DeclarationAST* declaration() { return m_declaration.get(); }
+ void setDeclaration( DeclarationAST::Node& decl );
+
+private:
+ AST::Node m_externType;
+ LinkageBodyAST::Node m_linkageBody;
+ DeclarationAST::Node m_declaration;
+
+private:
+ LinkageSpecificationAST( const LinkageSpecificationAST& source );
+ void operator = ( const LinkageSpecificationAST& source );
+};
+
+class NamespaceAST: public DeclarationAST
+{
+public:
+ typedef AUTO_PTR<NamespaceAST> Node;
+ enum { Type = NodeType_Namespace };
+
+ DECLARE_ALLOC( NamespaceAST )
+
+public:
+ NamespaceAST();
+
+ AST* namespaceName() { return m_namespaceName.get(); }
+ void setNamespaceName( AST::Node& namespaceName );
+
+ LinkageBodyAST* linkageBody() { return m_linkageBody.get(); }
+ void setLinkageBody( LinkageBodyAST::Node& linkageBody );
+
+private:
+ AST::Node m_namespaceName;
+ LinkageBodyAST::Node m_linkageBody;
+
+private:
+ NamespaceAST( const NamespaceAST& source );
+ void operator = ( const NamespaceAST& source );
+};
+
+class NamespaceAliasAST: public DeclarationAST
+{
+public:
+ typedef AUTO_PTR<NamespaceAliasAST> Node;
+ enum { Type = NodeType_NamespaceAlias };
+
+ DECLARE_ALLOC( NamespaceAliasAST )
+
+public:
+ NamespaceAliasAST();
+
+ AST* namespaceName() { return m_namespaceName.get(); }
+ void setNamespaceName( AST::Node& name );
+
+ NameAST* aliasName() { return m_aliasName.get(); }
+ void setAliasName( NameAST::Node& name );
+
+private:
+ AST::Node m_namespaceName;
+ NameAST::Node m_aliasName;
+
+private:
+ NamespaceAliasAST( const NamespaceAliasAST& source );
+ void operator = ( const NamespaceAliasAST& source );
+};
+
+class UsingAST: public DeclarationAST
+{
+public:
+ typedef AUTO_PTR<UsingAST> Node;
+ enum { Type = NodeType_Using };
+
+ DECLARE_ALLOC( UsingAST )
+
+public:
+ UsingAST();
+
+ AST* typeName() { return m_typeName.get(); }
+ void setTypeName( AST::Node& typeName );
+
+ NameAST* name() { return m_name.get(); }
+ void setName( NameAST::Node& name );
+
+private:
+ AST::Node m_typeName;
+ NameAST::Node m_name;
+
+private:
+ UsingAST( const UsingAST& source );
+ void operator = ( const UsingAST& source );
+};
+
+class UsingDirectiveAST: public DeclarationAST
+{
+public:
+ typedef AUTO_PTR<UsingDirectiveAST> Node;
+ enum { Type = NodeType_UsingDirective };
+
+ DECLARE_ALLOC( UsingDirectiveAST )
+
+public:
+ UsingDirectiveAST();
+
+ NameAST* name() { return m_name.get(); }
+ void setName( NameAST::Node& name );
+
+private:
+ NameAST::Node m_name;
+
+private:
+ UsingDirectiveAST( const UsingDirectiveAST& source );
+ void operator = ( const UsingDirectiveAST& source );
+};
+
+class DeclaratorAST: public AST
+{
+public:
+ typedef AUTO_PTR<DeclaratorAST> Node;
+ enum { Type = NodeType_Declarator };
+
+ DECLARE_ALLOC( DeclaratorAST )
+
+public:
+ DeclaratorAST();
+
+ QPtrList<AST> ptrOpList() { return m_ptrOpList; }
+ void addPtrOp( AST::Node& ptrOp );
+
+ DeclaratorAST* subDeclarator() { return m_subDeclarator.get(); }
+ void setSubDeclarator( Node& subDeclarator );
+
+ NameAST* declaratorId() { return m_declaratorId.get(); }
+ void setDeclaratorId( NameAST::Node& declaratorId );
+
+ AST* bitfieldInitialization() { return m_bitfieldInitialization.get(); }
+ void setBitfieldInitialization( AST::Node& bitfieldInitialization );
+
+ QPtrList<AST> arrayDimensionList() { return m_arrayDimensionList; }
+ void addArrayDimension( AST::Node& arrayDimension );
+
+ class ParameterDeclarationClauseAST* parameterDeclarationClause() { return m_parameterDeclarationClause.get(); }
+ void setParameterDeclarationClause( AUTO_PTR<class ParameterDeclarationClauseAST>& parameterDeclarationClause );
+
+ // ### replace 'constant' with cvQualify
+ AST* constant() { return m_constant.get(); }
+ void setConstant( AST::Node& constant );
+
+ GroupAST* exceptionSpecification() { return m_exceptionSpecification.get(); }
+ void setExceptionSpecification( GroupAST::Node& exceptionSpecification );
+
+private:
+ QPtrList<AST> m_ptrOpList;
+ Node m_subDeclarator;
+ NameAST::Node m_declaratorId;
+ AST::Node m_bitfieldInitialization;
+ QPtrList<AST> m_arrayDimensionList;
+ AUTO_PTR<class ParameterDeclarationClauseAST> m_parameterDeclarationClause;
+ AST::Node m_constant;
+ GroupAST::Node m_exceptionSpecification;
+
+private:
+ DeclaratorAST( const DeclaratorAST& source );
+ void operator = ( const DeclaratorAST& source );
+};
+
+class ParameterDeclarationAST: public AST
+{
+public:
+ typedef AUTO_PTR<ParameterDeclarationAST> Node;
+ enum { Type = NodeType_ParameterDeclaration };
+
+ DECLARE_ALLOC( ParameterDeclarationAST )
+
+public:
+ ParameterDeclarationAST();
+
+ TypeSpecifierAST* typeSpec() { return m_typeSpec.get(); }
+ void setTypeSpec( TypeSpecifierAST::Node& typeSpec );
+
+ DeclaratorAST* declarator() { return m_declarator.get(); }
+ void setDeclarator( DeclaratorAST::Node& declarator );
+
+ AST* expression() { return m_expression.get(); }
+ void setExpression( AST::Node& expression );
+
+ virtual QString text() const;
+
+private:
+ TypeSpecifierAST::Node m_typeSpec;
+ DeclaratorAST::Node m_declarator;
+ AST::Node m_expression;
+
+private:
+ ParameterDeclarationAST( const ParameterDeclarationAST& source );
+ void operator = ( const ParameterDeclarationAST& source );
+};
+
+class ParameterDeclarationListAST: public AST
+{
+public:
+ typedef AUTO_PTR<ParameterDeclarationListAST> Node;
+ enum { Type = NodeType_ParameterDeclarationList };
+
+ DECLARE_ALLOC( ParameterDeclarationListAST )
+
+public:
+ ParameterDeclarationListAST();
+
+ QPtrList<ParameterDeclarationAST> parameterList() { return m_parameterList; }
+ void addParameter( ParameterDeclarationAST::Node& parameter );
+
+ virtual QString text() const;
+
+private:
+ QPtrList<ParameterDeclarationAST> m_parameterList;
+
+private:
+ ParameterDeclarationListAST( const ParameterDeclarationListAST& source );
+ void operator = ( const ParameterDeclarationListAST& source );
+};
+
+class ParameterDeclarationClauseAST: public AST
+{
+public:
+ typedef AUTO_PTR<ParameterDeclarationClauseAST> Node;
+ enum { Type = NodeType_ParameterDeclarationClause };
+
+ DECLARE_ALLOC( ParameterDeclarationClauseAST )
+
+public:
+ ParameterDeclarationClauseAST();
+
+ ParameterDeclarationListAST* parameterDeclarationList() { return m_parameterDeclarationList.get(); }
+ void setParameterDeclarationList( ParameterDeclarationListAST::Node& parameterDeclarationList );
+
+ AST* ellipsis() { return m_ellipsis.get(); }
+ void setEllipsis( AST::Node& ellipsis );
+
+ virtual QString text() const;
+
+private:
+ ParameterDeclarationListAST::Node m_parameterDeclarationList;
+ AST::Node m_ellipsis;
+
+private:
+ ParameterDeclarationClauseAST( const ParameterDeclarationClauseAST& source );
+ void operator = ( const ParameterDeclarationClauseAST& source );
+};
+
+
+class InitDeclaratorAST: public AST
+{
+public:
+ typedef AUTO_PTR<InitDeclaratorAST> Node;
+ enum { Type = NodeType_InitDeclarator };
+
+ DECLARE_ALLOC( InitDeclaratorAST )
+
+public:
+ InitDeclaratorAST();
+
+ DeclaratorAST* declarator() { return m_declarator.get(); }
+ void setDeclarator( DeclaratorAST::Node& declarator );
+
+ AST* initializer() { return m_initializer.get(); }
+ void setInitializer( AST::Node& initializer );
+
+private:
+ DeclaratorAST::Node m_declarator;
+ AST::Node m_initializer;
+
+private:
+ InitDeclaratorAST( const InitDeclaratorAST& source );
+ void operator = ( const InitDeclaratorAST& source );
+};
+
+class InitDeclaratorListAST: public AST
+{
+public:
+ typedef AUTO_PTR<InitDeclaratorListAST> Node;
+ enum { Type = NodeType_InitDeclaratorList };
+
+ DECLARE_ALLOC( InitDeclaratorListAST )
+
+public:
+ InitDeclaratorListAST();
+
+ QPtrList<InitDeclaratorAST> initDeclaratorList() { return m_initDeclaratorList; }
+ void addInitDeclarator( InitDeclaratorAST::Node& decl );
+
+private:
+ QPtrList<InitDeclaratorAST> m_initDeclaratorList;
+
+private:
+ InitDeclaratorListAST( const InitDeclaratorListAST& source );
+ void operator = ( const InitDeclaratorListAST& source );
+};
+
+class TypedefAST: public DeclarationAST
+{
+public:
+ typedef AUTO_PTR<TypedefAST> Node;
+ enum { Type = NodeType_Typedef };
+
+ DECLARE_ALLOC( TypedefAST )
+
+public:
+ TypedefAST();
+
+ TypeSpecifierAST* typeSpec() { return m_typeSpec.get(); }
+ void setTypeSpec( TypeSpecifierAST::Node& typeSpec );
+
+ InitDeclaratorListAST* initDeclaratorList() { return m_initDeclaratorList.get(); }
+ void setInitDeclaratorList( InitDeclaratorListAST::Node& initDeclaratorList );
+
+private:
+ TypeSpecifierAST::Node m_typeSpec;
+ InitDeclaratorListAST::Node m_initDeclaratorList;
+
+private:
+ TypedefAST( const TypedefAST& source );
+ void operator = ( const TypedefAST& source );
+};
+
+class TemplateParameterAST: public AST
+{
+public:
+ typedef AUTO_PTR<TemplateParameterAST> Node;
+ enum { Type = NodeType_TemplateParameter };
+
+ DECLARE_ALLOC( TemplateParameterAST )
+
+public:
+ TemplateParameterAST();
+
+ TypeParameterAST* typeParameter() { return m_typeParameter.get(); }
+ void setTypeParameter( TypeParameterAST::Node& typeParameter );
+
+ ParameterDeclarationAST* typeValueParameter() { return m_typeValueParameter.get(); }
+ void setTypeValueParameter( ParameterDeclarationAST::Node& typeValueParameter );
+
+private:
+ TypeParameterAST::Node m_typeParameter;
+ ParameterDeclarationAST::Node m_typeValueParameter;
+
+private:
+ TemplateParameterAST( const TemplateParameterAST& source );
+ void operator = ( const TemplateParameterAST& source );
+};
+
+class TemplateParameterListAST: public AST
+{
+public:
+ typedef AUTO_PTR<TemplateParameterListAST> Node;
+ enum { Type = NodeType_TemplateParameterList };
+
+ DECLARE_ALLOC( TemplateParameterListAST )
+
+public:
+ TemplateParameterListAST();
+
+ QPtrList<TemplateParameterAST> templateParameterList() { return m_templateParameterList; }
+ void addTemplateParameter( TemplateParameterAST::Node& templateParameter );
+
+private:
+ QPtrList<TemplateParameterAST> m_templateParameterList;
+
+private:
+ TemplateParameterListAST( const TemplateParameterListAST& source );
+ void operator = ( const TemplateParameterListAST& source );
+};
+
+class TemplateDeclarationAST: public DeclarationAST
+{
+public:
+ typedef AUTO_PTR<TemplateDeclarationAST> Node;
+ enum { Type = NodeType_TemplateDeclaration };
+
+ DECLARE_ALLOC( TemplateDeclarationAST )
+
+public:
+ TemplateDeclarationAST();
+
+ AST* exported() { return m_exported.get(); }
+ void setExported( AST::Node& exported );
+
+ TemplateParameterListAST* templateParameterList() { return m_templateParameterList.get(); }
+ void setTemplateParameterList( TemplateParameterListAST::Node& templateParameterList );
+
+ DeclarationAST* declaration() { return m_declaration.get(); }
+ void setDeclaration( DeclarationAST::Node& declaration );
+
+private:
+ AST::Node m_exported;
+ TemplateParameterListAST::Node m_templateParameterList;
+ DeclarationAST::Node m_declaration;
+
+private:
+ TemplateDeclarationAST( const TemplateDeclarationAST& source );
+ void operator = ( const TemplateDeclarationAST& source );
+};
+
+class SimpleDeclarationAST: public DeclarationAST
+{
+public:
+ typedef AUTO_PTR<SimpleDeclarationAST> Node;
+ enum { Type = NodeType_SimpleDeclaration };
+
+ DECLARE_ALLOC( SimpleDeclarationAST )
+
+public:
+ SimpleDeclarationAST();
+
+ GroupAST* functionSpecifier() { return m_functionSpecifier.get(); }
+ void setFunctionSpecifier( GroupAST::Node& functionSpecifier );
+
+ GroupAST* storageSpecifier() { return m_storageSpecifier.get(); }
+ void setStorageSpecifier( GroupAST::Node& storageSpecifier );
+
+ TypeSpecifierAST* typeSpec() { return m_typeSpec.get(); }
+ void setTypeSpec( TypeSpecifierAST::Node& typeSpec );
+
+ InitDeclaratorListAST* initDeclaratorList() { return m_initDeclaratorList.get(); }
+ void setInitDeclaratorList( InitDeclaratorListAST::Node& initDeclaratorList );
+
+ GroupAST* winDeclSpec() { return m_winDeclSpec.get(); }
+ void setWinDeclSpec( GroupAST::Node& winDeclSpec );
+
+private:
+ GroupAST::Node m_functionSpecifier;
+ GroupAST::Node m_storageSpecifier;
+ TypeSpecifierAST::Node m_typeSpec;
+ InitDeclaratorListAST::Node m_initDeclaratorList;
+ GroupAST::Node m_winDeclSpec;
+
+private:
+ SimpleDeclarationAST( const SimpleDeclarationAST& source );
+ void operator = ( const SimpleDeclarationAST& source );
+};
+
+class StatementAST: public AST
+{
+public:
+ typedef AUTO_PTR<StatementAST> Node;
+ enum { Type = NodeType_Statement };
+
+ DECLARE_ALLOC( StatementAST )
+
+public:
+ StatementAST();
+
+private:
+ StatementAST( const StatementAST& source );
+ void operator = ( const StatementAST& source );
+};
+
+class ExpressionStatementAST: public StatementAST
+{
+public:
+ typedef AUTO_PTR<ExpressionStatementAST> Node;
+ enum { Type = NodeType_ExpressionStatement };
+
+ DECLARE_ALLOC( ExpressionStatementAST )
+
+public:
+ ExpressionStatementAST();
+
+ AST* expression() { return m_expression.get(); }
+ void setExpression( AST::Node& expression );
+
+private:
+ AST::Node m_expression;
+
+private:
+ ExpressionStatementAST( const ExpressionStatementAST& source );
+ void operator = ( const ExpressionStatementAST& source );
+};
+
+class ConditionAST: public AST
+{
+public:
+ typedef AUTO_PTR<ConditionAST> Node;
+ enum { Type = NodeType_Condition };
+
+ DECLARE_ALLOC( ConditionAST )
+
+public:
+ ConditionAST();
+
+ TypeSpecifierAST* typeSpec() { return m_typeSpec.get(); }
+ void setTypeSpec( TypeSpecifierAST::Node& typeSpec );
+
+ DeclaratorAST* declarator() { return m_declarator.get(); }
+ void setDeclarator( DeclaratorAST::Node& declarator );
+
+ AST* expression() { return m_expression.get(); }
+ void setExpression( AST::Node& expression );
+
+private:
+ TypeSpecifierAST::Node m_typeSpec;
+ DeclaratorAST::Node m_declarator;
+ AST::Node m_expression;
+
+private:
+ ConditionAST( const ConditionAST& source );
+ void operator = ( const ConditionAST& source );
+};
+
+class IfStatementAST: public StatementAST
+{
+public:
+ typedef AUTO_PTR<IfStatementAST> Node;
+ enum { Type = NodeType_IfStatement };
+
+ DECLARE_ALLOC( IfStatementAST )
+
+public:
+ IfStatementAST();
+
+ ConditionAST* condition() const { return m_condition.get(); }
+ void setCondition( ConditionAST::Node& condition );
+
+ StatementAST* statement() { return m_statement.get(); }
+ void setStatement( StatementAST::Node& statement );
+
+ StatementAST* elseStatement() { return m_elseStatement.get(); }
+ void setElseStatement( StatementAST::Node& statement );
+
+private:
+ ConditionAST::Node m_condition;
+ StatementAST::Node m_statement;
+ StatementAST::Node m_elseStatement;
+
+private:
+ IfStatementAST( const IfStatementAST& source );
+ void operator = ( const IfStatementAST& source );
+};
+
+class WhileStatementAST: public StatementAST
+{
+public:
+ typedef AUTO_PTR<WhileStatementAST> Node;
+ enum { Type = NodeType_WhileStatement };
+
+ DECLARE_ALLOC( WhileStatementAST )
+
+public:
+ WhileStatementAST();
+
+ ConditionAST* condition() const { return m_condition.get(); }
+ void setCondition( ConditionAST::Node& condition );
+
+ StatementAST* statement() { return m_statement.get(); }
+ void setStatement( StatementAST::Node& statement );
+
+private:
+ ConditionAST::Node m_condition;
+ StatementAST::Node m_statement;
+
+private:
+ WhileStatementAST( const WhileStatementAST& source );
+ void operator = ( const WhileStatementAST& source );
+};
+
+class DoStatementAST: public StatementAST
+{
+public:
+ typedef AUTO_PTR<DoStatementAST> Node;
+ enum { Type = NodeType_DoStatement };
+
+ DECLARE_ALLOC( DoStatementAST )
+
+public:
+ DoStatementAST();
+
+ ConditionAST* condition() const { return m_condition.get(); }
+ void setCondition( ConditionAST::Node& condition );
+
+ StatementAST* statement() { return m_statement.get(); }
+ void setStatement( StatementAST::Node& statement );
+
+private:
+ ConditionAST::Node m_condition;
+ StatementAST::Node m_statement;
+
+private:
+ DoStatementAST( const DoStatementAST& source );
+ void operator = ( const DoStatementAST& source );
+};
+
+class ForStatementAST: public StatementAST
+{
+public:
+ typedef AUTO_PTR<ForStatementAST> Node;
+ enum { Type = NodeType_ForStatement };
+
+ DECLARE_ALLOC( ForStatementAST )
+
+public:
+ ForStatementAST();
+
+ StatementAST* initStatement() { return m_initStatement.get(); }
+ void setInitStatement( StatementAST::Node& statement );
+
+ ConditionAST* condition() const { return m_condition.get(); }
+ void setCondition( ConditionAST::Node& condition );
+
+ AST* expression() const { return m_expression.get(); }
+ void setExpression( AST::Node& expression );
+
+ StatementAST* statement() { return m_statement.get(); }
+ void setStatement( StatementAST::Node& statement );
+
+private:
+ ConditionAST::Node m_condition;
+ StatementAST::Node m_initStatement;
+ StatementAST::Node m_statement;
+ AST::Node m_expression;
+
+private:
+ ForStatementAST( const ForStatementAST& source );
+ void operator = ( const ForStatementAST& source );
+};
+
+class SwitchStatementAST: public StatementAST
+{
+public:
+ typedef AUTO_PTR<SwitchStatementAST> Node;
+ enum { Type = NodeType_SwitchStatement };
+
+ DECLARE_ALLOC( SwitchStatementAST )
+
+public:
+ SwitchStatementAST();
+
+ ConditionAST* condition() const { return m_condition.get(); }
+ void setCondition( ConditionAST::Node& condition );
+
+ StatementAST* statement() { return m_statement.get(); }
+ void setStatement( StatementAST::Node& statement );
+
+private:
+ ConditionAST::Node m_condition;
+ StatementAST::Node m_statement;
+
+private:
+ SwitchStatementAST( const SwitchStatementAST& source );
+ void operator = ( const SwitchStatementAST& source );
+};
+
+class StatementListAST: public StatementAST
+{
+public:
+ typedef AUTO_PTR<StatementListAST> Node;
+ enum { Type = NodeType_StatementList };
+
+ DECLARE_ALLOC( StatementListAST )
+
+public:
+ StatementListAST();
+
+ QPtrList<StatementAST> statementList() { return m_statementList; }
+ void addStatement( StatementAST::Node& statement );
+
+private:
+ QPtrList<StatementAST> m_statementList;
+
+private:
+ StatementListAST( const StatementListAST& source );
+ void operator = ( const StatementListAST& source );
+};
+
+class DeclarationStatementAST: public StatementAST
+{
+public:
+ typedef AUTO_PTR<DeclarationStatementAST> Node;
+ enum { Type = NodeType_DeclarationStatement };
+
+ DECLARE_ALLOC( DeclarationStatementAST )
+
+public:
+ DeclarationStatementAST();
+
+ DeclarationAST* declaration() { return m_declaration.get(); }
+ void setDeclaration( DeclarationAST::Node& declaration );
+
+private:
+ DeclarationAST::Node m_declaration;
+
+private:
+ DeclarationStatementAST( const DeclarationStatementAST& source );
+ void operator = ( const DeclarationStatementAST& source );
+};
+
+class FunctionDefinitionAST: public DeclarationAST
+{
+public:
+ typedef AUTO_PTR<FunctionDefinitionAST> Node;
+ enum { Type = NodeType_FunctionDefinition };
+
+ DECLARE_ALLOC( FunctionDefinitionAST )
+
+public:
+ FunctionDefinitionAST();
+
+ GroupAST* functionSpecifier() { return m_functionSpecifier.get(); }
+ void setFunctionSpecifier( GroupAST::Node& functionSpecifier );
+
+ GroupAST* storageSpecifier() { return m_storageSpecifier.get(); }
+ void setStorageSpecifier( GroupAST::Node& storageSpecifier );
+
+ TypeSpecifierAST* typeSpec() { return m_typeSpec.get(); }
+ void setTypeSpec( TypeSpecifierAST::Node& typeSpec );
+
+ InitDeclaratorAST* initDeclarator() { return m_initDeclarator.get(); }
+ void setInitDeclarator( InitDeclaratorAST::Node& initDeclarator );
+
+ StatementListAST* functionBody() { return m_functionBody.get(); }
+ void setFunctionBody( StatementListAST::Node& functionBody );
+
+ GroupAST* winDeclSpec() { return m_winDeclSpec.get(); }
+ void setWinDeclSpec( GroupAST::Node& winDeclSpec );
+
+private:
+ GroupAST::Node m_functionSpecifier;
+ GroupAST::Node m_storageSpecifier;
+ TypeSpecifierAST::Node m_typeSpec;
+ InitDeclaratorAST::Node m_initDeclarator;
+ StatementListAST::Node m_functionBody;
+ GroupAST::Node m_winDeclSpec;
+
+private:
+ FunctionDefinitionAST( const FunctionDefinitionAST& source );
+ void operator = ( const FunctionDefinitionAST& source );
+};
+
+
+class TranslationUnitAST: public AST
+{
+public:
+ typedef AUTO_PTR<TranslationUnitAST> Node;
+ enum { Type = NodeType_TranslationUnit };
+
+ DECLARE_ALLOC( TranslationUnitAST )
+
+public:
+ TranslationUnitAST();
+
+ void addDeclaration( DeclarationAST::Node& ast );
+ QPtrList<DeclarationAST> declarationList() { return m_declarationList; }
+
+private:
+ QPtrList<DeclarationAST> m_declarationList;
+
+private:
+ TranslationUnitAST( const TranslationUnitAST& source );
+ void operator = ( const TranslationUnitAST& source );
+};
+
+#endif
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/ast_utils.cpp b/umbrello/umbrello/codeimport/kdevcppparser/ast_utils.cpp
new file mode 100644
index 00000000..e30f0c1e
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/ast_utils.cpp
@@ -0,0 +1,176 @@
+/***************************************************************************
+ * Copyright (C) 2002 by Roberto Raggi *
+ * roberto@kdevelop.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "ast_utils.h"
+#include "ast.h"
+
+#include <qstringlist.h>
+#include <qregexp.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+#include <kapplication.h>
+
+AST* findNodeAt( AST* node, int line, int column )
+{
+ // kdDebug(9007) << "findNodeAt(" << node << ")" << endl;
+
+ if( !node )
+ return 0;
+
+ int startLine, startColumn;
+ int endLine, endColumn;
+
+ node->getStartPosition( &startLine, &startColumn );
+ node->getEndPosition( &endLine, &endColumn );
+
+ if( (line > startLine || (line == startLine && column >= startColumn)) &&
+ (line < endLine || (line == endLine && column < endColumn)) ){
+
+ QPtrList<AST> children = node->children();
+ QPtrListIterator<AST> it( children );
+ while( it.current() ){
+ AST* a = it.current();
+ ++it;
+
+ AST* r = findNodeAt( a, line, column );
+ if( r )
+ return r;
+ }
+
+ return node;
+ }
+
+ return 0;
+}
+
+void scopeOfNode( AST* ast, QStringList& scope )
+{
+ if( !ast )
+ return;
+
+ if( ast->parent() )
+ scopeOfNode( ast->parent(), scope );
+
+ QString s;
+ switch( ast->nodeType() )
+ {
+ case NodeType_ClassSpecifier:
+ if( ((ClassSpecifierAST*)ast)->name() ){
+ s = ((ClassSpecifierAST*)ast)->name()->text();
+ s = s.isEmpty() ? QString::fromLatin1("<unnamed>") : s;
+ scope.push_back( s );
+ }
+ break;
+
+ case NodeType_Namespace:
+ {
+ AST* namespaceName = ((NamespaceAST*)ast)->namespaceName();
+ s = namespaceName ? namespaceName->text() : QString::fromLatin1("<unnamed>");
+ scope.push_back( s );
+ }
+ break;
+
+ case NodeType_FunctionDefinition:
+ {
+ FunctionDefinitionAST* funDef = static_cast<FunctionDefinitionAST*>( ast );
+ DeclaratorAST* d = funDef->initDeclarator()->declarator();
+
+ // hotfix for bug #68726
+ if ( !d->declaratorId() )
+ break;
+
+ QPtrList<ClassOrNamespaceNameAST> l = d->declaratorId()->classOrNamespaceNameList();
+ QPtrListIterator<ClassOrNamespaceNameAST> nameIt( l );
+ while( nameIt.current() ){
+ AST* name = nameIt.current()->name();
+ scope.push_back( name->text() );
+
+ ++nameIt;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+QString typeSpecToString( TypeSpecifierAST* typeSpec ) /// @todo remove
+{
+ if( !typeSpec )
+ return QString::null;
+
+ return typeSpec->text().replace( QRegExp(" :: "), "::" );
+}
+
+QString declaratorToString( DeclaratorAST* declarator, const QString& scope, bool skipPtrOp )
+{
+ if( !declarator )
+ return QString::null;
+
+ QString text;
+
+ if( !skipPtrOp ){
+ QPtrList<AST> ptrOpList = declarator->ptrOpList();
+ for( QPtrListIterator<AST> it(ptrOpList); it.current(); ++it ){
+ text += it.current()->text();
+ }
+ text += ' ';
+ }
+
+ text += scope;
+
+ if( declarator->subDeclarator() )
+ text += QString::fromLatin1("(") + declaratorToString(declarator->subDeclarator()) + QString::fromLatin1(")");
+
+ if( declarator->declaratorId() )
+ text += declarator->declaratorId()->text();
+
+ QPtrList<AST> arrays = declarator->arrayDimensionList();
+ QPtrListIterator<AST> it( arrays );
+ while( it.current() ){
+ text += "[]";
+ ++it;
+ }
+
+ if( declarator->parameterDeclarationClause() ){
+ text += "( ";
+
+ ParameterDeclarationListAST* l = declarator->parameterDeclarationClause()->parameterDeclarationList();
+ if( l != 0 ){
+ QPtrList<ParameterDeclarationAST> params = l->parameterList();
+ QPtrListIterator<ParameterDeclarationAST> it( params );
+
+ while( it.current() ){
+ QString type = typeSpecToString( it.current()->typeSpec() );
+ text += type;
+ if( !type.isEmpty() )
+ text += ' ';
+ text += declaratorToString( it.current()->declarator() );
+
+ ++it;
+
+ if( it.current() )
+ text += ", ";
+ }
+ }
+
+ text += " )";
+
+ if( declarator->constant() != 0 )
+ text += " const";
+ }
+
+ return text.replace( QRegExp(" :: "), "::" ).simplifyWhiteSpace();
+}
+
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/ast_utils.h b/umbrello/umbrello/codeimport/kdevcppparser/ast_utils.h
new file mode 100644
index 00000000..187647b7
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/ast_utils.h
@@ -0,0 +1,29 @@
+/***************************************************************************
+ * Copyright (C) 2002 by Roberto Raggi *
+ * roberto@kdevelop.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __ast_utils_h
+#define __ast_utils_h
+
+#include <qstring.h>
+
+class AST;
+class DeclaratorAST;
+class TypeSpecifierAST;
+class QStringList;
+
+namespace KTextEditor{ class EditInterface; }
+
+AST* findNodeAt( AST* unit, int line, int column );
+void scopeOfNode( AST* ast, QStringList& );
+QString typeSpecToString( TypeSpecifierAST* typeSpec );
+QString declaratorToString( DeclaratorAST* declarator, const QString& scope = QString::null, bool skipPtrOp=false );
+
+#endif // __ast_utils_h
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/cpptree2uml.cpp b/umbrello/umbrello/codeimport/kdevcppparser/cpptree2uml.cpp
new file mode 100644
index 00000000..e7d0b848
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/cpptree2uml.cpp
@@ -0,0 +1,640 @@
+/***************************************************************************
+ * Based on kdevelop-3.0 languages/cpp/store_walker.cpp by Roberto Raggi *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2004-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "cpptree2uml.h"
+// qt/kde includes
+#include <qfileinfo.h>
+#include <qdir.h>
+#include <qregexp.h>
+#include <kdebug.h>
+// app includes
+#include "ast_utils.h"
+#include "urlutil.h"
+#include "../import_utils.h"
+// FIXME: The sole reason for the next 2 includes is parseTypedef().
+// Make capsule methods in ClassImport, and remove these includes.
+#include "../../classifier.h"
+// FIXME The next include is motivated by template params
+#include "../../template.h"
+
+CppTree2Uml::CppTree2Uml( const QString& fileName)
+ : m_anon( 0 ), m_nsCnt( 0 ), m_clsCnt( 0 )
+{
+ m_fileName = URLUtil::canonicalPath(fileName);
+}
+
+CppTree2Uml::~CppTree2Uml()
+{
+}
+
+void CppTree2Uml::parseTranslationUnit( TranslationUnitAST* ast )
+{
+ m_currentScope.clear();
+ m_currentNamespace[0] = NULL; // index 0 is reserved (always NULL)
+ m_currentClass[0] = NULL; // index 0 is reserved (always NULL)
+ m_nsCnt = 0;
+ m_clsCnt = 0;
+
+ m_currentAccess = Uml::Visibility::Public;
+ m_inSlots = false;
+ m_inSignals = false;
+ m_inStorageSpec = false;
+ m_inTypedef = false;
+ m_currentDeclarator = 0;
+ m_anon = 0;
+
+ TreeParser::parseTranslationUnit( ast );
+}
+
+void CppTree2Uml::parseNamespace( NamespaceAST* ast )
+{
+ if (m_clsCnt > 0) {
+ kDebug() << "CppTree2Uml::parseNamespace: error - cannot nest namespace inside class"
+ << endl;
+ return;
+ }
+
+ QString nsName;
+ if( !ast->namespaceName() || ast->namespaceName()->text().isEmpty() ){
+ QFileInfo fileInfo( m_fileName );
+ QString shortFileName = fileInfo.baseName();
+
+ nsName.sprintf( "(%s_%d)", shortFileName.local8Bit().data(), m_anon++ );
+ } else {
+ nsName = ast->namespaceName()->text();
+ }
+
+#ifdef DEBUG_CPPTREE2UML
+ kDebug() << "CppTree2Uml::parseNamespace: " << nsName << endl;
+#endif
+ UMLObject * o = Import_Utils::createUMLObject( Uml::ot_Package, nsName,
+ m_currentNamespace[m_nsCnt],
+ ast->comment());
+ UMLPackage *ns = (UMLPackage *)o;
+ m_currentScope.push_back( nsName );
+ if (++m_nsCnt > STACKSIZE) {
+ kdError() << "CppTree2Uml::parseNamespace: excessive namespace nesting" << endl;
+ m_nsCnt = STACKSIZE;
+ }
+ m_currentNamespace[m_nsCnt] = ns;
+
+ TreeParser::parseNamespace( ast );
+
+ --m_nsCnt;
+ m_currentScope.pop_back();
+}
+
+void CppTree2Uml::parseTypedef( TypedefAST* ast )
+{
+#if 0
+ DeclaratorAST* oldDeclarator = m_currentDeclarator;
+
+ if( ast && ast->initDeclaratorList() && ast->initDeclaratorList()->initDeclaratorList().count() > 0 ) {
+ QPtrList<InitDeclaratorAST> lst( ast->initDeclaratorList()->initDeclaratorList() );
+ m_currentDeclarator = lst.at( 0 )->declarator();
+ }
+
+ m_inTypedef = true;
+
+ TreeParser::parseTypedef( ast );
+
+ m_inTypedef = false;
+ m_currentDeclarator = oldDeclarator;
+#else
+ TypeSpecifierAST* typeSpec = ast->typeSpec();
+ InitDeclaratorListAST* declarators = ast->initDeclaratorList();
+
+ if( typeSpec && declarators ){
+ QString typeId;
+
+ if( typeSpec->name() )
+ typeId = typeSpec->name()->text();
+
+ QPtrList<InitDeclaratorAST> l( declarators->initDeclaratorList() );
+ QPtrListIterator<InitDeclaratorAST> it( l );
+
+ InitDeclaratorAST* initDecl = 0;
+ while( 0 != (initDecl = it.current()) ){
+
+ QString type, id;
+ if( initDecl->declarator() ){
+ type = typeOfDeclaration( typeSpec, initDecl->declarator() );
+
+ DeclaratorAST* d = initDecl->declarator();
+ while( d->subDeclarator() ){
+ d = d->subDeclarator();
+ }
+
+ if( d->declaratorId() )
+ id = d->declaratorId()->text();
+ }
+//#ifdef DEBUG_CPPTREE2UML
+ kDebug() << "CppTree2Uml::parseTypedef: name=" << id << ", type=" << type << endl;
+//#endif
+ /* @todo Trace typedefs back to their root type for deciding
+ whether to build a Datatype (for pointers.) */
+ /* check out if the ID type is a Datatype
+ ex: typedef unsigned int uint;
+ where unsigned int is a known datatype
+ I'm not sure if setIsReference() should be run
+ */
+ bool isDatatype = Import_Utils::isDatatype(typeId, m_currentNamespace[m_nsCnt]);
+
+ if (type.contains('*') || isDatatype) {
+ UMLObject *inner =
+ Import_Utils::createUMLObject( Uml::ot_Class, typeId,
+ m_currentNamespace[m_nsCnt] );
+ UMLObject *typedefObj =
+ Import_Utils::createUMLObject( Uml::ot_Datatype, id,
+ m_currentNamespace[m_nsCnt] );
+ UMLClassifier *dt = static_cast<UMLClassifier*>(typedefObj);
+ dt->setIsReference();
+ dt->setOriginType(static_cast<UMLClassifier*>(inner));
+ } else {
+ Import_Utils::createUMLObject( Uml::ot_Class, id,
+ m_currentNamespace[m_nsCnt],
+ "" /* doc */,
+ "typedef" /* stereotype */);
+ }
+ ++it;
+ }
+
+ }
+#endif
+}
+
+void CppTree2Uml::parseTemplateDeclaration( TemplateDeclarationAST* ast )
+{
+ TemplateParameterListAST* parmListAST = ast->templateParameterList();
+ if (parmListAST == NULL)
+ return;
+ QPtrList<TemplateParameterAST> parmList = parmListAST->templateParameterList();
+ for (QPtrListIterator<TemplateParameterAST> it(parmList); it.current(); ++it) {
+ // The template is either a typeParameter or a typeValueParameter.
+
+ TemplateParameterAST* tmplParmNode = it.current();
+ TypeParameterAST* typeParmNode = tmplParmNode->typeParameter();
+ if (typeParmNode) {
+ NameAST* nameNode = typeParmNode->name();
+ if (nameNode) {
+ QString typeName = nameNode->unqualifiedName()->text();
+ Model_Utils::NameAndType nt(typeName, NULL);
+ m_templateParams.append(nt);
+ } else {
+ kdError() << "CppTree2Uml::parseTemplateDeclaration(type):"
+ << " nameNode is NULL" << endl;
+ }
+ }
+
+ ParameterDeclarationAST* valueNode = tmplParmNode->typeValueParameter();
+ if (valueNode) {
+ TypeSpecifierAST* typeSpec = valueNode->typeSpec();
+ if (typeSpec == NULL) {
+ kdError() << "CppTree2Uml::parseTemplateDeclaration(value):"
+ << " typeSpec is NULL" << endl;
+ continue;
+ }
+ QString typeName = typeSpec->name()->text();
+ UMLObject *t = Import_Utils::createUMLObject( Uml::ot_UMLObject, typeName,
+ m_currentNamespace[m_nsCnt] );
+ DeclaratorAST* declNode = valueNode->declarator();
+ NameAST* nameNode = declNode->declaratorId();
+ if (nameNode == NULL) {
+ kdError() << "CppTree2Uml::parseTemplateDeclaration(value):"
+ << " nameNode is NULL" << endl;
+ continue;
+ }
+ QString paramName = nameNode->unqualifiedName()->text();
+ Model_Utils::NameAndType nt(paramName, t);
+ m_templateParams.append(nt);
+ }
+ }
+
+ if( ast->declaration() )
+ TreeParser::parseDeclaration( ast->declaration() );
+}
+
+void CppTree2Uml::parseSimpleDeclaration( SimpleDeclarationAST* ast )
+{
+ TypeSpecifierAST* typeSpec = ast->typeSpec();
+ InitDeclaratorListAST* declarators = ast->initDeclaratorList();
+
+ m_comment = ast->comment();
+
+ if( typeSpec )
+ parseTypeSpecifier( typeSpec );
+
+ if( declarators ){
+ QPtrList<InitDeclaratorAST> l = declarators->initDeclaratorList();
+
+ QPtrListIterator<InitDeclaratorAST> it( l );
+ while( it.current() ){
+ parseDeclaration( ast->functionSpecifier(), ast->storageSpecifier(), typeSpec, it.current() );
+ ++it;
+ }
+ }
+}
+
+void CppTree2Uml::parseFunctionDefinition( FunctionDefinitionAST* ast )
+{
+ TypeSpecifierAST* typeSpec = ast->typeSpec();
+ GroupAST* funSpec = ast->functionSpecifier();
+ GroupAST* storageSpec = ast->storageSpecifier();
+
+ if( !ast->initDeclarator() )
+ return;
+
+ DeclaratorAST* d = ast->initDeclarator()->declarator();
+
+ if( !d->declaratorId() )
+ return;
+
+ bool isFriend = false;
+ bool isVirtual = false;
+ bool isStatic = false;
+ bool isInline = false;
+ bool isConstructor = false;
+
+ if( funSpec ){
+ QPtrList<AST> l = funSpec->nodeList();
+ QPtrListIterator<AST> it( l );
+ while( it.current() ){
+ QString text = it.current()->text();
+ if( text == "virtual" ) isVirtual = true;
+ else if( text == "inline" ) isInline = true;
+ ++it;
+ }
+ }
+
+ if( storageSpec ){
+ QPtrList<AST> l = storageSpec->nodeList();
+ QPtrListIterator<AST> it( l );
+ while( it.current() ){
+ QString text = it.current()->text();
+ if( text == "friend" ) isFriend = true;
+ else if( text == "static" ) isStatic = true;
+ ++it;
+ }
+ }
+
+ QString id = d->declaratorId()->unqualifiedName()->text().stripWhiteSpace();
+
+ UMLClassifier *c = m_currentClass[m_clsCnt];
+ if (c == NULL) {
+ kDebug() << "CppTree2Uml::parseFunctionDefinition (" << id
+ << "): need a surrounding class." << endl;
+ return;
+ }
+
+ QString returnType = typeOfDeclaration( typeSpec, d );
+ UMLOperation *m = Import_Utils::makeOperation(c, id);
+ // if a class has no return type, it could be a constructor or
+ // a destructor
+ if (d && returnType.isEmpty() && id.find("~") == -1)
+ isConstructor = true;
+
+ parseFunctionArguments( d, m );
+ Import_Utils::insertMethod( c, m, m_currentAccess, returnType,
+ isStatic, false /*isAbstract*/, isFriend, isConstructor, m_comment);
+ m_comment = "";
+
+/* For reference, Kdevelop does some more:
+ method->setFileName( m_fileName );
+ if( m_inSignals )
+ method->setSignal( true );
+ if( m_inSlots )
+ method->setSlot( true );
+ */
+}
+
+void CppTree2Uml::parseClassSpecifier( ClassSpecifierAST* ast )
+{
+ Uml::Visibility oldAccess = m_currentAccess;
+ bool oldInSlots = m_inSlots;
+ bool oldInSignals = m_inSignals;
+
+ QString kind = ast->classKey()->text();
+ m_currentAccess=Uml::Visibility::fromString(kind);
+ m_inSlots = false;
+ m_inSignals = false;
+
+ QString className;
+ if( !ast->name() && m_currentDeclarator && m_currentDeclarator->declaratorId() ) {
+ className = m_currentDeclarator->declaratorId()->text().stripWhiteSpace();
+ } else if( !ast->name() ){
+ QFileInfo fileInfo( m_fileName );
+ QString shortFileName = fileInfo.baseName();
+ className.sprintf( "(%s_%d)", shortFileName.local8Bit().data(), m_anon++ );
+ } else {
+ className = ast->name()->unqualifiedName()->text().stripWhiteSpace();
+ }
+//#ifdef DEBUG_CPPTREE2UML
+ kDebug() << "CppTree2Uml::parseClassSpecifier: name=" << className << endl;
+//#endif
+ if( !scopeOfName( ast->name(), QStringList() ).isEmpty() ){
+ kDebug() << "skip private class declarations" << endl;
+ return;
+ }
+
+ if (className.isEmpty()) {
+ className = "anon_" + QString::number(m_anon);
+ m_anon++;
+ }
+ UMLObject * o = Import_Utils::createUMLObject( Uml::ot_Class, className,
+ m_currentNamespace[m_nsCnt],
+ ast->comment() );
+ UMLClassifier *klass = static_cast<UMLClassifier*>(o);
+ flushTemplateParams(klass);
+ if ( ast->baseClause() )
+ parseBaseClause( ast->baseClause(), klass );
+
+ m_currentScope.push_back( className );
+ if (++m_clsCnt > STACKSIZE) {
+ kdError() << "CppTree2Uml::parseNamespace: excessive class nesting" << endl;
+ m_clsCnt = STACKSIZE;
+ }
+ m_currentClass[m_clsCnt] = klass;
+ if (++m_nsCnt > STACKSIZE) {
+ kdError() << "CppTree2Uml::parseNamespace: excessive namespace nesting" << endl;
+ m_nsCnt = STACKSIZE;
+ }
+ m_currentNamespace[m_nsCnt] = (UMLPackage*)klass;
+
+ TreeParser::parseClassSpecifier( ast );
+
+ --m_nsCnt;
+ --m_clsCnt;
+
+ m_currentScope.pop_back();
+
+ m_currentAccess = oldAccess;
+ m_inSlots = oldInSlots;
+ m_inSignals = oldInSignals;
+}
+
+void CppTree2Uml::parseEnumSpecifier( EnumSpecifierAST* ast )
+{
+ NameAST *nameNode = ast->name();
+ if (nameNode == NULL)
+ return; // skip constants
+ QString typeName = nameNode->unqualifiedName()->text().stripWhiteSpace();
+ if (typeName.isEmpty())
+ return; // skip constants
+ UMLObject *o = Import_Utils::createUMLObject( Uml::ot_Enum, typeName,
+ m_currentNamespace[m_nsCnt],
+ ast->comment() );
+
+ QPtrList<EnumeratorAST> l = ast->enumeratorList();
+ QPtrListIterator<EnumeratorAST> it( l );
+ while ( it.current() ) {
+ QString enumLiteral = it.current()->id()->text();
+ Import_Utils::addEnumLiteral( (UMLEnum*)o, enumLiteral );
+ ++it;
+ }
+}
+
+void CppTree2Uml::parseElaboratedTypeSpecifier( ElaboratedTypeSpecifierAST* typeSpec )
+{
+ // This is invoked for forward declarations.
+ /// @todo Refine - Currently only handles class forward declarations.
+ /// - Using typeSpec->text() is probably not good, decode
+ /// the kind() instead.
+ QString text = typeSpec->text();
+ kDebug() << "CppTree2Uml::parseElaboratedTypeSpecifier: text is " << text << endl;
+ text.remove(QRegExp("^class\\s+"));
+ UMLObject *o = Import_Utils::createUMLObject(Uml::ot_Class, text, m_currentNamespace[m_nsCnt]);
+ flushTemplateParams( static_cast<UMLClassifier*>(o) );
+}
+
+void CppTree2Uml::parseDeclaration( GroupAST* funSpec, GroupAST* storageSpec,
+ TypeSpecifierAST* typeSpec, InitDeclaratorAST* decl )
+{
+ if( m_inStorageSpec )
+ return;
+
+ DeclaratorAST* d = decl->declarator();
+
+ if( !d )
+ return;
+
+ if( !d->subDeclarator() && d->parameterDeclarationClause() )
+ return parseFunctionDeclaration( funSpec, storageSpec, typeSpec, decl );
+
+ DeclaratorAST* t = d;
+ while( t && t->subDeclarator() )
+ t = t->subDeclarator();
+
+ QString id;
+ if( t && t->declaratorId() && t->declaratorId()->unqualifiedName() )
+ id = t->declaratorId()->unqualifiedName()->text();
+
+ if( !scopeOfDeclarator(d, QStringList()).isEmpty() ){
+ kDebug() << "CppTree2Uml::parseDeclaration (" << id << "): skipping."
+ << endl;
+ return;
+ }
+
+ UMLClassifier *c = m_currentClass[m_clsCnt];
+ if (c == NULL) {
+ kDebug() << "CppTree2Uml::parseDeclaration (" << id
+ << "): need a surrounding class." << endl;
+ return;
+ }
+
+ QString typeName = typeOfDeclaration( typeSpec, d );
+ bool isFriend = false;
+ bool isStatic = false;
+ //bool isInitialized = decl->initializer() != 0;
+
+ if( storageSpec ){
+ QPtrList<AST> l = storageSpec->nodeList();
+ QPtrListIterator<AST> it( l );
+ while( it.current() ){
+ QString text = it.current()->text();
+ if( text == "friend" ) isFriend = true;
+ else if( text == "static" ) isStatic = true;
+ ++it;
+ }
+ }
+
+ Import_Utils::insertAttribute( c, m_currentAccess, id, typeName,
+ m_comment, isStatic);
+ m_comment = "";
+}
+
+void CppTree2Uml::parseAccessDeclaration( AccessDeclarationAST * access )
+{
+ QPtrList<AST> l = access->accessList();
+
+ QString accessStr = l.at( 0 )->text();
+
+ m_currentAccess=Uml::Visibility::fromString(accessStr);
+
+ m_inSlots = l.count() > 1 ? l.at( 1 )->text() == "slots" : false;
+ m_inSignals = l.count() >= 1 ? l.at( 0 )->text() == "signals" : false;
+}
+
+void CppTree2Uml::parseFunctionDeclaration( GroupAST* funSpec, GroupAST* storageSpec,
+ TypeSpecifierAST * typeSpec, InitDeclaratorAST * decl )
+{
+ bool isFriend = false;
+ bool isVirtual = false;
+ bool isStatic = false;
+ bool isInline = false;
+ bool isPure = decl->initializer() != 0;
+ bool isConstructor = false;
+
+ if( funSpec ){
+ QPtrList<AST> l = funSpec->nodeList();
+ QPtrListIterator<AST> it( l );
+ while( it.current() ){
+ QString text = it.current()->text();
+ if( text == "virtual" ) isVirtual = true;
+ else if( text == "inline" ) isInline = true;
+ ++it;
+ }
+ }
+
+ if( storageSpec ){
+ QPtrList<AST> l = storageSpec->nodeList();
+ QPtrListIterator<AST> it( l );
+ while( it.current() ){
+ QString text = it.current()->text();
+ if( text == "friend" ) isFriend = true;
+ else if( text == "static" ) isStatic = true;
+ ++it;
+ }
+ }
+
+ DeclaratorAST* d = decl->declarator();
+ QString id = d->declaratorId()->unqualifiedName()->text();
+
+ UMLClassifier *c = m_currentClass[m_clsCnt];
+ if (c == NULL) {
+ kDebug() << "CppTree2Uml::parseFunctionDeclaration (" << id
+ << "): need a surrounding class." << endl;
+ return;
+ }
+
+ QString returnType = typeOfDeclaration( typeSpec, d );
+ UMLOperation *m = Import_Utils::makeOperation(c, id);
+ // if a class has no return type, it could be a constructor or
+ // a destructor
+ if (d && returnType.isEmpty() && id.find("~") == -1)
+ isConstructor = true;
+
+ parseFunctionArguments( d, m );
+ Import_Utils::insertMethod( c, m, m_currentAccess, returnType,
+ isStatic, isPure, isFriend, isConstructor, m_comment);
+ m_comment = "";
+}
+
+void CppTree2Uml::parseFunctionArguments(DeclaratorAST* declarator,
+ UMLOperation* method)
+{
+ ParameterDeclarationClauseAST* clause = declarator->parameterDeclarationClause();
+
+ if( clause && clause->parameterDeclarationList() ){
+ ParameterDeclarationListAST* params = clause->parameterDeclarationList();
+ QPtrList<ParameterDeclarationAST> l( params->parameterList() );
+ QPtrListIterator<ParameterDeclarationAST> it( l );
+ while( it.current() ){
+ ParameterDeclarationAST* param = it.current();
+ ++it;
+
+ QString name;
+ if (param->declarator())
+ name = declaratorToString(param->declarator(), QString::null, true );
+
+ QString tp = typeOfDeclaration( param->typeSpec(), param->declarator() );
+
+ if (tp != "void")
+ Import_Utils::addMethodParameter( method, tp, name );
+ }
+ }
+}
+
+QString CppTree2Uml::typeOfDeclaration( TypeSpecifierAST* typeSpec, DeclaratorAST* declarator )
+{
+ if( !typeSpec || !declarator )
+ return QString::null;
+
+ QString text;
+
+ text += typeSpec->text();
+
+ QPtrList<AST> ptrOpList = declarator->ptrOpList();
+ for( QPtrListIterator<AST> it(ptrOpList); it.current(); ++it ){
+ text += it.current()->text();
+ }
+
+ return text;
+}
+
+void CppTree2Uml::parseBaseClause( BaseClauseAST * baseClause, UMLClassifier* klass )
+{
+ QPtrList<BaseSpecifierAST> l = baseClause->baseSpecifierList();
+ QPtrListIterator<BaseSpecifierAST> it( l );
+ while( it.current() ){
+ BaseSpecifierAST* baseSpecifier = it.current();
+ ++it;
+
+ if (baseSpecifier->name() == NULL) {
+ kDebug() << "CppTree2Uml::parseBaseClause: baseSpecifier->name() is NULL"
+ << endl;
+ continue;
+ }
+
+ QString baseName = baseSpecifier->name()->text();
+ Import_Utils::createGeneralization( klass, baseName );
+ }
+}
+
+QStringList CppTree2Uml::scopeOfName( NameAST* id, const QStringList& startScope )
+{
+ QStringList scope = startScope;
+ if( id && id->classOrNamespaceNameList().count() ){
+ if( id->isGlobal() )
+ scope.clear();
+ QPtrList<ClassOrNamespaceNameAST> l = id->classOrNamespaceNameList();
+ QPtrListIterator<ClassOrNamespaceNameAST> it( l );
+ while( it.current() ){
+ if( it.current()->name() ){
+ scope << it.current()->name()->text();
+ }
+ ++it;
+ }
+ }
+
+ return scope;
+}
+
+QStringList CppTree2Uml::scopeOfDeclarator( DeclaratorAST* d, const QStringList& startScope )
+{
+ return scopeOfName( d->declaratorId(), startScope );
+}
+
+void CppTree2Uml::flushTemplateParams(UMLClassifier *klass) {
+ if (m_templateParams.count()) {
+ Model_Utils::NameAndType_ListIt it;
+ for (it = m_templateParams.begin(); it != m_templateParams.end(); ++it) {
+ const Model_Utils::NameAndType &nt = *it;
+ kDebug() << "CppTree2Uml::parseClassSpecifier: adding template param: "
+ << nt.m_name << endl;
+ UMLTemplate *tmpl = klass->addTemplate(nt.m_name);
+ tmpl->setType(nt.m_type);
+ }
+ m_templateParams.clear();
+ }
+}
+
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/cpptree2uml.h b/umbrello/umbrello/codeimport/kdevcppparser/cpptree2uml.h
new file mode 100644
index 00000000..b9791372
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/cpptree2uml.h
@@ -0,0 +1,98 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2005-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef CPPTREE2UML_H
+#define CPPTREE2UML_H
+
+#include "tree_parser.h"
+#include <qstringlist.h>
+#include "../../model_utils.h"
+
+// fwd decls
+class UMLClassifier;
+class UMLOperation;
+class UMLPackage;
+
+class CppTree2Uml: public TreeParser
+{
+public:
+ CppTree2Uml( const QString& fileName);
+ virtual ~CppTree2Uml();
+
+ //FileDom file() { return m_file; }
+
+ // translation-unit
+ virtual void parseTranslationUnit( TranslationUnitAST* );
+
+ // declarations
+ //virtual void parseDeclaration( DeclarationAST* ); // use parent method
+ //virtual void parseLinkageSpecification( LinkageSpecificationAST* ); // use parent method
+ virtual void parseNamespace( NamespaceAST* );
+ //virtual void parseNamespaceAlias( NamespaceAliasAST* ); // use parent method
+ //virtual void parseUsing( UsingAST* ); // use parent method
+ //virtual void parseUsingDirective( UsingDirectiveAST* ); // use parent method
+ virtual void parseTypedef( TypedefAST* );
+ virtual void parseTemplateDeclaration( TemplateDeclarationAST* );
+ virtual void parseSimpleDeclaration( SimpleDeclarationAST* );
+ virtual void parseFunctionDefinition( FunctionDefinitionAST* );
+ //virtual void parseLinkageBody( LinkageBodyAST* ); // use parent method
+ virtual void parseAccessDeclaration( AccessDeclarationAST* );
+
+ // type-specifier
+ //virtual void parseTypeSpecifier( TypeSpecifierAST* ); // use parent method
+ virtual void parseClassSpecifier( ClassSpecifierAST* );
+ virtual void parseEnumSpecifier( EnumSpecifierAST* );
+ virtual void parseElaboratedTypeSpecifier( ElaboratedTypeSpecifierAST* );
+
+ // non-overriding (locally added) methods
+
+ virtual void parseDeclaration( GroupAST* funSpec, GroupAST* storageSpec, TypeSpecifierAST* typeSpec, InitDeclaratorAST* decl );
+ virtual void parseFunctionDeclaration( GroupAST* funSpec, GroupAST* storageSpec, TypeSpecifierAST* typeSpec, InitDeclaratorAST* decl );
+ void parseFunctionArguments( DeclaratorAST* declarator, UMLOperation* method);
+ virtual void parseBaseClause( BaseClauseAST* baseClause, UMLClassifier* klass );
+
+private:
+ //NamespaceDom findOrInsertNamespace( NamespaceAST* ast, const QString& name );
+
+ QString typeOfDeclaration( TypeSpecifierAST* typeSpec, DeclaratorAST* declarator );
+ QStringList scopeOfName( NameAST* id, const QStringList& scope );
+ QStringList scopeOfDeclarator( DeclaratorAST* d, const QStringList& scope );
+ /**
+ * Flush template parameters pending in m_templateParams to the klass.
+ */
+ void flushTemplateParams(UMLClassifier *klass);
+
+private:
+ //FileDom m_file;
+ QString m_fileName;
+ QStringList m_currentScope;
+ Uml::Visibility m_currentAccess;
+ bool m_inSlots;
+ bool m_inSignals;
+ int m_anon;
+ bool m_inStorageSpec;
+ bool m_inTypedef;
+ QString m_comment;
+ Model_Utils::NameAndType_List m_templateParams;
+
+ DeclaratorAST* m_currentDeclarator;
+# define STACKSIZE 30
+ UMLPackage* m_currentNamespace[STACKSIZE+1]; ///< stack
+ UMLClassifier* m_currentClass[STACKSIZE+1]; ///< stack
+ int m_nsCnt; ///< stack top for m_currentNamespace
+ int m_clsCnt; ///< stack top for m_currentClass
+
+private:
+ CppTree2Uml( const CppTree2Uml& source );
+ void operator = ( const CppTree2Uml& source );
+};
+
+#endif // CPPTREE2UML
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/driver.cpp b/umbrello/umbrello/codeimport/kdevcppparser/driver.cpp
new file mode 100644
index 00000000..84941025
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/driver.cpp
@@ -0,0 +1,435 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "driver.h"
+#include "lexer.h"
+#include "parser.h"
+#include <kdebug.h>
+#include <stdlib.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qdir.h>
+
+class DefaultSourceProvider: public SourceProvider
+{
+public:
+ DefaultSourceProvider() {}
+
+ virtual QString contents( const QString& fileName )
+ {
+ QString source;
+
+ QFile f( fileName );
+ if( f.open(IO_ReadOnly) ){
+ QTextStream s( &f );
+ source = s.read();
+ f.close();
+ }
+ return source;
+ }
+
+ virtual bool isModified( const QString& fileName )
+ {
+ Q_UNUSED( fileName );
+ return true;
+ }
+
+private:
+ DefaultSourceProvider( const DefaultSourceProvider& source );
+ void operator = ( const DefaultSourceProvider& source );
+};
+
+
+Driver::Driver()
+ : depresolv( false ), lexer( 0 )
+{
+ m_sourceProvider = new DefaultSourceProvider();
+}
+
+Driver::~Driver()
+{
+ reset();
+ delete( m_sourceProvider );
+}
+
+SourceProvider* Driver::sourceProvider()
+{
+ return m_sourceProvider;
+}
+
+void Driver::setSourceProvider( SourceProvider* sourceProvider )
+{
+ if( m_sourceProvider )
+ delete( m_sourceProvider );
+ m_sourceProvider = sourceProvider;
+}
+
+void Driver::reset( )
+{
+ m_dependences.clear();
+ m_macros.clear();
+ m_problems.clear();
+ m_includePaths.clear();
+
+ while( m_parsedUnits.size() ){
+ TranslationUnitAST* unit = *m_parsedUnits.begin();
+ m_parsedUnits.remove( m_parsedUnits.begin() );
+ delete( unit );
+ }
+}
+
+void Driver::remove( const QString & fileName )
+{
+ m_dependences.remove( fileName );
+ m_problems.remove( fileName );
+ removeAllMacrosInFile( fileName );
+
+ QMap<QString, TranslationUnitAST*>::Iterator it = m_parsedUnits.find( fileName );
+ if( it != m_parsedUnits.end() ){
+ TranslationUnitAST* unit = *it;
+ m_parsedUnits.remove( it );
+ delete( unit );
+ }
+}
+
+void Driver::removeAllMacrosInFile( const QString& fileName )
+{
+ QMap<QString, Macro>::Iterator it = m_macros.begin();
+ while( it != m_macros.end() ){
+ Macro m = *it++;
+ if( m.fileName() == fileName )
+ removeMacro( m.name() );
+ }
+}
+
+TranslationUnitAST::Node Driver::takeTranslationUnit( const QString& fileName )
+{
+ QMap<QString, TranslationUnitAST*>::Iterator it = m_parsedUnits.find( fileName );
+ TranslationUnitAST::Node unit( *it );
+ //m_parsedUnits.remove( it );
+ m_parsedUnits[ fileName] = 0;
+ return unit;
+}
+
+TranslationUnitAST* Driver::translationUnit( const QString& fileName ) const
+{
+ QMap<QString, TranslationUnitAST*>::ConstIterator it = m_parsedUnits.find( fileName );
+ return it != m_parsedUnits.end() ? *it : 0;
+}
+
+void Driver::addDependence( const QString & fileName, const Dependence & dep )
+{
+ QFileInfo fileInfo( dep.first );
+ QString fn = fileInfo.absFilePath();
+
+ if ( !depresolv ){
+ findOrInsertDependenceList( fileName ).insert( fn, dep );
+ return;
+ }
+
+ QString file = findIncludeFile( dep );
+ findOrInsertDependenceList( fileName ).insert( file, dep );
+
+ if ( m_parsedUnits.find(file) != m_parsedUnits.end() )
+ return;
+
+ if ( !QFile::exists( file ) ) {
+ Problem p( "Couldn't find include file " + dep.first,
+ lexer ? lexer->currentLine() : -1,
+ lexer ? lexer->currentColumn() : -1 );
+ addProblem( fileName, p );
+ return;
+ }
+
+ QString cfn = m_currentFileName;
+ Lexer *l = lexer;
+ parseFile( file );
+ m_currentFileName = cfn;
+ lexer = l;
+}
+
+void Driver::addMacro( const Macro & macro )
+{
+ m_macros.insert( macro.name(), macro );
+}
+
+void Driver::addProblem( const QString & fileName, const Problem & problem )
+{
+ findOrInsertProblemList( fileName ).append( problem );
+}
+
+QMap< QString, Dependence >& Driver::findOrInsertDependenceList( const QString & fileName )
+{
+ QMap<QString, QMap<QString, Dependence> >::Iterator it = m_dependences.find( fileName );
+ if( it != m_dependences.end() )
+ return it.data();
+
+ QMap<QString, Dependence> l;
+ m_dependences.insert( fileName, l );
+ return m_dependences[ fileName ];
+}
+
+QValueList < Problem >& Driver::findOrInsertProblemList( const QString & fileName )
+{
+ QMap<QString, QValueList<Problem> >::Iterator it = m_problems.find( fileName );
+ if( it != m_problems.end() )
+ return it.data();
+
+ QValueList<Problem> l;
+ m_problems.insert( fileName, l );
+ return m_problems[ fileName ];
+}
+
+QMap< QString, Dependence > Driver::dependences( const QString & fileName ) const
+{
+ QMap<QString, QMap<QString, Dependence> >::ConstIterator it = m_dependences.find( fileName );
+ if( it != m_dependences.end() )
+ return it.data();
+ return QMap<QString, Dependence>();
+}
+
+QMap< QString, Macro > Driver::macros() const
+{
+ return m_macros;
+}
+
+QValueList < Problem > Driver::problems( const QString & fileName ) const
+{
+ QMap<QString, QValueList<Problem> >::ConstIterator it = m_problems.find( fileName );
+ if( it != m_problems.end() )
+ return it.data();
+ return QValueList<Problem>();
+}
+
+void Driver::parseFile( const QString& fileName, bool onlyPreProcess, bool force )
+{
+ QFileInfo fileInfo( fileName );
+ QString absFilePath = fileInfo.absFilePath();
+
+ QMap<QString, TranslationUnitAST*>::Iterator it = m_parsedUnits.find( absFilePath );
+
+ if( force && it != m_parsedUnits.end() ){
+ takeTranslationUnit( absFilePath );
+ } else if( it != m_parsedUnits.end() && *it != 0 ){
+ // file already processed
+ return;
+ }
+
+ m_dependences.remove( fileName );
+ m_problems.remove( fileName );
+
+ m_currentFileName = fileName;
+
+ Lexer lex( this );
+ lexer = &lex;
+ setupLexer( &lex );
+
+ lex.setSource( sourceProvider()->contents(fileName) );
+
+ if( !onlyPreProcess ){
+ Parser parser( this, &lex );
+ setupParser( &parser );
+
+ TranslationUnitAST :: Node translationUnit;
+ parser.parseTranslationUnit( translationUnit );
+ m_parsedUnits.insert( fileName, translationUnit.release() );
+ fileParsed( fileName );
+ }
+
+ m_currentFileName = QString::null;
+ lexer = 0;
+}
+
+void Driver::setupLexer( Lexer * lexer )
+{
+ // stl
+ lexer->addSkipWord( "__STL_BEGIN_NAMESPACE" );
+ lexer->addSkipWord( "__STL_END_NAMESPACE" );
+ lexer->addSkipWord( "__STL_BEGIN_RELOPS_NAMESPACE" );
+ lexer->addSkipWord( "__STL_END_RELOPS_NAMESPACE" );
+ lexer->addSkipWord( "__STL_TEMPLATE_NULL" );
+ lexer->addSkipWord( "__STL_TRY" );
+ lexer->addSkipWord( "__STL_UNWIND" );
+ lexer->addSkipWord( "__STL_NOTHROW" );
+ lexer->addSkipWord( "__STL_NULL_TMPL_ARGS" );
+ lexer->addSkipWord( "__STL_UNWIND", SkipWordAndArguments );
+ lexer->addSkipWord( "__GC_CONST" );
+ lexer->addSkipWord( "__HASH_ALLOC_INIT", SkipWordAndArguments );
+ lexer->addSkipWord( "__STL_DEFAULT_ALLOCATOR", SkipWordAndArguments, "T" );
+ lexer->addSkipWord( "__STL_MUTEX_INITIALIZER" );
+ lexer->addSkipWord( "__STL_NULL_TMPL_ARGS" );
+
+ // antlr
+ lexer->addSkipWord( "ANTLR_BEGIN_NAMESPACE", SkipWordAndArguments );
+ lexer->addSkipWord( "ANTLR_USE_NAMESPACE", SkipWordAndArguments );
+ lexer->addSkipWord( "ANTLR_USING_NAMESPACE", SkipWordAndArguments );
+ lexer->addSkipWord( "ANTLR_END_NAMESPACE" );
+ lexer->addSkipWord( "ANTLR_C_USING", SkipWordAndArguments );
+ lexer->addSkipWord( "ANTLR_API" );
+
+ // gnu
+ lexer->addSkipWord( "__extension__", SkipWordAndArguments );
+ lexer->addSkipWord( "__attribute__", SkipWordAndArguments );
+ lexer->addSkipWord( "__BEGIN_DECLS" );
+ lexer->addSkipWord( "__END_DECLS" );
+ lexer->addSkipWord( "__THROW" );
+ lexer->addSkipWord( "__restrict" );
+ lexer->addSkipWord( "__restrict__" );
+ lexer->addSkipWord( "__attribute_pure__" );
+ lexer->addSkipWord( "__attribute_malloc__" );
+ lexer->addSkipWord( "__attribute_format_strfmon__" );
+ lexer->addSkipWord( "__asm__", SkipWordAndArguments );
+ lexer->addSkipWord( "__devinit" );
+ lexer->addSkipWord( "__devinit__" );
+ lexer->addSkipWord( "__init" );
+ lexer->addSkipWord( "__init__" );
+ lexer->addSkipWord( "__signed" );
+ lexer->addSkipWord( "__signed__" );
+ lexer->addSkipWord( "__unsigned" );
+ lexer->addSkipWord( "__unsigned__" );
+ lexer->addSkipWord( "asmlinkage" );
+ lexer->addSkipWord( "____cacheline_aligned" );
+ lexer->addSkipWord( "__glibcpp_class_requires", SkipWordAndArguments );
+ lexer->addSkipWord( "__glibcpp_class2_requires", SkipWordAndArguments );
+ lexer->addSkipWord( "__glibcpp_class4_requires", SkipWordAndArguments );
+ lexer->addSkipWord( "__glibcpp_function_requires", SkipWordAndArguments );
+ lexer->addSkipWord( "restrict" );
+
+ lexer->addSkipWord( "__BEGIN_NAMESPACE_STD" );
+ lexer->addSkipWord( "__END_NAMESPACE_STD" );
+ lexer->addSkipWord( "__BEGIN_NAMESPACE_C99" );
+ lexer->addSkipWord( "__END_NAMESPACE_C99" );
+ lexer->addSkipWord( "__USING_NAMESPACE_STD", SkipWordAndArguments );
+
+ // kde
+ lexer->addSkipWord( "K_SYCOCATYPE", SkipWordAndArguments );
+ lexer->addSkipWord( "EXPORT_DOCKCLASS" );
+ lexer->addSkipWord( "K_EXPORT_COMPONENT_FACTORY", SkipWordAndArguments );
+ lexer->addSkipWord( "K_SYCOCAFACTORY", SkipWordAndArguments );
+ lexer->addSkipWord( "KDE_DEPRECATED" );
+
+ // qt
+ lexer->addSkipWord( "Q_OVERRIDE", SkipWordAndArguments );
+ lexer->addSkipWord( "Q_ENUMS", SkipWordAndArguments );
+ lexer->addSkipWord( "Q_PROPERTY", SkipWordAndArguments );
+ lexer->addSkipWord( "Q_CLASSINFO", SkipWordAndArguments );
+ lexer->addSkipWord( "Q_SETS", SkipWordAndArguments );
+ lexer->addSkipWord( "Q_UNUSED", SkipWordAndArguments );
+ lexer->addSkipWord( "Q_CREATE_INSTANCE", SkipWordAndArguments );
+ lexer->addSkipWord( "Q_DUMMY_COMPARISON_OPERATOR", SkipWordAndArguments );
+ lexer->addSkipWord( "ACTIVATE_SIGNAL_WITH_PARAM", SkipWordAndArguments );
+ lexer->addSkipWord( "Q_INLINE_TEMPLATES" );
+ lexer->addSkipWord( "Q_TEMPLATE_EXTERN" );
+ lexer->addSkipWord( "Q_TYPENAME" );
+ lexer->addSkipWord( "Q_REFCOUNT" );
+ lexer->addSkipWord( "Q_EXPLICIT" );
+ lexer->addSkipWord( "QMAC_PASCAL" );
+ lexer->addSkipWord( "QT_STATIC_CONST" );
+ lexer->addSkipWord( "QT_STATIC_CONST_IMPL" );
+ lexer->addSkipWord( "QT_WIN_PAINTER_MEMBERS" );
+ lexer->addSkipWord( "QT_NC_MSGBOX" );
+ lexer->addSkipWord( "Q_VARIANT_AS", SkipWordAndArguments );
+ lexer->addSkipWord( "CALLBACK_CALL_TYPE" );
+
+ // flex
+ lexer->addSkipWord( "yyconst" );
+ lexer->addSkipWord( "YY_RULE_SETUP" );
+ lexer->addSkipWord( "YY_BREAK" );
+ lexer->addSkipWord( "YY_RESTORE_YY_MORE_OFFSET" );
+
+ // gtk
+ lexer->addSkipWord( "G_BEGIN_DECLS" );
+ lexer->addSkipWord( "G_END_DECLS" );
+ lexer->addSkipWord( "G_GNUC_CONST" );
+ lexer->addSkipWord( "G_CONST_RETURN" );
+ lexer->addSkipWord( "GTKMAIN_C_VAR" );
+ lexer->addSkipWord( "GTKVAR" );
+ lexer->addSkipWord( "GDKVAR" );
+ lexer->addSkipWord( "G_GNUC_PRINTF", SkipWordAndArguments );
+
+ // windows
+ lexer->addSkipWord( "WINAPI" );
+ lexer->addSkipWord( "__stdcall" );
+ lexer->addSkipWord( "__cdecl" );
+ lexer->addSkipWord( "_cdecl" );
+ lexer->addSkipWord( "CALLBACK" );
+
+ // gcc extensions
+ addMacro( Macro("__asm__", "asm") );
+ addMacro( Macro("__inline", "inline") );
+ addMacro( Macro("__inline__", "inline") );
+ addMacro( Macro("__const", "const") );
+ addMacro( Macro("__const__", "const") );
+ addMacro( Macro("__volatile__", "volatile") );
+ addMacro( Macro("__complex__", "") );
+}
+
+void Driver::setupParser( Parser * parser )
+{
+ Q_UNUSED( parser );
+}
+
+void Driver::removeMacro( const QString& macroName )
+{
+ m_macros.remove( macroName );
+}
+
+void Driver::addIncludePath( const QString &path )
+{
+ if( !path.stripWhiteSpace().isEmpty() )
+ m_includePaths << path;
+}
+
+QString Driver::findIncludeFile( const Dependence& dep ) const
+{
+ QString fileName = dep.first;
+
+ if( dep.second == Dep_Local ){
+ QString path = QFileInfo( currentFileName() ).dirPath( true );
+ QFileInfo fileInfo( QFileInfo(path, fileName) );
+ if ( fileInfo.exists() && fileInfo.isFile() )
+ return fileInfo.absFilePath();
+
+ }
+
+ QStringList::ConstIterator end(m_includePaths.end());
+ for ( QStringList::ConstIterator it(m_includePaths.begin()); it != end; ++it ) {
+ QFileInfo fileInfo( *it, fileName );
+ if ( fileInfo.exists() && fileInfo.isFile() )
+ return fileInfo.absFilePath();
+ }
+
+ return QString::null;
+}
+
+void Driver::setResolveDependencesEnabled( bool enabled )
+{
+ depresolv = enabled;
+ if ( depresolv )
+ setupPreProcessor();
+}
+
+void Driver::setupPreProcessor()
+{
+}
+
+void Driver::fileParsed( const QString & fileName )
+{
+ Q_UNUSED( fileName );
+}
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/driver.h b/umbrello/umbrello/codeimport/kdevcppparser/driver.h
new file mode 100644
index 00000000..ecb603ab
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/driver.h
@@ -0,0 +1,230 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef DRIVER_H
+#define DRIVER_H
+
+#include "ast.h"
+
+#include <qpair.h>
+#include <qvaluestack.h>
+#include <qstringlist.h>
+#include <qmap.h>
+
+class Lexer;
+class Parser;
+
+class Problem
+{
+public:
+ enum
+ {
+ Level_Error = 0,
+ Level_Warning,
+ Level_Todo,
+ Level_Fixme
+ };
+
+public:
+ Problem() {}
+ Problem( const Problem& source )
+ : m_text( source.m_text ), m_line( source.m_line ),
+ m_column( source.m_column ), m_level( source.m_level ) {}
+ Problem( const QString& text, int line, int column, int level=Level_Error )
+ : m_text( text ), m_line( line ), m_column( column ), m_level(level) {}
+
+ Problem& operator = ( const Problem& source )
+ {
+ m_text = source.m_text;
+ m_line = source.m_line;
+ m_column = source.m_column;
+ m_level = source.m_level;
+ return( *this );
+ }
+
+ bool operator == ( const Problem& p ) const
+ {
+ return m_text == p.m_text && m_line == p.m_line && m_column == p.m_column && m_level == p.m_level;
+ }
+
+ QString text() const { return m_text; }
+ int line() const { return m_line; }
+ int column() const { return m_column; }
+ int level() const { return m_level; }
+
+private:
+ QString m_text;
+ int m_line;
+ int m_column;
+ int m_level;
+};
+
+enum
+{
+ Dep_Global,
+ Dep_Local
+};
+
+typedef QPair<QString, int> Dependence;
+
+class Macro
+{
+public:
+ typedef QString Argument;
+
+public:
+ Macro( bool hasArguments = false ): m_hasArguments( hasArguments ) {}
+ Macro( const QString &n, const QString &b ) : m_name( n ), m_body( b ), m_hasArguments( false ) {}
+
+ Macro( const Macro& source )
+ : m_name( source.m_name),
+ m_fileName( source.m_fileName ),
+ m_body( source.m_body ),
+ m_hasArguments( source.m_hasArguments ),
+ m_argumentList( source.m_argumentList ) {}
+
+ Macro& operator = ( const Macro& source )
+ {
+ m_name = source.m_name;
+ m_body = source.m_body;
+ m_fileName = source.m_fileName;
+ m_hasArguments = source.m_hasArguments;
+ m_argumentList = source.m_argumentList;
+ return *this;
+ }
+
+ bool operator == ( const Macro& source ) const
+ {
+ return
+ m_name == source.m_name &&
+ m_fileName == source.m_fileName &&
+ m_body == source.m_body &&
+ m_hasArguments == source.m_hasArguments &&
+ m_argumentList == source.m_argumentList;
+ }
+
+ QString name() const { return m_name; }
+ void setName( const QString& name ) { m_name = name; }
+
+ QString fileName() const { return m_fileName; }
+ void setFileName( const QString& fileName ) { m_fileName = fileName; }
+
+ QString body() const { return m_body; }
+ void setBody( const QString& body ) { m_body = body; }
+
+ bool hasArguments() const { return m_hasArguments; }
+ void setHasArguments( bool hasArguments ) { m_hasArguments = hasArguments; }
+ QValueList<Argument> argumentList() const { return m_argumentList; }
+
+ void clearArgumentList() { m_argumentList.clear(); m_hasArguments = false; }
+ void addArgument( const Argument& argument ) { m_argumentList << argument; }
+ void addArgumentList( const QValueList<Argument>& arguments ) { m_argumentList += arguments; }
+
+private:
+ QString m_name;
+ QString m_fileName;
+ QString m_body;
+ bool m_hasArguments;
+ QValueList<Argument> m_argumentList;
+};
+
+class SourceProvider
+{
+public:
+ SourceProvider() {}
+ virtual ~SourceProvider() {}
+
+ virtual QString contents( const QString& fileName ) = 0;
+ virtual bool isModified( const QString& fileName ) = 0;
+
+private:
+ SourceProvider( const SourceProvider& source );
+ void operator = ( const SourceProvider& source );
+};
+
+class Driver
+{
+public:
+ Driver();
+ virtual ~Driver();
+
+ SourceProvider* sourceProvider();
+ void setSourceProvider( SourceProvider* sourceProvider );
+
+ virtual void reset();
+
+ virtual void parseFile( const QString& fileName, bool onlyPreProcesss=false, bool force=false );
+ virtual void fileParsed( const QString& fileName );
+ virtual void remove( const QString& fileName );
+
+ virtual void addDependence( const QString& fileName, const Dependence& dep );
+ virtual void addMacro( const Macro& macro );
+ virtual void addProblem( const QString& fileName, const Problem& problem );
+
+
+ QString currentFileName() const { return m_currentFileName; }
+ TranslationUnitAST::Node takeTranslationUnit( const QString& fileName );
+ TranslationUnitAST* translationUnit( const QString& fileName ) const;
+ QMap<QString, Dependence> dependences( const QString& fileName ) const;
+ QMap<QString, Macro> macros() const;
+ QValueList<Problem> problems( const QString& fileName ) const;
+
+ bool hasMacro( const QString& name ) const { return m_macros.contains( name ); }
+ const Macro& macro( const QString& name ) const { return m_macros[ name ]; }
+ Macro& macro( const QString& name ) { return m_macros[ name ]; }
+
+ virtual void removeMacro( const QString& macroName );
+ virtual void removeAllMacrosInFile( const QString& fileName );
+
+ QStringList includePaths() const { return m_includePaths; }
+ virtual void addIncludePath( const QString &path );
+
+ /// @todo remove
+ const QMap<QString, TranslationUnitAST*> &parsedUnits() const { return m_parsedUnits; }
+
+ virtual void setResolveDependencesEnabled( bool enabled );
+ bool isResolveDependencesEnabled() const { return depresolv; }
+
+protected:
+ virtual void setupLexer( Lexer* lexer );
+ virtual void setupParser( Parser* parser );
+ virtual void setupPreProcessor();
+
+private:
+ QMap<QString, Dependence>& findOrInsertDependenceList( const QString& fileName );
+ QValueList<Problem>& findOrInsertProblemList( const QString& fileName );
+ QString findIncludeFile( const Dependence& dep ) const;
+
+private:
+ QString m_currentFileName;
+ QMap< QString, QMap<QString, Dependence> > m_dependences;
+ QMap<QString, Macro> m_macros;
+ QMap< QString, QValueList<Problem> > m_problems;
+ QMap<QString, TranslationUnitAST*> m_parsedUnits;
+ QStringList m_includePaths;
+ uint depresolv : 1;
+ Lexer *lexer;
+ SourceProvider* m_sourceProvider;
+
+private:
+ Driver( const Driver& source );
+ void operator = ( const Driver& source );
+};
+
+#endif
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/errors.cpp b/umbrello/umbrello/codeimport/kdevcppparser/errors.cpp
new file mode 100644
index 00000000..154301c6
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/errors.cpp
@@ -0,0 +1,25 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "errors.h"
+#include <klocale.h>
+
+QT_STATIC_CONST_IMPL Error& Errors::InternalError = Error( 1, -1, i18n("Internal Error") );
+QT_STATIC_CONST_IMPL Error& Errors::SyntaxError = Error( 2, -1, i18n("Syntax Error before '%1'") );
+QT_STATIC_CONST_IMPL Error& Errors::ParseError = Error( 3, -1, i18n("Parse Error before '%1'") );
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/errors.h b/umbrello/umbrello/codeimport/kdevcppparser/errors.h
new file mode 100644
index 00000000..f846533d
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/errors.h
@@ -0,0 +1,45 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef ERRORS_H
+#define ERRORS_H
+
+#include <qstring.h>
+
+
+struct Error{
+ int code;
+ int level;
+ QString text;
+
+ Error( int c, int l, const QString& s )
+ : code( c ), level( l ), text( s )
+ {}
+};
+
+class Errors{
+public:
+ QT_STATIC_CONST Error& InternalError;
+ QT_STATIC_CONST Error& SyntaxError;
+ QT_STATIC_CONST Error& ParseError;
+};
+
+
+
+#endif
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/keywords.lut.h b/umbrello/umbrello/codeimport/kdevcppparser/keywords.lut.h
new file mode 100644
index 00000000..5c276953
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/keywords.lut.h
@@ -0,0 +1,123 @@
+/* Automatically generated from keywords.table using /home/roberto/src/kdelibs/kjs/create_hash_table. DO NOT EDIT ! */
+
+
+static const struct HashEntry keywordEntries[] = {
+ { "template", Token_template, 0, 0, 0 },
+ { "emit", Token_emit, 0, 0, &keywordEntries[88] },
+ { "long", Token_long, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "void", Token_void, 0, 0, &keywordEntries[113] },
+ { 0, 0, 0, 0, 0 },
+ { "explicit", Token_explicit, 0, 0, &keywordEntries[100] },
+ { "enum", Token_enum, 0, 0, &keywordEntries[105] },
+ { 0, 0, 0, 0, 0 },
+ { "continue", Token_continue, 0, 0, &keywordEntries[99] },
+ { "k_dcop_signals", Token_k_dcop_signals, 0, 0, &keywordEntries[104] },
+ { "auto", Token_auto, 0, 0, &keywordEntries[91] },
+ { 0, 0, 0, 0, 0 },
+ { "Q_OBJECT", Token_Q_OBJECT, 0, 0, &keywordEntries[86] },
+ { "and_eq", Token_and_eq, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "operator", Token_operator, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "class", Token_class, 0, 0, &keywordEntries[90] },
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "while", Token_while, 0, 0, 0 },
+ { "k_dcop", Token_k_dcop, 0, 0, 0 },
+ { "compl", Token_compl, 0, 0, 0 },
+ { "bitand", Token_bitand, 0, 0, &keywordEntries[97] },
+ { "__int64", Token_int, 0, 0, &keywordEntries[89] },
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "bitor", Token_bitor, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "friend", Token_friend, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "signed", Token_signed, 0, 0, 0 },
+ { "double", Token_double, 0, 0, 0 },
+ { "K_DCOP", Token_K_DCOP, 0, 0, &keywordEntries[111] },
+ { "const", Token_const, 0, 0, &keywordEntries[92] },
+ { 0, 0, 0, 0, 0 },
+ { "inline", Token_inline, 0, 0, &keywordEntries[98] },
+ { 0, 0, 0, 0, 0 },
+ { "do", Token_do, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "const_cast", Token_const_cast, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "not_eq", Token_not_eq, 0, 0, &keywordEntries[102] },
+ { 0, 0, 0, 0, 0 },
+ { "static", Token_static, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "throw", Token_throw, 0, 0, 0 },
+ { "slots", Token_slots, 0, 0, &keywordEntries[87] },
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "static_cast", Token_static_cast, 0, 0, &keywordEntries[115] },
+ { "default", Token_default, 0, 0, &keywordEntries[95] },
+ { "sizeof", Token_sizeof, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "switch", Token_switch, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "mutable", Token_mutable, 0, 0, 0 },
+ { "dynamic_cast", Token_dynamic_cast, 0, 0, 0 },
+ { "extern", Token_extern, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "asm", Token_asm, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "signals", Token_signals, 0, 0, &keywordEntries[106] },
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "case", Token_case, 0, 0, 0 },
+ { "for", Token_for, 0, 0, 0 },
+ { "char", Token_char, 0, 0, &keywordEntries[101] },
+ { 0, 0, 0, 0, 0 },
+ { "export", Token_export, 0, 0, &keywordEntries[94] },
+ { "int", Token_int, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "private", Token_private, 0, 0, &keywordEntries[103] },
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "not", Token_not, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "else", Token_else, 0, 0, &keywordEntries[93] },
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "bool", Token_bool, 0, 0, 0 },
+ { "catch", Token_catch, 0, 0, 0 },
+ { "__asm__", Token_asm, 0, 0, 0 },
+ { "and", Token_and, 0, 0, 0 },
+ { "break", Token_break, 0, 0, &keywordEntries[110] },
+ { "delete", Token_delete, 0, 0, 0 },
+ { "float", Token_float, 0, 0, &keywordEntries[96] },
+ { "goto", Token_goto, 0, 0, 0 },
+ { "if", Token_if, 0, 0, 0 },
+ { "namespace", Token_namespace, 0, 0, 0 },
+ { "new", Token_new, 0, 0, 0 },
+ { "or", Token_or, 0, 0, &keywordEntries[107] },
+ { "or_eq", Token_or_eq, 0, 0, 0 },
+ { "protected", Token_protected, 0, 0, 0 },
+ { "public", Token_public, 0, 0, &keywordEntries[109] },
+ { "register", Token_register, 0, 0, 0 },
+ { "reinterpret_cast", Token_reinterpret_cast, 0, 0, 0 },
+ { "return", Token_return, 0, 0, 0 },
+ { "short", Token_short, 0, 0, 0 },
+ { "struct", Token_struct, 0, 0, 0 },
+ { "this", Token_this, 0, 0, 0 },
+ { "try", Token_try, 0, 0, &keywordEntries[108] },
+ { "typedef", Token_typedef, 0, 0, 0 },
+ { "typeid", Token_typeid, 0, 0, 0 },
+ { "typename", Token_typename, 0, 0, 0 },
+ { "union", Token_union, 0, 0, 0 },
+ { "unsigned", Token_unsigned, 0, 0, &keywordEntries[112] },
+ { "using", Token_using, 0, 0, 0 },
+ { "virtual", Token_virtual, 0, 0, &keywordEntries[114] },
+ { "volatile", Token_volatile, 0, 0, 0 },
+ { "xor", Token_xor, 0, 0, 0 },
+ { "xor_eq", Token_xor_eq, 0, 0, 0 }
+};
+
+static const struct HashTable keyword = { 2, 116, keywordEntries, 86 };
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/lexer.cpp b/umbrello/umbrello/codeimport/kdevcppparser/lexer.cpp
new file mode 100644
index 00000000..2748688f
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/lexer.cpp
@@ -0,0 +1,1002 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "lexer.h"
+#include "lookup.h"
+#include "keywords.lut.h"
+
+#include <kdebug.h>
+#include <klocale.h>
+
+#include <qregexp.h>
+#include <qmap.h>
+#include <qvaluelist.h>
+
+#if defined( KDEVELOP_BGPARSER )
+#include <qthread.h>
+
+class KDevTread: public QThread
+{
+public:
+ static void yield()
+ {
+ msleep( 0 );
+ }
+};
+
+inline void qthread_yield()
+{
+ KDevTread::yield();
+}
+
+#endif
+
+#define CREATE_TOKEN(type, start, len) Token( (type), (start), (len), m_source )
+#define ADD_TOKEN(tk) m_tokens.insert( m_size++, new Token(tk) );
+
+using namespace std;
+
+struct LexerData
+{
+ typedef QMap<QString, QString> Scope;
+ typedef QValueList<Scope> StaticChain;
+
+ StaticChain staticChain;
+
+ void beginScope()
+ {
+ Scope scope;
+ staticChain.push_front( scope );
+ }
+
+ void endScope()
+ {
+ staticChain.pop_front();
+ }
+
+ void bind( const QString& name, const QString& value )
+ {
+ Q_ASSERT( staticChain.size() > 0 );
+ staticChain.front().insert( name, value );
+ }
+
+ bool hasBind( const QString& name ) const
+ {
+ StaticChain::ConstIterator it = staticChain.begin();
+ while( it != staticChain.end() ){
+ const Scope& scope = *it;
+ ++it;
+
+ if( scope.contains(name) )
+ return true;
+ }
+
+ return false;
+ }
+
+ QString apply( const QString& name ) const
+ {
+ StaticChain::ConstIterator it = staticChain.begin();
+ while( it != staticChain.end() ){
+ const Scope& scope = *it;
+ ++it;
+
+ if( scope.contains(name) )
+ return scope[ name ];
+ }
+
+ return QString::null;
+ }
+
+};
+
+Lexer::Lexer( Driver* driver )
+ : d( new LexerData),
+ m_driver( driver ),
+ m_recordComments( false ),
+ m_recordWhiteSpaces( false ),
+ m_skipWordsEnabled( true ),
+ m_preprocessorEnabled( true ),
+ m_reportWarnings( false ),
+ m_reportMessages( false )
+{
+ m_tokens.setAutoDelete( true );
+ reset();
+ d->beginScope();
+}
+
+Lexer::~Lexer()
+{
+ d->endScope();
+ delete( d );
+}
+
+void Lexer::setSource( const QString& source )
+{
+ reset();
+ m_source = source;
+ m_ptr = 0;
+ m_endPtr = m_source.length();
+ m_inPreproc = false;
+
+ tokenize();
+}
+
+void Lexer::reset()
+{
+ m_index = 0;
+ m_size = 0;
+ m_tokens.clear();
+ m_source = QString::null;
+ m_ptr = 0;
+ m_endPtr = 0;
+ m_startLine = false;
+ m_ifLevel = 0;
+ m_skipping.resize( 200 );
+ m_skipping.fill( 0 );
+ m_trueTest.resize( 200 );
+ m_trueTest.fill( 0 );
+
+ m_currentLine = 0;
+ m_currentColumn = 0;
+}
+
+// ### should all be done with a "long" type IMO
+int Lexer::toInt( const Token& token )
+{
+ QString s = token.text();
+ if( token.type() == Token_number_literal ){
+ // hex literal ?
+ if( s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
+ return s.mid( 2 ).toInt( 0, 16 );
+ QString n;
+ int i = 0;
+ while( i < int(s.length()) && s[i].isDigit() )
+ n += s[i++];
+ // ### respect more prefixes and suffixes ?
+ return n.toInt();
+ } else if( token.type() == Token_char_literal ){
+ int i = s[0] == 'L' ? 2 : 1; // wide char ?
+ if( s[i] == '\\' ){
+ // escaped char
+ int c = s[i+1].unicode();
+ switch( c ) {
+ case '0':
+ return 0;
+ case 'n':
+ return '\n';
+ // ### more
+ default:
+ return c;
+ }
+ } else {
+ return s[i].unicode();
+ }
+ } else {
+ return 0;
+ }
+}
+
+void Lexer::getTokenPosition( const Token& token, int* line, int* col )
+{
+ token.getStartPosition( line, col );
+}
+
+void Lexer::nextToken( Token& tk, bool stopOnNewline )
+{
+ int op = 0;
+
+ if( m_size == (int)m_tokens.size() ){
+ m_tokens.resize( m_tokens.size() + 5000 );
+ }
+
+ readWhiteSpaces( !stopOnNewline );
+
+ int startLine = m_currentLine;
+ int startColumn = m_currentColumn;
+
+ QChar ch = currentChar();
+ QChar ch1 = peekChar();
+
+ if( ch.isNull() || ch.isSpace() ){
+ /* skip */
+ } else if( m_startLine && ch == '#' ){
+
+ nextChar(); // skip #
+ readWhiteSpaces( false ); // skip white spaces
+ m_startLine = false;
+
+ int start = currentPosition();
+ readIdentifier(); // read the directive
+ QString directive = m_source.mid( start, currentPosition() - start );
+
+ handleDirective( directive );
+ } else if( m_startLine && m_skipping[ m_ifLevel ] ){
+ // skip line and continue
+ m_startLine = false;
+ int ppe = preprocessorEnabled();
+ setPreprocessorEnabled( false );
+ while( currentChar() && currentChar() != '\n' ){
+ Token tok;
+ nextToken( tok, true );
+ }
+ m_startLine = true;
+ setPreprocessorEnabled( ppe );
+ return;
+ } else if( ch == '/' && ch1 == '/' ){
+ int start = currentPosition();
+ readLineComment();
+ if( recordComments() ){
+ tk = CREATE_TOKEN( Token_comment, start, currentPosition() - start );
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ }
+ } else if( ch == '/' && ch1 == '*' ){
+ int start = currentPosition();
+ nextChar( 2 );
+ readMultiLineComment();
+
+ if( recordComments() ){
+ tk = CREATE_TOKEN( Token_comment, start, currentPosition() - start );
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ }
+ } else if( ch == '\'' || (ch == 'L' && ch1 == '\'') ){
+ int start = currentPosition();
+ readCharLiteral();
+ tk = CREATE_TOKEN( Token_char_literal, start, currentPosition() - start );
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ } else if( ch == '"' ){
+ int start = currentPosition();
+ readStringLiteral();
+ tk = CREATE_TOKEN( Token_string_literal, start, currentPosition() - start );
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ } else if( ch.isLetter() || ch == '_' ){
+ int start = currentPosition();
+ readIdentifier();
+ QString ide = m_source.mid( start, currentPosition() - start );
+ int k = Lookup::find( &keyword, ide );
+ if( m_preprocessorEnabled && m_driver->hasMacro(ide) &&
+ (k == -1 || !m_driver->macro(ide).body().isEmpty()) ){
+
+
+ bool preproc = m_preprocessorEnabled;
+ m_preprocessorEnabled = false;
+
+ d->beginScope();
+
+ int svLine = currentLine();
+ int svColumn = currentColumn();
+
+// Macro& m = m_driver->macro( ide );
+ Macro m = m_driver->macro( ide );
+ //m_driver->removeMacro( m.name() );
+
+ QString ellipsisArg;
+
+ if( m.hasArguments() ){
+ int endIde = currentPosition();
+
+ readWhiteSpaces();
+ if( currentChar() == '(' ){
+ nextChar();
+ int argIdx = 0;
+ int argCount = m.argumentList().size();
+ while( currentChar() && argIdx<argCount ){
+ readWhiteSpaces();
+
+ QString argName = m.argumentList()[ argIdx ];
+
+ bool ellipsis = argName == "...";
+
+ QString arg = readArgument();
+
+ if( !ellipsis )
+ d->bind( argName, arg );
+ else
+ ellipsisArg += arg;
+
+ if( currentChar() == ',' ){
+ nextChar();
+ if( !ellipsis ){
+ ++argIdx;
+ } else {
+ ellipsisArg += ", ";
+ }
+ } else if( currentChar() == ')' ){
+ break;
+ }
+ }
+ if( currentChar() == ')' ){
+ // valid macro
+ nextChar();
+ }
+ } else {
+ tk = CREATE_TOKEN( Token_identifier, start, endIde - start );
+ tk.setStartPosition( svLine, svColumn );
+ tk.setEndPosition( svLine, svColumn + (endIde - start) );
+
+ m_startLine = false;
+
+ d->endScope(); // OPS!!
+ m_preprocessorEnabled = preproc;
+ return;
+ }
+ }
+
+ int argsEndAtLine = currentLine();
+ int argsEndAtColumn = currentColumn();
+
+#if defined( KDEVELOP_BGPARSER )
+ qthread_yield();
+#endif
+ m_source.insert( currentPosition(), m.body() );
+
+ // tokenize the macro body
+
+ QString textToInsert;
+
+ m_endPtr = currentPosition() + m.body().length();
+ while( currentChar() ){
+
+ readWhiteSpaces();
+
+ Token tok;
+ nextToken( tok );
+
+ bool stringify = !m_inPreproc && tok == '#';
+ bool merge = !m_inPreproc && tok == Token_concat;
+
+ if( stringify || merge )
+ nextToken( tok );
+
+ if( tok == Token_eof )
+ break;
+
+ QString tokText = tok.text();
+ QString str = (tok == Token_identifier && d->hasBind(tokText)) ? d->apply( tokText ) : tokText;
+ if( str == ide ){
+ //Problem p( i18n("unsafe use of macro '%1'").arg(ide), m_currentLine, m_currentColumn );
+ //m_driver->addProblem( m_driver->currentFileName(), p );
+ m_driver->removeMacro( ide );
+ // str = QString::null;
+ }
+
+ if( stringify ) {
+ textToInsert.append( QString::fromLatin1("\"") + str + QString::fromLatin1("\" ") );
+ } else if( merge ){
+ textToInsert.truncate( textToInsert.length() - 1 );
+ textToInsert.append( str );
+ } else if( tok == Token_ellipsis && d->hasBind("...") ){
+ textToInsert.append( ellipsisArg );
+ } else {
+ textToInsert.append( str + QString::fromLatin1(" ") );
+ }
+ }
+
+#if defined( KDEVELOP_BGPARSER )
+ qthread_yield();
+#endif
+ m_source.insert( currentPosition(), textToInsert );
+
+ d->endScope();
+ m_preprocessorEnabled = preproc;
+ //m_driver->addMacro( m );
+ m_currentLine = argsEndAtLine;
+ m_currentColumn = argsEndAtColumn;
+ m_endPtr = m_source.length();
+ } else if( k != -1 ){
+ tk = CREATE_TOKEN( k, start, currentPosition() - start );
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ } else if( m_skipWordsEnabled ){
+ QMap< QString, QPair<SkipType, QString> >::Iterator pos = m_words.find( ide );
+ if( pos != m_words.end() ){
+ if( (*pos).first == SkipWordAndArguments ){
+ readWhiteSpaces();
+ if( currentChar() == '(' )
+ skip( '(', ')' );
+ }
+ if( !(*pos).second.isEmpty() ){
+#if defined( KDEVELOP_BGPARSER )
+ qthread_yield();
+#endif
+ m_source.insert( currentPosition(), QString(" ") + (*pos).second + QString(" ") );
+ m_endPtr = m_source.length();
+ }
+ } else if( /*qt_rx.exactMatch(ide) ||*/
+ ide.endsWith("EXPORT") ||
+ (ide.startsWith("Q_EXPORT") && ide != "Q_EXPORT_INTERFACE") ||
+ ide.startsWith("QM_EXPORT") ||
+ ide.startsWith("QM_TEMPLATE")){
+
+ readWhiteSpaces();
+ if( currentChar() == '(' )
+ skip( '(', ')' );
+ } else if( ide.startsWith("K_TYPELIST_") || ide.startsWith("TYPELIST_") ){
+ tk = CREATE_TOKEN( Token_identifier, start, currentPosition() - start );
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ readWhiteSpaces();
+ if( currentChar() == '(' )
+ skip( '(', ')' );
+ } else{
+ tk = CREATE_TOKEN( Token_identifier, start, currentPosition() - start );
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ }
+ } else {
+ tk = CREATE_TOKEN( Token_identifier, start, currentPosition() - start );
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ }
+ } else if( ch.isNumber() ){
+ int start = currentPosition();
+ readNumberLiteral();
+ tk = CREATE_TOKEN( Token_number_literal, start, currentPosition() - start );
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ } else if( -1 != (op = findOperator3()) ){
+ tk = CREATE_TOKEN( op, currentPosition(), 3 );
+ nextChar( 3 );
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ } else if( -1 != (op = findOperator2()) ){
+ tk = CREATE_TOKEN( op, currentPosition(), 2 );
+ nextChar( 2 );
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ } else {
+ tk = CREATE_TOKEN( ch.unicode(), currentPosition(), 1 );
+ nextChar();
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ }
+
+ m_startLine = false;
+}
+
+
+void Lexer::tokenize()
+{
+ m_startLine = true;
+ m_size = 0;
+
+ for( ;; ) {
+ Token tk;
+ nextToken( tk );
+
+ if( tk.type() != -1 )
+ ADD_TOKEN( tk );
+
+ if( currentChar().isNull() )
+ break;
+ }
+
+ Token tk = CREATE_TOKEN( Token_eof, currentPosition(), 0 );
+ tk.setStartPosition( m_currentLine, m_currentColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ ADD_TOKEN( tk );
+}
+
+void Lexer::resetSkipWords()
+{
+ m_words.clear();
+}
+
+void Lexer::addSkipWord( const QString& word, SkipType skipType, const QString& str )
+{
+ m_words[ word ] = qMakePair( skipType, str );
+}
+
+void Lexer::skip( int l, int r )
+{
+ int svCurrentLine = m_currentLine;
+ int svCurrentColumn = m_currentColumn;
+
+ int count = 0;
+
+ while( !eof() ){
+ Token tk;
+ nextToken( tk );
+
+ if( (int)tk == l )
+ ++count;
+ else if( (int)tk == r )
+ --count;
+
+ if( count == 0 )
+ break;
+ }
+
+ m_currentLine = svCurrentLine;
+ m_currentColumn = svCurrentColumn;
+}
+
+QString Lexer::readArgument()
+{
+ int count = 0;
+
+ QString arg;
+
+ readWhiteSpaces();
+ while( currentChar() ){
+
+ readWhiteSpaces();
+ QChar ch = currentChar();
+
+ if( ch.isNull() || (!count && (ch == ',' || ch == ')')) )
+ break;
+
+ Token tk;
+ nextToken( tk );
+
+ if( tk == '(' ){
+ ++count;
+ } else if( tk == ')' ){
+ --count;
+ }
+
+ if( tk != -1 )
+ arg += tk.text() + ' ';
+ }
+
+ return arg.stripWhiteSpace();
+}
+
+void Lexer::handleDirective( const QString& directive )
+{
+ m_inPreproc = true;
+
+ bool skip = skipWordsEnabled();
+ bool preproc = preprocessorEnabled();
+
+ setSkipWordsEnabled( false );
+ setPreprocessorEnabled( false );
+
+ if( directive == "define" ){
+ if( !m_skipping[ m_ifLevel ] ){
+ Macro m;
+ processDefine( m );
+ }
+ } else if( directive == "else" ){
+ processElse();
+ } else if( directive == "elif" ){
+ processElif();
+ } else if( directive == "endif" ){
+ processEndif();
+ } else if( directive == "if" ){
+ processIf();
+ } else if( directive == "ifdef" ){
+ processIfdef();
+ } else if( directive == "ifndef" ){
+ processIfndef();
+ } else if( directive == "include" ){
+ if( !m_skipping[ m_ifLevel ] ){
+ processInclude();
+ }
+ } else if( directive == "undef" ){
+ if( !m_skipping[ m_ifLevel ] ){
+ processUndef();
+ }
+ }
+
+ // skip line
+ while( currentChar() && currentChar() != '\n' ){
+ Token tk;
+ nextToken( tk, true );
+ }
+
+ setSkipWordsEnabled( skip );
+ setPreprocessorEnabled( preproc );
+
+ m_inPreproc = false;
+}
+
+int Lexer::testIfLevel()
+{
+ int rtn = !m_skipping[ m_ifLevel++ ];
+ m_skipping[ m_ifLevel ] = m_skipping[ m_ifLevel - 1 ];
+ return rtn;
+}
+
+int Lexer::macroDefined()
+{
+ readWhiteSpaces( false );
+ int startWord = currentPosition();
+ readIdentifier();
+ QString word = m_source.mid( startWord, currentPosition() - startWord );
+ bool r = m_driver->hasMacro( word );
+
+ return r;
+}
+
+void Lexer::processDefine( Macro& m )
+{
+ m.setFileName( m_driver->currentFileName() );
+ readWhiteSpaces( false );
+
+ int startMacroName = currentPosition();
+ readIdentifier();
+ QString macroName = m_source.mid( startMacroName, int(currentPosition()-startMacroName) );
+ m_driver->removeMacro( macroName );
+ m.setName( macroName );
+
+ if( currentChar() == '(' ){
+ m.setHasArguments( true );
+ nextChar();
+
+ readWhiteSpaces( false );
+
+ while( currentChar() && currentChar() != ')' ){
+ readWhiteSpaces( false );
+
+ int startArg = currentPosition();
+
+ if( currentChar() == '.' && peekChar() == '.' && peekChar(2) == '.' )
+ nextChar( 3 );
+ else
+ readIdentifier();
+
+ QString arg = m_source.mid( startArg, int(currentPosition()-startArg) );
+
+ m.addArgument( Macro::Argument(arg) );
+
+ readWhiteSpaces( false );
+ if( currentChar() != ',' )
+ break;
+
+ nextChar(); // skip ','
+ }
+
+ if( currentChar() == ')' )
+ nextChar(); // skip ')'
+ }
+
+ setPreprocessorEnabled( true );
+
+ QString body;
+ while( currentChar() && currentChar() != '\n' ){
+
+ if( currentChar().isSpace() ){
+ readWhiteSpaces( false );
+ body += ' ';
+ } else {
+
+ Token tk;
+ nextToken( tk, true );
+
+ if( tk.type() != -1 ){
+ QString s = tk.text();
+ body += s;
+ }
+ }
+ }
+
+ m.setBody( body );
+ m_driver->addMacro( m );
+}
+
+void Lexer::processElse()
+{
+ if( m_ifLevel == 0 )
+ /// @todo report error
+ return;
+
+ if( m_ifLevel > 0 && m_skipping[m_ifLevel-1] )
+ m_skipping[ m_ifLevel ] = m_skipping[ m_ifLevel - 1 ];
+ else
+ m_skipping[ m_ifLevel ] = m_trueTest[ m_ifLevel ];
+}
+
+void Lexer::processElif()
+{
+ if( m_ifLevel == 0 )
+ /// @todo report error
+ return;
+
+ if( !m_trueTest[m_ifLevel] ){
+ /// @todo implement the correct semantic for elif!!
+ bool inSkip = m_ifLevel > 0 && m_skipping[ m_ifLevel-1 ];
+ m_trueTest[ m_ifLevel ] = macroExpression() != 0;
+ m_skipping[ m_ifLevel ] = inSkip ? inSkip : !m_trueTest[ m_ifLevel ];
+ }
+ else
+ m_skipping[ m_ifLevel ] = true;
+}
+
+void Lexer::processEndif()
+{
+ if( m_ifLevel == 0 )
+ /// @todo report error
+ return;
+
+ m_skipping[ m_ifLevel ] = 0;
+ m_trueTest[ m_ifLevel-- ] = 0;
+}
+
+void Lexer::processIf()
+{
+ bool inSkip = m_skipping[ m_ifLevel ];
+
+ if( testIfLevel() ) {
+#if 0
+ int n;
+ if( (n = testDefined()) != 0 ) {
+ int isdef = macroDefined();
+ m_trueTest[ m_ifLevel ] = (n == 1 && isdef) || (n == -1 && !isdef);
+ } else
+#endif
+ m_trueTest[ m_ifLevel ] = macroExpression() != 0;
+ m_skipping[ m_ifLevel ] = inSkip ? inSkip : !m_trueTest[ m_ifLevel ];
+ }
+}
+
+void Lexer::processIfdef()
+{
+ bool inSkip = m_skipping[ m_ifLevel ];
+
+ if( testIfLevel() ){
+ m_trueTest[ m_ifLevel ] = macroDefined();
+ m_skipping[ m_ifLevel ] = inSkip ? inSkip : !m_trueTest[ m_ifLevel ];
+ }
+}
+
+void Lexer::processIfndef()
+{
+ bool inSkip = m_skipping[ m_ifLevel ];
+
+ if( testIfLevel() ){
+ m_trueTest[ m_ifLevel ] = !macroDefined();
+ m_skipping[ m_ifLevel ] = inSkip ? inSkip : !m_trueTest[ m_ifLevel ];
+ }
+}
+
+void Lexer::processInclude()
+{
+ if( m_skipping[m_ifLevel] )
+ return;
+
+ readWhiteSpaces( false );
+ if( currentChar() ){
+ QChar ch = currentChar();
+ if( ch == '"' || ch == '<' ){
+ nextChar();
+ QChar ch2 = ch == QChar('"') ? QChar('"') : QChar('>');
+
+ int startWord = currentPosition();
+ while( currentChar() && currentChar() != ch2 )
+ nextChar();
+ if( currentChar() ){
+ QString word = m_source.mid( startWord, int(currentPosition()-startWord) );
+ m_driver->addDependence( m_driver->currentFileName(),
+ Dependence(word, ch == '"' ? Dep_Local : Dep_Global) );
+ nextChar();
+ }
+ }
+ }
+}
+
+void Lexer::processUndef()
+{
+ readWhiteSpaces();
+ int startWord = currentPosition();
+ readIdentifier();
+ QString word = m_source.mid( startWord, currentPosition() - startWord );
+ m_driver->removeMacro( word );
+}
+
+int Lexer::macroPrimary()
+{
+ readWhiteSpaces( false );
+ int result = 0;
+ switch( currentChar().unicode() ) {
+ case '(':
+ nextChar();
+ result = macroExpression();
+ if( currentChar() != ')' ){
+ /// @todo report error
+ return 0;
+ }
+ nextChar();
+ return result;
+
+ case '+':
+ case '-':
+ case '!':
+ case '~':
+ {
+ QChar tk = currentChar();
+ nextChar();
+ int result = macroPrimary();
+ if( tk == '-' ) return -result;
+ else if( tk == '!' ) return !result;
+ else if( tk == '~' ) return ~result;
+ }
+ break;
+
+ default:
+ {
+ Token tk;
+ nextToken( tk, false );
+ switch( tk.type() ){
+ case Token_identifier:
+ if( tk.text() == "defined" ){
+ return macroPrimary();
+ }
+ /// @todo implement
+ return m_driver->hasMacro( tk.text() );
+ case Token_number_literal:
+ case Token_char_literal:
+ return toInt( tk );
+ default:
+ break;
+ } // end switch
+
+ } // end default
+
+ } // end switch
+
+ return 0;
+}
+
+int Lexer::macroMultiplyDivide()
+{
+ int result = macroPrimary();
+ int iresult, op;
+ for (;;) {
+ readWhiteSpaces( false );
+ if( currentChar() == '*' )
+ op = 0;
+ else if( currentChar() == '/' && !(peekChar() == '*' || peekChar() == '/') )
+ op = 1;
+ else if( currentChar() == '%' )
+ op = 2;
+ else
+ break;
+ nextChar();
+ iresult = macroPrimary();
+ result = op == 0 ? (result * iresult) :
+ op == 1 ? (iresult == 0 ? 0 : (result / iresult)) :
+ (iresult == 0 ? 0 : (result % iresult)) ;
+ }
+ return result;
+}
+
+int Lexer::macroAddSubtract()
+{
+ int result = macroMultiplyDivide();
+ int iresult, ad;
+ readWhiteSpaces( false );
+ while( currentChar() == '+' || currentChar() == '-') {
+ ad = currentChar() == '+';
+ nextChar();
+ iresult = macroMultiplyDivide();
+ result = ad ? (result+iresult) : (result-iresult);
+ }
+ return result;
+}
+
+int Lexer::macroRelational()
+{
+ int result = macroAddSubtract();
+ int iresult;
+ readWhiteSpaces( false );
+ while( currentChar() == '<' || currentChar() == '>') {
+ int lt = currentChar() == '<';
+ nextChar();
+ if( currentChar() == '=') {
+ nextChar();
+
+ iresult = macroAddSubtract();
+ result = lt ? (result <= iresult) : (result >= iresult);
+ }
+ else {
+ iresult = macroAddSubtract();
+ result = lt ? (result < iresult) : (result > iresult);
+ }
+ }
+
+ return result;
+}
+
+int Lexer::macroEquality()
+{
+ int result = macroRelational();
+ int iresult, eq;
+ readWhiteSpaces( false );
+ while ((currentChar() == '=' || currentChar() == '!') && peekChar() == '=') {
+ eq = currentChar() == '=';
+ nextChar( 2 );
+ iresult = macroRelational();
+ result = eq ? (result==iresult) : (result!=iresult);
+ }
+ return result;
+}
+
+int Lexer::macroBoolAnd()
+{
+ int result = macroEquality();
+ readWhiteSpaces( false );
+ while( currentChar() == '&' && peekChar() != '&') {
+ nextChar();
+ result &= macroEquality();
+ }
+ return result;
+}
+
+int Lexer::macroBoolXor()
+{
+ int result = macroBoolAnd();
+ readWhiteSpaces( false );
+ while( currentChar() == '^') {
+ nextChar();
+ result ^= macroBoolAnd();
+ }
+ return result;
+}
+
+int Lexer::macroBoolOr()
+{
+ int result = macroBoolXor();
+ readWhiteSpaces( false );
+ while( currentChar() == '|' && peekChar() != '|') {
+ nextChar();
+ result |= macroBoolXor();
+ }
+ return result;
+}
+
+int Lexer::macroLogicalAnd()
+{
+ int result = macroBoolOr();
+ readWhiteSpaces( false );
+ while( currentChar() == '&' && peekChar() == '&') {
+ nextChar( 2 );
+ int start = currentPosition();
+ result = macroBoolOr() && result;
+ QString s = m_source.mid( start, currentPosition() - start );
+ }
+ return result;
+}
+
+int Lexer::macroLogicalOr()
+{
+ int result = macroLogicalAnd();
+ readWhiteSpaces( false );
+ while( currentChar() == '|' && peekChar() == '|') {
+ nextChar( 2 );
+ result = macroLogicalAnd() || result;
+ }
+ return result;
+}
+
+int Lexer::macroExpression()
+{
+ readWhiteSpaces( false );
+ return macroLogicalOr();
+}
+
+// *IMPORTANT*
+// please, don't include lexer.moc here, because Lexer isn't a QObject class!!
+// if you have problem while recompiling try to remove cppsupport/.deps,
+// cppsupport/Makefile.in and rerun automake/autoconf
+
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/lexer.h b/umbrello/umbrello/codeimport/kdevcppparser/lexer.h
new file mode 100644
index 00000000..cce951d4
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/lexer.h
@@ -0,0 +1,791 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef LEXER_H
+#define LEXER_H
+
+#include "driver.h"
+
+#include <qstring.h>
+#include <qmap.h>
+#include <qvaluestack.h>
+#include <qpair.h>
+#include <qptrvector.h>
+
+enum Type {
+ Token_eof = 0,
+ Token_identifier = 1000,
+ Token_number_literal,
+ Token_char_literal,
+ Token_string_literal,
+ Token_whitespaces,
+ Token_comment,
+ Token_preproc,
+
+ Token_assign = 2000,
+ Token_ptrmem,
+ Token_ellipsis,
+ Token_scope,
+ Token_shift,
+ Token_eq,
+ Token_leq,
+ Token_geq,
+ Token_incr,
+ Token_decr,
+ Token_arrow,
+
+ Token_concat,
+
+ Token_K_DCOP,
+ Token_k_dcop,
+ Token_k_dcop_signals,
+
+ Token_Q_OBJECT,
+ Token_signals,
+ Token_slots,
+ Token_emit,
+
+ Token_and,
+ Token_and_eq,
+ Token_asm,
+ Token_auto,
+ Token_bitand,
+ Token_bitor,
+ Token_bool,
+ Token_break,
+ Token_case,
+ Token_catch,
+ Token_char,
+ Token_class,
+ Token_compl,
+ Token_const,
+ Token_const_cast,
+ Token_continue,
+ Token_default,
+ Token_delete,
+ Token_do,
+ Token_double,
+ Token_dynamic_cast,
+ Token_else,
+ Token_enum,
+ Token_explicit,
+ Token_export,
+ Token_extern,
+ Token_false,
+ Token_float,
+ Token_for,
+ Token_friend,
+ Token_goto,
+ Token_if,
+ Token_inline,
+ Token_int,
+ Token_long,
+ Token_mutable,
+ Token_namespace,
+ Token_new,
+ Token_not,
+ Token_not_eq,
+ Token_operator,
+ Token_or,
+ Token_or_eq,
+ Token_private,
+ Token_protected,
+ Token_public,
+ Token_register,
+ Token_reinterpret_cast,
+ Token_return,
+ Token_short,
+ Token_signed,
+ Token_sizeof,
+ Token_static,
+ Token_static_cast,
+ 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_xor,
+ Token_xor_eq
+};
+
+enum SkipType {
+ SkipWord,
+ SkipWordAndArguments
+};
+
+struct LexerData;
+
+class Token
+{
+public:
+ Token();
+ Token( int type, int position, int length, const QString& text );
+ Token( const Token& source );
+
+ Token& operator = ( const Token& source );
+ bool operator == ( const Token& token ) const;
+ operator int () const;
+
+ bool isNull() const;
+
+ int type() const;
+ void setType( int type );
+
+ void getStartPosition( int* line, int* column ) const;
+ void setStartPosition( int line, int column );
+ void getEndPosition( int* line, int* column ) const;
+ void setEndPosition( int line, int column );
+
+ unsigned int length() const;
+ void setLength( unsigned int length );
+
+ int position() const;
+ void setPosition( int position );
+
+ QString text() const;
+
+private:
+ int m_type;
+ int m_position;
+ int m_length;
+ int m_startLine;
+ int m_startColumn;
+ int m_endLine;
+ int m_endColumn;
+ QString m_text;
+
+ friend class Lexer;
+ friend class Parser;
+}; // class Token
+
+class Lexer
+{
+public:
+ Lexer( Driver* driver );
+ ~Lexer();
+
+ bool recordComments() const;
+ void setRecordComments( bool record );
+
+ bool recordWhiteSpaces() const;
+ void setRecordWhiteSpaces( bool record );
+
+ bool reportWarnings() const;
+ void setReportWarnings( bool enable );
+
+ bool reportMessages() const;
+ void setReportMessages( bool enable );
+
+ bool skipWordsEnabled() const;
+ void setSkipWordsEnabled( bool enabled );
+
+ bool preprocessorEnabled() const;
+ void setPreprocessorEnabled( bool enabled );
+
+ void resetSkipWords();
+ void addSkipWord( const QString& word, SkipType skipType=SkipWord, const QString& str = QString::null );
+
+ QString source() const;
+ void setSource( const QString& source );
+
+ int index() const;
+ void setIndex( int index );
+
+ void reset();
+
+ const Token& tokenAt( int position ) const;
+ const Token& nextToken();
+ const Token& lookAhead( int n ) const;
+
+ static int toInt( const Token& token );
+
+ int tokenPosition( const Token& token ) const;
+ void getTokenPosition( const Token& token, int* line, int* col );
+
+ int currentLine() const { return m_currentLine; }
+ int currentColumn() const { return m_currentColumn; }
+
+private:
+ QChar currentChar() const;
+ QChar peekChar( int n=1 ) const;
+ int currentPosition() const;
+
+ void tokenize();
+ void nextToken( Token& token, bool stopOnNewline=false );
+ void nextChar();
+ void nextChar( int n );
+ void skip( int l, int r );
+ void readIdentifier();
+ void readWhiteSpaces( bool skipNewLine=true );
+ void readLineComment();
+ void readMultiLineComment();
+ void readCharLiteral();
+ void readStringLiteral();
+ void readNumberLiteral();
+
+ int findOperator3() const;
+ int findOperator2() const;
+ bool eof() const;
+
+ // preprocessor (based on an article of Al Stevens on Dr.Dobb's journal)
+ int testIfLevel();
+ int macroDefined();
+ QString readArgument();
+
+ int macroPrimary();
+ int macroMultiplyDivide();
+ int macroAddSubtract();
+ int macroRelational();
+ int macroEquality();
+ int macroBoolAnd();
+ int macroBoolXor();
+ int macroBoolOr();
+ int macroLogicalAnd();
+ int macroLogicalOr();
+ int macroExpression();
+
+ void handleDirective( const QString& directive );
+ void processDefine( Macro& macro );
+ void processElse();
+ void processElif();
+ void processEndif();
+ void processIf();
+ void processIfdef();
+ void processIfndef();
+ void processInclude();
+ void processUndef();
+
+private:
+ LexerData* d;
+ Driver* m_driver;
+ QPtrVector< Token > m_tokens;
+ int m_size;
+ int m_index;
+ QString m_source;
+ int m_ptr;
+ int m_endPtr;
+ bool m_recordComments;
+ bool m_recordWhiteSpaces;
+ bool m_startLine;
+ QMap< QString, QPair<SkipType, QString> > m_words;
+
+ int m_currentLine;
+ int m_currentColumn;
+ bool m_skipWordsEnabled;
+
+ // preprocessor
+ QMemArray<bool> m_skipping;
+ QMemArray<bool> m_trueTest;
+ int m_ifLevel;
+ bool m_preprocessorEnabled;
+ bool m_inPreproc;
+
+ bool m_reportWarnings;
+ bool m_reportMessages;
+
+private:
+ Lexer( const Lexer& source );
+ void operator = ( const Lexer& source );
+};
+
+
+inline Token::Token()
+ : m_type( -1 ),
+ m_position( 0 ),
+ m_length( 0 ),
+ m_text( 0 )
+{
+}
+
+inline Token::Token( int type, int position, int length, const QString& text )
+ : m_type( type ),
+ m_position( position ),
+ m_length( length ),
+ m_text( text )
+{
+}
+
+inline Token::Token( const Token& source )
+ : m_type( source.m_type ),
+ m_position( source.m_position ),
+ m_length( source.m_length ),
+ m_startLine( source.m_startLine ),
+ m_startColumn( source.m_startColumn ),
+ m_endLine( source.m_endLine ),
+ m_endColumn( source.m_endColumn ),
+ m_text( source.m_text )
+{
+}
+
+inline Token& Token::operator = ( const Token& source )
+{
+ m_type = source.m_type;
+ m_position = source.m_position;
+ m_length = source.m_length;
+ m_startLine = source.m_startLine;
+ m_startColumn = source.m_startColumn;
+ m_endLine = source.m_endLine;
+ m_endColumn = source.m_endColumn;
+ m_text = source.m_text;
+ return( *this );
+}
+
+inline Token::operator int () const
+{
+ return m_type;
+}
+
+inline bool Token::operator == ( const Token& token ) const
+{
+ return m_type == token.m_type &&
+ m_position == token.m_position &&
+ m_length == token.m_length &&
+ m_startLine == token.m_startLine &&
+ m_startColumn == token.m_startColumn &&
+ m_endLine == token.m_endLine &&
+ m_endColumn == token.m_endColumn &&
+ m_text == token.m_text;
+}
+
+inline bool Token::isNull() const
+{
+ return m_type == Token_eof || m_length == 0;
+}
+
+inline int Token::type() const
+{
+ return m_type;
+}
+
+inline void Token::setType( int type )
+{
+ m_type = type;
+}
+
+inline int Token::position() const
+{
+ return m_position;
+}
+
+inline QString Token::text() const
+{
+ return m_text.mid(m_position, m_length);
+}
+
+inline void Token::setStartPosition( int line, int column )
+{
+ m_startLine = line;
+ m_startColumn = column;
+}
+
+inline void Token::setEndPosition( int line, int column )
+{
+ m_endLine = line;
+ m_endColumn = column;
+}
+
+inline void Token::getStartPosition( int* line, int* column ) const
+{
+ if( line ) *line = m_startLine;
+ if( column ) *column = m_startColumn;
+}
+
+inline void Token::getEndPosition( int* line, int* column ) const
+{
+ if( line ) *line = m_endLine;
+ if( column ) *column = m_endColumn;
+}
+
+inline void Token::setPosition( int position )
+{
+ m_position = position;
+}
+
+inline unsigned int Token::length() const
+{
+ return m_length;
+}
+
+inline void Token::setLength( unsigned int length )
+{
+ m_length = length;
+}
+
+inline bool Lexer::recordComments() const
+{
+ return m_recordComments;
+}
+
+inline void Lexer::setRecordComments( bool record )
+{
+ m_recordComments = record;
+}
+
+inline bool Lexer::recordWhiteSpaces() const
+{
+ return m_recordWhiteSpaces;
+}
+
+inline void Lexer::setRecordWhiteSpaces( bool record )
+{
+ m_recordWhiteSpaces = record;
+}
+
+inline QString Lexer::source() const
+{
+ return m_source;
+}
+
+inline int Lexer::index() const
+{
+ return m_index;
+}
+
+inline void Lexer::setIndex( int index )
+{
+ m_index = index;
+}
+
+inline const Token& Lexer::nextToken()
+{
+ if( m_index < m_size )
+ return *m_tokens[ m_index++ ];
+
+ return *m_tokens[ m_index ];
+}
+
+inline const Token& Lexer::tokenAt( int n ) const
+{
+ return *m_tokens[ QMIN(n, m_size-1) ];
+}
+
+inline const Token& Lexer::lookAhead( int n ) const
+{
+ return *m_tokens[ QMIN(m_index + n, m_size-1) ];
+}
+
+inline int Lexer::tokenPosition( const Token& token ) const
+{
+ return token.position();
+}
+
+inline void Lexer::nextChar()
+{
+ if(m_source[m_ptr++] == '\n') {
+ ++m_currentLine;
+ m_currentColumn = 0;
+ m_startLine = true;
+ } else {
+ ++m_currentColumn;
+ }
+}
+
+inline void Lexer::nextChar( int n )
+{
+ m_currentColumn += n;
+ m_ptr += n;
+}
+
+inline void Lexer::readIdentifier()
+{
+ while( currentChar().isLetterOrNumber() || currentChar() == '_' )
+ nextChar();
+}
+
+inline void Lexer::readWhiteSpaces( bool skipNewLine )
+{
+ while( !currentChar().isNull() ){
+ QChar ch = currentChar();
+
+ if( ch == '\n' && !skipNewLine ){
+ break;
+ } else if( ch.isSpace() ){
+ nextChar();
+ } else if( m_inPreproc && currentChar() == '\\' ){
+ nextChar();
+ readWhiteSpaces( true );
+ } else {
+ break;
+ }
+ }
+}
+
+inline void Lexer::readLineComment()
+{
+ while( !currentChar().isNull() && currentChar() != '\n' ){
+ if( m_reportMessages && currentChar() == '@' && m_source.mid(currentPosition()+1, 4).lower() == "todo" ){
+ nextChar( 5 );
+ QString msg;
+ int line = m_currentLine;
+ int col = m_currentColumn;
+
+ while( currentChar() ){
+ if( currentChar() == '*' && peekChar() == '/' )
+ break;
+ else if( currentChar() == '\n' )
+ break;
+
+ msg += currentChar();
+ nextChar();
+ }
+ m_driver->addProblem( m_driver->currentFileName(), Problem(msg, line, col, Problem::Level_Todo) );
+ } else
+ if( m_reportMessages && m_source.mid(currentPosition(), 5).lower() == "fixme" ){
+ nextChar( 5 );
+ QString msg;
+ int line = m_currentLine;
+ int col = m_currentColumn;
+
+ while( currentChar() ){
+ if( currentChar() == '*' && peekChar() == '/' )
+ break;
+ else if( currentChar() == '\n' )
+ break;
+
+ msg += currentChar();
+ nextChar();
+ }
+ m_driver->addProblem( m_driver->currentFileName(), Problem(msg, line, col, Problem::Level_Fixme) );
+ } else
+ nextChar();
+ }
+}
+
+inline void Lexer::readMultiLineComment()
+{
+ while( !currentChar().isNull() ){
+ if( currentChar() == '*' && peekChar() == '/' ){
+ nextChar( 2 );
+ return;
+ } else if( m_reportMessages && currentChar() == '@' && m_source.mid(currentPosition()+1, 4).lower() == "todo" ){
+ nextChar( 5 );
+ QString msg;
+ int line = m_currentLine;
+ int col = m_currentColumn;
+
+ while( currentChar() ){
+ if( currentChar() == '*' && peekChar() == '/' )
+ break;
+ else if( currentChar() == '\n' )
+ break;
+ msg += currentChar();
+ nextChar();
+ }
+ m_driver->addProblem( m_driver->currentFileName(), Problem(msg, line, col, Problem::Level_Todo) );
+ } else
+ if( m_reportMessages && m_source.mid(currentPosition(), 5).lower() == "fixme" ){
+ nextChar( 5 );
+ QString msg;
+ int line = m_currentLine;
+ int col = m_currentColumn;
+
+ while( currentChar() ){
+ if( currentChar() == '*' && peekChar() == '/' )
+ break;
+ else if( currentChar() == '\n' )
+ break;
+
+ msg += currentChar();
+ nextChar();
+ }
+ m_driver->addProblem( m_driver->currentFileName(), Problem(msg, line, col, Problem::Level_Fixme) );
+ } else
+ nextChar();
+ }
+}
+
+inline void Lexer::readCharLiteral()
+{
+ if( currentChar() == '\'' )
+ nextChar(); // skip '
+ else if( currentChar() == 'L' && peekChar() == '\'' )
+ nextChar( 2 ); // slip L'
+ else
+ return;
+
+ while( !currentChar().isNull() ){
+ int len = m_endPtr - currentPosition();
+
+ if( len>=2 && (currentChar() == '\\' && peekChar() == '\'') ){
+ nextChar( 2 );
+ } else if( len>=2 && (currentChar() == '\\' && peekChar() == '\\') ){
+ nextChar( 2 );
+ } else if( currentChar() == '\'' ){
+ nextChar();
+ break;
+ } else {
+ nextChar();
+ }
+ }
+}
+
+inline void Lexer::readStringLiteral()
+{
+ if( currentChar() != '"' )
+ return;
+
+ nextChar(); // skip "
+
+ while( !currentChar().isNull() ){
+ int len = m_endPtr - m_ptr;
+
+ if( len>=2 && currentChar() == '\\' && peekChar() == '"' ){
+ nextChar( 2 );
+ } else if( len>=2 && currentChar() == '\\' && peekChar() == '\\' ){
+ nextChar( 2 );
+ } else if( currentChar() == '"' ){
+ nextChar();
+ break;
+ } else {
+ nextChar();
+ }
+ }
+}
+
+inline void Lexer::readNumberLiteral()
+{
+ while( currentChar().isLetterOrNumber() || currentChar() == '.' )
+ nextChar();
+}
+
+inline int Lexer::findOperator3() const
+{
+ int n = int(m_endPtr - m_ptr);
+
+ if( n >= 3){
+ QChar ch = currentChar(), ch1=peekChar(), ch2=peekChar(2);
+
+ if( ch == '<' && ch1 == '<' && ch2 == '=' ) return Token_assign;
+ else if( ch == '>' && ch1 == '>' && ch2 == '=' ) return Token_assign;
+ else if( ch == '-' && ch1 == '>' && ch2 == '*' ) return Token_ptrmem;
+ else if( ch == '.' && ch1 == '.' && ch2 == '.' ) return Token_ellipsis;
+ }
+
+ return -1;
+}
+
+inline int Lexer::findOperator2() const
+{
+ int n = int(m_endPtr - m_ptr);
+
+ if( n>=2 ){
+ QChar ch = currentChar(), ch1=peekChar();
+
+ if( ch == ':' && ch1 == ':' ) return Token_scope;
+ else if( ch == '.' && ch1 == '*' ) return Token_ptrmem;
+ else if( ch == '+' && ch1 == '=' ) return Token_assign;
+ else if( ch == '-' && ch1 == '=' ) return Token_assign;
+ else if( ch == '*' && ch1 == '=' ) return Token_assign;
+ else if( ch == '/' && ch1 == '=' ) return Token_assign;
+ else if( ch == '%' && ch1 == '=' ) return Token_assign;
+ else if( ch == '^' && ch1 == '=' ) return Token_assign;
+ else if( ch == '&' && ch1 == '=' ) return Token_assign;
+ else if( ch == '|' && ch1 == '=' ) return Token_assign;
+ else if( ch == '<' && ch1 == '<' ) return Token_shift;
+ else if( ch == '>' && ch1 == '>' ) return Token_shift;
+ else if( ch == '=' && ch1 == '=' ) return Token_eq;
+ else if( ch == '!' && ch1 == '=' ) return Token_eq;
+ else if( ch == '<' && ch1 == '=' ) return Token_leq;
+ else if( ch == '>' && ch1 == '=' ) return Token_geq;
+ else if( ch == '&' && ch1 == '&' ) return Token_and;
+ else if( ch == '|' && ch1 == '|' ) return Token_or;
+ else if( ch == '+' && ch1 == '+' ) return Token_incr;
+ else if( ch == '-' && ch1 == '-' ) return Token_decr;
+ else if( ch == '-' && ch1 == '>' ) return Token_arrow;
+ else if( ch == '#' && ch1 == '#' ) return Token_concat;
+ }
+
+ return -1;
+}
+
+inline bool Lexer::skipWordsEnabled() const
+{
+ return m_skipWordsEnabled;
+}
+
+inline void Lexer::setSkipWordsEnabled( bool enabled )
+{
+ m_skipWordsEnabled = enabled;
+}
+
+inline bool Lexer::preprocessorEnabled() const
+{
+ return m_preprocessorEnabled;
+}
+
+inline void Lexer::setPreprocessorEnabled( bool enabled )
+{
+ m_preprocessorEnabled = enabled;
+}
+
+inline int Lexer::currentPosition() const
+{
+ return m_ptr;
+}
+
+inline QChar Lexer::currentChar() const
+{
+ return m_ptr < m_endPtr ? m_source[m_ptr] : QChar::null;
+}
+
+inline QChar Lexer::peekChar( int n ) const
+{
+ return m_ptr+n < m_endPtr ? m_source[m_ptr + n] : QChar::null;
+}
+
+inline bool Lexer::eof() const
+{
+ return m_ptr >= m_endPtr;
+}
+
+inline bool Lexer::reportWarnings() const
+{
+ return m_reportWarnings;
+}
+
+inline void Lexer::setReportWarnings( bool enable )
+{
+ m_reportWarnings = enable;
+}
+
+inline bool Lexer::reportMessages() const
+{
+ return m_reportMessages;
+}
+
+inline void Lexer::setReportMessages( bool enable )
+{
+ m_reportMessages = enable;
+}
+
+
+#endif
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/lookup.cpp b/umbrello/umbrello/codeimport/kdevcppparser/lookup.cpp
new file mode 100644
index 00000000..86299304
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/lookup.cpp
@@ -0,0 +1,113 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+// adapted to kdevelop by Roberto Raggi <roberto@kdevelop.org>
+
+#include "lookup.h"
+
+#include <kdebug.h>
+
+#include <stdio.h>
+#include <string.h>
+
+const HashEntry* Lookup::findEntry( const struct HashTable *table,
+ const QChar *c, unsigned int len )
+{
+ if (table->type != 2) {
+ kdDebug() << "KJS: Unknown hash table version" << endl;
+ return 0;
+ }
+ char *ascii = new char[len+1];
+ unsigned int i;
+ for(i = 0; i < len; i++, c++) {
+ if (!c->row())
+ ascii[i] = c->cell();
+ else
+ break;
+ }
+ ascii[i] = '\0';
+
+ int h = hash(ascii) % table->hashSize;
+ const HashEntry *e = &table->entries[h];
+
+ // empty bucket ?
+ if (!e->s) {
+ delete [] ascii;
+ return 0;
+ }
+
+ do {
+ // compare strings
+ if (strcmp(ascii, e->s) == 0) {
+ delete [] ascii;
+ return e;
+ }
+ // try next bucket
+ e = e->next;
+ } while (e);
+
+ delete [] ascii;
+ return 0;
+}
+
+const HashEntry* Lookup::findEntry( const struct HashTable *table,
+ const QString &s )
+{
+ return findEntry( table, s.unicode(), s.length() );
+}
+
+int Lookup::find(const struct HashTable *table,
+ const QChar *c, unsigned int len)
+{
+ const HashEntry *entry = findEntry( table, c, len );
+ if (entry)
+ return entry->value;
+ return -1;
+}
+
+int Lookup::find(const struct HashTable *table, const QString &s)
+{
+ return find(table, s.unicode(), s.length());
+}
+
+unsigned int Lookup::hash(const QChar *c, unsigned int len)
+{
+ unsigned int val = 0;
+ // ignoring rower byte
+ for (unsigned int i = 0; i < len; i++, c++)
+ val += c->cell();
+
+ return val;
+}
+
+unsigned int Lookup::hash(const QString &key)
+{
+ return hash(key.unicode(), key.length());
+}
+
+unsigned int Lookup::hash(const char *s)
+{
+ unsigned int val = 0;
+ while (*s)
+ val += *s++;
+
+ return val;
+}
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/lookup.h b/umbrello/umbrello/codeimport/kdevcppparser/lookup.h
new file mode 100644
index 00000000..3e9c713c
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/lookup.h
@@ -0,0 +1,119 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+// adapted to kdevelop by Roberto Raggi <roberto@kdevelop.org>
+
+#ifndef _KJSLOOKUP_H_
+#define _KJSLOOKUP_H_
+
+#include <qstring.h>
+#include <stdio.h>
+
+ /**
+ * An entry in a hash table.
+ */
+ struct HashEntry {
+ /**
+ * s is the key (e.g. a property name)
+ */
+ const char *s;
+ /**
+ * value is the result value (usually an enum value)
+ */
+ int value;
+ /**
+ * attr is a set for flags (e.g. the property flags, see object.h)
+ */
+ short int attr;
+ /**
+ * params is another number. For property hashtables, it is used to
+ * denote the number of argument of the function
+ */
+ short int params;
+ /**
+ * next is the pointer to the next entry for the same hash value
+ */
+ const HashEntry *next;
+ };
+
+ /**
+ * A hash table
+ * Usually the hashtable is generated by the create_hash_table script, from a .table file.
+ *
+ * The implementation uses an array of entries, "size" is the total size of that array.
+ * The entries between 0 and hashSize-1 are the entry points
+ * for each hash value, and the entries between hashSize and size-1
+ * are the overflow entries for the hash values that need one.
+ * The "next" pointer of the entry links entry points to overflow entries,
+ * and links overflow entries between them.
+ */
+ struct HashTable {
+ /**
+ * type is a version number. Currently always 2
+ */
+ int type;
+ /**
+ * size is the total number of entries in the hashtable, including the null entries,
+ * i.e. the size of the "entries" array.
+ * Used to iterate over all entries in the table
+ */
+ int size;
+ /**
+ * pointer to the array of entries
+ * Mind that some entries in the array are null (0,0,0,0).
+ */
+ const HashEntry *entries;
+ /**
+ * the maximum value for the hash. Always smaller than size.
+ */
+ int hashSize;
+ };
+
+ /**
+ * @short Fast keyword lookup.
+ */
+ class Lookup {
+ public:
+ /**
+ * Find an entry in the table, and return its value (i.e. the value field of HashEntry)
+ */
+ static int find(const struct HashTable *table, const QString& s);
+ static int find(const struct HashTable *table, const QChar *c, unsigned int len);
+
+ /**
+ * Find an entry in the table, and return the entry
+ * This variant gives access to the other attributes of the entry,
+ * especially the attr field.
+ */
+ static const HashEntry* findEntry(const struct HashTable *table,
+ const QString &s);
+ static const HashEntry* findEntry(const struct HashTable *table,
+ const QChar *c, unsigned int len);
+
+ /**
+ * Calculate the hash value for a given key
+ */
+ static unsigned int hash(const QString &key);
+ static unsigned int hash(const QChar *c, unsigned int len);
+ static unsigned int hash(const char *s);
+ };
+
+#endif
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/parser.cpp b/umbrello/umbrello/codeimport/kdevcppparser/parser.cpp
new file mode 100644
index 00000000..0314a60c
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/parser.cpp
@@ -0,0 +1,4238 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+// c++ support
+#include "parser.h"
+#include "driver.h"
+#include "lexer.h"
+#include "errors.h"
+
+// qt
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qasciidict.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+
+using namespace std;
+
+#define ADVANCE(tk, descr) \
+{ \
+ const Token& token = lex->lookAhead( 0 ); \
+ if( token != tk ){ \
+ reportError( i18n("'%1' expected found '%2'").arg(descr).arg(token.text()) ); \
+ return false; \
+ } \
+ lex->nextToken(); \
+}
+
+#define ADVANCE_NR(tk, descr) \
+{ \
+ const Token& token = lex->lookAhead( 0 ); \
+ if( token != tk ){ \
+ reportError( i18n("'%1' expected found '%2'").arg(descr).arg(token.text()) ); \
+ } \
+ else \
+ lex->nextToken(); \
+}
+
+#define CHECK(tk, descr) \
+{ \
+ const Token& token = lex->lookAhead( 0 ); \
+ if( token != tk ){ \
+ return false; \
+ } \
+ lex->nextToken(); \
+}
+
+#define MATCH(tk, descr) \
+{ \
+ const Token& token = lex->lookAhead( 0 ); \
+ if( token != tk ){ \
+ reportError( Errors::SyntaxError ); \
+ return false; \
+ } \
+}
+
+#define UPDATE_POS(node, start, end) \
+{ \
+ int line, col; \
+ const Token &a = lex->tokenAt(start); \
+ const Token &b = lex->tokenAt( end!=start ? end-1 : end ); \
+ a.getStartPosition( &line, &col ); \
+ (node)->setStartPosition( line, col ); \
+ b.getEndPosition( &line, &col ); \
+ (node)->setEndPosition( line, col ); \
+ if( (node)->nodeType() == NodeType_Generic ) { \
+ if ((start) == (end) || (end) == (start)+1) \
+ (node)->setSlice(lex->source(), a.position(), a.length()); \
+ else \
+ (node)->setText( toString((start),(end)) ); \
+ } \
+}
+
+#define AST_FROM_TOKEN(node, tk) \
+ AST::Node node = CreateNode<AST>(); \
+ UPDATE_POS( node, (tk), (tk)+1 );
+
+
+//@todo remove me
+enum
+{
+ OBJC_CLASS,
+ OBJC_PROTOCOL,
+ OBJC_ALIAS
+};
+
+struct ParserPrivateData
+{
+ ParserPrivateData()
+ {}
+};
+
+Parser::Parser( Driver* driver, Lexer* lexer )
+ : m_driver( driver ),
+ lex( lexer )
+{
+ d = new ParserPrivateData();
+
+ m_maxProblems = 5;
+ objcp = false;
+}
+
+Parser::~Parser()
+{
+ delete d;
+ d = 0;
+}
+
+bool Parser::reportError( const Error& err )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::reportError()" << endl;
+ if( m_problems < m_maxProblems ){
+ ++m_problems;
+ int line=0, col=0;
+ const Token& token = lex->lookAhead( 0 );
+ lex->getTokenPosition( token, &line, &col );
+
+ QString s = lex->lookAhead(0).text();
+ s = s.left( 30 ).stripWhiteSpace();
+ if( s.isEmpty() )
+ s = i18n( "<eof>" );
+
+ m_driver->addProblem( m_driver->currentFileName(), Problem(err.text.arg(s), line, col) );
+ }
+
+ return true;
+}
+
+bool Parser::reportError( const QString& msg )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::reportError()" << endl;
+ if( m_problems < m_maxProblems ){
+ ++m_problems;
+ int line=0, col=0;
+ const Token& token = lex->lookAhead( 0 );
+ lex->getTokenPosition( token, &line, &col );
+
+ m_driver->addProblem( m_driver->currentFileName(), Problem(msg, line, col) );
+ }
+
+ return true;
+}
+
+void Parser::syntaxError()
+{
+ (void) reportError( Errors::SyntaxError );
+}
+
+bool Parser::skipUntil( int token )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::skipUntil()" << endl;
+ while( !lex->lookAhead(0).isNull() ){
+ if( lex->lookAhead(0) == token )
+ return true;
+
+ lex->nextToken();
+ }
+
+ return false;
+}
+
+bool Parser::skipUntilDeclaration()
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::skipUntilDeclaration()" << endl;
+
+ while( !lex->lookAhead(0).isNull() ){
+
+ switch( lex->lookAhead(0) ){
+ 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;
+
+ case '}':
+ return false;
+
+ default:
+ lex->nextToken();
+ }
+ }
+
+ return false;
+}
+
+bool Parser::skipUntilStatement()
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::skipUntilStatement() -- token = " << lex->lookAhead(0).text() << endl;
+
+ while( !lex->lookAhead(0).isNull() ){
+ switch( lex->lookAhead(0) ){
+ 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:
+ lex->nextToken();
+ }
+ }
+
+ return false;
+}
+
+bool Parser::skip( int l, int r )
+{
+ int count = 0;
+ while( !lex->lookAhead(0).isNull() ){
+ int tk = lex->lookAhead( 0 );
+
+ if( tk == l )
+ ++count;
+ else if( tk == r )
+ --count;
+ else if( l != '{' && (tk == '{' || tk == '}' || tk == ';') )
+ return false;
+
+ if( count == 0 )
+ return true;
+
+ lex->nextToken();
+ }
+
+ return false;
+}
+
+bool Parser::skipCommaExpression( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::skipCommaExpression()" << endl;
+
+ int start = lex->index();
+
+ AST::Node expr;
+ if( !skipExpression(expr) )
+ return false;
+
+ QString comment;
+ while( lex->lookAhead(0) == ',' ){
+ comment = QString::null;
+ advanceAndCheckTrailingComment( comment );
+
+ if( !skipExpression(expr) ){
+ reportError( i18n("expression expected") );
+ return false;
+ }
+ }
+
+ AST::Node ast = CreateNode<AST>();
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::skipExpression( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::skipExpression()" << endl;
+
+ int start = lex->index();
+
+ while( !lex->lookAhead(0).isNull() ){
+ int tk = lex->lookAhead( 0 );
+
+ switch( tk ){
+ case '(':
+ skip( '(', ')' );
+ lex->nextToken();
+ break;
+
+ case '[':
+ skip( '[', ']' );
+ lex->nextToken();
+ break;
+
+#if 0
+ case Token_identifier:
+ lex->nextToken();
+ if( lex->lookAhead( 0 ) == Token_identifier )
+ return true;
+ break;
+#endif
+
+ case ';':
+ case ',':
+ case ']':
+ case ')':
+ case '{':
+ case '}':
+ case Token_case:
+ case Token_default:
+ case Token_if:
+ case Token_while:
+ case Token_do:
+ case Token_for:
+ case Token_break:
+ case Token_continue:
+ case Token_return:
+ case Token_goto:
+ {
+ AST::Node ast = CreateNode<AST>();
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ }
+ return true;
+
+ default:
+ lex->nextToken();
+ }
+ }
+
+ return false;
+}
+
+bool Parser::parseName( NameAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseName()" << endl;
+
+ GroupAST::Node winDeclSpec;
+ parseWinDeclSpec( winDeclSpec );
+
+ int start = lex->index();
+
+ NameAST::Node ast = CreateNode<NameAST>();
+
+ if( lex->lookAhead(0) == Token_scope ){
+ ast->setGlobal( true );
+ lex->nextToken();
+ }
+
+ int idx = lex->index();
+
+ while( true ){
+ ClassOrNamespaceNameAST::Node n;
+ if( !parseUnqualifiedName(n) ) {
+ return false;
+ }
+
+ if( lex->lookAhead(0) == Token_scope ){
+ lex->nextToken();
+ ast->addClassOrNamespaceName( n );
+ if( lex->lookAhead(0) == Token_template )
+ lex->nextToken(); /// skip optional template #### @todo CHECK
+ } else {
+ ast->setUnqualifiedName( n );
+ break;
+ }
+ }
+
+ if( idx == lex->index() )
+ return false;
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTranslationUnit( TranslationUnitAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTranslationUnit()" << endl;
+
+ int start = lex->index();
+
+ m_problems = 0;
+ TranslationUnitAST::Node tun = CreateNode<TranslationUnitAST>();
+ node = tun;
+ while( !lex->lookAhead(0).isNull() ){
+ DeclarationAST::Node def;
+ int startDecl = lex->index();
+ if( !parseDeclaration(def) ){
+ // error recovery
+ if( startDecl == lex->index() )
+ lex->nextToken(); // skip at least one token
+ skipUntilDeclaration();
+ }
+ node->addDeclaration( def );
+ }
+
+ UPDATE_POS( node, start, lex->index() );
+
+ // force (0,0) as start position
+ node->setStartPosition( 0, 0 );
+
+ return m_problems == 0;
+}
+
+bool Parser::parseDeclaration( DeclarationAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseDeclaration()" << endl;
+
+ QString comment;
+ while( lex->lookAhead(0) == Token_comment ) {
+ comment += lex->lookAhead(0).text();
+ lex->nextToken();
+ }
+ if( lex->lookAhead(0).isNull() )
+ return false;
+
+ int start = lex->index();
+ bool success = false;
+
+ switch( lex->lookAhead(0) ){
+
+ case ';':
+ lex->nextToken();
+ return true;
+
+ case Token_extern:
+ success = parseLinkageSpecification( node );
+ break;
+
+ case Token_namespace:
+ success = parseNamespace( node );
+ break;
+
+ case Token_using:
+ success = parseUsing( node );
+ break;
+
+ case Token_typedef:
+ success = parseTypedef( node );
+ break;
+
+ case Token_asm:
+ success = parseAsmDefinition( node );
+ break;
+
+ case Token_template:
+ case Token_export:
+ success = parseTemplateDeclaration( node );
+ break;
+
+ default:
+ {
+ // lex->setIndex( start );
+
+ if( objcp && parseObjcDef(node) )
+ return true;
+
+ lex->setIndex( start );
+
+ GroupAST::Node storageSpec;
+ parseStorageClassSpecifier( storageSpec );
+
+ GroupAST::Node cv;
+ parseCvQualify( cv );
+
+ TypeSpecifierAST::Node spec;
+ AST::Node declarator;
+ if( parseEnumSpecifier(spec) || parseClassSpecifier(spec) ){
+ spec->setCvQualify( cv );
+
+ GroupAST::Node cv2;
+ parseCvQualify( cv2 );
+ spec->setCv2Qualify( cv2 );
+
+ InitDeclaratorListAST::Node declarators;
+ parseInitDeclaratorList(declarators);
+ ADVANCE( ';', ";" );
+
+ if( !comment.isEmpty() ) {
+ //kdDebug(9007) << "Parser::parseDeclaration(spec): comment is " << comment << endl;
+ spec->setComment( comment );
+ }
+
+ SimpleDeclarationAST::Node ast = CreateNode<SimpleDeclarationAST>();
+ ast->setStorageSpecifier( storageSpec );
+ ast->setTypeSpec( spec );
+ ast->setInitDeclaratorList( declarators );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+ }
+
+ lex->setIndex( start );
+ success = parseDeclarationInternal( node, comment );
+ }
+
+ } // end switch
+
+ if( success && !comment.isEmpty() ) {
+ //kdDebug(9007) << "Parser::parseDeclaration(): comment is " << comment << endl;
+ node->setComment( comment );
+ }
+ return success;
+}
+
+bool Parser::parseLinkageSpecification( DeclarationAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseLinkageSpecification()" << endl;
+
+ int start = lex->index();
+
+ if( lex->lookAhead(0) != Token_extern ){
+ return false;
+ }
+ lex->nextToken();
+
+ LinkageSpecificationAST::Node ast = CreateNode<LinkageSpecificationAST>();
+
+ int startExternType = lex->index();
+ if( lex->lookAhead(0) == Token_string_literal ){
+ lex->nextToken();
+ AST::Node externType = CreateNode<AST>();
+ UPDATE_POS( externType, startExternType, lex->index() );
+
+ ast->setExternType( externType );
+ }
+
+ if( lex->lookAhead(0) == '{' ){
+ LinkageBodyAST::Node linkageBody;
+ parseLinkageBody( linkageBody );
+ ast->setLinkageBody( linkageBody );
+ } else {
+ DeclarationAST::Node decl;
+ if( !parseDeclaration(decl) ){
+ reportError( i18n("Declaration syntax error") );
+ }
+ ast->setDeclaration( decl );
+ }
+
+ UPDATE_POS( ast, start, lex->index() );
+
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseLinkageBody( LinkageBodyAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseLinkageBody()" << endl;
+
+ int start = lex->index();
+
+ if( lex->lookAhead(0) != '{' ){
+ return false;
+ }
+ lex->nextToken();
+
+ LinkageBodyAST::Node lba = CreateNode<LinkageBodyAST>();
+ node = lba;
+
+ while( !lex->lookAhead(0).isNull() ){
+ int tk = lex->lookAhead( 0 );
+
+ if( tk == '}' )
+ break;
+
+ DeclarationAST::Node def;
+ int startDecl = lex->index();
+ if( parseDeclaration(def) ){
+ node->addDeclaration( def );
+ } else {
+ // error recovery
+ if( startDecl == lex->index() )
+ lex->nextToken(); // skip at least one token
+ skipUntilDeclaration();
+ }
+ }
+
+ if( lex->lookAhead(0) != '}' ){
+ reportError( i18n("} expected") );
+ } else
+ lex->nextToken();
+
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+}
+
+bool Parser::parseNamespace( DeclarationAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseNamespace()" << endl;
+
+ int start = lex->index();
+
+ if( lex->lookAhead(0) != Token_namespace ){
+ return false;
+ }
+ lex->nextToken();
+
+ int startNamespaceName = lex->index();
+ if( lex->lookAhead(0) == Token_identifier ){
+ lex->nextToken();
+ }
+ AST::Node namespaceName = CreateNode<AST>();
+ UPDATE_POS( namespaceName, startNamespaceName, lex->index() );
+
+ if ( lex->lookAhead(0) == '=' ) {
+ // namespace alias
+ lex->nextToken();
+
+ NameAST::Node name;
+ if( parseName(name) ){
+ ADVANCE( ';', ";" );
+
+ NamespaceAliasAST::Node ast = CreateNode<NamespaceAliasAST>();
+ ast->setNamespaceName( namespaceName );
+ ast->setAliasName( name );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+ } else {
+ reportError( i18n("namespace expected") );
+ return false;
+ }
+ } else if( lex->lookAhead(0) != '{' ){
+ reportError( i18n("{ expected") );
+ return false;
+ }
+
+ NamespaceAST::Node ast = CreateNode<NamespaceAST>();
+ ast->setNamespaceName( namespaceName );
+
+ LinkageBodyAST::Node linkageBody;
+ parseLinkageBody( linkageBody );
+
+ ast->setLinkageBody( linkageBody );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseUsing( DeclarationAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseUsing()" << endl;
+
+ int start = lex->index();
+
+ if( lex->lookAhead(0) != Token_using ){
+ return false;
+ }
+ lex->nextToken();
+
+ if( lex->lookAhead(0) == Token_namespace ){
+ if( !parseUsingDirective(node) ){
+ return false;
+ }
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+ }
+
+ UsingAST::Node ast = CreateNode<UsingAST>();
+
+ int startTypeName = lex->index();
+ if( lex->lookAhead(0) == Token_typename ){
+ lex->nextToken();
+ AST::Node tn = CreateNode<AST>();
+ UPDATE_POS( tn, startTypeName, lex->index() );
+ ast->setTypeName( tn );
+ }
+
+ NameAST::Node name;
+ if( !parseName(name) )
+ return false;
+
+ ast->setName( name );
+
+ ADVANCE( ';', ";" );
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseUsingDirective( DeclarationAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseUsingDirective()" << endl;
+
+ int start = lex->index();
+
+ if( lex->lookAhead(0) != Token_namespace ){
+ return false;
+ }
+ lex->nextToken();
+
+ NameAST::Node name;
+ if( !parseName(name) ){
+ reportError( i18n("Namespace name expected") );
+ return false;
+ }
+
+ ADVANCE( ';', ";" );
+
+ UsingDirectiveAST::Node ast = CreateNode<UsingDirectiveAST>();
+ ast->setName( name );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+
+bool Parser::parseOperatorFunctionId( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseOperatorFunctionId()" << endl;
+
+ int start = lex->index();
+
+ if( lex->lookAhead(0) != Token_operator ){
+ return false;
+ }
+ lex->nextToken();
+
+ AST::Node op;
+ if( parseOperator(op) ){
+ AST::Node asn = CreateNode<AST>();
+ node = asn;
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+ } else {
+ // parse cast operator
+ GroupAST::Node cv;
+ parseCvQualify(cv);
+
+ TypeSpecifierAST::Node spec;
+ if( !parseSimpleTypeSpecifier(spec) ){
+ syntaxError();
+ return false;
+ }
+ spec->setCvQualify( cv );
+
+ GroupAST::Node cv2;
+ parseCvQualify(cv2);
+ spec->setCv2Qualify( cv2 );
+
+ AST::Node ptrOp;
+ while( parsePtrOperator(ptrOp) )
+ ;
+
+ AST::Node asn = CreateNode<AST>();
+ node = asn;
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+ }
+}
+
+bool Parser::parseTemplateArgumentList( TemplateArgumentListAST::Node& node, bool reportError )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTemplateArgumentList()" << endl;
+
+ int start = lex->index();
+
+ TemplateArgumentListAST::Node ast = CreateNode<TemplateArgumentListAST>();
+
+ AST::Node templArg;
+ if( !parseTemplateArgument(templArg) )
+ return false;
+ ast->addArgument( templArg );
+
+ QString comment;
+ while( lex->lookAhead(0) == ',' ){
+ comment = QString::null;
+ advanceAndCheckTrailingComment( comment );
+
+ if( !parseTemplateArgument(templArg) ){
+ if( reportError ){
+ syntaxError();
+ break;
+ } else
+ return false;
+ }
+ if (!comment.isEmpty())
+ templArg->setComment(comment);
+ ast->addArgument( templArg );
+ }
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTypedef( DeclarationAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTypedef()" << endl;
+
+ int start = lex->index();
+
+ if( lex->lookAhead(0) != Token_typedef ){
+ return false;
+ }
+ lex->nextToken();
+
+ TypeSpecifierAST::Node spec;
+ if( !parseTypeSpecifierOrClassSpec(spec) ){
+ reportError( i18n("Need a type specifier to declare") );
+ return false;
+ }
+
+ InitDeclaratorListAST::Node declarators;
+ if( !parseInitDeclaratorList(declarators) ){
+ //reportError( i18n("Need an identifier to declare") );
+ //return false;
+ }
+
+ ADVANCE( ';', ";" );
+
+ TypedefAST::Node ast = CreateNode<TypedefAST>();
+ ast->setTypeSpec( spec );
+ ast->setInitDeclaratorList( declarators );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseAsmDefinition( DeclarationAST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseAsmDefinition()" << endl;
+
+ ADVANCE( Token_asm, "asm" );
+
+ GroupAST::Node cv;
+ parseCvQualify( cv );
+
+ skip( '(', ')' );
+ ADVANCE( ')', ")" );
+ ADVANCE( ';', ';' );
+
+ return true;
+}
+
+bool Parser::parseTemplateDeclaration( DeclarationAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTemplateDeclaration()" << endl;
+
+ int start = lex->index();
+
+ AST::Node exp;
+
+ int startExport = lex->index();
+ if( lex->lookAhead(0) == Token_export ){
+ lex->nextToken();
+ AST::Node n = CreateNode<AST>();
+ UPDATE_POS( n, startExport, lex->index() );
+ exp = n;
+ }
+
+ if( lex->lookAhead(0) != Token_template ){
+ return false;
+ }
+ lex->nextToken();
+
+ TemplateParameterListAST::Node params;
+ if( lex->lookAhead(0) == '<' ){
+ lex->nextToken();
+ if (lex->lookAhead(0) != '>')
+ parseTemplateParameterList( params );
+
+ ADVANCE( '>', ">" );
+ }
+
+ DeclarationAST::Node def;
+ if( !parseDeclaration(def) ){
+ reportError( i18n("expected a declaration") );
+ }
+
+ TemplateDeclarationAST::Node ast = CreateNode<TemplateDeclarationAST>();
+ ast->setExported( exp );
+ ast->setTemplateParameterList( params );
+ ast->setDeclaration( def );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseOperator( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseOperator()" << endl;
+ QString text = lex->lookAhead(0).text();
+
+ switch( lex->lookAhead(0) ){
+ case Token_new:
+ case Token_delete:
+ lex->nextToken();
+ if( lex->lookAhead(0) == '[' && lex->lookAhead(1) == ']' ){
+ lex->nextToken();
+ lex->nextToken();
+ text += "[]";
+ }
+ return true;
+
+ 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:
+ lex->nextToken();
+ return true;
+
+ default:
+ if( lex->lookAhead(0) == '(' && lex->lookAhead(1) == ')' ){
+ lex->nextToken();
+ lex->nextToken();
+ return true;
+ } else if( lex->lookAhead(0) == '[' && lex->lookAhead(1) == ']' ){
+ lex->nextToken();
+ lex->nextToken();
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool Parser::parseCvQualify( GroupAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseCvQualify()" << endl;
+
+ int start = lex->index();
+
+ GroupAST::Node ast = CreateNode<GroupAST>();
+
+ int n = 0;
+ while( !lex->lookAhead(0).isNull() ){
+ int tk = lex->lookAhead( 0 );
+ if( tk == Token_const || tk == Token_volatile ){
+ ++n;
+ int startWord = lex->index();
+ lex->nextToken();
+ AST::Node word = CreateNode<AST>();
+ UPDATE_POS( word, startWord, lex->index() );
+ ast->addNode( word );
+ } else
+ break;
+ }
+
+ if( n == 0 )
+ return false;
+
+
+ //kdDebug(9007)<< "-----------------> token = " << lex->lookAhead(0).text() << endl;
+ UPDATE_POS( ast, start, lex->index() );
+
+ node = ast;
+ return true;
+}
+
+bool Parser::parseSimpleTypeSpecifier( TypeSpecifierAST::Node& node )
+{
+ int start = lex->index();
+ bool isIntegral = false;
+ bool done = false;
+
+ while( !done ){
+
+ switch( lex->lookAhead(0) ){
+ 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:
+ isIntegral = true;
+ lex->nextToken();
+ break;
+
+ default:
+ done = true;
+ }
+ }
+
+ TypeSpecifierAST::Node ast = CreateNode<TypeSpecifierAST>();
+ if( isIntegral ){
+ ClassOrNamespaceNameAST::Node cl = CreateNode<ClassOrNamespaceNameAST>();
+
+ AST::Node n = CreateNode<AST>();
+ UPDATE_POS( n, start, lex->index() );
+ cl->setName( n );
+ UPDATE_POS( cl, start, lex->index() );
+
+ NameAST::Node name = CreateNode<NameAST>();
+ name->setUnqualifiedName( cl );
+ UPDATE_POS( name, start, lex->index() );
+ ast->setName( name );
+
+ } else {
+ NameAST::Node name;
+ if( !parseName(name) ){
+ lex->setIndex( start );
+ return false;
+ }
+ ast->setName( name );
+ }
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+}
+
+bool Parser::parsePtrOperator( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parsePtrOperator()" << endl;
+
+ int start = lex->index();
+
+ if( lex->lookAhead(0) == '&' ){
+ lex->nextToken();
+ } else if( lex->lookAhead(0) == '*' ){
+ lex->nextToken();
+ } else {
+ int index = lex->index();
+ AST::Node memPtr;
+ if( !parsePtrToMember(memPtr) ){
+ lex->setIndex( index );
+ return false;
+ }
+ }
+
+ GroupAST::Node cv;
+ parseCvQualify( cv );
+
+ AST::Node ast = CreateNode<AST>();
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+
+bool Parser::parseTemplateArgument( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTemplateArgument()" << endl;
+
+ int start = lex->index();
+ if( parseTypeId(node) ){
+ if( lex->lookAhead(0) == ',' || lex->lookAhead(0) == '>' )
+ return true;
+ }
+
+ lex->setIndex( start );
+ if( !parseLogicalOrExpression(node, true) ){
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseTypeSpecifier( TypeSpecifierAST::Node& spec )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTypeSpecifier()" << endl;
+
+ GroupAST::Node cv;
+ parseCvQualify( cv );
+
+ if( parseElaboratedTypeSpecifier(spec) || parseSimpleTypeSpecifier(spec) ){
+ spec->setCvQualify( cv );
+
+ GroupAST::Node cv2;
+ parseCvQualify( cv2 );
+ spec->setCv2Qualify( cv2 );
+
+ return true;
+ }
+
+ return false;
+}
+
+bool Parser::parseDeclarator( DeclaratorAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseDeclarator()" << endl;
+
+ int start = lex->index();
+
+ DeclaratorAST::Node ast = CreateNode<DeclaratorAST>();
+
+ DeclaratorAST::Node decl;
+ NameAST::Node declId;
+
+ AST::Node ptrOp;
+ while( parsePtrOperator(ptrOp) ){
+ ast->addPtrOp( ptrOp );
+ }
+
+ if( lex->lookAhead(0) == '(' ){
+ lex->nextToken();
+
+ if( !parseDeclarator(decl) ){
+ return false;
+ }
+ ast->setSubDeclarator( decl );
+
+ if( lex->lookAhead(0) != ')'){
+ return false;
+ }
+ lex->nextToken();
+ } else {
+
+ if( lex->lookAhead(0) == ':' ){
+ // unnamed bitfield
+ } else if( parseDeclaratorId(declId) ){
+ ast->setDeclaratorId( declId );
+ } else {
+ lex->setIndex( start );
+ return false;
+ }
+
+ if( lex->lookAhead(0) == ':' ){
+ lex->nextToken();
+ AST::Node expr;
+ if( !parseConstantExpression(expr) ){
+ reportError( i18n("Constant expression expected") );
+ }
+ goto update_pos;
+ }
+ }
+
+ {
+ bool isVector = true;
+
+ while( lex->lookAhead(0) == '[' ){
+ int startArray = lex->index();
+ lex->nextToken();
+ AST::Node expr;
+ parseCommaExpression( expr );
+
+ ADVANCE( ']', "]" );
+ AST::Node array = CreateNode<AST>();
+ UPDATE_POS( array, startArray, lex->index() );
+ ast->addArrayDimension( array );
+ isVector = true;
+ }
+
+ bool skipParen = false;
+ if( lex->lookAhead(0) == Token_identifier && lex->lookAhead(1) == '(' && lex->lookAhead(2) == '(' ){
+ lex->nextToken();
+ lex->nextToken();
+ skipParen = true;
+ }
+
+ if( ast->subDeclarator() && (!isVector || lex->lookAhead(0) != '(') ){
+ lex->setIndex( start );
+ return false;
+ }
+
+ int index = lex->index();
+ if( lex->lookAhead(0) == '(' ){
+ lex->nextToken();
+
+ ParameterDeclarationClauseAST::Node params;
+ if( !parseParameterDeclarationClause(params) ){
+ //kdDebug(9007)<< "----------------------> not a parameter declaration, maybe an initializer!?" << endl;
+ lex->setIndex( index );
+ goto update_pos;
+ }
+ ast->setParameterDeclarationClause( params );
+
+ if( lex->lookAhead(0) != ')' ){
+ lex->setIndex( index );
+ goto update_pos;
+ }
+
+ lex->nextToken(); // skip ')'
+
+ int startConstant = lex->index();
+ if( lex->lookAhead(0) == Token_const ){
+ lex->nextToken();
+ AST::Node constant = CreateNode<AST>();
+ UPDATE_POS( constant, startConstant, lex->index() );
+ ast->setConstant( constant );
+ }
+
+ GroupAST::Node except;
+ if( parseExceptionSpecification(except) ){
+ ast->setExceptionSpecification( except );
+ }
+ }
+
+ if( skipParen ){
+ if( lex->lookAhead(0) != ')' ){
+ reportError( i18n("')' expected") );
+ } else
+ lex->nextToken();
+ }
+
+ }
+
+update_pos:
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseAbstractDeclarator( DeclaratorAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseDeclarator()" << endl;
+ int start = lex->index();
+
+ DeclaratorAST::Node ast = CreateNode<DeclaratorAST>();
+
+ DeclaratorAST::Node decl;
+ NameAST::Node declId;
+
+ AST::Node ptrOp;
+ while( parsePtrOperator(ptrOp) ){
+ ast->addPtrOp( ptrOp );
+ }
+
+ if( lex->lookAhead(0) == '(' ){
+ lex->nextToken();
+
+ if( !parseAbstractDeclarator(decl) ){
+ return false;
+ }
+ ast->setSubDeclarator( decl );
+
+ if( lex->lookAhead(0) != ')'){
+ return false;
+ }
+ lex->nextToken();
+ }
+
+ {
+
+ while( lex->lookAhead(0) == '[' ){
+ int startArray = lex->index();
+ lex->nextToken();
+ AST::Node expr;
+ skipCommaExpression( expr );
+
+ ADVANCE( ']', "]" );
+ AST::Node array = CreateNode<AST>();
+ UPDATE_POS( array, startArray, lex->index() );
+ ast->addArrayDimension( array );
+ }
+
+ bool skipParen = false;
+ if( lex->lookAhead(0) == Token_identifier && lex->lookAhead(1) == '(' && lex->lookAhead(2) == '(' ){
+ lex->nextToken();
+ lex->nextToken();
+ skipParen = true;
+ }
+
+ int index = lex->index();
+ if( lex->lookAhead(0) == '(' ){
+ lex->nextToken();
+
+ ParameterDeclarationClauseAST::Node params;
+ if( !parseParameterDeclarationClause(params) ){
+ lex->setIndex( index );
+ goto UPDATE_POS;
+ }
+ ast->setParameterDeclarationClause( params );
+
+ if( lex->lookAhead(0) != ')' ){
+ lex->setIndex( index );
+ goto UPDATE_POS;
+ } else
+ lex->nextToken();
+
+ int startConstant = lex->index();
+ if( lex->lookAhead(0) == Token_const ){
+ lex->nextToken();
+ AST::Node constant = CreateNode<AST>();
+ UPDATE_POS( constant, startConstant, lex->index() );
+ ast->setConstant( constant );
+ }
+
+ GroupAST::Node except;
+ if( parseExceptionSpecification(except) ){
+ ast->setExceptionSpecification( except );
+ }
+ }
+
+ if( skipParen ){
+ if( lex->lookAhead(0) != ')' ){
+ reportError( i18n("')' expected") );
+ } else
+ lex->nextToken();
+ }
+
+ }
+
+UPDATE_POS:
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+
+bool Parser::parseEnumSpecifier( TypeSpecifierAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseEnumSpecifier()" << endl;
+
+ QString comment;
+ while( lex->lookAhead(0) == Token_comment ) {
+ comment += lex->lookAhead(0).text();
+ lex->nextToken();
+ }
+ if( lex->lookAhead(0).isNull() )
+ return false;
+
+ int start = lex->index();
+
+ if( lex->lookAhead(0) != Token_enum ){
+ return false;
+ }
+
+ lex->nextToken();
+
+ NameAST::Node name;
+ parseName( name );
+
+ if( lex->lookAhead(0) != '{' ){
+ lex->setIndex( start );
+ return false;
+ }
+ lex->nextToken();
+
+ EnumSpecifierAST::Node ast = CreateNode<EnumSpecifierAST>();
+ ast->setName( name );
+
+ EnumeratorAST::Node enumerator;
+ if( parseEnumerator(enumerator) ){
+ ast->addEnumerator( enumerator );
+
+ QString comment;
+ while( lex->lookAhead(0) == ',' ){
+ comment = "";
+ advanceAndCheckTrailingComment( comment );
+ if ( !comment.isEmpty() ){
+ EnumeratorAST *lastLit = ast->enumeratorList().last();
+ if( lastLit )
+ lastLit->setComment( comment );
+ }
+
+ if( !parseEnumerator(enumerator) ){
+ //reportError( i18n("Enumerator expected") );
+ break;
+ }
+
+ ast->addEnumerator( enumerator );
+ }
+ }
+
+ if( lex->lookAhead(0) == Token_comment )
+ lex->nextToken();
+ if( lex->lookAhead(0) != '}' )
+ reportError( i18n("} missing") );
+ else
+ lex->nextToken();
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTemplateParameterList( TemplateParameterListAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTemplateParameterList()" << endl;
+
+ int start = lex->index();
+
+ TemplateParameterListAST::Node ast = CreateNode<TemplateParameterListAST>();
+
+ TemplateParameterAST::Node param;
+ if( !parseTemplateParameter(param) ){
+ return false;
+ }
+ ast->addTemplateParameter( param );
+
+ QString comment;
+ while( lex->lookAhead(0) == ',' ){
+ comment = QString::null;
+ advanceAndCheckTrailingComment( comment );
+
+ if( !parseTemplateParameter(param) ){
+ syntaxError();
+ break;
+ } else {
+ if (!comment.isEmpty())
+ param->setComment(comment);
+ ast->addTemplateParameter( param );
+ }
+ }
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTemplateParameter( TemplateParameterAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTemplateParameter()" << endl;
+
+ int start = lex->index();
+ TemplateParameterAST::Node ast = CreateNode<TemplateParameterAST>();
+
+ TypeParameterAST::Node typeParameter;
+ ParameterDeclarationAST::Node param;
+
+ int tk = lex->lookAhead( 0 );
+
+ if( (tk == Token_class || tk == Token_typename || tk == Token_template) && parseTypeParameter(typeParameter) ){
+ ast->setTypeParameter( typeParameter );
+ goto ok;
+ }
+
+ if( !parseParameterDeclaration(param) )
+ return false;
+ ast->setTypeValueParameter( param );
+
+ok:
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTypeParameter( TypeParameterAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTypeParameter()" << endl;
+
+ int start = lex->index();
+ TypeParameterAST::Node ast = CreateNode<TypeParameterAST>();
+
+ AST_FROM_TOKEN( kind, lex->index() );
+ ast->setKind( kind );
+
+ switch( lex->lookAhead(0) ){
+
+ case Token_class:
+ case Token_typename:
+ {
+ lex->nextToken(); // skip class
+
+ // parse optional name
+ NameAST::Node name;
+ if( parseName(name) ){
+ ast->setName( name );
+ if( lex->lookAhead(0) == '=' ){
+ lex->nextToken();
+
+ AST::Node typeId;
+ if( !parseTypeId(typeId) ){
+ syntaxError();
+ return false;
+ }
+ ast->setTypeId( typeId );
+ }
+ }
+ }
+ break;
+
+ case Token_template:
+ {
+ lex->nextToken(); // skip template
+ ADVANCE( '<', '<' );
+
+ TemplateParameterListAST::Node params;
+ if( !parseTemplateParameterList(params) ){
+ return false;
+ }
+ ast->setTemplateParameterList( params );
+
+ ADVANCE( '>', ">" );
+
+ if( lex->lookAhead(0) == Token_class )
+ lex->nextToken();
+
+ // parse optional name
+ NameAST::Node name;
+ if( parseName(name) ){
+ ast->setName( name );
+ if( lex->lookAhead(0) == '=' ){
+ lex->nextToken();
+
+ AST::Node typeId;
+ if( !parseTypeId(typeId) ){
+ syntaxError();
+ return false;
+ }
+ ast->setTypeId( typeId );
+ }
+ }
+
+ if( lex->lookAhead(0) == '=' ){
+ lex->nextToken();
+
+ NameAST::Node templ_name;
+ parseName( templ_name );
+ }
+ }
+ break;
+
+ default:
+ return false;
+
+ } // end switch
+
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+}
+
+bool Parser::parseStorageClassSpecifier( GroupAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseStorageClassSpecifier()" << endl;
+
+ int start = lex->index();
+ GroupAST::Node ast = CreateNode<GroupAST>();
+
+ while( !lex->lookAhead(0).isNull() ){
+ int tk = lex->lookAhead( 0 );
+ if( tk == Token_friend || tk == Token_auto || tk == Token_register || tk == Token_static ||
+ tk == Token_extern || tk == Token_mutable ){
+ int startNode = lex->index();
+ lex->nextToken();
+
+ AST::Node n = CreateNode<AST>();
+ UPDATE_POS( n, startNode, lex->index() );
+ ast->addNode( n );
+ } else
+ break;
+ }
+
+ if( ast->nodeList().count() == 0 )
+ return false;
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+}
+
+bool Parser::parseFunctionSpecifier( GroupAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseFunctionSpecifier()" << endl;
+
+ int start = lex->index();
+ GroupAST::Node ast = CreateNode<GroupAST>();
+
+ while( !lex->lookAhead(0).isNull() ){
+ int tk = lex->lookAhead( 0 );
+ if( tk == Token_inline || tk == Token_virtual || tk == Token_explicit ){
+ int startNode = lex->index();
+ lex->nextToken();
+
+ AST::Node n = CreateNode<AST>();
+ UPDATE_POS( n, startNode, lex->index() );
+ ast->addNode( n );
+ } else {
+ break;
+ }
+ }
+
+ if( ast->nodeList().count() == 0 )
+ return false;
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+}
+
+bool Parser::parseTypeId( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTypeId()" << endl;
+
+ /// @todo implement the AST for typeId
+ int start = lex->index();
+ AST::Node ast = CreateNode<AST>();
+
+ TypeSpecifierAST::Node spec;
+ if( !parseTypeSpecifier(spec) ){
+ return false;
+ }
+
+ DeclaratorAST::Node decl;
+ parseAbstractDeclarator( decl );
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseInitDeclaratorList( InitDeclaratorListAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseInitDeclaratorList()" << endl;
+
+ int start = lex->index();
+
+ InitDeclaratorListAST::Node ast = CreateNode<InitDeclaratorListAST>();
+ InitDeclaratorAST::Node decl;
+
+ if( !parseInitDeclarator(decl) ){
+ return false;
+ }
+ ast->addInitDeclarator( decl );
+
+ QString comment;
+ while( lex->lookAhead(0) == ',' ){
+ comment = "";
+ advanceAndCheckTrailingComment( comment );
+
+ if( !parseInitDeclarator(decl) ){
+ syntaxError();
+ break;
+ }
+ if ( !comment.isEmpty() )
+ decl->setComment( comment );
+ ast->addInitDeclarator( decl );
+ }
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseInitDeclaratorList() -- end" << endl;
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseParameterDeclarationClause( ParameterDeclarationClauseAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseParameterDeclarationClause()" << endl;
+
+ int start = lex->index();
+
+ ParameterDeclarationClauseAST::Node ast = CreateNode<ParameterDeclarationClauseAST>();
+
+ ParameterDeclarationListAST::Node params;
+ if( !parseParameterDeclarationList(params) ){
+
+ if ( lex->lookAhead(0) == ')' )
+ goto good;
+
+ if( lex->lookAhead(0) == Token_ellipsis && lex->lookAhead(1) == ')' ){
+ AST_FROM_TOKEN( ellipsis, lex->index() );
+ ast->setEllipsis( ellipsis );
+ lex->nextToken();
+ goto good;
+ }
+ return false;
+ }
+
+ if( lex->lookAhead(0) == Token_ellipsis ){
+ AST_FROM_TOKEN( ellipsis, lex->index() );
+ ast->setEllipsis( ellipsis );
+ lex->nextToken();
+ }
+
+good:
+ ast->setParameterDeclarationList( params );
+
+ /// @todo add ellipsis
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseParameterDeclarationList( ParameterDeclarationListAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseParameterDeclarationList()" << endl;
+
+ int start = lex->index();
+
+ ParameterDeclarationListAST::Node ast = CreateNode<ParameterDeclarationListAST>();
+
+ ParameterDeclarationAST::Node param;
+ if( !parseParameterDeclaration(param) ){
+ lex->setIndex( start );
+ return false;
+ }
+ ast->addParameter( param );
+
+ QString comment;
+ while( lex->lookAhead(0) == ',' ){
+ comment = QString::null;
+ advanceAndCheckTrailingComment( comment );
+
+ if( lex->lookAhead(0) == Token_ellipsis )
+ break;
+
+ if( !parseParameterDeclaration(param) ){
+ lex->setIndex( start );
+ return false;
+ }
+ if (!comment.isEmpty())
+ param->setComment(comment);
+ ast->addParameter( param );
+ }
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseParameterDeclaration( ParameterDeclarationAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseParameterDeclaration()" << endl;
+
+ int start = lex->index();
+
+ // parse decl spec
+ TypeSpecifierAST::Node spec;
+ if( !parseTypeSpecifier(spec) ){
+ lex->setIndex( start );
+ return false;
+ }
+
+ int index = lex->index();
+
+ DeclaratorAST::Node decl;
+ if( !parseDeclarator(decl) ){
+ lex->setIndex( index );
+
+ // try with abstract declarator
+ if( !parseAbstractDeclarator(decl) )
+ return false;
+ }
+
+ AST::Node expr;
+ if( lex->lookAhead(0) == '=' ){
+ lex->nextToken();
+ if( !parseLogicalOrExpression(expr,true) ){
+ //reportError( i18n("Expression expected") );
+ }
+ }
+
+ ParameterDeclarationAST::Node ast = CreateNode<ParameterDeclarationAST>();
+ ast->setTypeSpec( spec );
+ ast->setDeclarator( decl );
+ ast->setExpression( expr );
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseClassSpecifier( TypeSpecifierAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseClassSpecifier()" << endl;
+
+ int start = lex->index();
+
+ AST::Node classKey;
+ int classKeyStart = lex->index();
+
+ int kind = lex->lookAhead( 0 );
+ if( kind == Token_class || kind == Token_struct || kind == Token_union ){
+ AST::Node asn = CreateNode<AST>();
+ classKey = asn;
+ lex->nextToken();
+ UPDATE_POS( classKey, classKeyStart, lex->index() );
+ } else {
+ return false;
+ }
+
+ GroupAST::Node winDeclSpec;
+ parseWinDeclSpec( winDeclSpec );
+
+ while( lex->lookAhead(0) == Token_identifier && lex->lookAhead(1) == Token_identifier )
+ lex->nextToken();
+
+ NameAST::Node name;
+ parseName( name );
+
+ BaseClauseAST::Node bases;
+ if( lex->lookAhead(0) == ':' ){
+ if( !parseBaseClause(bases) ){
+ skipUntil( '{' );
+ }
+ }
+
+ QString comment;
+ while (lex->lookAhead(0) == Token_comment) {
+ comment += lex->lookAhead(0).text();
+ lex->nextToken();
+ }
+ if( lex->lookAhead(0) != '{' ){
+ lex->setIndex( start );
+ return false;
+ }
+
+ ADVANCE( '{', '{' );
+
+ ClassSpecifierAST::Node ast = CreateNode<ClassSpecifierAST>();
+ ast->setWinDeclSpec( winDeclSpec );
+ ast->setClassKey( classKey );
+ ast->setName( name );
+ ast->setBaseClause( bases );
+
+ while( !lex->lookAhead(0).isNull() ){
+ if( lex->lookAhead(0) == '}' )
+ break;
+
+ DeclarationAST::Node memSpec = CreateNode<DeclarationAST>();
+ int startDecl = lex->index();
+ if( !parseMemberSpecification(memSpec) ){
+ if( startDecl == lex->index() )
+ lex->nextToken(); // skip at least one token
+ skipUntilDeclaration();
+ } else
+ ast->addDeclaration( memSpec );
+ }
+
+ if( lex->lookAhead(0) != '}' ){
+ reportError( i18n("} missing") );
+ } else
+ lex->nextToken();
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseAccessSpecifier( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseAccessSpecifier()" << endl;
+
+ int start = lex->index();
+
+ switch( lex->lookAhead(0) ){
+ case Token_public:
+ case Token_protected:
+ case Token_private: {
+ AST::Node asn = CreateNode<AST>();
+ node = asn;
+ lex->nextToken();
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void Parser::advanceAndCheckTrailingComment(QString& comment)
+{
+ Token t = lex->tokenAt( lex->index() );
+ int previousTokenEndLine = 0;
+ t.getEndPosition( &previousTokenEndLine, 0 );
+ lex->nextToken();
+ if( lex->lookAhead(0) != Token_comment )
+ return;
+ t = lex->tokenAt( lex->index() );
+ int commentStartLine = 0;
+ t.getStartPosition( &commentStartLine, 0 );
+ if( commentStartLine != previousTokenEndLine )
+ return;
+ comment += lex->lookAhead(0).text();
+ lex->nextToken();
+}
+
+bool Parser::parseMemberSpecification( DeclarationAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseMemberSpecification()" << endl;
+
+ QString comment;
+ while( lex->lookAhead(0) == Token_comment ) {
+ comment += lex->lookAhead(0).text();
+ lex->nextToken();
+ }
+ if( lex->lookAhead(0).isNull() )
+ return false;
+
+ int start = lex->index();
+
+ AST::Node access;
+
+ if( lex->lookAhead(0) == ';' ){
+ advanceAndCheckTrailingComment( comment );
+ if ( !comment.isEmpty() )
+ node->setComment( comment );
+ return true;
+ } else if( lex->lookAhead(0) == Token_Q_OBJECT || lex->lookAhead(0) == Token_K_DCOP ){
+ lex->nextToken();
+ return true;
+ } else if( lex->lookAhead(0) == Token_signals || lex->lookAhead(0) == Token_k_dcop || lex->lookAhead(0) == Token_k_dcop_signals ){
+ AccessDeclarationAST::Node ast = CreateNode<AccessDeclarationAST>();
+ lex->nextToken();
+ AST::Node n = CreateNode<AST>();
+ UPDATE_POS( n, start, lex->index() );
+ ast->addAccess( n );
+ ADVANCE( ':', ":" );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+ } else if( parseTypedef(node) ){
+ return true;
+ } else if( parseUsing(node) ){
+ return true;
+ } else if( parseTemplateDeclaration(node) ){
+ return true;
+ } else if( parseAccessSpecifier(access) ){
+ AccessDeclarationAST::Node ast = CreateNode<AccessDeclarationAST>();
+ ast->addAccess( access );
+
+ int startSlot = lex->index();
+ if( lex->lookAhead(0) == Token_slots ){
+ lex->nextToken();
+ AST::Node sl = CreateNode<AST>();
+ UPDATE_POS( sl, startSlot, lex->index() );
+ ast->addAccess( sl );
+ }
+ ADVANCE( ':', ":" );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+ }
+
+ lex->setIndex( start );
+
+ GroupAST::Node storageSpec;
+ parseStorageClassSpecifier( storageSpec );
+
+ GroupAST::Node cv;
+ parseCvQualify( cv );
+
+ TypeSpecifierAST::Node spec;
+ if( parseEnumSpecifier(spec) || parseClassSpecifier(spec) ){
+ spec->setCvQualify( cv );
+
+ GroupAST::Node cv2;
+ parseCvQualify( cv2 );
+ spec->setCv2Qualify( cv2 );
+
+ InitDeclaratorListAST::Node declarators;
+ parseInitDeclaratorList( declarators );
+ ADVANCE( ';', ";" );
+
+ if( !comment.isEmpty() ) {
+ //kdDebug(9007) << "Parser::parseMemberSpecification(spec): comment is " << comment << endl;
+ spec->setComment( comment );
+ }
+
+ SimpleDeclarationAST::Node ast = CreateNode<SimpleDeclarationAST>();
+ ast->setTypeSpec( spec );
+ ast->setInitDeclaratorList( declarators );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+ }
+
+ lex->setIndex( start );
+
+ bool success = parseDeclarationInternal(node, comment);
+ if( success && !comment.isEmpty() ) {
+ node->setComment( comment );
+ //kdDebug(9007) << "Parser::parseMemberSpecification(): comment is " << comment << endl;
+ }
+ return success;
+}
+
+bool Parser::parseCtorInitializer( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseCtorInitializer()" << endl;
+
+ if( lex->lookAhead(0) != ':' ){
+ return false;
+ }
+ lex->nextToken();
+
+ AST::Node inits;
+ if( !parseMemInitializerList(inits) ){
+ reportError( i18n("Member initializers expected") );
+ }
+
+ return true;
+}
+
+bool Parser::parseElaboratedTypeSpecifier( TypeSpecifierAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseElaboratedTypeSpecifier()" << endl;
+
+ int start = lex->index();
+
+ int tk = lex->lookAhead( 0 );
+ if( tk == Token_class ||
+ tk == Token_struct ||
+ tk == Token_union ||
+ tk == Token_enum ||
+ tk == Token_typename )
+ {
+ AST::Node kind = CreateNode<AST>();
+ lex->nextToken();
+ UPDATE_POS( kind, start, lex->index() );
+
+ NameAST::Node name;
+
+ if( parseName(name) ){
+ ElaboratedTypeSpecifierAST::Node ast = CreateNode<ElaboratedTypeSpecifierAST>();
+ ast->setKind( kind );
+ ast->setName( name );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+ }
+ }
+
+ lex->setIndex( start );
+ return false;
+}
+
+bool Parser::parseDeclaratorId( NameAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseDeclaratorId()" << endl;
+ return parseName( node );
+}
+
+bool Parser::parseExceptionSpecification( GroupAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseExceptionSpecification()" << endl;
+
+ if( lex->lookAhead(0) != Token_throw ){
+ return false;
+ }
+ lex->nextToken();
+
+ ADVANCE( '(', "(" );
+ if( lex->lookAhead(0) == Token_ellipsis ){
+ // extension found in MSVC++ 7.x headers
+ int start = lex->index();
+ GroupAST::Node ast = CreateNode<GroupAST>();
+ AST_FROM_TOKEN( ellipsis, lex->index() );
+ ast->addNode( ellipsis );
+ lex->nextToken();
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ } else {
+ parseTypeIdList( node );
+ }
+ ADVANCE( ')', ")" );
+
+ return true;
+}
+
+bool Parser::parseEnumerator( EnumeratorAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseEnumerator()" << endl;
+
+ QString comment;
+ while( lex->lookAhead(0) == Token_comment ) {
+ comment += lex->lookAhead(0).text();
+ lex->nextToken();
+ }
+ if( lex->lookAhead(0).isNull() )
+ return false;
+
+ int start = lex->index();
+
+ if( lex->lookAhead(0) != Token_identifier ){
+ return false;
+ }
+ lex->nextToken();
+
+ EnumeratorAST::Node ena = CreateNode<EnumeratorAST>();
+ node = ena;
+
+ AST::Node id = CreateNode<AST>();
+ UPDATE_POS( id, start, lex->index() );
+ node->setId( id );
+
+ if( lex->lookAhead(0) == '=' ){
+ lex->nextToken();
+
+ AST::Node expr;
+ if( !parseConstantExpression(expr) ){
+ reportError( i18n("Constant expression expected") );
+ }
+ node->setExpr( expr );
+ }
+
+ UPDATE_POS( node, start, lex->index() );
+
+ return true;
+}
+
+bool Parser::parseInitDeclarator( InitDeclaratorAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseInitDeclarator()" << endl;
+
+ int start = lex->index();
+
+ DeclaratorAST::Node decl;
+ AST::Node init;
+ if( !parseDeclarator(decl) ){
+ return false;
+ }
+
+ parseInitializer( init );
+
+ InitDeclaratorAST::Node ast = CreateNode<InitDeclaratorAST>();
+ ast->setDeclarator( decl );
+ ast->setInitializer( init );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+
+
+bool Parser::parseBaseClause( BaseClauseAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseBaseClause()" << endl;
+
+ int start = lex->index();
+ if( lex->lookAhead(0) != ':' ){
+ return false;
+ }
+ lex->nextToken();
+
+ BaseClauseAST::Node bca = CreateNode<BaseClauseAST>();
+
+ BaseSpecifierAST::Node baseSpec;
+ if( parseBaseSpecifier(baseSpec) ){
+ bca->addBaseSpecifier( baseSpec );
+
+ QString comment;
+ while( lex->lookAhead(0) == ',' ){
+ comment = QString::null;
+ advanceAndCheckTrailingComment( comment );
+
+ if( !parseBaseSpecifier(baseSpec) ){
+ reportError( i18n("Base class specifier expected") );
+ return false;
+ }
+ if (!comment.isEmpty())
+ baseSpec->setComment(comment);
+ bca->addBaseSpecifier( baseSpec );
+ }
+ } else
+ return false;
+
+ UPDATE_POS( bca, start, lex->index() );
+ node = bca;
+
+ return true;
+}
+
+bool Parser::parseInitializer( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseInitializer()" << endl;
+
+ if( lex->lookAhead(0) == '=' ){
+ lex->nextToken();
+
+ AST::Node init;
+ if( !parseInitializerClause(node) ){
+ reportError( i18n("Initializer clause expected") );
+ return false;
+ }
+ } else if( lex->lookAhead(0) == '(' ){
+ lex->nextToken();
+ AST::Node expr;
+ skipCommaExpression( expr );
+
+ ADVANCE( ')', ")" );
+ }
+
+ return false;
+}
+
+bool Parser::parseMemInitializerList( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseMemInitializerList()" << endl;
+
+ AST::Node init;
+ if( !parseMemInitializer(init) ){
+ return false;
+ }
+
+ QString comment;
+ while( lex->lookAhead(0) == ',' ){
+ comment = QString::null;
+ advanceAndCheckTrailingComment( comment );
+
+ if( parseMemInitializer(init) ){
+ } else {
+ break;
+ }
+ }
+
+ return true;
+}
+
+bool Parser::parseMemInitializer( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseMemInitializer()" << endl;
+
+ NameAST::Node initId;
+ if( !parseMemInitializerId(initId) ){
+ reportError( i18n("Identifier expected") );
+ return false;
+ }
+ ADVANCE( '(', '(' );
+ AST::Node expr;
+ skipCommaExpression( expr );
+ ADVANCE( ')', ')' );
+
+ return true;
+}
+
+bool Parser::parseTypeIdList( GroupAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTypeIdList()" << endl;
+
+ int start = lex->index();
+
+ AST::Node typeId;
+ if( !parseTypeId(typeId) ){
+ return false;
+ }
+
+ GroupAST::Node ast = CreateNode<GroupAST>();
+ ast->addNode( typeId );
+
+ QString comment;
+ while( lex->lookAhead(0) == ',' ){
+ comment = QString::null;
+ advanceAndCheckTrailingComment( comment );
+ if( parseTypeId(typeId) ){
+ if (!comment.isEmpty())
+ typeId->setComment(comment);
+ ast->addNode( typeId );
+ } else {
+ reportError( i18n("Type id expected") );
+ break;
+ }
+ }
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+}
+
+bool Parser::parseBaseSpecifier( BaseSpecifierAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseBaseSpecifier()" << endl;
+
+ int start = lex->index();
+ BaseSpecifierAST::Node ast = CreateNode<BaseSpecifierAST>();
+
+ AST::Node access;
+ if( lex->lookAhead(0) == Token_virtual ){
+ AST_FROM_TOKEN( virt, lex->index() );
+ ast->setIsVirtual( virt );
+
+ lex->nextToken();
+
+ parseAccessSpecifier( access );
+ } else {
+ parseAccessSpecifier( access );
+
+ if( lex->lookAhead(0) == Token_virtual ){
+ AST_FROM_TOKEN( virt, lex->index() );
+ ast->setIsVirtual( virt );
+ lex->nextToken();
+ }
+ }
+
+ NameAST::Node name;
+ if( !parseName(name) ){
+ reportError( i18n("Class name expected") );
+ }
+
+ ast->setAccess( access );
+ ast->setName( name );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+
+bool Parser::parseInitializerClause( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseInitializerClause()" << endl;
+
+ if( lex->lookAhead(0) == '{' ){
+ if( !skip('{','}') ){
+ reportError( i18n("} missing") );
+ } else
+ lex->nextToken();
+ } else {
+ if( !parseAssignmentExpression(node) ){
+ //reportError( i18n("Expression expected") );
+ }
+ }
+
+ return true;
+}
+
+bool Parser::parseMemInitializerId( NameAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseMemInitializerId()" << endl;
+
+ return parseName( node );
+}
+
+bool Parser::parsePtrToMember( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parsePtrToMember()" << endl;
+
+ if( lex->lookAhead(0) == Token_scope ){
+ lex->nextToken();
+ }
+
+ while( lex->lookAhead(0) == Token_identifier ){
+ lex->nextToken();
+
+ if( lex->lookAhead(0) == Token_scope && lex->lookAhead(1) == '*' ){
+ lex->nextToken(); // skip ::
+ lex->nextToken(); // skip *
+ return true;
+ } else
+ break;
+ }
+
+ return false;
+}
+
+bool Parser::parseUnqualifiedName( ClassOrNamespaceNameAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseUnqualifiedName()" << endl;
+
+ int start = lex->index();
+ bool isDestructor = false;
+
+ ClassOrNamespaceNameAST::Node ast = CreateNode<ClassOrNamespaceNameAST>();
+
+ if( lex->lookAhead(0) == Token_identifier ){
+ int startName = lex->index();
+ AST::Node n = CreateNode<AST>();
+ lex->nextToken();
+ UPDATE_POS( n, startName, lex->index() );
+ ast->setName( n );
+ } else if( lex->lookAhead(0) == '~' && lex->lookAhead(1) == Token_identifier ){
+ int startName = lex->index();
+ AST::Node n = CreateNode<AST>();
+ lex->nextToken(); // skip ~
+ lex->nextToken(); // skip classname
+ UPDATE_POS( n, startName, lex->index() );
+ ast->setName( n );
+ isDestructor = true;
+ } else if( lex->lookAhead(0) == Token_operator ){
+ AST::Node n;
+ if( !parseOperatorFunctionId(n) )
+ return false;
+ ast->setName( n );
+ } else {
+ return false;
+ }
+
+ if( !isDestructor ){
+
+ int index = lex->index();
+
+ if( lex->lookAhead(0) == '<' ){
+ lex->nextToken();
+
+ // optional template arguments
+ TemplateArgumentListAST::Node args;
+ parseTemplateArgumentList( args );
+
+ if( lex->lookAhead(0) != '>' ){
+ lex->setIndex( index );
+ } else {
+ lex->nextToken();
+ ast->setTemplateArgumentList( args );
+ }
+ }
+ }
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseStringLiteral( AST::Node& /*node*/ )
+{
+ while( !lex->lookAhead(0).isNull() ) {
+ if( lex->lookAhead(0) == Token_identifier &&
+ lex->lookAhead(0).text() == "L" && lex->lookAhead(1) == Token_string_literal ) {
+
+ lex->nextToken();
+ lex->nextToken();
+ } else if( lex->lookAhead(0) == Token_string_literal ) {
+ lex->nextToken();
+ } else
+ return false;
+ }
+ return true;
+}
+
+bool Parser::skipExpressionStatement( StatementAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::skipExpressionStatement()" << endl;
+
+ int start = lex->index();
+
+ AST::Node expr;
+ skipCommaExpression( expr );
+
+ ADVANCE( ';', ";" );
+
+ ExpressionStatementAST::Node ast = CreateNode<ExpressionStatementAST>();
+ ast->setExpression( expr );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseStatement( StatementAST::Node& node ) // thanks to fiore@8080.it ;)
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseStatement()" << endl;
+ switch( lex->lookAhead(0) ){
+
+ 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:
+ lex->nextToken();
+ ADVANCE( ';', ";" );
+ return true;
+
+ case Token_goto:
+ lex->nextToken();
+ ADVANCE( Token_identifier, "identifier" );
+ ADVANCE( ';', ";" );
+ return true;
+
+ case Token_return:
+ {
+ lex->nextToken();
+ AST::Node expr;
+ skipCommaExpression( expr );
+ ADVANCE( ';', ";" );
+ }
+ return true;
+
+ case '{':
+ return parseCompoundStatement( node );
+
+ case Token_identifier:
+ if( parseLabeledStatement(node) )
+ return true;
+ break;
+ }
+
+ //kdDebug(9007)<< "------------> try with declaration statement" << endl;
+ if ( parseDeclarationStatement(node) )
+ return true;
+
+ return skipExpressionStatement( node );
+}
+
+bool Parser::parseCondition( ConditionAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseCondition()" << endl;
+
+ int start = lex->index();
+
+ ConditionAST::Node ast = CreateNode<ConditionAST>();
+
+ TypeSpecifierAST::Node spec;
+ if( parseTypeSpecifier(spec) ){
+ DeclaratorAST::Node decl;
+ if( parseDeclarator(decl) && lex->lookAhead(0) == '=' ) {
+ lex->nextToken();
+
+ AST::Node expr;
+ if( skipExpression(expr) ){
+ ast->setTypeSpec( spec );
+ ast->setDeclarator( decl );
+ ast->setExpression( expr );
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+ }
+ }
+ }
+
+ lex->setIndex( start );
+
+ AST::Node expr;
+ if( !skipCommaExpression(expr) )
+ return false;
+
+ ast->setExpression( expr );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+}
+
+
+bool Parser::parseWhileStatement( StatementAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseWhileStatement()" << endl;
+ int start = lex->index();
+
+ ADVANCE( Token_while, "while" );
+ ADVANCE( '(' , "(" );
+
+ ConditionAST::Node cond;
+ if( !parseCondition(cond) ){
+ reportError( i18n("condition expected") );
+ return false;
+ }
+ ADVANCE( ')', ")" );
+
+ StatementAST::Node body;
+ if( !parseStatement(body) ){
+ reportError( i18n("statement expected") );
+ return false;
+ }
+
+ WhileStatementAST::Node ast = CreateNode<WhileStatementAST>();
+ ast->setCondition( cond );
+ ast->setStatement( body );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseDoStatement( StatementAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseDoStatement()" << endl;
+ int start = lex->index();
+
+ ADVANCE( Token_do, "do" );
+
+ StatementAST::Node body;
+ if( !parseStatement(body) ){
+ reportError( i18n("statement expected") );
+ //return false;
+ }
+
+ ADVANCE_NR( Token_while, "while" );
+ ADVANCE_NR( '(' , "(" );
+
+ AST::Node expr;
+ if( !skipCommaExpression(expr) ){
+ reportError( i18n("expression expected") );
+ //return false;
+ }
+
+ ADVANCE_NR( ')', ")" );
+ ADVANCE_NR( ';', ";" );
+
+ DoStatementAST::Node ast = CreateNode<DoStatementAST>();
+ ast->setStatement( body );
+ //ast->setCondition( condition );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseForStatement( StatementAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseForStatement()" << endl;
+ int start = lex->index();
+
+ ADVANCE( Token_for, "for" );
+ ADVANCE( '(', "(" );
+
+ StatementAST::Node init;
+ if( !parseForInitStatement(init) ){
+ reportError( i18n("for initialization expected") );
+ return false;
+ }
+
+ ConditionAST::Node cond;
+ parseCondition( cond );
+ ADVANCE( ';', ";" );
+
+ AST::Node expr;
+ skipCommaExpression( expr );
+ ADVANCE( ')', ")" );
+
+ StatementAST::Node body;
+ if( !parseStatement(body) )
+ return false;
+
+ ForStatementAST::Node ast = CreateNode<ForStatementAST>();
+ ast->setInitStatement( init );
+ ast->setCondition( cond );
+ // ast->setExpression( expression );
+ ast->setStatement( body );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseForInitStatement( StatementAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseForInitStatement()" << endl;
+
+ if ( parseDeclarationStatement(node) )
+ return true;
+
+ return skipExpressionStatement( node );
+}
+
+bool Parser::parseCompoundStatement( StatementAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseCompoundStatement()" << endl;
+ int start = lex->index();
+
+ if( lex->lookAhead(0) != '{' ){
+ return false;
+ }
+ lex->nextToken();
+
+ StatementListAST::Node ast = CreateNode<StatementListAST>();
+
+ while( !lex->lookAhead(0).isNull() ){
+ if( lex->lookAhead(0) == '}' )
+ break;
+
+ StatementAST::Node stmt;
+ int startStmt = lex->index();
+ if( !parseStatement(stmt) ){
+ if( startStmt == lex->index() )
+ lex->nextToken();
+ skipUntilStatement();
+ } else {
+ ast->addStatement( stmt );
+ }
+ }
+
+ if( lex->lookAhead(0) != '}' ){
+ reportError( i18n("} expected") );
+ } else {
+ lex->nextToken();
+ }
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseIfStatement( StatementAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseIfStatement()" << endl;
+
+ int start = lex->index();
+
+ ADVANCE( Token_if, "if" );
+
+ ADVANCE( '(' , "(" );
+
+ IfStatementAST::Node ast = CreateNode<IfStatementAST>();
+
+ ConditionAST::Node cond;
+ if( !parseCondition(cond) ){
+ reportError( i18n("condition expected") );
+ return false;
+ }
+ ADVANCE( ')', ")" );
+
+ StatementAST::Node stmt;
+ if( !parseStatement(stmt) ){
+ reportError( i18n("statement expected") );
+ return false;
+ }
+
+ ast->setCondition( cond );
+ ast->setStatement( stmt );
+
+ if( lex->lookAhead(0) == Token_else ){
+ lex->nextToken();
+ StatementAST::Node elseStmt;
+ if( !parseStatement(elseStmt) ) {
+ reportError( i18n("statement expected") );
+ return false;
+ }
+ ast->setElseStatement( elseStmt );
+ }
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseSwitchStatement( StatementAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseSwitchStatement()" << endl;
+ int start = lex->index();
+ ADVANCE( Token_switch, "switch" );
+
+ ADVANCE( '(' , "(" );
+
+ ConditionAST::Node cond;
+ if( !parseCondition(cond) ){
+ reportError( i18n("condition expected") );
+ return false;
+ }
+ ADVANCE( ')', ")" );
+
+ StatementAST::Node stmt;
+ if( !parseCompoundStatement(stmt) ){
+ syntaxError();
+ return false;
+ }
+
+ SwitchStatementAST::Node ast = CreateNode<SwitchStatementAST>();
+ ast->setCondition( cond );
+ ast->setStatement( stmt );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseLabeledStatement( StatementAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseLabeledStatement()" << endl;
+ switch( lex->lookAhead(0) ){
+ case Token_identifier:
+ case Token_default:
+ if( lex->lookAhead(1) == ':' ){
+ lex->nextToken();
+ lex->nextToken();
+
+ StatementAST::Node stmt;
+ if( parseStatement(stmt) ){
+ node = stmt;
+ return true;
+ }
+ }
+ break;
+
+ case Token_case:
+ {
+ lex->nextToken();
+ AST::Node expr;
+ if( !parseConstantExpression(expr) ){
+ reportError( i18n("expression expected") );
+ } else if( lex->lookAhead(0) == Token_ellipsis ){
+ lex->nextToken();
+
+ AST::Node expr2;
+ if( !parseConstantExpression(expr2) ){
+ reportError( i18n("expression expected") );
+ }
+ }
+ ADVANCE( ':', ":" );
+
+ StatementAST::Node stmt;
+ if( parseStatement(stmt) ){
+ node = stmt;
+ return true;
+ }
+ }
+ break;
+
+ }
+
+ return false;
+}
+
+bool Parser::parseBlockDeclaration( DeclarationAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseBlockDeclaration()" << endl;
+ switch( lex->lookAhead(0) ) {
+ case Token_typedef:
+ return parseTypedef( node );
+ case Token_using:
+ return parseUsing( node );
+ case Token_asm:
+ return parseAsmDefinition( node );
+ case Token_namespace:
+ return parseNamespaceAliasDefinition( node );
+ }
+
+ int start = lex->index();
+
+ GroupAST::Node storageSpec;
+ parseStorageClassSpecifier( storageSpec );
+
+ GroupAST::Node cv;
+ parseCvQualify( cv );
+
+ TypeSpecifierAST::Node spec;
+ if ( !parseTypeSpecifierOrClassSpec(spec) ) { // replace with simpleTypeSpecifier?!?!
+ lex->setIndex( start );
+ return false;
+ }
+ spec->setCvQualify( cv );
+
+ GroupAST::Node cv2;
+ parseCvQualify( cv2 );
+ spec->setCv2Qualify( cv2 );
+
+ InitDeclaratorListAST::Node declarators;
+ parseInitDeclaratorList( declarators );
+
+ if( lex->lookAhead(0) != ';' ){
+ lex->setIndex( start );
+ return false;
+ }
+ lex->nextToken();
+
+ SimpleDeclarationAST::Node ast = CreateNode<SimpleDeclarationAST>();
+ ast->setTypeSpec( spec );
+ ast->setInitDeclaratorList( declarators );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseNamespaceAliasDefinition( DeclarationAST::Node& /*node*/ )
+{
+ if ( lex->lookAhead(0) != Token_namespace ) {
+ return false;
+ }
+ lex->nextToken();
+
+ ADVANCE( Token_identifier, "identifier" );
+ ADVANCE( '=', "=" );
+
+ NameAST::Node name;
+ if( !parseName(name) ){
+ reportError( i18n("Namespace name expected") );
+ }
+
+ ADVANCE( ';', ";" );
+
+ return true;
+
+}
+
+bool Parser::parseDeclarationStatement( StatementAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseDeclarationStatement()" << endl;
+
+ int start = lex->index();
+
+ DeclarationAST::Node decl;
+ if ( !parseBlockDeclaration(decl) ){
+ return false;
+ }
+
+ DeclarationStatementAST::Node ast = CreateNode<DeclarationStatementAST>();
+ ast->setDeclaration( decl );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ //kdDebug(9007)<< "---------------------> found a block declaration" << endl;
+ return true;
+}
+
+bool Parser::parseDeclarationInternal( DeclarationAST::Node& node, QString& comment )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseDeclarationInternal()" << endl;
+
+ int start = lex->index();
+
+ // that is for the case '__declspec(dllexport) int ...' or
+ // '__declspec(dllexport) inline int ...', etc.
+ GroupAST::Node winDeclSpec;
+ parseWinDeclSpec( winDeclSpec );
+
+ GroupAST::Node funSpec;
+ bool hasFunSpec = parseFunctionSpecifier( funSpec );
+
+ GroupAST::Node storageSpec;
+ bool hasStorageSpec = parseStorageClassSpecifier( storageSpec );
+
+ if( hasStorageSpec && !hasFunSpec )
+ hasFunSpec = parseFunctionSpecifier( funSpec );
+
+ // that is for the case 'friend __declspec(dllexport) ....'
+ GroupAST::Node winDeclSpec2;
+ parseWinDeclSpec( winDeclSpec2 );
+
+ GroupAST::Node cv;
+ parseCvQualify( cv );
+
+ int index = lex->index();
+ NameAST::Node name;
+ if( parseName(name) && lex->lookAhead(0) == '(' ){
+ // no type specifier, maybe a constructor or a cast operator??
+
+ lex->setIndex( index );
+
+ InitDeclaratorAST::Node declarator;
+ if( parseInitDeclarator(declarator) ){
+ int endSignature = lex->index();
+
+ switch( lex->lookAhead(0) ){
+ case ';':
+ {
+ lex->nextToken();
+
+ InitDeclaratorListAST::Node declarators = CreateNode<InitDeclaratorListAST>();
+
+ // update declarators position
+ int startLine, startColumn, endLine, endColumn;
+ if( declarator.get() ){
+ declarator->getStartPosition( &startLine, &startColumn );
+ declarator->getEndPosition( &endLine, &endColumn );
+ declarators->setStartPosition( startLine, startColumn );
+ declarators->setEndPosition( endLine, endColumn );
+ }
+ declarators->addInitDeclarator( declarator );
+
+ SimpleDeclarationAST::Node ast = CreateNode<SimpleDeclarationAST>();
+ ast->setInitDeclaratorList( declarators );
+ ast->setText( toString(start, endSignature) );
+ node = ast;
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+
+ }
+ break;
+
+ case ':':
+ {
+ AST::Node ctorInit;
+ StatementListAST::Node funBody;
+ if( parseCtorInitializer(ctorInit) && parseFunctionBody(funBody) ){
+ FunctionDefinitionAST::Node ast = CreateNode<FunctionDefinitionAST>();
+ ast->setStorageSpecifier( storageSpec );
+ ast->setFunctionSpecifier( funSpec );
+ ast->setInitDeclarator( declarator );
+ ast->setFunctionBody( funBody );
+ ast->setText( toString(start, endSignature) );
+ node = ast;
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+ }
+ }
+ break;
+
+ case '{':
+ {
+ StatementListAST::Node funBody;
+ if( parseFunctionBody(funBody) ){
+ FunctionDefinitionAST::Node ast = CreateNode<FunctionDefinitionAST>();
+ ast->setStorageSpecifier( storageSpec );
+ ast->setFunctionSpecifier( funSpec );
+ ast->setInitDeclarator( declarator );
+ ast->setText( toString(start, endSignature) );
+ ast->setFunctionBody( funBody );
+ node = ast;
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+ }
+ }
+ break;
+
+ case '(':
+ case '[':
+ // ops!! it seems a declarator
+ goto start_decl;
+ break;
+ }
+
+ }
+
+ syntaxError();
+ return false;
+ }
+
+start_decl:
+ lex->setIndex( index );
+
+ if( lex->lookAhead(0) == Token_const && lex->lookAhead(1) == Token_identifier && lex->lookAhead(2) == '=' ){
+ // constant definition
+ lex->nextToken();
+ InitDeclaratorListAST::Node declarators;
+ if( parseInitDeclaratorList(declarators) ){
+ ADVANCE( ';', ";" );
+ DeclarationAST::Node ast = CreateNode<DeclarationAST>();
+ node = ast;
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+ }
+ syntaxError();
+ return false;
+ }
+
+ TypeSpecifierAST::Node spec;
+ if( parseTypeSpecifier(spec) ){
+ if ( !hasFunSpec )
+ parseFunctionSpecifier( funSpec ); // e.g. "void inline"
+ spec->setCvQualify( cv );
+
+ InitDeclaratorListAST::Node declarators;
+
+ InitDeclaratorAST::Node decl;
+ int startDeclarator = lex->index();
+ bool maybeFunctionDefinition = false;
+
+ if( lex->lookAhead(0) != ';' ){
+ if( parseInitDeclarator(decl) && lex->lookAhead(0) == '{' ){
+ // function definition
+ maybeFunctionDefinition = true;
+ } else {
+ lex->setIndex( startDeclarator );
+ if( !parseInitDeclaratorList(declarators) ){
+ syntaxError();
+ return false;
+ }
+ }
+ }
+
+ int endSignature = lex->index();
+ switch( lex->lookAhead(0) ){
+ case ';':
+ {
+ advanceAndCheckTrailingComment( comment );
+ SimpleDeclarationAST::Node ast = CreateNode<SimpleDeclarationAST>();
+ ast->setStorageSpecifier( storageSpec );
+ ast->setFunctionSpecifier( funSpec );
+ ast->setText( toString(start, endSignature) );
+ ast->setTypeSpec( spec );
+ ast->setWinDeclSpec( winDeclSpec );
+ ast->setInitDeclaratorList( declarators );
+ node = ast;
+ UPDATE_POS( node, start, lex->index() );
+ }
+ return true;
+
+ case '{':
+ {
+ if( !maybeFunctionDefinition ){
+ syntaxError();
+ return false;
+ }
+ StatementListAST::Node funBody;
+ if ( parseFunctionBody(funBody) ) {
+ FunctionDefinitionAST::Node ast = CreateNode<FunctionDefinitionAST>();
+ ast->setWinDeclSpec( winDeclSpec );
+ ast->setStorageSpecifier( storageSpec );
+ ast->setFunctionSpecifier( funSpec );
+ ast->setText( toString(start, endSignature) );
+ ast->setTypeSpec( spec );
+ ast->setFunctionBody( funBody );
+ ast->setInitDeclarator( decl );
+ node = ast;
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+ }
+ }
+ break;
+
+ }
+ }
+
+ syntaxError();
+ return false;
+}
+
+bool Parser::parseFunctionBody( StatementListAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseFunctionBody()" << endl;
+
+ int start = lex->index();
+ if( lex->lookAhead(0) != '{' ){
+ return false;
+ }
+ lex->nextToken();
+
+ StatementListAST::Node ast = CreateNode<StatementListAST>();
+
+ while( !lex->lookAhead(0).isNull() ){
+ if( lex->lookAhead(0) == '}' )
+ break;
+
+ StatementAST::Node stmt;
+ int startStmt = lex->index();
+ if( !parseStatement(stmt) ){
+ if( startStmt == lex->index() )
+ lex->nextToken();
+ skipUntilStatement();
+ } else
+ ast->addStatement( stmt );
+ }
+
+ if( lex->lookAhead(0) != '}' ){
+ reportError( i18n("} expected") );
+ } else
+ lex->nextToken();
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+QString Parser::toString( int start, int end, const QString& sep ) const
+{
+ QStringList l;
+
+ for( int i=start; i<end; ++i ){
+ l << lex->tokenAt(i).text();
+ }
+
+ return l.join( sep ).stripWhiteSpace();
+}
+
+bool Parser::parseTypeSpecifierOrClassSpec( TypeSpecifierAST::Node& 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& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTryBlockStatement()" << endl;
+
+ if( lex->lookAhead(0) != Token_try ){
+ return false;
+ }
+ lex->nextToken();
+
+ StatementAST::Node stmt;
+ if( !parseCompoundStatement(stmt) ){
+ syntaxError();
+ return false;
+ }
+
+ if( lex->lookAhead(0) != Token_catch ){
+ reportError( i18n("catch expected") );
+ return false;
+ }
+
+ while( lex->lookAhead(0) == Token_catch ){
+ lex->nextToken();
+ ADVANCE( '(', "(" );
+ ConditionAST::Node cond;
+ if( !parseCondition(cond) ){
+ reportError( i18n("condition expected") );
+ return false;
+ }
+ ADVANCE( ')', ")" );
+
+ StatementAST::Node body;
+ if( !parseCompoundStatement(body) ){
+ syntaxError();
+ return false;
+ }
+ }
+
+ node = stmt;
+ return true;
+}
+
+bool Parser::parsePrimaryExpression( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parsePrimarExpression()" << endl;
+
+
+ switch( lex->lookAhead(0) ){
+ case Token_string_literal:
+ {
+ AST::Node lit;
+ parseStringLiteral( lit );
+ }
+ return true;
+
+ case Token_number_literal:
+ case Token_char_literal:
+ case Token_true:
+ case Token_false:
+ lex->nextToken();
+ return true;
+
+ case Token_this:
+ lex->nextToken();
+ return true;
+
+ case Token_dynamic_cast:
+ case Token_static_cast:
+ case Token_reinterpret_cast:
+ case Token_const_cast:
+ {
+ lex->nextToken();
+
+ CHECK( '<', "<" );
+ AST::Node typeId;
+ parseTypeId( typeId );
+ CHECK( '>', ">" );
+
+ CHECK( '(', "(" );
+ AST::Node expr;
+ parseCommaExpression( expr );
+ CHECK( ')', ")" );
+ }
+ return true;
+
+ case Token_typeid:
+ {
+ lex->nextToken();
+ CHECK( '(', "(" );
+ AST::Node expr;
+ parseCommaExpression( expr );
+ CHECK( ')', ")" );
+ }
+ return true;
+
+ case '(':
+ {
+ lex->nextToken();
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "token = " << lex->lookAhead(0).text() << endl;
+ AST::Node expr;
+ if( !parseExpression(expr) ){
+ return false;
+ }
+ CHECK( ')', ")" );
+ }
+ return true;
+
+ default:
+ {
+ int start = lex->index();
+ TypeSpecifierAST::Node typeSpec;
+ if( parseSimpleTypeSpecifier(typeSpec) && lex->lookAhead(0) == '(' ){
+ lex->nextToken();
+ AST::Node expr;
+ parseCommaExpression( expr );
+ CHECK( ')', ")" );
+ return true;
+ }
+
+ lex->setIndex( start );
+ NameAST::Node name;
+ if( parseName(name) )
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool Parser::parsePostfixExpression( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parsePostfixExpression()" << endl;
+
+ AST::Node expr;
+ if( !parsePrimaryExpression(expr) )
+ return false;
+
+ while( true ){
+ switch(lex->lookAhead(0))
+ {
+ case '[':
+ {
+ lex->nextToken();
+ AST::Node e;
+ parseCommaExpression( e );
+ CHECK( ']', "]" );
+ }
+ break;
+
+ case '(':
+ {
+ lex->nextToken();
+ AST::Node funArgs;
+ parseCommaExpression( funArgs );
+ CHECK( ')', ")" );
+ }
+ break;
+
+ case Token_incr:
+ case Token_decr:
+ lex->nextToken();
+ break;
+
+ case '.':
+ case Token_arrow:
+ {
+ lex->nextToken();
+ if( lex->lookAhead(0) == Token_template )
+ lex->nextToken();
+
+ NameAST::Node name;
+ if( !parseName(name) ){
+ return false;
+ }
+ }
+ break;
+
+ case Token_typename:
+ {
+ lex->nextToken();
+
+ NameAST::Node name;
+ if( !parseName(name) ){
+ return false;
+ }
+
+ CHECK( '(', "(" );
+ AST::Node expr;
+ parseCommaExpression(expr);
+ CHECK( ')', ")" );
+ }
+ return true;
+
+ default:
+ return true;
+
+ } // end switch
+
+ } // end while
+
+ return true;
+}
+
+bool Parser::parseUnaryExpression( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseUnaryExpression()" << endl;
+
+ switch( lex->lookAhead(0) ){
+ case Token_incr:
+ case Token_decr:
+ case '*':
+ case '&':
+ case '+':
+ case '-':
+ case '!':
+ case '~':
+ {
+ lex->nextToken();
+ AST::Node expr;
+ return parseCastExpression( expr );
+ }
+
+ case Token_sizeof:
+ {
+ lex->nextToken();
+ int index = lex->index();
+ if( lex->lookAhead(0) == '(' ){
+ lex->nextToken();
+ AST::Node typeId;
+ if( parseTypeId(typeId) && lex->lookAhead(0) == ')' ){
+ lex->nextToken();
+ return true;
+ }
+ lex->setIndex( index );
+ }
+ AST::Node expr;
+ return parseUnaryExpression( expr );
+ }
+
+ case Token_new:
+ return parseNewExpression( node );
+
+ case Token_delete:
+ return parseDeleteExpression( node );
+ }
+
+ return parsePostfixExpression( node );
+}
+
+bool Parser::parseNewExpression( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseNewExpression()" << endl;
+ if( lex->lookAhead(0) == Token_scope && lex->lookAhead(1) == Token_new )
+ lex->nextToken();
+
+ CHECK( Token_new, "new");
+
+ if( lex->lookAhead(0) == '(' ){
+ lex->nextToken();
+ AST::Node expr;
+ parseCommaExpression( expr );
+ CHECK( ')', ")" );
+ }
+
+ if( lex->lookAhead(0) == '(' ){
+ lex->nextToken();
+ AST::Node typeId;
+ parseTypeId( typeId );
+ CHECK( ')', ")" );
+ } else {
+ AST::Node typeId;
+ parseNewTypeId( typeId );
+ }
+
+ AST::Node init;
+ parseNewInitializer( init );
+ return true;
+}
+
+bool Parser::parseNewTypeId( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseNewTypeId()" << endl;
+ TypeSpecifierAST::Node typeSpec;
+ if( parseTypeSpecifier(typeSpec) ){
+ AST::Node declarator;
+ parseNewDeclarator( declarator );
+ return true;
+ }
+
+ return false;
+}
+
+bool Parser::parseNewDeclarator( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseNewDeclarator()" << endl;
+ AST::Node ptrOp;
+ if( parsePtrOperator(ptrOp) ){
+ AST::Node declarator;
+ parseNewDeclarator( declarator );
+ return true;
+ }
+
+ if( lex->lookAhead(0) == '[' ){
+ while( lex->lookAhead(0) == '[' ){
+ lex->nextToken();
+ AST::Node expr;
+ parseExpression( expr );
+ ADVANCE( ']', "]" );
+ }
+ return true;
+ }
+
+ return false;
+}
+
+bool Parser::parseNewInitializer( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseNewInitializer()" << endl;
+ if( lex->lookAhead(0) != '(' )
+ return false;
+
+ lex->nextToken();
+ AST::Node expr;
+ parseCommaExpression( expr );
+ CHECK( ')', ")" );
+
+ return true;
+}
+
+bool Parser::parseDeleteExpression( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseDeleteExpression()" << endl;
+ if( lex->lookAhead(0) == Token_scope && lex->lookAhead(1) == Token_delete )
+ lex->nextToken();
+
+ CHECK( Token_delete, "delete" );
+
+ if( lex->lookAhead(0) == '[' ){
+ lex->nextToken();
+ CHECK( ']', "]" );
+ }
+
+ AST::Node expr;
+ return parseCastExpression( expr );
+}
+
+bool Parser::parseCastExpression( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseCastExpression()" << endl;
+
+ int index = lex->index();
+
+ if( lex->lookAhead(0) == '(' ){
+ lex->nextToken();
+ AST::Node typeId;
+ if ( parseTypeId(typeId) ) {
+ if ( lex->lookAhead(0) == ')' ) {
+ lex->nextToken();
+ AST::Node expr;
+ if( parseCastExpression(expr) )
+ return true;
+ }
+ }
+ }
+
+ lex->setIndex( index );
+
+ AST::Node expr;
+ return parseUnaryExpression( expr );
+}
+
+bool Parser::parsePmExpression( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser:parsePmExpression()" << endl;
+ AST::Node expr;
+ if( !parseCastExpression(expr) )
+ return false;
+
+ while( lex->lookAhead(0) == Token_ptrmem ){
+ lex->nextToken();
+
+ if( !parseCastExpression(expr) )
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseMultiplicativeExpression( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseMultiplicativeExpression()" << endl;
+ AST::Node expr;
+ if( !parsePmExpression(expr) )
+ return false;
+
+ while( lex->lookAhead(0) == '*' || lex->lookAhead(0) == '/' || lex->lookAhead(0) == '%' ){
+ lex->nextToken();
+
+ if( !parsePmExpression(expr) )
+ return false;
+ }
+
+ return true;
+}
+
+
+bool Parser::parseAdditiveExpression( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseAdditiveExpression()" << endl;
+ AST::Node expr;
+ if( !parseMultiplicativeExpression(expr) )
+ return false;
+
+ while( lex->lookAhead(0) == '+' || lex->lookAhead(0) == '-' ){
+ lex->nextToken();
+
+ if( !parseMultiplicativeExpression(expr) )
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseShiftExpression( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseShiftExpression()" << endl;
+ AST::Node expr;
+ if( !parseAdditiveExpression(expr) )
+ return false;
+
+ while( lex->lookAhead(0) == Token_shift ){
+ lex->nextToken();
+
+ if( !parseAdditiveExpression(expr) )
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseRelationalExpression( AST::Node& /*node*/, bool templArgs )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseRelationalExpression()" << endl;
+ AST::Node expr;
+ if( !parseShiftExpression(expr) )
+ return false;
+
+ while( lex->lookAhead(0) == '<' || (lex->lookAhead(0) == '>' && !templArgs) ||
+ lex->lookAhead(0) == Token_leq || lex->lookAhead(0) == Token_geq ){
+ lex->nextToken();
+
+ if( !parseShiftExpression(expr) )
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseEqualityExpression( AST::Node& /*node*/, bool templArgs )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseEqualityExpression()" << endl;
+ AST::Node expr;
+ if( !parseRelationalExpression(expr, templArgs) )
+ return false;
+
+ while( lex->lookAhead(0) == Token_eq || lex->lookAhead(0) == Token_not_eq ){
+ lex->nextToken();
+
+ if( !parseRelationalExpression(expr, templArgs) )
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseAndExpression( AST::Node& /*node*/, bool templArgs )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseAndExpression()" << endl;
+ AST::Node expr;
+ if( !parseEqualityExpression(expr, templArgs) )
+ return false;
+
+ while( lex->lookAhead(0) == '&' ){
+ lex->nextToken();
+
+ if( !parseEqualityExpression(expr, templArgs) )
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseExclusiveOrExpression( AST::Node& /*node*/, bool templArgs )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseExclusiveOrExpression()" << endl;
+ AST::Node expr;
+ if( !parseAndExpression(expr, templArgs) )
+ return false;
+
+ while( lex->lookAhead(0) == '^' ){
+ lex->nextToken();
+
+ if( !parseAndExpression(expr, templArgs) )
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseInclusiveOrExpression( AST::Node& /*node*/, bool templArgs )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseInclusiveOrExpression()" << endl;
+ AST::Node expr;
+ if( !parseExclusiveOrExpression(expr, templArgs) )
+ return false;
+
+ while( lex->lookAhead(0) == '|' ){
+ lex->nextToken();
+
+ if( !parseExclusiveOrExpression(expr, templArgs) )
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseLogicalAndExpression( AST::Node& /*node*/, bool templArgs )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseLogicalAndExpression()" << endl;
+
+ AST::Node expr;
+ if( !parseInclusiveOrExpression(expr, templArgs) )
+ return false;
+
+ while( lex->lookAhead(0) == Token_and ){
+ lex->nextToken();
+
+ if( !parseInclusiveOrExpression(expr, templArgs) )
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseLogicalOrExpression( AST::Node& node, bool templArgs )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseLogicalOrExpression()" << endl;
+
+ int start = lex->index();
+
+ AST::Node expr;
+ if( !parseLogicalAndExpression(expr, templArgs) )
+ return false;
+
+ while( lex->lookAhead(0) == Token_or ){
+ lex->nextToken();
+
+ if( !parseLogicalAndExpression(expr, templArgs) )
+ return false;
+ }
+
+ AST::Node ast = CreateNode<AST>();
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+}
+
+bool Parser::parseConditionalExpression( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseConditionalExpression()" << endl;
+ AST::Node expr;
+ if( !parseLogicalOrExpression(expr) )
+ return false;
+
+ if( lex->lookAhead(0) == '?' ){
+ lex->nextToken();
+
+ if( !parseExpression(expr) )
+ return false;
+
+ CHECK( ':', ":" );
+
+ if( !parseAssignmentExpression(expr) )
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseAssignmentExpression( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseAssignmentExpression()" << endl;
+ int start = lex->index();
+ AST::Node expr;
+ if( lex->lookAhead(0) == Token_throw && !parseThrowExpression(expr) )
+ return false;
+ else if( !parseConditionalExpression(expr) )
+ return false;
+
+ while( lex->lookAhead(0) == Token_assign || lex->lookAhead(0) == '=' ){
+ lex->nextToken();
+
+ if( !parseConditionalExpression(expr) )
+ return false;
+ }
+
+ AST::Node ast = CreateNode<AST>();
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+}
+
+bool Parser::parseConstantExpression( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseConstantExpression()" << endl;
+ int start = lex->index();
+ if( parseConditionalExpression(node) ){
+ AST::Node ast = CreateNode<AST>();
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseExpression( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseExpression()" << endl;
+
+ int start = lex->index();
+
+ if( !parseCommaExpression(node) )
+ return false;
+
+ AST::Node ast = CreateNode<AST>();
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+}
+
+bool Parser::parseCommaExpression( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseCommaExpression()" << endl;
+ int start = lex->index();
+
+ AST::Node expr;
+ if( !parseAssignmentExpression(expr) )
+ return false;
+
+ QString comment;
+ while( lex->lookAhead(0) == ',' ){
+ comment = QString::null;
+ advanceAndCheckTrailingComment( comment );
+
+ if( !parseAssignmentExpression(expr) )
+ return false;
+ if (!comment.isEmpty())
+ expr->setComment(comment);
+ }
+
+ AST::Node ast = CreateNode<AST>();
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+}
+
+bool Parser::parseThrowExpression( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseThrowExpression()" << endl;
+ if( lex->lookAhead(0) != Token_throw )
+ return false;
+
+ CHECK( Token_throw, "throw" );
+ AST::Node expr;
+ if( !parseAssignmentExpression(expr) )
+ return false;
+
+ return true;
+}
+
+bool Parser::parseIvarDeclList( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseIvarDecls( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseIvarDecl( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseIvars( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseIvarDeclarator( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseMethodDecl( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseUnarySelector( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseKeywordSelector( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseSelector( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseKeywordDecl( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseReceiver( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseObjcMessageExpr( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseMessageArgs( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseKeywordExpr( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseKeywordArgList( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseKeywordArg( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseReservedWord( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseMyParms( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseMyParm( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseOptParmList( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseObjcSelectorExpr( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseSelectorArg( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseKeywordNameList( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseKeywordName( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseObjcEncodeExpr( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseObjcString( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseProtocolRefs( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseIdentifierList( GroupAST::Node & node )
+{
+ int start = lex->index();
+
+ if( lex->lookAhead(0) != Token_identifier )
+ return false;
+
+ GroupAST::Node ast = CreateNode<GroupAST>();
+
+ AST_FROM_TOKEN( tk, lex->index() );
+ ast->addNode( tk );
+ lex->nextToken();
+
+ QString comment;
+ while( lex->lookAhead(0) == ',' ){
+ comment = QString::null;
+ advanceAndCheckTrailingComment( comment );
+ if( lex->lookAhead(0) == Token_identifier ){
+ AST_FROM_TOKEN( tk, lex->index() );
+ ast->addNode( tk );
+ lex->nextToken();
+ }
+ ADVANCE( Token_identifier, "identifier" );
+ }
+
+ node = ast;
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+}
+
+bool Parser::parseIdentifierColon( AST::Node & node )
+{
+ Q_UNUSED( node );
+
+ if( lex->lookAhead(0) == Token_identifier && lex->lookAhead(1) == ':' ){
+ lex->nextToken();
+ lex->nextToken();
+ return true;
+ } // ### else if PTYPENAME -> return true ;
+
+ return false;
+}
+
+bool Parser::parseObjcProtocolExpr( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseObjcOpenBracketExpr( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseObjcCloseBracket( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseObjcDef( DeclarationAST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseObjcClassDef( DeclarationAST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseObjcClassDecl( DeclarationAST::Node & node )
+{
+ Q_UNUSED( node );
+
+ ADVANCE( OBJC_CLASS, "@class" );
+
+ GroupAST::Node idList;
+ parseIdentifierList( idList );
+ ADVANCE( ';', ";" );
+
+ return true;
+}
+
+bool Parser::parseObjcProtocolDecl( DeclarationAST::Node & node )
+{
+ Q_UNUSED( node );
+
+ ADVANCE( OBJC_PROTOCOL, "@protocol" );
+
+ GroupAST::Node idList;
+ parseIdentifierList( idList );
+ ADVANCE( ';', ";" );
+
+ return true;
+}
+
+bool Parser::parseObjcAliasDecl( DeclarationAST::Node & node )
+{
+ Q_UNUSED( node );
+
+ ADVANCE( OBJC_ALIAS, "@alias" );
+
+ GroupAST::Node idList;
+ parseIdentifierList( idList );
+ ADVANCE( ';', ";" );
+
+ return true;
+}
+
+bool Parser::parseObjcProtocolDef( DeclarationAST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseObjcMethodDef( DeclarationAST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseWinDeclSpec( GroupAST::Node & node )
+{
+ if( lex->lookAhead(0) == Token_identifier && lex->lookAhead(0).text() == "__declspec" && lex->lookAhead(1) == '(' ){
+ int start = lex->index();
+ lex->nextToken();
+ lex->nextToken(); // skip '('
+
+ parseIdentifierList( node );
+ ADVANCE( ')', ")" );
+
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+ }
+
+ return false;
+}
+
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/parser.h b/umbrello/umbrello/codeimport/kdevcppparser/parser.h
new file mode 100644
index 00000000..611ceb14
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/parser.h
@@ -0,0 +1,221 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef PARSER_H
+#define PARSER_H
+
+#include "ast.h"
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qvaluelist.h>
+#include <qvaluestack.h>
+
+struct ParserPrivateData;
+
+class Driver;
+class Lexer;
+class Token;
+struct Error;
+
+class Parser
+{
+public:
+ Parser( Driver* driver, Lexer* lexer );
+ virtual ~Parser();
+
+private:
+ virtual bool reportError( const Error& err );
+ /** @todo remove*/ virtual bool reportError( const QString& msg );
+ /** @todo remove*/ virtual void syntaxError();
+
+public: /*rules*/
+
+ bool parseTranslationUnit( TranslationUnitAST::Node& node );
+
+ bool parseDeclaration( DeclarationAST::Node& node );
+ bool parseBlockDeclaration( DeclarationAST::Node& node );
+ bool parseLinkageSpecification( DeclarationAST::Node& node );
+ bool parseLinkageBody( LinkageBodyAST::Node& node );
+ bool parseNamespace( DeclarationAST::Node& node );
+ bool parseNamespaceAliasDefinition( DeclarationAST::Node& node );
+ bool parseUsing( DeclarationAST::Node& node );
+ bool parseUsingDirective( DeclarationAST::Node& node );
+ bool parseTypedef( DeclarationAST::Node& node );
+ bool parseAsmDefinition( DeclarationAST::Node& node );
+ bool parseTemplateDeclaration( DeclarationAST::Node& node );
+ bool parseDeclarationInternal( DeclarationAST::Node& node, QString& comment );
+
+ bool parseUnqualifiedName( ClassOrNamespaceNameAST::Node& node );
+ bool parseStringLiteral( AST::Node& node );
+ bool parseName( NameAST::Node& node );
+ bool parseOperatorFunctionId( AST::Node& node );
+ bool parseTemplateArgumentList( TemplateArgumentListAST::Node& node, bool reportError=true );
+ bool parseOperator( AST::Node& node );
+ bool parseCvQualify( GroupAST::Node& node );
+ bool parseSimpleTypeSpecifier( TypeSpecifierAST::Node& node );
+ bool parsePtrOperator( AST::Node& node );
+ bool parseTemplateArgument( AST::Node& node );
+ bool parseTypeSpecifier( TypeSpecifierAST::Node& node );
+ bool parseTypeSpecifierOrClassSpec( TypeSpecifierAST::Node& node );
+ bool parseDeclarator( DeclaratorAST::Node& node );
+ bool parseTemplateParameterList( TemplateParameterListAST::Node& node );
+ bool parseTemplateParameter( TemplateParameterAST::Node& node );
+ bool parseStorageClassSpecifier( GroupAST::Node& node );
+ bool parseFunctionSpecifier( GroupAST::Node& node );
+ bool parseInitDeclaratorList( InitDeclaratorListAST::Node& node );
+ bool parseInitDeclarator( InitDeclaratorAST::Node& node );
+ bool parseParameterDeclarationClause( ParameterDeclarationClauseAST::Node& node );
+ bool parseCtorInitializer( AST::Node& node );
+ bool parsePtrToMember( AST::Node& node );
+ bool parseEnumSpecifier( TypeSpecifierAST::Node& node );
+ bool parseClassSpecifier( TypeSpecifierAST::Node& node );
+ bool parseWinDeclSpec( GroupAST::Node& node );
+ bool parseElaboratedTypeSpecifier( TypeSpecifierAST::Node& node );
+ bool parseDeclaratorId( NameAST::Node& node );
+ bool parseExceptionSpecification( GroupAST::Node& node );
+ bool parseEnumerator( EnumeratorAST::Node& node );
+ bool parseTypeParameter( TypeParameterAST::Node& node );
+ bool parseParameterDeclaration( ParameterDeclarationAST::Node& node );
+ bool parseTypeId( AST::Node& node );
+ bool parseAbstractDeclarator( DeclaratorAST::Node& node );
+ bool parseParameterDeclarationList( ParameterDeclarationListAST::Node& node );
+ bool parseMemberSpecification( DeclarationAST::Node& node );
+ bool parseAccessSpecifier( AST::Node& node );
+ bool parseTypeIdList( GroupAST::Node& node );
+ bool parseMemInitializerList( AST::Node& node );
+ bool parseMemInitializer( AST::Node& node );
+ bool parseInitializer( AST::Node& node );
+ bool parseBaseClause( BaseClauseAST::Node& node );
+ bool parseBaseSpecifier( BaseSpecifierAST::Node& node );
+ bool parseInitializerClause( AST::Node& node );
+ bool parseMemInitializerId( NameAST::Node& node );
+ bool parseFunctionBody( StatementListAST::Node& node );
+
+ // expression
+ bool skipExpression( AST::Node& node );
+ bool skipCommaExpression( AST::Node& node );
+ bool skipExpressionStatement( StatementAST::Node& node );
+
+ bool parseExpression( AST::Node& node );
+ bool parsePrimaryExpression( AST::Node& node );
+ bool parsePostfixExpression( AST::Node& node );
+ bool parseUnaryExpression( AST::Node& node );
+ bool parseNewExpression( AST::Node& node );
+ bool parseNewTypeId( AST::Node& node );
+ bool parseNewDeclarator( AST::Node& node );
+ bool parseNewInitializer( AST::Node& node );
+ bool parseDeleteExpression( AST::Node& node );
+ bool parseCastExpression( AST::Node& node );
+ bool parsePmExpression( AST::Node& node );
+ bool parseMultiplicativeExpression( AST::Node& node );
+ bool parseAdditiveExpression( AST::Node& node );
+ bool parseShiftExpression( AST::Node& node );
+ bool parseRelationalExpression( AST::Node& node, bool templArgs=false );
+ bool parseEqualityExpression( AST::Node& node, bool templArgs=false );
+ bool parseAndExpression( AST::Node& node, bool templArgs=false );
+ bool parseExclusiveOrExpression( AST::Node& node, bool templArgs=false );
+ bool parseInclusiveOrExpression( AST::Node& node, bool templArgs=false );
+ bool parseLogicalAndExpression( AST::Node& node, bool templArgs=false );
+ bool parseLogicalOrExpression( AST::Node& node, bool templArgs=false );
+ bool parseConditionalExpression( AST::Node& node );
+ bool parseAssignmentExpression( AST::Node& node );
+ bool parseConstantExpression( AST::Node& node );
+ bool parseCommaExpression( AST::Node& node );
+ bool parseThrowExpression( AST::Node& node );
+
+ // statement
+ bool parseCondition( ConditionAST::Node& node );
+ bool parseStatement( StatementAST::Node& node );
+ bool parseWhileStatement( StatementAST::Node& node );
+ bool parseDoStatement( StatementAST::Node& node );
+ bool parseForStatement( StatementAST::Node& node );
+ bool parseCompoundStatement( StatementAST::Node& node );
+ bool parseForInitStatement( StatementAST::Node& node );
+ bool parseIfStatement( StatementAST::Node& node );
+ bool parseSwitchStatement( StatementAST::Node& node );
+ bool parseLabeledStatement( StatementAST::Node& node );
+ bool parseDeclarationStatement( StatementAST::Node& node );
+ bool parseTryBlockStatement( StatementAST::Node& node );
+
+ // objective c
+ bool parseObjcDef( DeclarationAST::Node& node );
+ bool parseObjcClassDef( DeclarationAST::Node& node );
+ bool parseObjcClassDecl( DeclarationAST::Node& node );
+ bool parseObjcProtocolDecl( DeclarationAST::Node& node );
+ bool parseObjcAliasDecl( DeclarationAST::Node& node );
+ bool parseObjcProtocolDef( DeclarationAST::Node& node );
+ bool parseObjcMethodDef( DeclarationAST::Node& node );
+
+ bool parseIvarDeclList( AST::Node& node );
+ bool parseIvarDecls( AST::Node& node );
+ bool parseIvarDecl( AST::Node& node );
+ bool parseIvars( AST::Node& node );
+ bool parseIvarDeclarator( AST::Node& node );
+ bool parseMethodDecl( AST::Node& node );
+ bool parseUnarySelector( AST::Node& node );
+ bool parseKeywordSelector( AST::Node& node );
+ bool parseSelector( AST::Node& node );
+ bool parseKeywordDecl( AST::Node& node );
+ bool parseReceiver( AST::Node& node );
+ bool parseObjcMessageExpr( AST::Node& node );
+ bool parseMessageArgs( AST::Node& node );
+ bool parseKeywordExpr( AST::Node& node );
+ bool parseKeywordArgList( AST::Node& node );
+ bool parseKeywordArg( AST::Node& node );
+ bool parseReservedWord( AST::Node& node );
+ bool parseMyParms( AST::Node& node );
+ bool parseMyParm( AST::Node& node );
+ bool parseOptParmList( AST::Node& node );
+ bool parseObjcSelectorExpr( AST::Node& node );
+ bool parseSelectorArg( AST::Node& node );
+ bool parseKeywordNameList( AST::Node& node );
+ bool parseKeywordName( AST::Node& node );
+ bool parseObjcEncodeExpr( AST::Node& node );
+ bool parseObjcString( AST::Node& node );
+ bool parseProtocolRefs( AST::Node& node );
+ bool parseIdentifierList( GroupAST::Node& node );
+ bool parseIdentifierColon( AST::Node& node );
+ bool parseObjcProtocolExpr( AST::Node& node );
+ bool parseObjcOpenBracketExpr( AST::Node& node );
+ bool parseObjcCloseBracket( AST::Node& node );
+
+ void advanceAndCheckTrailingComment(QString& comment);
+
+ bool skipUntil( int token );
+ bool skipUntilDeclaration();
+ bool skipUntilStatement();
+ bool skip( int l, int r );
+ QString toString( int start, int end, const QString& sep=" " ) const;
+
+private:
+ ParserPrivateData* d;
+ Driver* m_driver;
+ Lexer* lex;
+ int m_problems;
+ int m_maxProblems;
+ bool objcp;
+
+private:
+ Parser( const Parser& source );
+ void operator = ( const Parser& source );
+};
+
+
+#endif
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/tree_parser.cpp b/umbrello/umbrello/codeimport/kdevcppparser/tree_parser.cpp
new file mode 100644
index 00000000..7f9210e2
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/tree_parser.cpp
@@ -0,0 +1,207 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "tree_parser.h"
+#include <kdebug.h>
+
+TreeParser::TreeParser()
+{
+}
+
+TreeParser::~TreeParser()
+{
+}
+
+void TreeParser::parseTranslationUnit( TranslationUnitAST* translationUnit )
+{
+ //kdDebug(9007) << "TreeParser::parseTranslationUnit()" << endl;
+
+ QPtrList<DeclarationAST> declarations = translationUnit->declarationList();
+ QPtrListIterator<DeclarationAST> it( declarations );
+ while( it.current() ){
+ parseDeclaration( it.current() );
+ ++it;
+ }
+}
+
+void TreeParser::parseDeclaration( DeclarationAST* declaration )
+{
+ //kdDebug(9007) << "TreeParser::parseDeclaration()" << endl;
+
+ if( !declaration )
+ return;
+
+ switch( declaration->nodeType() )
+ {
+ case NodeType_LinkageSpecification:
+ parseLinkageSpecification( static_cast<LinkageSpecificationAST*>(declaration) );
+ break;
+
+ case NodeType_Namespace:
+ parseNamespace( static_cast<NamespaceAST*>(declaration) );
+ break;
+
+ case NodeType_NamespaceAlias:
+ parseNamespaceAlias( static_cast<NamespaceAliasAST*>(declaration) );
+ break;
+
+ case NodeType_Using:
+ parseUsing( static_cast<UsingAST*>(declaration) );
+ break;
+
+ case NodeType_UsingDirective:
+ parseUsingDirective( static_cast<UsingDirectiveAST*>(declaration) );
+ break;
+
+ case NodeType_Typedef:
+ parseTypedef( static_cast<TypedefAST*>(declaration) );
+ break;
+
+ case NodeType_TemplateDeclaration:
+ parseTemplateDeclaration( static_cast<TemplateDeclarationAST*>(declaration) );
+ break;
+
+ case NodeType_SimpleDeclaration:
+ parseSimpleDeclaration( static_cast<SimpleDeclarationAST*>(declaration) );
+ break;
+
+ case NodeType_FunctionDefinition:
+ parseFunctionDefinition( static_cast<FunctionDefinitionAST*>(declaration) );
+ break;
+
+ case NodeType_AccessDeclaration:
+ parseAccessDeclaration( static_cast<AccessDeclarationAST*>(declaration) );
+ break;
+ }
+}
+
+void TreeParser::parseLinkageSpecification( LinkageSpecificationAST* ast )
+{
+ //kdDebug(9007) << "TreeParser::parseLinkageSpecification()" << endl;
+ if( ast->linkageBody() )
+ parseLinkageBody( ast->linkageBody() );
+ else if( ast->declaration() )
+ parseDeclaration( ast->declaration() );
+}
+
+void TreeParser::parseNamespace( NamespaceAST* decl )
+{
+ //kdDebug(9007) << "TreeParser::parseNamespace()" << endl;
+ if( decl->linkageBody() )
+ parseLinkageBody( decl->linkageBody() );
+}
+
+void TreeParser::parseNamespaceAlias( NamespaceAliasAST* decl )
+{
+ //kdDebug(9007) << "TreeParser::parseNamespaceAlias()" << endl;
+ Q_UNUSED( decl );
+}
+
+void TreeParser::parseUsing( UsingAST* decl )
+{
+ //kdDebug(9007) << "TreeParser::parseUsing()" << endl;
+ Q_UNUSED( decl );
+}
+
+void TreeParser::parseUsingDirective( UsingDirectiveAST* decl )
+{
+ //kdDebug(9007) << "TreeParser::parseUsingDirective()" << endl;
+ Q_UNUSED( decl );
+}
+
+void TreeParser::parseTypedef( TypedefAST* decl )
+{
+ //kdDebug(9007) << "TreeParser::parseTypedef()" << endl;
+ if( decl->typeSpec() )
+ parseTypeSpecifier( decl->typeSpec() );
+}
+
+void TreeParser::parseTemplateDeclaration( TemplateDeclarationAST* decl )
+{
+ //kdDebug(9007) << "TreeParser::parseTemplateDeclaration()" << endl;
+ Q_UNUSED( decl );
+}
+
+void TreeParser::parseSimpleDeclaration( SimpleDeclarationAST* decl )
+{
+ //kdDebug(9007) << "TreeParser::parseSimpleDeclaration()" << endl;
+ Q_UNUSED( decl );
+}
+
+void TreeParser::parseFunctionDefinition( FunctionDefinitionAST* def )
+{
+ //kdDebug(9007) << "TreeParser::parseFunctionDefinition()" << endl;
+ Q_UNUSED( def );
+}
+
+void TreeParser::parseLinkageBody( LinkageBodyAST* linkageBody )
+{
+ //kdDebug(9007) << "TreeParser::parseLinkageBody()" << endl;
+ QPtrList<DeclarationAST> declarations = linkageBody->declarationList();
+ for( QPtrListIterator<DeclarationAST> it(declarations); it.current(); ++it ){
+ parseDeclaration( it.current() );
+ }
+}
+
+void TreeParser::parseTypeSpecifier( TypeSpecifierAST* typeSpec )
+{
+ //kdDebug(9007) << "TreeParser::parseTypeSpecifier()" << endl;
+ switch( typeSpec->nodeType() )
+ {
+ case NodeType_ClassSpecifier:
+ parseClassSpecifier( static_cast<ClassSpecifierAST*>(typeSpec) );
+ break;
+
+ case NodeType_EnumSpecifier:
+ parseEnumSpecifier( static_cast<EnumSpecifierAST*>(typeSpec) );
+ break;
+
+ case NodeType_ElaboratedTypeSpecifier:
+ parseElaboratedTypeSpecifier( static_cast<ElaboratedTypeSpecifierAST*>(typeSpec) );
+ break;
+ }
+}
+
+void TreeParser::parseClassSpecifier( ClassSpecifierAST* classSpec )
+{
+ //kdDebug(9007) << "TreeParser::parseClassSpecifier()" << endl;
+ QPtrList<DeclarationAST> declarations = classSpec->declarationList();
+ for( QPtrListIterator<DeclarationAST> it(declarations); it.current(); ++it ){
+ parseDeclaration( it.current() );
+ }
+}
+
+void TreeParser::parseEnumSpecifier( EnumSpecifierAST* enumSpec )
+{
+ //kdDebug(9007) << "TreeParser::parseEnumSpecifier()" << endl;
+ Q_UNUSED( enumSpec );
+}
+
+void TreeParser::parseElaboratedTypeSpecifier( ElaboratedTypeSpecifierAST* typeSpec )
+{
+ //kdDebug(9007) << "TreeParser::parseElaboratedTypeSpecifier()" << endl;
+ Q_UNUSED( typeSpec );
+}
+
+void TreeParser::parseAccessDeclaration ( AccessDeclarationAST * access )
+{
+ //kdDebug(9007) << "TreeParser::parseAccessDeclaration()" << endl;
+ Q_UNUSED( access );
+}
+
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/tree_parser.h b/umbrello/umbrello/codeimport/kdevcppparser/tree_parser.h
new file mode 100644
index 00000000..42059408
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/tree_parser.h
@@ -0,0 +1,59 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __tree_parser_h
+#define __tree_parser_h
+
+#include "ast.h"
+
+class TreeParser
+{
+public:
+ TreeParser();
+ virtual ~TreeParser();
+
+ // translation-unit
+ virtual void parseTranslationUnit( TranslationUnitAST* );
+
+ // declarations
+ virtual void parseDeclaration( DeclarationAST* );
+ virtual void parseLinkageSpecification( LinkageSpecificationAST* );
+ virtual void parseNamespace( NamespaceAST* );
+ virtual void parseNamespaceAlias( NamespaceAliasAST* );
+ virtual void parseUsing( UsingAST* );
+ virtual void parseUsingDirective( UsingDirectiveAST* );
+ virtual void parseTypedef( TypedefAST* );
+ virtual void parseTemplateDeclaration( TemplateDeclarationAST* );
+ virtual void parseSimpleDeclaration( SimpleDeclarationAST* );
+ virtual void parseFunctionDefinition( FunctionDefinitionAST* );
+ virtual void parseLinkageBody( LinkageBodyAST* );
+ virtual void parseAccessDeclaration( AccessDeclarationAST* );
+
+ // type-specifier
+ virtual void parseTypeSpecifier( TypeSpecifierAST* );
+ virtual void parseClassSpecifier( ClassSpecifierAST* );
+ virtual void parseEnumSpecifier( EnumSpecifierAST* );
+ virtual void parseElaboratedTypeSpecifier( ElaboratedTypeSpecifierAST* );
+
+private:
+ TreeParser( const TreeParser& source );
+ void operator = ( const TreeParser& source );
+};
+
+#endif // __tree_parser_h
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/urlutil.cpp b/umbrello/umbrello/codeimport/kdevcppparser/urlutil.cpp
new file mode 100644
index 00000000..a2fd29dd
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/urlutil.cpp
@@ -0,0 +1,310 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003 Julian Rockey <linux@jrockey.com>
+ Copyright (C) 2003 Alexander Dymo <cloudtemple@mksat.net>
+ Copyright (C) 2003 Mario Scalas <mario.scalas@libero.it>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+#include "urlutil.h"
+
+#include <qstringlist.h>
+
+#include <qdir.h>
+#include <qfileinfo.h>
+#include <kdebug.h>
+
+#include <unistd.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#include <kdeversion.h>
+#if (KDE_VERSION_MINOR==0) && (KDE_VERSION_MAJOR==3)
+#include <kdevkurl.h>
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Namespace URLUtil
+///////////////////////////////////////////////////////////////////////////////
+
+QString URLUtil::filename(const QString & name) {
+ int slashPos = name.findRev("/");
+ return slashPos<0 ? name : name.mid(slashPos+1);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+QString URLUtil::directory(const QString & name) {
+ int slashPos = name.findRev("/");
+ return slashPos<0 ? QString("") : name.left(slashPos);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+QString URLUtil::relativePath(const KURL & parent, const KURL & child, uint slashPolicy) {
+ bool slashPrefix = slashPolicy & SLASH_PREFIX;
+ bool slashSuffix = slashPolicy & SLASH_SUFFIX;
+ if (parent == child)
+ return slashPrefix ? QString("/") : QString("");
+
+ if (!parent.isParentOf(child)) return QString();
+ int a=slashPrefix ? -1 : 1;
+ int b=slashSuffix ? 1 : -1;
+ return child.path(b).mid(parent.path(a).length());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+QString URLUtil::relativePath(const QString & parent, const QString & child, uint slashPolicy) {
+ return relativePath(KURL(parent), KURL(child), slashPolicy);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+QString URLUtil::upDir(const QString & path, bool slashSuffix) {
+ int slashPos = path.findRev("/");
+ if (slashPos<1) return QString::null;
+ return path.mid(0,slashPos+ (slashSuffix ? 1 : 0) );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+KURL URLUtil::mergeURL(const KURL & source, const KURL & dest, const KURL & child) {
+
+ // if already a child of source, then fine
+ if (source.isParentOf(child) || source == child) return child;
+
+ // if not a child of dest, return blank URL (error)
+ if (!dest.isParentOf(child) && dest != child) return KURL();
+
+ // if child is same as dest, return source
+ if (dest == child) return source;
+
+ // calculate
+ QString childUrlStr = child.url(-1);
+ QString destStemStr = dest.url(1);
+ QString sourceStemStr = source.url(1);
+ return KURL(sourceStemStr.append( childUrlStr.mid( destStemStr.length() ) ) );
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+QString URLUtil::getExtension(const QString & path) {
+ int dotPos = path.findRev('.');
+ if (dotPos<0) return QString("");
+ return path.mid(dotPos+1);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+QString URLUtil::extractPathNameRelative(const KURL &baseDirUrl, const KURL &url )
+{
+ QString absBase = extractPathNameAbsolute( baseDirUrl ),
+ absRef = extractPathNameAbsolute( url );
+ int i = absRef.find( absBase, 0, true );
+
+ if (i == -1)
+ return QString();
+
+ if (absRef == absBase)
+ return QString( "." );
+ else
+ return absRef.replace( 0, absBase.length(), QString() );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+QString URLUtil::extractPathNameRelative(const QString &basePath, const KURL &url )
+{
+#if (KDE_VERSION_MINOR!=0) || (KDE_VERSION_MAJOR!=3)
+ KURL baseDirUrl = KURL::fromPathOrURL( basePath );
+#else
+ KURL baseDirUrl = KdevKURL::fromPathOrURL( basePath );
+#endif
+ return extractPathNameRelative( baseDirUrl, url );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+QString URLUtil::extractPathNameRelative(const QString &basePath, const QString &absFilePath )
+{
+#if (KDE_VERSION_MINOR!=0) || (KDE_VERSION_MAJOR!=3)
+ KURL baseDirUrl = KURL::fromPathOrURL( basePath ),
+ fileUrl = KURL::fromPathOrURL( absFilePath );
+#else
+ KURL baseDirUrl = KdevKURL::fromPathOrURL( basePath ),
+ fileUrl = KdevKURL::fromPathOrURL( absFilePath );
+#endif
+ return extractPathNameRelative( baseDirUrl, fileUrl );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+QString URLUtil::extractPathNameAbsolute( const KURL &url )
+{
+ if (isDirectory( url ))
+ return url.path( +1 ); // with trailing "/" if none is present
+ else
+ {
+ // Ok, this is an over-tight pre-condition on "url" since I hope nobody will never
+ // stress this function with absurd cases ... but who knows?
+ /*
+ QString path = url.path();
+ QFileInfo fi( path ); // Argh: QFileInfo is back ;))
+ return ( fi.exists()? path : QString() );
+ */
+ return url.path();
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool URLUtil::isDirectory( const KURL &url )
+{
+ return isDirectory( url.path() );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool URLUtil::isDirectory( const QString &absFilePath )
+{
+ return QDir( absFilePath ).exists();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void URLUtil::dump( const KURL::List &urls, const QString &aMessage )
+{
+ if (!aMessage.isNull())
+ {
+ kdDebug(9000) << aMessage << endl;
+ }
+ kdDebug(9000) << " List has " << urls.count() << " elements." << endl;
+
+ for (size_t i = 0; i<urls.count(); ++i)
+ {
+ KURL url = urls[ i ];
+// kdDebug(9000) << " * Element = " << url.path() << endl;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+QStringList URLUtil::toRelativePaths( const QString &baseDir, const KURL::List &urls)
+{
+ QStringList paths;
+
+ for (size_t i=0; i<urls.count(); ++i)
+ {
+ paths << extractPathNameRelative( baseDir, urls[i] );
+ }
+
+ return paths;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+QString URLUtil::relativePathToFile( const QString & dirUrl, const QString & fileUrl )
+{
+ if (dirUrl.isEmpty() || (dirUrl == "/"))
+ return fileUrl;
+
+ QStringList dir = QStringList::split("/", dirUrl, false);
+ QStringList file = QStringList::split("/", fileUrl, false);
+
+ QString resFileName = file.last();
+ file.remove(file.last());
+
+ uint i = 0;
+ while ( (i < dir.count()) && (i < (file.count())) && (dir[i] == file[i]) )
+ i++;
+
+ QString result_up;
+ QString result_down;
+ QString currDir;
+ QString currFile;
+ do
+ {
+ i >= dir.count() ? currDir = "" : currDir = dir[i];
+ i >= file.count() ? currFile = "" : currFile = file[i];
+ qWarning("i = %d, currDir = %s, currFile = %s", i, currDir.latin1(), currFile.latin1());
+ if (currDir.isEmpty() && currFile.isEmpty())
+ break;
+ else if (currDir.isEmpty())
+ result_down += file[i] + '/';
+ else if (currFile.isEmpty())
+ result_up += "../";
+ else
+ {
+ result_down += file[i] + '/';
+ result_up += "../";
+ }
+ i++;
+ }
+ while ( (!currDir.isEmpty()) || (!currFile.isEmpty()) );
+
+ return result_up + result_down + resFileName;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+// code from qt-3.1.2 version of QDir::canonicalPath()
+QString URLUtil::canonicalPath( const QString & path )
+{
+ QString r;
+ char cur[PATH_MAX+1];
+ if ( ::getcwd( cur, PATH_MAX ) )
+ {
+ char tmp[PATH_MAX+1];
+ if( ::realpath( QFile::encodeName( path ), tmp ) )
+ {
+ r = QFile::decodeName( tmp );
+ }
+ //always make sure we go back to the current dir
+ ::chdir( cur );
+ }
+ return r;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+//written by "Dawit A." <adawit@kde.org>
+//borrowed from his patch to KShell
+QString URLUtil::envExpand ( const QString& str )
+{
+ uint len = str.length();
+
+ if (len > 1 && str[0] == '$')
+ {
+ int pos = str.find ('/');
+
+ if (pos < 0)
+ pos = len;
+
+ char* ret = getenv( QConstString(str.unicode()+1, pos-1).string().local8Bit().data() );
+
+ if (ret)
+ {
+ QString expandedStr ( QFile::decodeName( ret ) );
+ if (pos < (int)len)
+ expandedStr += str.mid(pos);
+ return expandedStr;
+ }
+ }
+
+ return str;
+}
+
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/urlutil.h b/umbrello/umbrello/codeimport/kdevcppparser/urlutil.h
new file mode 100644
index 00000000..3460d28b
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/urlutil.h
@@ -0,0 +1,132 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003 Julian Rockey <linux@jrockey.com>
+ Copyright (C) 2003 Mario Scalas <mario.scalas@libero.it>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef _URLUTIL_H_
+#define _URLUTIL_H_
+
+#include <qstring.h>
+#include <qvaluelist.h>
+#include <kurl.h>
+
+namespace URLUtil
+{
+ enum SlashesPosition { SLASH_PREFIX = 1, SLASH_SUFFIX = 2 };
+
+ /**
+ * Returns the filename part of a pathname (i.e. everything past the last slash)
+ */
+ QString filename(const QString & pathName);
+ /**
+ * Returns the directory part of a path (i.e. everything up to but not including the last slash)
+ */
+ QString directory(const QString & pathName);
+ /**
+ * Returns the relative path between a parent and child URL, or blank if the specified child is not a child of parent
+ */
+ QString relativePath(const KURL & parent, const KURL & child, uint slashPolicy = SLASH_PREFIX);
+ /**
+ * Returns the relative path between a parent and child URL, or blank if the specified child is not a child of parent
+ */
+ QString relativePath(const QString & parent, const QString & child, uint slashPolicy = SLASH_PREFIX);
+ /**
+ * Returns the relative path between a directory and file. Should never return empty path.
+ * Example:
+ * dirUrl: /home/test/src
+ * fileUrl: /home/test/lib/mylib.cpp
+ * returns: ../lib/mylib.cpp
+ */
+ QString relativePathToFile( const QString & dirUrl, const QString & fileUrl );
+ /**
+ *Returns the path 'up one level' - the opposite of what filename returns
+ */
+ QString upDir(const QString & path, bool slashSuffix = false);
+ /**
+ * 'Merges' URLs - changes a URL that starts with dest to start with source instead
+ * Example:
+ * source is /home/me/
+ * dest is /home/you/
+ * child is /home/you/dir1/file1
+ * returns /home/me/dir1/fil1
+ */
+ KURL mergeURL(const KURL & source, const KURL & dest, const KURL & child);
+ /**
+ * Returns the file extension for a filename or path
+ */
+ QString getExtension(const QString & path);
+
+ /**
+ * Given a base directory url in @p baseDirUrl and the url referring to a date sub-directory or file,
+ * it will return the path relative to @p baseDirUrl.
+ * If baseDirUrl == url.path() then it will return ".".
+ * <code>
+ * KURL baseUrl, dirUrl;
+ * baseUrl.setPath( "/home/mario/src/kdevelop/" );
+ * dirUrl.setPath( "/home/mario/src/kdevelop/parts/cvs/" );
+ * QString relPathName = extractDirPathRelative( baseUrl, url ); // == "parts/cvs/"
+ * QString absPathName = extractDirPathAbsolute( url ); // == "/home/mario/src/kdevelop/parts/cvs/"
+ * </code>
+ * Note that if you pass a file name in @p url (instead of a directory) or the @p baseUrl is not contained
+ * in @p url then the function will return "" (void string).
+ */
+ QString extractPathNameRelative(const KURL &baseDirUrl, const KURL &url );
+ QString extractPathNameRelative(const QString &basePath, const KURL &url );
+ QString extractPathNameRelative(const QString &basePath, const QString &absFilePath );
+
+ /**
+ * Will return the absolute path name referred in @p url.
+ * Look at above for an example.
+ */
+ QString extractPathNameAbsolute( const KURL &url );
+
+ /**
+ * Returns a QStringList of relative (to @p baseDir) paths from a list of KURLs in @p urls
+ */
+ QStringList toRelativePaths( const QString &baseDir, const KURL::List &urls);
+
+ /**
+ * If @p url is a directory will return true, false otherwise.
+ */
+ bool isDirectory( const KURL &url );
+ bool isDirectory( const QString &absFilePath );
+
+ /**
+ * Will dump the list of KURL @p urls on standard output, eventually printing @ aMessage if it
+ * is not null.
+ */
+ void dump( const KURL::List &urls, const QString &aMessage = QString::null );
+
+ /**
+ * Same as QDir::canonicalPath in later versions of QT. Earlier versions of QT
+ * had this broken, so it's reproduced here.
+ */
+ QString canonicalPath( const QString & path );
+
+ /**
+ * Performs environment variable expansion on @p variable.
+ *
+ * @param variable the string with the environment variable to expand.
+ * @return the expanded environment variable value. if the variable
+ * cannot be expanded, @p variable itself is returned.
+ */
+ QString envExpand ( const QString &variable );
+
+}
+
+#endif