Przeglądaj źródła

Working on AtomicTool javascript binding funtionality

Josh Engebretson 10 lat temu
rodzic
commit
cc856acdd5
100 zmienionych plików z 45821 dodań i 0 usunięć
  1. 5 0
      Source/AtomicJS/Packages/Atomic/Container.json
  2. 8 0
      Source/AtomicJS/Packages/Atomic/Core.json
  3. 8 0
      Source/AtomicJS/Packages/Atomic/Package.json
  4. 1 0
      Source/ToolCore/CMakeLists.txt
  5. 61 0
      Source/ToolCore/Command/BindCmd.cpp
  6. 34 0
      Source/ToolCore/Command/BindCmd.h
  7. 5 0
      Source/ToolCore/Command/CommandParser.cpp
  8. 24 0
      Source/ToolCore/JSBind/JSBClass.cpp
  9. 53 0
      Source/ToolCore/JSBind/JSBClass.h
  10. 74 0
      Source/ToolCore/JSBind/JSBEnum.cpp
  11. 40 0
      Source/ToolCore/JSBind/JSBEnum.h
  12. 0 0
      Source/ToolCore/JSBind/JSBFunction.cpp
  13. 155 0
      Source/ToolCore/JSBind/JSBFunction.h
  14. 74 0
      Source/ToolCore/JSBind/JSBHeader.cpp
  15. 56 0
      Source/ToolCore/JSBind/JSBHeader.h
  16. 2 0
      Source/ToolCore/JSBind/JSBHeaderVisitor.cpp
  17. 445 0
      Source/ToolCore/JSBind/JSBHeaderVisitor.h
  18. 197 0
      Source/ToolCore/JSBind/JSBModule.cpp
  19. 63 0
      Source/ToolCore/JSBind/JSBModule.h
  20. 237 0
      Source/ToolCore/JSBind/JSBNameVisitor.cpp
  21. 41 0
      Source/ToolCore/JSBind/JSBNameVisitor.h
  22. 152 0
      Source/ToolCore/JSBind/JSBPackage.cpp
  23. 61 0
      Source/ToolCore/JSBind/JSBPackage.h
  24. 1 0
      Source/ToolCore/JSBind/JSBPreprocessVisitor.cpp
  25. 83 0
      Source/ToolCore/JSBind/JSBPreprocessVisitor.h
  26. 35 0
      Source/ToolCore/JSBind/JSBSymbol.h
  27. 55 0
      Source/ToolCore/JSBind/JSBType.cpp
  28. 166 0
      Source/ToolCore/JSBind/JSBType.h
  29. 31 0
      Source/ToolCore/JSBind/JSBind.cpp
  30. 36 0
      Source/ToolCore/JSBind/JSBind.h
  31. 4560 0
      Source/ToolCore/JSBind/cplusplus/AST.cpp
  32. 4665 0
      Source/ToolCore/JSBind/cplusplus/AST.h
  33. 1806 0
      Source/ToolCore/JSBind/cplusplus/ASTClone.cpp
  34. 1226 0
      Source/ToolCore/JSBind/cplusplus/ASTMatch0.cpp
  35. 3071 0
      Source/ToolCore/JSBind/cplusplus/ASTMatcher.cpp
  36. 187 0
      Source/ToolCore/JSBind/cplusplus/ASTMatcher.h
  37. 2 0
      Source/ToolCore/JSBind/cplusplus/ASTPatternBuilder.cpp
  38. 1382 0
      Source/ToolCore/JSBind/cplusplus/ASTPatternBuilder.h
  39. 1313 0
      Source/ToolCore/JSBind/cplusplus/ASTVisit.cpp
  40. 92 0
      Source/ToolCore/JSBind/cplusplus/ASTVisitor.cpp
  41. 382 0
      Source/ToolCore/JSBind/cplusplus/ASTVisitor.h
  42. 229 0
      Source/ToolCore/JSBind/cplusplus/ASTfwd.h
  43. 3261 0
      Source/ToolCore/JSBind/cplusplus/Bind.cpp
  44. 295 0
      Source/ToolCore/JSBind/cplusplus/Bind.h
  45. 56 0
      Source/ToolCore/JSBind/cplusplus/CPlusPlus.h
  46. 140 0
      Source/ToolCore/JSBind/cplusplus/CPlusPlusForwardDeclarations.h
  47. 838 0
      Source/ToolCore/JSBind/cplusplus/Control.cpp
  48. 232 0
      Source/ToolCore/JSBind/cplusplus/Control.h
  49. 206 0
      Source/ToolCore/JSBind/cplusplus/CoreTypes.cpp
  50. 246 0
      Source/ToolCore/JSBind/cplusplus/CoreTypes.h
  51. 31 0
      Source/ToolCore/JSBind/cplusplus/DiagnosticClient.cpp
  52. 53 0
      Source/ToolCore/JSBind/cplusplus/DiagnosticClient.h
  53. 242 0
      Source/ToolCore/JSBind/cplusplus/FullySpecifiedType.cpp
  54. 155 0
      Source/ToolCore/JSBind/cplusplus/FullySpecifiedType.h
  55. 1862 0
      Source/ToolCore/JSBind/cplusplus/Keywords.cpp
  56. 86 0
      Source/ToolCore/JSBind/cplusplus/Keywords.kwgen
  57. 855 0
      Source/ToolCore/JSBind/cplusplus/Lexer.cpp
  58. 151 0
      Source/ToolCore/JSBind/cplusplus/Lexer.h
  59. 169 0
      Source/ToolCore/JSBind/cplusplus/LiteralTable.h
  60. 143 0
      Source/ToolCore/JSBind/cplusplus/Literals.cpp
  61. 129 0
      Source/ToolCore/JSBind/cplusplus/Literals.h
  62. 371 0
      Source/ToolCore/JSBind/cplusplus/Matcher.cpp
  63. 84 0
      Source/ToolCore/JSBind/cplusplus/Matcher.h
  64. 113 0
      Source/ToolCore/JSBind/cplusplus/MemoryPool.cpp
  65. 102 0
      Source/ToolCore/JSBind/cplusplus/MemoryPool.h
  66. 98 0
      Source/ToolCore/JSBind/cplusplus/Name.cpp
  67. 78 0
      Source/ToolCore/JSBind/cplusplus/Name.h
  68. 33 0
      Source/ToolCore/JSBind/cplusplus/NameVisitor.cpp
  69. 56 0
      Source/ToolCore/JSBind/cplusplus/NameVisitor.h
  70. 235 0
      Source/ToolCore/JSBind/cplusplus/Names.cpp
  71. 277 0
      Source/ToolCore/JSBind/cplusplus/Names.h
  72. 463 0
      Source/ToolCore/JSBind/cplusplus/ObjectiveCAtKeywords.cpp
  73. 222 0
      Source/ToolCore/JSBind/cplusplus/ObjectiveCTypeQualifiers.cpp
  74. 32 0
      Source/ToolCore/JSBind/cplusplus/ObjectiveCTypeQualifiers.h
  75. 6755 0
      Source/ToolCore/JSBind/cplusplus/Parser.cpp
  76. 340 0
      Source/ToolCore/JSBind/cplusplus/Parser.h
  77. 201 0
      Source/ToolCore/JSBind/cplusplus/QtContextKeywords.cpp
  78. 28 0
      Source/ToolCore/JSBind/cplusplus/QtContextKeywords.h
  79. 161 0
      Source/ToolCore/JSBind/cplusplus/SafeMatcher.cpp
  80. 65 0
      Source/ToolCore/JSBind/cplusplus/SafeMatcher.h
  81. 295 0
      Source/ToolCore/JSBind/cplusplus/Scope.cpp
  82. 83 0
      Source/ToolCore/JSBind/cplusplus/Scope.h
  83. 437 0
      Source/ToolCore/JSBind/cplusplus/Symbol.cpp
  84. 330 0
      Source/ToolCore/JSBind/cplusplus/Symbol.h
  85. 34 0
      Source/ToolCore/JSBind/cplusplus/SymbolVisitor.cpp
  86. 76 0
      Source/ToolCore/JSBind/cplusplus/SymbolVisitor.h
  87. 1097 0
      Source/ToolCore/JSBind/cplusplus/Symbols.cpp
  88. 912 0
      Source/ToolCore/JSBind/cplusplus/Symbols.h
  89. 578 0
      Source/ToolCore/JSBind/cplusplus/Templates.cpp
  90. 211 0
      Source/ToolCore/JSBind/cplusplus/Templates.h
  91. 128 0
      Source/ToolCore/JSBind/cplusplus/Token.cpp
  92. 410 0
      Source/ToolCore/JSBind/cplusplus/Token.h
  93. 585 0
      Source/ToolCore/JSBind/cplusplus/TranslationUnit.cpp
  94. 218 0
      Source/ToolCore/JSBind/cplusplus/TranslationUnit.h
  95. 113 0
      Source/ToolCore/JSBind/cplusplus/Type.cpp
  96. 112 0
      Source/ToolCore/JSBind/cplusplus/Type.h
  97. 35 0
      Source/ToolCore/JSBind/cplusplus/TypeVisitor.cpp
  98. 67 0
      Source/ToolCore/JSBind/cplusplus/TypeVisitor.h
  99. 71 0
      Source/ToolCore/JSBind/cplusplus/cplusplus.pri
  100. 47 0
      Source/ToolCore/JSBind/cplusplus/cppassert.h

+ 5 - 0
Source/AtomicJS/Packages/Atomic/Container.json

@@ -0,0 +1,5 @@
+{
+	"name" : "Container",
+	"sources" : ["Source/Atomic/Container"],
+	"classes" : ["RefCounted"]
+}

+ 8 - 0
Source/AtomicJS/Packages/Atomic/Core.json

@@ -0,0 +1,8 @@
+{
+	"name" : "Core",
+	"sources" : ["Source/Atomic/Core"],
+	"classes" : ["Context", "Object"],
+	"classes_rename" : {
+		"Object" : "AObject"
+	}
+}

+ 8 - 0
Source/AtomicJS/Packages/Atomic/Package.json

@@ -0,0 +1,8 @@
+
+{
+
+  "name" : "Atomic",
+  "namespace" : "Atomic",  
+  "modules" : ["Container", "Core"]
+
+}

+ 1 - 0
Source/ToolCore/CMakeLists.txt

@@ -2,6 +2,7 @@ include_directories (${CMAKE_SOURCE_DIR}/Source/ThirdParty/rapidjson/include
                      ${CMAKE_SOURCE_DIR}/Source/ThirdParty
                      ${CMAKE_SOURCE_DIR}/Source/ThirdParty/nativefiledialog)
 
+add_definitions(-DCPLUSPLUS_WITHOUT_QT)
 
 if (MSVC)
     include_directories (${CMAKE_SOURCE_DIR}/Source/ThirdParty/libcurl/include)

+ 61 - 0
Source/ToolCore/Command/BindCmd.cpp

@@ -0,0 +1,61 @@
+
+#include <Atomic/Core/Context.h>
+#include <Atomic/Core/StringUtils.h>
+#include <Atomic/IO/Log.h>
+#include <Atomic/IO/File.h>
+
+#include "../ToolSystem.h"
+#include "../ToolEnvironment.h"
+
+#include "../JSBind/JSBind.h"
+
+#include "BindCmd.h"
+
+namespace ToolCore
+{
+
+BindCmd::BindCmd(Context* context) : Command(context)
+{
+
+}
+
+BindCmd::~BindCmd()
+{
+
+}
+
+bool BindCmd::Parse(const Vector<String>& arguments, unsigned startIndex, String& errorMsg)
+{
+    String argument = arguments[startIndex].ToLower();
+    String value = startIndex + 1 < arguments.Size() ? arguments[startIndex + 1] : String::EMPTY;
+
+    if (argument != "bind")
+    {
+        errorMsg = "Unable to parse bind command";
+        return false;
+    }
+
+    return true;
+}
+
+void BindCmd::Run()
+{
+    ToolEnvironment* env = GetSubsystem<ToolEnvironment>();
+
+    bindPlatform_ = "MACOSX";
+    sourceRootFolder_ = env->GetRootSourceDir();
+    packageFolder_ = "Source/AtomicJS/Packages/Atomic/";
+
+    SharedPtr<JSBind> jsbind(new JSBind(context_));
+
+    context_->RegisterSubsystem(jsbind);
+
+    LOGINFOF("Generating JS Bindings");
+
+    jsbind->GenerateBindings(sourceRootFolder_, packageFolder_, bindPlatform_);
+
+    Finished();
+
+}
+
+}

+ 34 - 0
Source/ToolCore/Command/BindCmd.h

@@ -0,0 +1,34 @@
+
+#pragma once
+
+#include "Command.h"
+
+using namespace Atomic;
+
+namespace ToolCore
+{
+
+class BindCmd: public Command
+{
+    OBJECT(BindCmd);
+
+public:
+
+    BindCmd(Context* context);
+    virtual ~BindCmd();
+
+    bool Parse(const Vector<String>& arguments, unsigned startIndex, String& errorMsg);
+
+    void Run();
+
+    bool RequiresProjectLoad() { return false; }
+
+private:
+
+    String bindPlatform_;
+    String sourceRootFolder_;
+    String packageFolder_;
+
+};
+
+}

+ 5 - 0
Source/ToolCore/Command/CommandParser.cpp

@@ -7,6 +7,7 @@
 #include "ImportCmd.h"
 #include "PlayCmd.h"
 #include "EditCmd.h"
+#include "BindCmd.h"
 
 namespace ToolCore
 {
@@ -55,6 +56,10 @@ Command* CommandParser::Parse(const Vector<String>& arguments)
             {
                 cmd = new EditCmd(context_);
             }
+            else if (argument == "bind")
+            {
+                cmd = new BindCmd(context_);
+            }
 
         }
 

+ 24 - 0
Source/ToolCore/JSBind/JSBClass.cpp

@@ -0,0 +1,24 @@
+#include <Atomic/IO/Log.h>
+#include <Atomic/IO/File.h>
+#include <Atomic/Resource/JSONFile.h>
+
+#include "JSBModule.h"
+#include "JSBClass.h"
+#include "JSBFunction.h"
+
+namespace ToolCore
+{
+
+JSBClass::JSBClass(Context* context, JSBModule *module, const String& name, const String& nativeName) : Object(context),
+    module_(module), name_(name), nativeName_(nativeName),
+    isAbstract_(false)
+{
+
+}
+
+JSBClass::~JSBClass()
+{
+
+}
+
+}

+ 53 - 0
Source/ToolCore/JSBind/JSBClass.h

@@ -0,0 +1,53 @@
+
+#pragma once
+
+#include <Atomic/Core/Object.h>
+
+#include "JSBHeader.h"
+
+using namespace Atomic;
+
+namespace ToolCore
+{
+
+class JSBModule;
+class JSBFunction;
+
+class JSBClass : public Object
+{
+
+    OBJECT(JSBClass)
+
+public:
+
+    JSBClass(Context* context, JSBModule* module, const String& name, const String& nativeName);
+    virtual ~JSBClass();
+
+    const String& GetName() { return name_; }
+    const String& GetNativeName() { return nativeName_; }
+
+    void SetHeader(JSBHeader* header) { header_ = header; }
+
+    void AddBaseClass(JSBClass* baseClass) { baseClasses_.Push(baseClass); }
+    void SetAbstract() { isAbstract_ = true; }
+
+    void AddFunction(JSBFunction* function);
+
+private:
+
+    bool isAbstract_;
+
+    String name_;
+    String nativeName_;
+
+    SharedPtr<JSBHeader> header_;
+    SharedPtr<JSBModule> module_;
+
+
+    PODVector<JSBFunction*> functions;
+    PODVector<JSBClass*> baseClasses_;
+
+};
+
+
+}

+ 74 - 0
Source/ToolCore/JSBind/JSBEnum.cpp

@@ -0,0 +1,74 @@
+#include <Atomic/IO/Log.h>
+#include <Atomic/IO/File.h>
+#include <Atomic/Resource/JSONFile.h>
+
+#include "JSBind.h"
+#include "JSBModule.h"
+#include "JSBEnum.h"
+
+namespace ToolCore
+{
+
+JSBEnum::JSBEnum(Context* context, JSBModule *module, const String& name) : Object(context),
+    module_(module), name_(name)
+{
+
+}
+
+JSBEnum::~JSBEnum()
+{
+
+}
+
+void JSBEnum::Preprocess()
+{
+    // TextureUnit is a special case as uses preprocessor for values depending on
+    // Desktop or Mobile graphics
+
+    JSBind* jsbind = GetSubsystem<JSBind>();
+
+    if (name_ == "TextureUnit")
+    {
+        values_.Clear();
+
+        values_.Push("TU_DIFFUSE");
+        values_.Push("TU_ALBEDOBUFFER");
+        values_.Push("TU_NORMAL");
+        values_.Push("TU_NORMALBUFFER");
+        values_.Push("TU_SPECULAR");
+        values_.Push("TU_EMISSIVE");
+        values_.Push("TU_ENVIRONMENT");
+
+        String platform = jsbind->GetPlatform();
+
+        bool mobile = platform == "WEB" || platform == "ANDROID" || platform == "IOS";
+
+        if (mobile)
+        {
+            values_.Push("TU_LIGHTRAMP");
+            values_.Push("TU_LIGHTSHAPE");
+            values_.Push("TU_SHADOWMAP");
+            values_.Push("MAX_MATERIAL_TEXTURE_UNITS");
+            values_.Push("MAX_TEXTURE_UNITS");
+        }
+        else
+        {
+            values_.Push("TU_VOLUMEMAP");
+            values_.Push("TU_CUSTOM1");
+            values_.Push("TU_CUSTOM2");
+            values_.Push("TU_LIGHTRAMP");
+            values_.Push("TU_LIGHTSHAPE");
+            values_.Push("TU_SHADOWMAP");
+            values_.Push("TU_FACESELECT");
+            values_.Push("TU_INDIRECTION");
+            values_.Push("TU_DEPTHBUFFER");
+            values_.Push("TU_LIGHTBUFFER");
+            values_.Push("TU_ZONE");
+            values_.Push("MAX_MATERIAL_TEXTURE_UNITS");
+            values_.Push("MAX_TEXTURE_UNITS");
+        }
+
+    }
+}
+
+}

+ 40 - 0
Source/ToolCore/JSBind/JSBEnum.h

@@ -0,0 +1,40 @@
+
+#pragma once
+
+#include <Atomic/Core/Object.h>
+
+using namespace Atomic;
+
+namespace ToolCore
+{
+
+class JSBModule;
+
+class JSBEnum : public Object
+{
+
+    OBJECT(JSBEnum)
+
+public:
+
+    JSBEnum(Context* context, JSBModule* module, const String& name);
+    virtual ~JSBEnum();
+
+    const String& GetName() { return name_; }
+
+    void Preprocess();
+
+    void AddValue(const String& value) { values_.Push(value); }
+
+private:
+
+    String name_;
+
+    SharedPtr<JSBModule> module_;
+
+    Vector<String> values_;
+
+};
+
+
+}

+ 0 - 0
Source/ToolCore/JSBind/JSBFunction.cpp


+ 155 - 0
Source/ToolCore/JSBind/JSBFunction.h

@@ -0,0 +1,155 @@
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// Please see LICENSE.md in repository root for license information
+// https://github.com/AtomicGameEngine/AtomicGameEngine
+
+#pragma once
+
+#include <Atomic/IO/Log.h>
+#include "JSBClass.h"
+#include "JSBType.h"
+#include "JSBSymbol.h"
+
+using namespace Atomic;
+
+namespace ToolCore
+{
+
+class JSBFunctionType
+{
+public:
+
+    JSBFunctionType(JSBType* type) : type_(type)
+    {
+        isSharedPtr_ = false;
+        isPointer_ = false;
+        isReference_ = false;
+        isTemplate_ = false;
+    }
+
+    bool isSharedPtr_;
+    bool isPointer_;
+    bool isReference_;
+    bool isTemplate_;
+
+    String name_;
+    String initializer_;
+
+    JSBType* type_;
+
+    String ToString()
+    {
+        String tstring = type_->ToString();
+        if (isPointer_)
+            tstring += "*";
+        if (isReference_)
+            tstring += "&";
+
+        if (name_.Length())
+        {
+            tstring += " " + name_;
+        }
+
+        return tstring;
+    }
+
+    String ToArgString(int index)
+    {
+        String tstring = type_->ToString();
+
+        if (isPointer_)
+            tstring += "*";
+
+        if (isReference_ && tstring != "String")
+            tstring += "&";
+
+        if (name_.Length())
+        {
+            tstring.AppendWithFormat(" __arg%i", index);
+        }
+
+        return tstring;
+    }
+
+
+};
+
+class JSBFunction : public JSBSymbol
+{
+public:
+
+    JSBClass* class_;
+    String name_;
+    String propertyName_;
+    JSBFunctionType* returnType_;
+    Vector<JSBFunctionType*> parameters_;
+    String docString_;
+
+    bool isConstructor_;
+    bool isDestructor_;
+    bool isGetter_;
+    bool isSetter_;
+    bool isOverride_;
+    bool skip_;
+
+    int FirstDefaultParameter()
+    {
+        for (unsigned i = 0; i < parameters_.Size(); i++)
+        {
+            if (parameters_[i]->initializer_.Length())
+                return i;
+        }
+
+        return -1;
+    }
+
+    void AddParameter(JSBFunctionType* parm)
+    {
+        parameters_.Push(parm);
+    }
+
+    JSBFunction(JSBClass* klass) : class_(klass), returnType_(0),
+                                   isConstructor_(false), isDestructor_(false),
+                                   isGetter_(false), isSetter_(false),
+                                   isOverride_(false), skip_(false)
+    {
+
+    }
+
+    void SetSkip(bool value) { skip_ = value; }
+    bool Skip() { return skip_; }
+
+    void Process();
+
+    void WriteParameterMarshal(String& source);
+    void WriteFunction(String& source);
+    void WriteConstructor(String& source);
+
+    void Write(String& source);
+
+    void Dump()
+    {
+        String sig;
+        if (!returnType_)
+            sig += "void ";
+        else
+            sig += returnType_->ToString() + " ";
+
+        sig += name_;
+        sig += "(";
+        for (unsigned i = 0; i < parameters_.Size(); i++)
+        {
+
+            sig += parameters_.At(i)->ToString();
+
+            if (i != parameters_.Size() - 1)
+                 sig += ", ";
+        }
+        sig += ");";
+
+        LOGINFOF("      %s", sig.CString());
+
+    }
+
+};
+
+}

+ 74 - 0
Source/ToolCore/JSBind/JSBHeader.cpp

@@ -0,0 +1,74 @@
+#include <Atomic/IO/File.h>
+
+#include "cplusplus/CPlusPlus.h"
+using namespace CPlusPlus;
+
+#include "JSBPreprocessVisitor.h"
+
+#include "JSBModule.h"
+#include "JSBHeader.h"
+
+namespace ToolCore
+{
+
+JSBHeader::JSBHeader(Context* context, JSBModule* module, const String& filepath) : Object(context),
+    translationUnit_(0),
+    globalNamespace_(0),
+    filepath_(filepath),
+    module_(module)
+{
+
+}
+
+JSBHeader::~JSBHeader()
+{
+
+}
+
+void JSBHeader::Parse()
+{
+    Control* control = new Control();
+    const StringLiteral *fileId = control->stringLiteral(filepath_.CString(), filepath_.Length() );
+    LanguageFeatures features;
+    features.qtEnabled = false;
+    features.qtMocRunEnabled = false;
+    features.qtKeywordsEnabled = false;
+    features.cxx11Enabled = true;
+    features.objCEnabled = false;
+    features.c99Enabled = false;
+    translationUnit_ = new TranslationUnit(control, fileId);
+    translationUnit_->setLanguageFeatures(features);
+    control->switchTranslationUnit(translationUnit_);
+
+    File file(context_);
+    file.Open(filepath_);
+
+    unsigned size = file.GetSize();
+
+    data_ = new char[size + 1];
+    data_[size] = '\0';
+
+    file.Read(data_, size);
+
+    // TODO: add error reporting
+    translationUnit_->blockErrors(true);
+
+    translationUnit_->setSource(data_, size);
+    translationUnit_->tokenize();
+    translationUnit_->parse();
+
+    globalNamespace_ = control->newNamespace(0);
+    Bind* semantic = new Bind(translationUnit_);
+    semantic->setSkipFunctionBodies(true);
+
+    (*semantic)(translationUnit_->ast()->asTranslationUnit(), globalNamespace_);
+}
+
+void JSBHeader::VisitPreprocess()
+{
+    JSBPreprocessVisitor(this, translationUnit_,globalNamespace_);
+}
+
+
+
+}

+ 56 - 0
Source/ToolCore/JSBind/JSBHeader.h

@@ -0,0 +1,56 @@
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// Please see LICENSE.md in repository root for license information
+// https://github.com/AtomicGameEngine/AtomicGameEngine
+
+#pragma once
+
+#include <Atomic/Container/Vector.h>
+#include <Atomic/Container/Str.h>
+#include <Atomic/Container/ArrayPtr.h>
+
+#include <Atomic/Core/Object.h>
+
+using namespace Atomic;
+
+namespace CPlusPlus
+{
+    class TranslationUnit;
+    class Namespace;
+}
+
+namespace ToolCore
+{
+
+class JSBModule;
+
+class JSBHeader : public Object
+{
+
+    OBJECT(JSBHeader)
+
+public:
+
+    JSBHeader(Context* context, JSBModule* module, const String& filepath);
+    virtual ~JSBHeader();
+
+    void Parse();
+
+    void VisitPreprocess();
+    void VisitHeader();
+
+    JSBModule* GetModule() { return module_; }
+
+private:
+
+    CPlusPlus::TranslationUnit* translationUnit_;
+    CPlusPlus::Namespace* globalNamespace_;
+
+    SharedArrayPtr<char> data_;
+
+    // absolute path to source file
+    String filepath_;
+    SharedPtr<JSBModule> module_;
+
+};
+
+}

+ 2 - 0
Source/ToolCore/JSBind/JSBHeaderVisitor.cpp

@@ -0,0 +1,2 @@
+
+#include "JSBHeaderVisitor.h"

+ 445 - 0
Source/ToolCore/JSBind/JSBHeaderVisitor.h

@@ -0,0 +1,445 @@
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// Please see LICENSE.md in repository root for license information
+// https://github.com/AtomicGameEngine/AtomicGameEngine
+
+#pragma once
+
+#include <Atomic/IO/Log.h>
+#include <Atomic/Core/ProcessUtils.h>
+
+using namespace Atomic;
+
+
+#include "JSBHeader.h"
+#include "JSBModule.h"
+#include "JSBClass.h"
+#include "JSBPackage.h"
+#include "JSBFunction.h"
+
+#include "JSBNameVisitor.h"
+
+
+namespace ToolCore
+{
+
+class JSBHeader;
+
+
+class JSBHeaderVisitor : public SymbolVisitor
+{
+    JSBHeader* header_;
+    JSBModule* module_;
+    TranslationUnit* unit_;
+
+    Namespace* globalNamespace_;
+
+public:
+
+    JSBHeaderVisitor(JSBHeader* header, TranslationUnit *unit, Namespace* globalNamespace) :
+        header_(header),
+        unit_(unit),
+        globalNamespace_(globalNamespace)
+    {
+        module_ = header_->GetModule();
+
+        accept(globalNamespace_);
+
+    }
+
+    String getNameString(const Name* name)
+    {
+        JSBNameVisitor nvisitor;
+        return nvisitor(name);
+    }
+
+    JSBType* processTypeConversion(Type* type)
+    {
+        JSBType* jtype = NULL;
+
+        if (type->isIntegerType())
+        {
+            IntegerType* itype = type->asIntegerType();
+            jtype = new JSBPrimitiveType(itype->kind());
+        }
+        if (type->isFloatType())
+        {
+            jtype = new JSBPrimitiveType(JSBPrimitiveType::Float);
+        }
+        else if (type->isNamedType())
+        {
+            NamedType* ntype = type->asNamedType();
+            String classname = getNameString(ntype->name());
+
+            if (classname.StartsWith("Atomic::"))
+                classname.Replace("Atomic::", "");
+
+            if (classname == "String")
+            {
+                jtype = new JSBStringType();
+            }
+            else if (classname == "StringHash")
+            {
+                jtype = new JSBStringHashType();
+            }
+            else if (classname == "JS_HEAP_PTR")
+            {
+                jtype = new JSBHeapPtrType();
+            }
+            else
+            {
+                JSBClass* jclass = JSBPackage::GetClassAllPackages(classname);
+
+                if (jclass)
+                    jtype = new JSBClassType(jclass);
+                else
+                {
+                    // this might be an enum
+                    JSBEnum* jenum = JSBPackage::GetEnumAllPackages(classname);
+                    if (jenum)
+                        jtype = new JSBEnumType(jenum);
+
+                }
+            }
+        }
+        else if (type->asUndefinedType())
+        {
+            UndefinedType* utype = type->asUndefinedType();
+            //ErrorExit("Undefined type");
+        }
+
+        return jtype;
+
+    }
+
+    JSBFunctionType* processFunctionType(FullySpecifiedType fst, bool retType = false)
+    {
+        JSBType* jtype = NULL;
+        Type* type = fst.type();
+
+        bool isPointer = false;
+        bool isSharedPtr = false;
+        bool isReference = false;
+        bool isTemplate = false;
+
+        bool isConst = false;
+
+        if (type->isPointerType())
+        {
+            isPointer=true;
+            FullySpecifiedType pfst = type->asPointerType()->elementType();
+            type = pfst.type();
+        }
+        if (type->isReferenceType())
+        {
+            isReference=true;
+            FullySpecifiedType pfst = type->asReferenceType()->elementType();
+            type = pfst.type();
+            isConst = pfst.isConst();
+        }
+        if (!isPointer && retType)
+        {
+            if (type->isNamedType())
+            {
+                NamedType* ntype = type->asNamedType();
+                if (ntype->name()->asTemplateNameId())
+                {
+                    const TemplateNameId* tnid = ntype->name()->asTemplateNameId();
+                    String classname = getNameString(tnid->identifier()->asNameId());
+                    if (classname == "SharedPtr")
+                    {
+                        FullySpecifiedType pfst = tnid->templateArgumentAt(0);
+                        type = pfst.type();
+                        isTemplate = true;
+                    }
+                }
+            }
+        }
+
+        if (fst.isUnsigned())
+        {
+            if (type->isUndefinedType())
+            {
+                // this happens when just using "unsigned" in code
+                jtype = new JSBPrimitiveType(JSBPrimitiveType::Int, true);
+            }
+        }
+
+
+        if (!jtype)
+            jtype = processTypeConversion(type);
+
+        if (!jtype)
+            return NULL;
+
+        bool skip = false;
+
+        // no pointers to prim atm
+        if (isPointer || isReference)
+        {
+            if (jtype->asPrimitiveType())
+                skip = true;
+            else if (!retType && !isConst && (jtype->asStringType() || jtype->asStringHashType()))
+            {
+                skip = true;
+            }
+
+            if (skip)
+                return NULL;
+        }
+
+        JSBFunctionType* ftype = new JSBFunctionType(jtype);
+        ftype->isPointer_ = isPointer;
+        ftype->isSharedPtr_ = isSharedPtr;
+        ftype->isReference_ = isReference;
+        ftype->isTemplate_ = isTemplate;
+
+        return ftype;
+
+    }
+
+    JSBFunctionType* processFunctionArgType(Argument* arg)
+    {
+
+        JSBFunctionType* jtype = processFunctionType(arg->type());
+
+        if (!jtype)
+            return NULL;
+
+        jtype->name_ = getNameString(arg->name());
+
+        return jtype;
+
+    }
+
+
+    JSBFunctionType* processFunctionReturnType(Function* function)
+    {
+        if (!function->hasReturnType())
+        {
+            return NULL;
+        }
+
+        JSBFunctionType* jtype = processFunctionType(function->returnType(), true);
+
+        if (!jtype)
+            return NULL;
+
+        return jtype;
+
+    }
+
+    JSBFunction* processFunction(JSBClass* klass, Function* function)
+    {
+        JSBFunction* jfunction = new JSBFunction(klass);
+
+        // don't ... atm
+        if (function->isVariadic())
+            return NULL;
+
+        jfunction->name_ = getNameString(function->name());
+
+        // don't support operators atm
+        if (jfunction->name_.StartsWith("operator "))
+            return NULL;
+
+        if (jfunction->name_ == klass->GetName())
+            jfunction->isConstructor_ = true;
+
+        if (jfunction->name_.StartsWith("~"))
+            jfunction->isDestructor_ = true;
+
+        // see if we support return type
+        if (function->hasReturnType() && !function->returnType().type()->isVoidType())
+        {
+            jfunction->returnType_ = processFunctionReturnType(function);
+            if (!jfunction->returnType_)
+                return NULL;
+        }
+
+        if (function->hasArguments())
+        {
+            for (unsigned i = 0; i < function->argumentCount(); i++)
+            {
+                Symbol* symbol = function->argumentAt(i);
+                if (symbol->isArgument())
+                {
+                    Argument* arg = symbol->asArgument();
+
+                    JSBFunctionType* ftype = processFunctionArgType(arg);
+                    if (!ftype)
+                        return NULL;
+
+                    if (arg->hasInitializer())
+                    {
+                        ftype->initializer_ = arg->initializer()->chars();
+                        if (ftype->initializer_.StartsWith("\\"))
+                            ftype->initializer_ = "\"" + ftype->initializer_ + "\"";
+                    }
+
+                    jfunction->AddParameter(ftype);
+                }
+                else
+                {
+                    return NULL;
+                }
+
+            }
+        }
+
+        jfunction->sourceLocation_ = function->sourceLocation();
+        jfunction->fileName_ = function->fileName();
+        jfunction->sourceLine_ = function->line();
+        jfunction->sourceColumn_ = function->column();
+        //const Token &token = unit_->tokenAt(function->sourceLocation());
+        //const char* source = unit_->firstSourceChar() + token.byteOffset;
+        const char* comment = NULL;
+        for (unsigned i = 0; i < unit_->commentCount(); i++)
+        {
+            const Token &tcomment = unit_->commentAt(i);
+            unsigned line;
+            unit_->getPosition(tcomment.utf16charOffset, &line);
+
+            if (line ==  function->line() - 1)
+            {
+                comment = unit_->firstSourceChar() + tcomment.byteOffset;
+                break;
+            }
+        }
+
+        if (comment && strlen(comment) > 3)
+        {
+            if (comment[0] == '/' && comment[1] == '/' && comment[2] == '/')
+            {
+                int index = 3;
+                while(comment[index] && comment[index] != '\n' && comment[index] != '\r')
+                    jfunction->docString_ += comment[index++];
+
+            }
+
+        }
+
+
+        return jfunction;
+
+    }
+
+    virtual bool visit(Namespace *nspace)
+    {
+        String name = getNameString(nspace->name());
+
+        // LOGINFOF("Namespace: %s", name.CString());
+
+        return true;
+
+    }
+
+    // reject template types
+    virtual bool visit(Template *t)
+    {
+        return false;
+    }
+
+    // enums visited in preprocessor visitor
+    virtual bool visit(Enum *penum)
+    {
+        return false;
+    }
+
+    // global var decl or function
+    virtual bool visit(Declaration* decl)
+    {
+        if (decl->isTypedef())
+            return true;
+
+        FullySpecifiedType dtype = decl->type();
+
+        Type* type = dtype.type();
+
+        if (type->isPointerType() || type->isReferenceType())
+            return true;
+
+        if (type->asEnumType())
+            return true;
+
+        bool _unsigned = false;
+
+        if (dtype.isUnsigned())
+            _unsigned = true;
+
+
+        if (!type->asFloatType() && !type->asIntegerType() && !_unsigned)
+        {
+            return true;
+        }
+
+        module_->RegisterConstant(getNameString(decl->name()).CString());
+
+        return true;
+
+    }
+
+    virtual bool visit(Class *klass)
+    {
+        String name = getNameString(klass->name());
+
+        JSBClass* jclass = module_->GetClass(name);
+
+        if (!jclass)
+        {
+            return false;
+        }
+
+        jclass->SetHeader(header_);
+
+        for (unsigned i = 0; i < klass->baseClassCount(); i++)
+        {
+            BaseClass* baseclass = klass->baseClassAt(i);
+            String baseclassname = getNameString(baseclass->name());
+
+            JSBClass* base = JSBPackage::GetClassAllPackages(baseclassname);
+
+            if (!base)
+            {
+                LOGINFOF("Warning: %s baseclass %s not in bindings", name.CString(), baseclassname.CString());
+            }
+            else
+            {
+                jclass->AddBaseClass(base);
+            }
+        }
+
+        for (unsigned i = 0; i < klass->memberCount(); i++)
+        {
+            Symbol* symbol = klass->memberAt(i);
+
+            Declaration* decl = symbol->asDeclaration();
+
+            // if the function describes the body in the header
+            Function* function = symbol->asFunction();
+
+            // otherwise it could be a decl
+            if (!function && decl)
+                function = decl->type()->asFunctionType();
+
+            if (function)
+            {
+                if (function->isPureVirtual())
+                    jclass->SetAbstract();
+
+                // only want public functions
+                if (!symbol->isPublic())
+                    continue;
+
+                JSBFunction* jfunction = processFunction(jclass, function);
+                if (jfunction)
+                    jclass->AddFunction(jfunction);
+            }
+
+        }
+        // return false so we don't traverse the class members
+        return false;
+    }
+
+};
+
+}

+ 197 - 0
Source/ToolCore/JSBind/JSBModule.cpp

@@ -0,0 +1,197 @@
+#include <Atomic/IO/Log.h>
+#include <Atomic/IO/File.h>
+#include <Atomic/IO/FileSystem.h>
+#include <Atomic/Resource/JSONFile.h>
+
+#include "Atomic/Core/ProcessUtils.h"
+
+#include "JSBind.h"
+#include "JSBPackage.h"
+#include "JSBModule.h"
+#include "JSBHeader.h"
+#include "JSBClass.h"
+#include "JSBEnum.h"
+
+namespace ToolCore
+{
+
+JSBModule::JSBModule(Context* context, JSBPackage* package) : Object(context),
+    package_(package)
+{
+
+}
+
+JSBModule::~JSBModule()
+{
+
+}
+
+void JSBModule::PreprocessHeaders()
+{
+    for (unsigned i = 0; i < headers_.Size(); i++)
+    {
+        headers_[i]->VisitPreprocess();
+    }
+}
+
+void JSBModule::ScanHeaders()
+{
+    JSBind* jsbind = GetSubsystem<JSBind>();
+    FileSystem* fs = GetSubsystem<FileSystem>();
+
+    const String& sourceRoot = jsbind->GetSourceRootFolder();
+
+    for (unsigned i = 0; i < sourceDirs_.Size(); i++)
+    {
+        const String& dir = sourceRoot + sourceDirs_[i] + "/";
+
+        Vector<String> fileNames;
+        fs->ScanDir(fileNames, dir, "*.h", SCAN_FILES, false);
+
+        for (unsigned k = 0; k < fileNames.Size(); k++)
+        {
+            String filepath = dir + fileNames[k];
+
+            SharedPtr<JSBHeader> header(new JSBHeader(context_, this, filepath));
+
+            // Parse the C++ header
+            header->Parse();
+
+            headers_.Push(header);
+        }
+
+    }
+
+}
+
+JSBClass* JSBModule::GetClass(const String& name)
+{
+    if (classes_.Contains(name))
+        return classes_[name];
+
+    return 0;
+}
+
+void JSBModule::RegisterClass(String name)
+{
+    String nativeName = name;
+
+    if (classnames_.Contains(name))
+    {
+        if (classRenames_.Contains(name))
+        {
+            name = classRenames_[name];
+        }
+
+        if (JSBPackage::GetClassAllPackages(nativeName))
+        {
+            ErrorExit(ToString("Class collision: %s", name.CString()));
+        }
+
+        JSBClass* cls = new JSBClass(context_, this, name, nativeName);
+
+        classes_[nativeName] = cls;
+
+        LOGINFOF("Registered Class: %s", cls->GetName().CString());
+    }
+}
+
+void JSBModule::RegisterEnum(JSBEnum* jenum)
+{
+    if (JSBPackage::GetClassAllPackages(jenum->GetName()))
+    {
+        ErrorExit(ToString("Enum collision: %s", jenum->GetName().CString()));
+    }
+
+    enums_[jenum->GetName()] = jenum;
+
+    LOGINFOF("Registered Enum: %s", jenum->GetName().CString());
+}
+
+JSBEnum* JSBModule::GetEnum(const String& name)
+{
+    if (enums_.Contains(name))
+    {
+        return enums_[name];
+    }
+
+    return 0;
+
+}
+
+bool JSBModule::ContainsConstant(const String& constantName)
+{
+    return constants_.Contains(constantName);
+}
+
+void JSBModule::RegisterConstant(const String& constantName)
+{
+    if (JSBPackage::ContainsConstantAllPackages(constantName))
+    {
+        ErrorExit(ToString("Constant collision: %s", constantName.CString()));
+    }
+
+    constants_.Push(constantName);
+
+}
+
+bool JSBModule::Load(const String& jsonFilename)
+{
+    LOGINFOF("Loading Module: %s", jsonFilename.CString());
+
+    SharedPtr<File> jsonFile(new File(context_, jsonFilename));
+
+    if (!jsonFile->IsOpen())
+    {
+        LOGERRORF("Unable to open module json: %s", jsonFilename.CString());
+        return false;
+    }
+
+    SharedPtr<JSONFile> moduleJSON(new JSONFile(context_));
+
+    if (!moduleJSON->BeginLoad(*jsonFile))
+    {
+        LOGERRORF("Unable to parse module json: %s", jsonFilename.CString());
+        return false;
+    }
+
+    JSONValue root = moduleJSON->GetRoot();
+
+    name_ = root.GetString("name");
+
+    JSONValue classes = root.GetChild("classes");
+
+    for (unsigned i = 0; i < classes.GetSize(); i++)
+    {
+        classnames_.Push(classes.GetString(i));
+    }
+
+    JSONValue classes_rename = root.GetChild("classes_rename");
+
+    if (classes_rename.IsObject())
+    {
+        Vector<String> childNames = classes_rename.GetValueNames();
+        for (unsigned j = 0; j < childNames.Size(); j++)
+        {
+            String classname = childNames.At(j);
+            String crename = classes_rename.GetString(classname);
+
+            classRenames_[classname] = crename;
+
+        }
+
+    }
+
+    JSONValue sources = root.GetChild("sources");
+
+    for (unsigned i = 0; i < sources.GetSize(); i++)
+    {
+        sourceDirs_.Push(sources.GetString(i));
+    }
+
+    ScanHeaders();
+
+    return true;
+}
+
+}

+ 63 - 0
Source/ToolCore/JSBind/JSBModule.h

@@ -0,0 +1,63 @@
+
+#pragma once
+
+#include <Atomic/Core/Object.h>
+
+using namespace Atomic;
+
+namespace ToolCore
+{
+
+class JSBPackage;
+class JSBHeader;
+class JSBClass;
+class JSBEnum;
+
+class JSBModule : public Object
+{
+
+    OBJECT(JSBModule)
+
+public:
+
+    JSBModule(Context* context, JSBPackage* package);
+    virtual ~JSBModule();
+
+    JSBPackage* GetPackage() { return package_; }
+
+    JSBClass* GetClass(const String& name);
+    void RegisterClass(String name);
+
+    JSBEnum* GetEnum(const String& name);
+    void RegisterEnum(JSBEnum* jenum);
+
+    bool ContainsConstant(const String& constantName);
+    void RegisterConstant(const String& constantName);
+
+    bool Load(const String& jsonFilename);
+    void PreprocessHeaders();
+
+
+private:
+
+    void ScanHeaders();
+
+    String name_;
+
+    SharedPtr<JSBPackage> package_;
+    Vector<SharedPtr<JSBHeader>> headers_;
+
+    Vector<String> sourceDirs_;
+    Vector<String> classnames_;
+
+    HashMap<String, String> classRenames_;
+
+    // native name -> JSBClass
+    HashMap<StringHash, SharedPtr<JSBClass> > classes_;
+    HashMap<StringHash, SharedPtr<JSBEnum> > enums_;
+    Vector<String> constants_;
+
+};
+
+
+}

+ 237 - 0
Source/ToolCore/JSBind/JSBNameVisitor.cpp

@@ -0,0 +1,237 @@
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// Please see LICENSE.md in repository root for license information
+// https://github.com/AtomicGameEngine/AtomicGameEngine
+
+#include <Atomic/Atomic.h>
+
+#include "JSBNameVisitor.h"
+
+namespace ToolCore
+{
+
+JSBNameVisitor::JSBNameVisitor()
+{ }
+
+JSBNameVisitor::~JSBNameVisitor()
+{ }
+
+String JSBNameVisitor::operator()(const Name *name)
+{
+    String previousName = switchName();
+    accept(name);
+    return switchName(previousName);
+}
+
+String JSBNameVisitor::switchName(const String &name)
+{
+    String previousName = name_;
+    name_ = name;
+    return previousName;
+}
+
+void JSBNameVisitor::visit(const Identifier *name)
+{
+    const Identifier *id = name->identifier();
+    if (id)
+        name_ = String(id->chars(), id->size());
+    else
+        name_ = "anonymous";
+}
+
+void JSBNameVisitor::visit(const TemplateNameId *name)
+{
+    name_ = "Not Implemented TemplateNameId";
+
+    unsigned numTemplateArgs = name->templateArgumentCount();
+    if (numTemplateArgs != 1)
+        return;
+
+    FullySpecifiedType fst = name->templateArgumentAt(0);
+
+    const Identifier *id = name->identifier();
+
+    name_ = String(id->chars(), id->size());
+
+}
+
+void JSBNameVisitor::visit(const DestructorNameId *name)
+{
+    const Identifier *id = name->identifier();
+    name_ += "~";
+    name_ += String(id->chars(), id->size());
+}
+
+void JSBNameVisitor::visit(const OperatorNameId *name)
+{
+    name_ += "operator";
+    if (true) //_overview->includeWhiteSpaceInOperatorName)
+        name_ += " ";
+    switch (name->kind()) { // ### i should probably do this in OperatorNameId
+    case OperatorNameId::InvalidOp:
+        name_ += "<invalid>";
+        break;
+    case OperatorNameId::NewOp:
+        name_ += "new";
+        break;
+    case OperatorNameId::DeleteOp:
+        name_ += "delete";
+        break;
+    case OperatorNameId::NewArrayOp:
+        name_ += "new[]";
+        break;
+    case OperatorNameId::DeleteArrayOp:
+        name_ += "delete[]";
+        break;
+    case OperatorNameId::PlusOp:
+        name_ += '+';
+        break;
+    case OperatorNameId::MinusOp:
+        name_ += '-';
+        break;
+    case OperatorNameId::StarOp:
+        name_ += '*';
+        break;
+    case OperatorNameId::SlashOp:
+        name_ += '/';
+        break;
+    case OperatorNameId::PercentOp:
+        name_ += '%';
+        break;
+    case OperatorNameId::CaretOp:
+        name_ += '^';
+        break;
+    case OperatorNameId::AmpOp:
+        name_ += '&';
+        break;
+    case OperatorNameId::PipeOp:
+        name_ += '|';
+        break;
+    case OperatorNameId::TildeOp:
+        name_ += '~';
+        break;
+    case OperatorNameId::ExclaimOp:
+        name_ += '!';
+        break;
+    case OperatorNameId::EqualOp:
+        name_ += '=';
+        break;
+    case OperatorNameId::LessOp:
+        name_ += '<';
+        break;
+    case OperatorNameId::GreaterOp:
+        name_ += '>';
+        break;
+    case OperatorNameId::PlusEqualOp:
+        name_ += "+=";
+        break;
+    case OperatorNameId::MinusEqualOp:
+        name_ += "-=";
+        break;
+    case OperatorNameId::StarEqualOp:
+        name_ += "*=";
+        break;
+    case OperatorNameId::SlashEqualOp:
+        name_ += "/=";
+        break;
+    case OperatorNameId::PercentEqualOp:
+        name_ += "%=";
+        break;
+    case OperatorNameId::CaretEqualOp:
+        name_ += "^=";
+        break;
+    case OperatorNameId::AmpEqualOp:
+        name_ += "&=";
+        break;
+    case OperatorNameId::PipeEqualOp:
+        name_ += "|=";
+        break;
+    case OperatorNameId::LessLessOp:
+        name_ += "<<";
+        break;
+    case OperatorNameId::GreaterGreaterOp:
+        name_ += ">>";
+        break;
+    case OperatorNameId::LessLessEqualOp:
+        name_ += "<<=";
+        break;
+    case OperatorNameId::GreaterGreaterEqualOp:
+        name_ += ">>=";
+        break;
+    case OperatorNameId::EqualEqualOp:
+        name_ += "==";
+        break;
+    case OperatorNameId::ExclaimEqualOp:
+        name_ += "!=";
+        break;
+    case OperatorNameId::LessEqualOp:
+        name_ += "<=";
+        break;
+    case OperatorNameId::GreaterEqualOp:
+        name_ += ">=";
+        break;
+    case OperatorNameId::AmpAmpOp:
+        name_ += "&&";
+        break;
+    case OperatorNameId::PipePipeOp:
+        name_ += "||";
+        break;
+    case OperatorNameId::PlusPlusOp:
+        name_ += "++";
+        break;
+    case OperatorNameId::MinusMinusOp:
+        name_ += "--";
+        break;
+    case OperatorNameId::CommaOp:
+        name_ += ',';
+        break;
+    case OperatorNameId::ArrowStarOp:
+        name_ += "->*";
+        break;
+    case OperatorNameId::ArrowOp:
+        name_ += "->";
+        break;
+    case OperatorNameId::FunctionCallOp:
+        name_ += "()";
+        break;
+    case OperatorNameId::ArrayAccessOp:
+        name_ += "[]";
+        break;
+    } // switch
+}
+
+void JSBNameVisitor::visit(const ConversionNameId *name)
+{
+    name_ += "operator ";
+    name_ += "UNIMPLEMENTED";//overview()->prettyType(name->type());
+}
+
+void JSBNameVisitor::visit(const QualifiedNameId *name)
+{
+    if (name->base())
+        name_ += operator()(name->base());
+    name_ += "::";
+    name_ += operator()(name->name());
+}
+
+void JSBNameVisitor::visit(const SelectorNameId *name)
+{
+    for (unsigned i = 0; i < name->nameCount(); ++i) {
+        const Name *n = name->nameAt(i);
+        if (!n)
+            continue;
+
+        if (const Identifier *id = n->identifier()) {
+            name_ += String(id->chars(), id->size());
+
+            if (name->hasArguments() || name->nameCount() > 1)
+                name_ += ':';
+        }
+    }
+}
+
+void JSBNameVisitor::visit(const AnonymousNameId *name)
+{
+    name_ = "ANONYMOUS_UNIMPLEMENTED";//String::fromLatin1("Anonymous:%1").arg(name->classTokenIndex());
+}
+
+}

+ 41 - 0
Source/ToolCore/JSBind/JSBNameVisitor.h

@@ -0,0 +1,41 @@
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// Please see LICENSE.md in repository root for license information
+// https://github.com/AtomicGameEngine/AtomicGameEngine
+
+#pragma once
+
+#include <Atomic/Container/Str.h>
+
+#include "cplusplus/CPlusPlus.h"
+using namespace CPlusPlus;
+using namespace Atomic;
+
+namespace ToolCore
+{
+
+class JSBNameVisitor: protected NameVisitor
+{
+public:
+    JSBNameVisitor();
+    virtual ~JSBNameVisitor();
+
+    String operator()(const Name *name);
+
+protected:
+
+    String switchName(const String &name = String());
+
+    virtual void visit(const Identifier *name);
+    virtual void visit(const TemplateNameId *name);
+    virtual void visit(const DestructorNameId *name);
+    virtual void visit(const OperatorNameId *name);
+    virtual void visit(const ConversionNameId *name);
+    virtual void visit(const QualifiedNameId *name);
+    virtual void visit(const SelectorNameId *name);
+    virtual void visit(const AnonymousNameId *name);
+
+private:
+    String name_;
+};
+
+}

+ 152 - 0
Source/ToolCore/JSBind/JSBPackage.cpp

@@ -0,0 +1,152 @@
+#include <Atomic/IO/Log.h>
+#include <Atomic/IO/File.h>
+#include <Atomic/Resource/JSONFile.h>
+
+#include "JSBModule.h"
+#include "JSBPackage.h"
+
+namespace ToolCore
+{
+
+Vector<SharedPtr<JSBPackage> > JSBPackage::allPackages_;
+
+JSBPackage::JSBPackage(Context* context) : Object(context)
+{
+
+}
+
+JSBPackage::~JSBPackage()
+{
+
+}
+
+void JSBPackage::PreprocessModules()
+{
+    for (unsigned i = 0; i < modules_.Size(); i++)
+    {
+        modules_[i]->PreprocessHeaders();
+    }
+}
+
+JSBClass* JSBPackage::GetClass(const String& name)
+{
+    for (unsigned i = 0; i < modules_.Size(); i++)
+    {
+        JSBClass* cls = modules_[i]->GetClass(name);
+        if (cls)
+            return cls;
+    }
+
+    return 0;
+}
+
+JSBClass* JSBPackage::GetClassAllPackages(const String& name)
+{
+    for (unsigned i = 0; i < allPackages_.Size(); i++)
+    {
+        JSBClass* cls = allPackages_[i]->GetClass(name);
+        if (cls)
+            return cls;
+    }
+
+    return 0;
+
+}
+
+JSBEnum* JSBPackage::GetEnum(const String& name)
+{
+    for (unsigned i = 0; i < modules_.Size(); i++)
+    {
+        JSBEnum* cls = modules_[i]->GetEnum(name);
+        if (cls)
+            return cls;
+    }
+
+    return 0;
+}
+
+JSBEnum* JSBPackage::GetEnumAllPackages(const String& name)
+{
+    for (unsigned i = 0; i < allPackages_.Size(); i++)
+    {
+        JSBEnum* cls = allPackages_[i]->GetEnum(name);
+        if (cls)
+            return cls;
+    }
+
+    return 0;
+
+}
+
+bool JSBPackage::ContainsConstant(const String& constantName)
+{
+    for (unsigned i = 0; i < modules_.Size(); i++)
+        if (modules_[i]->ContainsConstant(constantName))
+            return true;
+
+    return false;
+}
+
+bool JSBPackage::ContainsConstantAllPackages(const String& constantName)
+{
+    for (unsigned i = 0; i < allPackages_.Size(); i++)
+    {
+        if (allPackages_[i]->ContainsConstant(constantName))
+            return true;
+    }
+
+    return false;
+
+}
+
+bool JSBPackage::Load(const String& packageFolder)
+{
+    LOGINFOF("Loading Package: %s", packageFolder.CString());
+
+    SharedPtr<File> jsonFile(new File(context_, packageFolder + "Package.json"));
+
+    if (!jsonFile->IsOpen())
+    {
+        LOGERRORF("Unable to open package json: %s", (packageFolder + "Package.json").CString());
+        return false;
+    }
+
+    SharedPtr<JSONFile> packageJSON(new JSONFile(context_));
+
+    if (!packageJSON->BeginLoad(*jsonFile))
+    {
+        LOGERRORF("Unable to parse package json: %s", (packageFolder + "Package.json").CString());
+        return false;
+    }
+
+    JSONValue root = packageJSON->GetRoot();
+
+    name_ = root.GetString("name");
+    namespace_ = root.GetString("namespace");
+
+    JSONValue modules = root.GetChild("modules");
+
+    for (unsigned i = 0; i < modules.GetSize(); i++)
+    {
+        String moduleName = modules.GetString(i);
+
+        SharedPtr<JSBModule> module(new JSBModule(context_, this));
+
+        if (!module->Load(packageFolder + moduleName + ".json"))
+        {
+            LOGERRORF("Unable to load module json: %s", (packageFolder + moduleName + ".json").CString());
+            return false;
+        }
+
+        modules_.Push(module);
+
+    }
+
+    PreprocessModules();
+
+    allPackages_.Push(SharedPtr<JSBPackage>(this));
+
+    return true;
+}
+
+}

+ 61 - 0
Source/ToolCore/JSBind/JSBPackage.h

@@ -0,0 +1,61 @@
+
+#pragma once
+
+#include <Atomic/Core/Object.h>
+
+using namespace Atomic;
+
+namespace ToolCore
+{
+
+class JSBModule;
+class JSBClass;
+class JSBEnum;
+
+class JSBPackage : public Object
+{
+
+    OBJECT(JSBPackage)
+
+public:
+
+    JSBPackage(Context* context);
+    virtual ~JSBPackage();
+
+    bool Load(const String& packageFolder);
+
+    void PreprocessModules();
+
+    JSBClass* GetClass(const String& name);
+
+    // get a class by name across all loaded packages
+    static JSBClass* GetClassAllPackages(const String& name);
+
+    JSBEnum* GetEnum(const String& name);
+
+    // get an enum by name across all loaded packages
+    static JSBEnum* GetEnumAllPackages(const String& name);
+
+    bool ContainsConstant(const String& constantName);
+
+    static bool ContainsConstantAllPackages(const String& constantName);
+
+
+private:
+
+    // The name of the package
+    String name_;
+
+    // The name of the C++ namespace if any
+    String namespace_;
+
+    Vector<SharedPtr<JSBPackage> > dependencies_;
+
+    Vector<SharedPtr<JSBModule> > modules_;
+
+    static Vector<SharedPtr<JSBPackage> > allPackages_;
+
+};
+
+
+}

+ 1 - 0
Source/ToolCore/JSBind/JSBPreprocessVisitor.cpp

@@ -0,0 +1 @@
+#include "JSBPreprocessVisitor.h"

+ 83 - 0
Source/ToolCore/JSBind/JSBPreprocessVisitor.h

@@ -0,0 +1,83 @@
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// Please see LICENSE.md in repository root for license information
+// https://github.com/AtomicGameEngine/AtomicGameEngine
+
+
+#pragma once
+
+#include <Atomic/IO/Log.h>
+
+#include "JSBNameVisitor.h"
+
+#include "JSBEnum.h"
+#include "JSBModule.h"
+#include "JSBHeader.h"
+
+namespace ToolCore
+{
+
+class JSBPreprocessVisitor : public SymbolVisitor
+{
+
+public:
+
+    JSBPreprocessVisitor(JSBHeader* header, TranslationUnit *unit, Namespace* globalNamespace) :
+        header_(header),
+        globalNamespace_(globalNamespace)
+    {
+        module_ = header_->GetModule();
+        accept(globalNamespace_);
+    }
+
+    String getNameString(const Name* name)
+    {
+        JSBNameVisitor nvisitor;
+        return nvisitor(name);
+    }
+
+    // reject template types
+    virtual bool visit(Template *t)
+    {
+        return false;
+    }
+
+    virtual bool visit(Enum *penum)
+    {
+        JSBModule* module = header_->GetModule();
+
+        JSBEnum* jenum = new JSBEnum(header_->GetContext(), module_, getNameString(penum->name()));
+
+        for (unsigned i = 0; i < penum->memberCount(); i++)
+        {
+            Symbol* symbol = penum->memberAt(i);
+            jenum->AddValue(getNameString(symbol->name()));
+        }
+
+        jenum->Preprocess();
+
+        module->RegisterEnum(jenum);
+
+        return true;
+    }
+
+    virtual bool visit(Class *klass)
+    {
+        String name = getNameString(klass->name());
+
+        JSBModule* module = header_->GetModule();
+
+        module->RegisterClass(name);
+
+        return true;
+    }
+
+private:
+
+    SharedPtr<JSBHeader> header_;
+    SharedPtr<JSBModule> module_;
+
+    Namespace* globalNamespace_;
+
+};
+
+}

+ 35 - 0
Source/ToolCore/JSBind/JSBSymbol.h

@@ -0,0 +1,35 @@
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// Please see LICENSE.md in repository root for license information
+// https://github.com/AtomicGameEngine/AtomicGameEngine
+
+#pragma once
+
+#include <Atomic/Container/Str.h>
+
+using namespace Atomic;
+
+namespace ToolCore
+{
+
+class JSBSymbol
+{
+
+public:
+
+    JSBSymbol() : sourceLocation_(0), sourceLine_(0), sourceColumn_(0)
+    {
+
+    }
+
+    String fileName_;
+
+    unsigned sourceLocation_;
+
+    // The line number is 1-based
+    unsigned sourceLine_;
+    // The column number is 1-based
+    unsigned sourceColumn_;
+
+};
+
+}

+ 55 - 0
Source/ToolCore/JSBind/JSBType.cpp

@@ -0,0 +1,55 @@
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// Please see LICENSE.md in repository root for license information
+// https://github.com/AtomicGameEngine/AtomicGameEngine
+
+#include "JSBPackage.h"
+
+#include "JSBType.h"
+
+namespace ToolCore
+{
+
+JSBType* JSBType::Parse(const String& value)
+{
+    JSBType* type = NULL;
+
+    if (JSBPackage::GetClassAllPackages(value))
+    {
+        type = new JSBClassType(JSBPackage::GetClassAllPackages(value));
+    }
+    else if (JSBPackage::GetEnumAllPackages(value))
+    {
+        type = new JSBEnumType(JSBPackage::GetEnumAllPackages(value));
+    }
+    else if (value == "int")
+    {
+        type = new JSBPrimitiveType(JSBPrimitiveType::Int);
+    }
+    else if (value == "bool")
+    {
+        type = new JSBPrimitiveType(JSBPrimitiveType::Bool);
+    }
+    else if (value == "unsigned")
+    {
+        type = new JSBPrimitiveType(JSBPrimitiveType::Int, true);
+
+    }
+    else if (value == "float")
+    {
+        type = new JSBPrimitiveType(JSBPrimitiveType::Float);
+    }
+    else if (value == "String")
+    {
+        type = new JSBStringType();
+
+    }
+    else if (value == "StringHash")
+    {
+        type = new JSBStringHashType();
+
+    }
+    return type;
+
+}
+
+}

+ 166 - 0
Source/ToolCore/JSBind/JSBType.h

@@ -0,0 +1,166 @@
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// Please see LICENSE.md in repository root for license information
+// https://github.com/AtomicGameEngine/AtomicGameEngine
+
+#pragma once
+
+#include <Atomic/Container/Str.h>
+
+using namespace Atomic;
+
+#include "JSBClass.h"
+#include "JSBEnum.h"
+
+namespace ToolCore
+{
+
+class JSBPrimitiveType;
+class JSBStringType;
+class JSBStringHashType;
+class JSBClassType;
+class JSBEnumType;
+class JSBHeapPtrType;
+
+class JSBType
+{
+
+public:
+
+    virtual JSBPrimitiveType* asPrimitiveType() { return 0; }
+    virtual JSBClassType* asClassType() { return 0; }
+    virtual JSBStringType* asStringType() { return 0; }
+    virtual JSBStringHashType* asStringHashType() { return 0; }
+    virtual JSBEnumType* asEnumType() { return 0; }
+    virtual JSBHeapPtrType* asHeapPtrType() { return 0; }
+
+    static JSBType* Parse(const String& value);
+
+    virtual String ToString() = 0;
+
+};
+
+class JSBPrimitiveType : public JSBType
+{
+public:
+    // needs to match IntegerType::Kind
+    enum Kind {
+        Char,
+        Char16,
+        Char32,
+        WideChar,
+        Bool,
+        Short,
+        Int,
+        Long,
+        LongLong,
+        Float // this doesn't exist in IntegerType::Kind
+    };
+
+    JSBPrimitiveType(int kind, bool isUnsigned = false)
+    {
+
+        kind_ = (Kind) kind;
+        isUnsigned_ = isUnsigned;
+
+    }
+
+    String ToString()
+    {
+        switch (kind_)
+        {
+        case Char:
+        case Char16:
+        case Char32:
+        case WideChar:
+            return "char";
+        case Bool:
+            return "bool";
+        case Short:
+            return "short";
+        case Int:
+            return "int";
+        case Long:
+            return "long";
+        case LongLong:
+            return "long long";
+        case Float:
+            return "float";
+        }
+
+        return "???";
+    }
+
+    Kind kind_;
+    bool isUnsigned_;
+
+    virtual JSBPrimitiveType* asPrimitiveType() { return this; }
+
+};
+
+class JSBStringType : public JSBType
+{
+public:
+
+    virtual JSBStringType* asStringType() { return this; }
+
+    String ToString() { return "String"; }
+
+};
+
+class JSBStringHashType : public JSBType
+{
+public:
+
+    virtual JSBStringHashType* asStringHashType() { return this; }
+
+    String ToString() { return "StringHash"; }
+
+};
+
+class JSBHeapPtrType : public JSBType
+{
+public:
+
+    virtual JSBHeapPtrType* asHeapPtrType() { return this; }
+
+    String ToString() { return "JS_HEAP_PTR"; }
+
+};
+
+
+class JSBEnumType : public JSBType
+{
+public:
+
+    JSBEnum* enum_;
+
+    JSBEnumType(JSBEnum* penum) : enum_(penum) {}
+
+    virtual JSBEnumType* asEnumType() { return this; }
+
+    String ToString() { return enum_->GetName(); }
+
+};
+
+
+class JSBClassType : public JSBType
+{
+public:
+
+    JSBClass* class_;
+
+    virtual JSBClassType* asClassType() { return this; }
+
+    JSBClassType(JSBClass* klass) : class_(klass)
+    {
+
+    }
+
+    String ToString()
+    {
+        return class_->GetName();
+    }
+
+};
+
+}

+ 31 - 0
Source/ToolCore/JSBind/JSBind.cpp

@@ -0,0 +1,31 @@
+
+#include "JSBPackage.h"
+#include "JSBind.h"
+
+namespace ToolCore
+{
+
+JSBind::JSBind(Context* context) : Object(context)
+{
+
+}
+
+JSBind::~JSBind()
+{
+
+}
+
+bool JSBind::GenerateBindings(const String& sourceRootFolder, const String& packageFolder, const String& platform)
+{
+    sourceRootFolder_ = sourceRootFolder;
+    packageFolder_ = packageFolder;
+    platform_ = platform;
+
+    SharedPtr<JSBPackage> package (new JSBPackage(context_));
+
+    package->Load(sourceRootFolder_ + packageFolder_);
+
+    return true;
+}
+
+}

+ 36 - 0
Source/ToolCore/JSBind/JSBind.h

@@ -0,0 +1,36 @@
+
+#pragma once
+
+#include <Atomic/Core/Object.h>
+
+using namespace Atomic;
+
+namespace ToolCore
+{
+
+class JSBind : public Object
+{
+
+    OBJECT(JSBind)
+
+public:
+
+    JSBind(Context* context);
+    virtual ~JSBind();
+
+    bool GenerateBindings(const String& sourceRootFolder, const String& packageFolder, const String& platform);
+
+    const String& GetSourceRootFolder() { return sourceRootFolder_; }
+    const String& GetPackageFolder() { return packageFolder_; }
+    const String& GetPlatform() { return platform_; }
+
+private:
+
+    String sourceRootFolder_;
+    String packageFolder_;
+    String platform_;
+
+};
+
+
+}

+ 4560 - 0
Source/ToolCore/JSBind/cplusplus/AST.cpp

@@ -0,0 +1,4560 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "AST.h"
+#include "ASTVisitor.h"
+#include "ASTMatcher.h"
+#include "MemoryPool.h"
+
+#include "cppassert.h"
+
+#include <algorithm>
+
+
+/*
+   All firstToken/lastToken functions below which have a doxygen comment with
+   \generated in it, will be re-generated when the tool "cplusplus-update-frontend" is run.
+
+   For functions which are hand-coded, or which should not be changed, make sure that
+   the comment is gone.
+ */
+
+
+using namespace CPlusPlus;
+
+AST::AST()
+{ }
+
+AST::~AST()
+{ CPP_CHECK(0); }
+
+void AST::accept(ASTVisitor *visitor)
+{
+    if (visitor->preVisit(this))
+        accept0(visitor);
+    visitor->postVisit(this);
+}
+
+bool AST::match(AST *ast, AST *pattern, ASTMatcher *matcher)
+{
+    if (ast == pattern)
+        return true;
+
+    else if (! ast || ! pattern)
+        return false;
+
+    return ast->match(pattern, matcher);
+}
+
+bool AST::match(AST *pattern, ASTMatcher *matcher)
+{
+    return match0(pattern, matcher);
+}
+
+unsigned GnuAttributeSpecifierAST::firstToken() const
+{
+    return attribute_token;
+}
+
+unsigned BaseSpecifierAST::firstToken() const
+{
+    if (virtual_token && access_specifier_token)
+        return std::min(virtual_token, access_specifier_token);
+    if (virtual_token)
+        return virtual_token;
+    if (access_specifier_token)
+        return access_specifier_token;
+    if (name)
+        return name->firstToken();
+    // assert?
+    return 0;
+}
+
+unsigned BaseSpecifierAST::lastToken() const
+{
+    if (name)
+        return name->lastToken();
+    else if (virtual_token && access_specifier_token)
+        return std::max(virtual_token, access_specifier_token) + 1;
+    else if (virtual_token)
+        return virtual_token + 1;
+    else if (access_specifier_token)
+        return access_specifier_token + 1;
+    // assert?
+    return 0;
+}
+
+/** \generated */
+unsigned AccessDeclarationAST::firstToken() const
+{
+    if (access_specifier_token)
+        return access_specifier_token;
+    if (slots_token)
+        return slots_token;
+    if (colon_token)
+        return colon_token;
+    return 0;
+}
+
+/** \generated */
+unsigned AccessDeclarationAST::lastToken() const
+{
+    if (colon_token)
+        return colon_token + 1;
+    if (slots_token)
+        return slots_token + 1;
+    if (access_specifier_token)
+        return access_specifier_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned ArrayAccessAST::firstToken() const
+{
+    if (base_expression)
+        if (unsigned candidate = base_expression->firstToken())
+            return candidate;
+    if (lbracket_token)
+        return lbracket_token;
+    if (expression)
+        if (unsigned candidate = expression->firstToken())
+            return candidate;
+    if (rbracket_token)
+        return rbracket_token;
+    return 0;
+}
+
+/** \generated */
+unsigned ArrayAccessAST::lastToken() const
+{
+    if (rbracket_token)
+        return rbracket_token + 1;
+    if (expression)
+        if (unsigned candidate = expression->lastToken())
+            return candidate;
+    if (lbracket_token)
+        return lbracket_token + 1;
+    if (base_expression)
+        if (unsigned candidate = base_expression->lastToken())
+            return candidate;
+    return 1;
+}
+
+/** \generated */
+unsigned ArrayDeclaratorAST::firstToken() const
+{
+    if (lbracket_token)
+        return lbracket_token;
+    if (expression)
+        if (unsigned candidate = expression->firstToken())
+            return candidate;
+    if (rbracket_token)
+        return rbracket_token;
+    return 0;
+}
+
+/** \generated */
+unsigned ArrayDeclaratorAST::lastToken() const
+{
+    if (rbracket_token)
+        return rbracket_token + 1;
+    if (expression)
+        if (unsigned candidate = expression->lastToken())
+            return candidate;
+    if (lbracket_token)
+        return lbracket_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned ArrayInitializerAST::firstToken() const
+{
+    if (lbrace_token)
+        return lbrace_token;
+    if (expression_list)
+        if (unsigned candidate = expression_list->firstToken())
+            return candidate;
+    if (rbrace_token)
+        return rbrace_token;
+    return 0;
+}
+
+/** \generated */
+unsigned ArrayInitializerAST::lastToken() const
+{
+    if (rbrace_token)
+        return rbrace_token + 1;
+    if (expression_list)
+        if (unsigned candidate = expression_list->lastToken())
+            return candidate;
+    if (lbrace_token)
+        return lbrace_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned AsmDefinitionAST::firstToken() const
+{
+    if (asm_token)
+        return asm_token;
+    if (volatile_token)
+        return volatile_token;
+    if (lparen_token)
+        return lparen_token;
+    if (rparen_token)
+        return rparen_token;
+    if (semicolon_token)
+        return semicolon_token;
+    return 0;
+}
+
+/** \generated */
+unsigned AsmDefinitionAST::lastToken() const
+{
+    if (semicolon_token)
+        return semicolon_token + 1;
+    if (rparen_token)
+        return rparen_token + 1;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (volatile_token)
+        return volatile_token + 1;
+    if (asm_token)
+        return asm_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned GnuAttributeAST::firstToken() const
+{
+    if (identifier_token)
+        return identifier_token;
+    if (lparen_token)
+        return lparen_token;
+    if (tag_token)
+        return tag_token;
+    if (expression_list)
+        if (unsigned candidate = expression_list->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    return 0;
+}
+
+/** \generated */
+unsigned GnuAttributeAST::lastToken() const
+{
+    if (rparen_token)
+        return rparen_token + 1;
+    if (expression_list)
+        if (unsigned candidate = expression_list->lastToken())
+            return candidate;
+    if (tag_token)
+        return tag_token + 1;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (identifier_token)
+        return identifier_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned BinaryExpressionAST::firstToken() const
+{
+    if (left_expression)
+        if (unsigned candidate = left_expression->firstToken())
+            return candidate;
+    if (binary_op_token)
+        return binary_op_token;
+    if (right_expression)
+        if (unsigned candidate = right_expression->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned BinaryExpressionAST::lastToken() const
+{
+    if (right_expression)
+        if (unsigned candidate = right_expression->lastToken())
+            return candidate;
+    if (binary_op_token)
+        return binary_op_token + 1;
+    if (left_expression)
+        if (unsigned candidate = left_expression->lastToken())
+            return candidate;
+    return 1;
+}
+
+/** \generated */
+unsigned BoolLiteralAST::firstToken() const
+{
+    if (literal_token)
+        return literal_token;
+    return 0;
+}
+
+/** \generated */
+unsigned BoolLiteralAST::lastToken() const
+{
+    if (literal_token)
+        return literal_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned BracedInitializerAST::firstToken() const
+{
+    if (lbrace_token)
+        return lbrace_token;
+    if (expression_list)
+        if (unsigned candidate = expression_list->firstToken())
+            return candidate;
+    if (comma_token)
+        return comma_token;
+    if (rbrace_token)
+        return rbrace_token;
+    return 0;
+}
+
+/** \generated */
+unsigned BracedInitializerAST::lastToken() const
+{
+    if (rbrace_token)
+        return rbrace_token + 1;
+    if (comma_token)
+        return comma_token + 1;
+    if (expression_list)
+        if (unsigned candidate = expression_list->lastToken())
+            return candidate;
+    if (lbrace_token)
+        return lbrace_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned BreakStatementAST::firstToken() const
+{
+    if (break_token)
+        return break_token;
+    if (semicolon_token)
+        return semicolon_token;
+    return 0;
+}
+
+/** \generated */
+unsigned BreakStatementAST::lastToken() const
+{
+    if (semicolon_token)
+        return semicolon_token + 1;
+    if (break_token)
+        return break_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned CallAST::firstToken() const
+{
+    if (base_expression)
+        if (unsigned candidate = base_expression->firstToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token;
+    if (expression_list)
+        if (unsigned candidate = expression_list->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    return 0;
+}
+
+/** \generated */
+unsigned CallAST::lastToken() const
+{
+    if (rparen_token)
+        return rparen_token + 1;
+    if (expression_list)
+        if (unsigned candidate = expression_list->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (base_expression)
+        if (unsigned candidate = base_expression->lastToken())
+            return candidate;
+    return 1;
+}
+
+/** \generated */
+unsigned CaptureAST::firstToken() const
+{
+    if (amper_token)
+        return amper_token;
+    if (identifier)
+        if (unsigned candidate = identifier->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned CaptureAST::lastToken() const
+{
+    if (identifier)
+        if (unsigned candidate = identifier->lastToken())
+            return candidate;
+    if (amper_token)
+        return amper_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned CaseStatementAST::firstToken() const
+{
+    if (case_token)
+        return case_token;
+    if (expression)
+        if (unsigned candidate = expression->firstToken())
+            return candidate;
+    if (colon_token)
+        return colon_token;
+    if (statement)
+        if (unsigned candidate = statement->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned CaseStatementAST::lastToken() const
+{
+    if (statement)
+        if (unsigned candidate = statement->lastToken())
+            return candidate;
+    if (colon_token)
+        return colon_token + 1;
+    if (expression)
+        if (unsigned candidate = expression->lastToken())
+            return candidate;
+    if (case_token)
+        return case_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned CastExpressionAST::firstToken() const
+{
+    if (lparen_token)
+        return lparen_token;
+    if (type_id)
+        if (unsigned candidate = type_id->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    if (expression)
+        if (unsigned candidate = expression->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned CastExpressionAST::lastToken() const
+{
+    if (expression)
+        if (unsigned candidate = expression->lastToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token + 1;
+    if (type_id)
+        if (unsigned candidate = type_id->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned CatchClauseAST::firstToken() const
+{
+    if (catch_token)
+        return catch_token;
+    if (lparen_token)
+        return lparen_token;
+    if (exception_declaration)
+        if (unsigned candidate = exception_declaration->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    if (statement)
+        if (unsigned candidate = statement->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned CatchClauseAST::lastToken() const
+{
+    if (statement)
+        if (unsigned candidate = statement->lastToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token + 1;
+    if (exception_declaration)
+        if (unsigned candidate = exception_declaration->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (catch_token)
+        return catch_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned ClassSpecifierAST::firstToken() const
+{
+    if (classkey_token)
+        return classkey_token;
+    if (attribute_list)
+        if (unsigned candidate = attribute_list->firstToken())
+            return candidate;
+    if (name)
+        if (unsigned candidate = name->firstToken())
+            return candidate;
+    if (final_token)
+        return final_token;
+    if (colon_token)
+        return colon_token;
+    if (base_clause_list)
+        if (unsigned candidate = base_clause_list->firstToken())
+            return candidate;
+    if (dot_dot_dot_token)
+        return dot_dot_dot_token;
+    if (lbrace_token)
+        return lbrace_token;
+    if (member_specifier_list)
+        if (unsigned candidate = member_specifier_list->firstToken())
+            return candidate;
+    if (rbrace_token)
+        return rbrace_token;
+    return 0;
+}
+
+/** \generated */
+unsigned ClassSpecifierAST::lastToken() const
+{
+    if (rbrace_token)
+        return rbrace_token + 1;
+    if (member_specifier_list)
+        if (unsigned candidate = member_specifier_list->lastToken())
+            return candidate;
+    if (lbrace_token)
+        return lbrace_token + 1;
+    if (dot_dot_dot_token)
+        return dot_dot_dot_token + 1;
+    if (base_clause_list)
+        if (unsigned candidate = base_clause_list->lastToken())
+            return candidate;
+    if (colon_token)
+        return colon_token + 1;
+    if (final_token)
+        return final_token + 1;
+    if (name)
+        if (unsigned candidate = name->lastToken())
+            return candidate;
+    if (attribute_list)
+        if (unsigned candidate = attribute_list->lastToken())
+            return candidate;
+    if (classkey_token)
+        return classkey_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned CompoundExpressionAST::firstToken() const
+{
+    if (lparen_token)
+        return lparen_token;
+    if (statement)
+        if (unsigned candidate = statement->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    return 0;
+}
+
+/** \generated */
+unsigned CompoundExpressionAST::lastToken() const
+{
+    if (rparen_token)
+        return rparen_token + 1;
+    if (statement)
+        if (unsigned candidate = statement->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned CompoundLiteralAST::firstToken() const
+{
+    if (lparen_token)
+        return lparen_token;
+    if (type_id)
+        if (unsigned candidate = type_id->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    if (initializer)
+        if (unsigned candidate = initializer->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned CompoundLiteralAST::lastToken() const
+{
+    if (initializer)
+        if (unsigned candidate = initializer->lastToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token + 1;
+    if (type_id)
+        if (unsigned candidate = type_id->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned CompoundStatementAST::firstToken() const
+{
+    if (lbrace_token)
+        return lbrace_token;
+    if (statement_list)
+        if (unsigned candidate = statement_list->firstToken())
+            return candidate;
+    if (rbrace_token)
+        return rbrace_token;
+    return 0;
+}
+
+/** \generated */
+unsigned CompoundStatementAST::lastToken() const
+{
+    if (rbrace_token)
+        return rbrace_token + 1;
+    if (statement_list)
+        if (unsigned candidate = statement_list->lastToken())
+            return candidate;
+    if (lbrace_token)
+        return lbrace_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned ConditionAST::firstToken() const
+{
+    if (type_specifier_list)
+        if (unsigned candidate = type_specifier_list->firstToken())
+            return candidate;
+    if (declarator)
+        if (unsigned candidate = declarator->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned ConditionAST::lastToken() const
+{
+    if (declarator)
+        if (unsigned candidate = declarator->lastToken())
+            return candidate;
+    if (type_specifier_list)
+        if (unsigned candidate = type_specifier_list->lastToken())
+            return candidate;
+    return 1;
+}
+
+/** \generated */
+unsigned ConditionalExpressionAST::firstToken() const
+{
+    if (condition)
+        if (unsigned candidate = condition->firstToken())
+            return candidate;
+    if (question_token)
+        return question_token;
+    if (left_expression)
+        if (unsigned candidate = left_expression->firstToken())
+            return candidate;
+    if (colon_token)
+        return colon_token;
+    if (right_expression)
+        if (unsigned candidate = right_expression->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned ConditionalExpressionAST::lastToken() const
+{
+    if (right_expression)
+        if (unsigned candidate = right_expression->lastToken())
+            return candidate;
+    if (colon_token)
+        return colon_token + 1;
+    if (left_expression)
+        if (unsigned candidate = left_expression->lastToken())
+            return candidate;
+    if (question_token)
+        return question_token + 1;
+    if (condition)
+        if (unsigned candidate = condition->lastToken())
+            return candidate;
+    return 1;
+}
+
+/** \generated */
+unsigned ContinueStatementAST::firstToken() const
+{
+    if (continue_token)
+        return continue_token;
+    if (semicolon_token)
+        return semicolon_token;
+    return 0;
+}
+
+/** \generated */
+unsigned ContinueStatementAST::lastToken() const
+{
+    if (semicolon_token)
+        return semicolon_token + 1;
+    if (continue_token)
+        return continue_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned ConversionFunctionIdAST::firstToken() const
+{
+    if (operator_token)
+        return operator_token;
+    if (type_specifier_list)
+        if (unsigned candidate = type_specifier_list->firstToken())
+            return candidate;
+    if (ptr_operator_list)
+        if (unsigned candidate = ptr_operator_list->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned ConversionFunctionIdAST::lastToken() const
+{
+    if (ptr_operator_list)
+        if (unsigned candidate = ptr_operator_list->lastToken())
+            return candidate;
+    if (type_specifier_list)
+        if (unsigned candidate = type_specifier_list->lastToken())
+            return candidate;
+    if (operator_token)
+        return operator_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned CppCastExpressionAST::firstToken() const
+{
+    if (cast_token)
+        return cast_token;
+    if (less_token)
+        return less_token;
+    if (type_id)
+        if (unsigned candidate = type_id->firstToken())
+            return candidate;
+    if (greater_token)
+        return greater_token;
+    if (lparen_token)
+        return lparen_token;
+    if (expression)
+        if (unsigned candidate = expression->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    return 0;
+}
+
+/** \generated */
+unsigned CppCastExpressionAST::lastToken() const
+{
+    if (rparen_token)
+        return rparen_token + 1;
+    if (expression)
+        if (unsigned candidate = expression->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (greater_token)
+        return greater_token + 1;
+    if (type_id)
+        if (unsigned candidate = type_id->lastToken())
+            return candidate;
+    if (less_token)
+        return less_token + 1;
+    if (cast_token)
+        return cast_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned CtorInitializerAST::firstToken() const
+{
+    if (colon_token)
+        return colon_token;
+    if (member_initializer_list)
+        if (unsigned candidate = member_initializer_list->firstToken())
+            return candidate;
+    if (dot_dot_dot_token)
+        return dot_dot_dot_token;
+    return 0;
+}
+
+/** \generated */
+unsigned CtorInitializerAST::lastToken() const
+{
+    if (dot_dot_dot_token)
+        return dot_dot_dot_token + 1;
+    if (member_initializer_list)
+        if (unsigned candidate = member_initializer_list->lastToken())
+            return candidate;
+    if (colon_token)
+        return colon_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned DeclarationStatementAST::firstToken() const
+{
+    if (declaration)
+        if (unsigned candidate = declaration->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned DeclarationStatementAST::lastToken() const
+{
+    if (declaration)
+        if (unsigned candidate = declaration->lastToken())
+            return candidate;
+    return 1;
+}
+
+/** \generated */
+unsigned DeclaratorAST::firstToken() const
+{
+    if (attribute_list)
+        if (unsigned candidate = attribute_list->firstToken())
+            return candidate;
+    if (ptr_operator_list)
+        if (unsigned candidate = ptr_operator_list->firstToken())
+            return candidate;
+    if (core_declarator)
+        if (unsigned candidate = core_declarator->firstToken())
+            return candidate;
+    if (postfix_declarator_list)
+        if (unsigned candidate = postfix_declarator_list->firstToken())
+            return candidate;
+    if (post_attribute_list)
+        if (unsigned candidate = post_attribute_list->firstToken())
+            return candidate;
+    if (equal_token)
+        return equal_token;
+    if (initializer)
+        if (unsigned candidate = initializer->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned DeclaratorAST::lastToken() const
+{
+    if (initializer)
+        if (unsigned candidate = initializer->lastToken())
+            return candidate;
+    if (equal_token)
+        return equal_token + 1;
+    if (post_attribute_list)
+        if (unsigned candidate = post_attribute_list->lastToken())
+            return candidate;
+    if (postfix_declarator_list)
+        if (unsigned candidate = postfix_declarator_list->lastToken())
+            return candidate;
+    if (core_declarator)
+        if (unsigned candidate = core_declarator->lastToken())
+            return candidate;
+    if (ptr_operator_list)
+        if (unsigned candidate = ptr_operator_list->lastToken())
+            return candidate;
+    if (attribute_list)
+        if (unsigned candidate = attribute_list->lastToken())
+            return candidate;
+    return 1;
+}
+
+/** \generated */
+unsigned DeclaratorIdAST::firstToken() const
+{
+    if (dot_dot_dot_token)
+        return dot_dot_dot_token;
+    if (name)
+        if (unsigned candidate = name->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned DeclaratorIdAST::lastToken() const
+{
+    if (name)
+        if (unsigned candidate = name->lastToken())
+            return candidate;
+    if (dot_dot_dot_token)
+        return dot_dot_dot_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned DeleteExpressionAST::firstToken() const
+{
+    if (scope_token)
+        return scope_token;
+    if (delete_token)
+        return delete_token;
+    if (lbracket_token)
+        return lbracket_token;
+    if (rbracket_token)
+        return rbracket_token;
+    if (expression)
+        if (unsigned candidate = expression->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned DeleteExpressionAST::lastToken() const
+{
+    if (expression)
+        if (unsigned candidate = expression->lastToken())
+            return candidate;
+    if (rbracket_token)
+        return rbracket_token + 1;
+    if (lbracket_token)
+        return lbracket_token + 1;
+    if (delete_token)
+        return delete_token + 1;
+    if (scope_token)
+        return scope_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned DestructorNameAST::firstToken() const
+{
+    if (tilde_token)
+        return tilde_token;
+    if (unqualified_name)
+        if (unsigned candidate = unqualified_name->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned DestructorNameAST::lastToken() const
+{
+    if (unqualified_name)
+        if (unsigned candidate = unqualified_name->lastToken())
+            return candidate;
+    if (tilde_token)
+        return tilde_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned DoStatementAST::firstToken() const
+{
+    if (do_token)
+        return do_token;
+    if (statement)
+        if (unsigned candidate = statement->firstToken())
+            return candidate;
+    if (while_token)
+        return while_token;
+    if (lparen_token)
+        return lparen_token;
+    if (expression)
+        if (unsigned candidate = expression->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    if (semicolon_token)
+        return semicolon_token;
+    return 0;
+}
+
+/** \generated */
+unsigned DoStatementAST::lastToken() const
+{
+    if (semicolon_token)
+        return semicolon_token + 1;
+    if (rparen_token)
+        return rparen_token + 1;
+    if (expression)
+        if (unsigned candidate = expression->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (while_token)
+        return while_token + 1;
+    if (statement)
+        if (unsigned candidate = statement->lastToken())
+            return candidate;
+    if (do_token)
+        return do_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned ElaboratedTypeSpecifierAST::firstToken() const
+{
+    if (classkey_token)
+        return classkey_token;
+    if (attribute_list)
+        if (unsigned candidate = attribute_list->firstToken())
+            return candidate;
+    if (name)
+        if (unsigned candidate = name->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned ElaboratedTypeSpecifierAST::lastToken() const
+{
+    if (name)
+        if (unsigned candidate = name->lastToken())
+            return candidate;
+    if (attribute_list)
+        if (unsigned candidate = attribute_list->lastToken())
+            return candidate;
+    if (classkey_token)
+        return classkey_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned EmptyDeclarationAST::firstToken() const
+{
+    if (semicolon_token)
+        return semicolon_token;
+    return 0;
+}
+
+/** \generated */
+unsigned EmptyDeclarationAST::lastToken() const
+{
+    if (semicolon_token)
+        return semicolon_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned EnumSpecifierAST::firstToken() const
+{
+    if (enum_token)
+        return enum_token;
+    if (key_token)
+        return key_token;
+    if (name)
+        if (unsigned candidate = name->firstToken())
+            return candidate;
+    if (colon_token)
+        return colon_token;
+    if (type_specifier_list)
+        if (unsigned candidate = type_specifier_list->firstToken())
+            return candidate;
+    if (lbrace_token)
+        return lbrace_token;
+    if (enumerator_list)
+        if (unsigned candidate = enumerator_list->firstToken())
+            return candidate;
+    if (stray_comma_token)
+        return stray_comma_token;
+    if (rbrace_token)
+        return rbrace_token;
+    return 0;
+}
+
+/** \generated */
+unsigned EnumSpecifierAST::lastToken() const
+{
+    if (rbrace_token)
+        return rbrace_token + 1;
+    if (stray_comma_token)
+        return stray_comma_token + 1;
+    if (enumerator_list)
+        if (unsigned candidate = enumerator_list->lastToken())
+            return candidate;
+    if (lbrace_token)
+        return lbrace_token + 1;
+    if (type_specifier_list)
+        if (unsigned candidate = type_specifier_list->lastToken())
+            return candidate;
+    if (colon_token)
+        return colon_token + 1;
+    if (name)
+        if (unsigned candidate = name->lastToken())
+            return candidate;
+    if (key_token)
+        return key_token + 1;
+    if (enum_token)
+        return enum_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned EnumeratorAST::firstToken() const
+{
+    if (identifier_token)
+        return identifier_token;
+    if (equal_token)
+        return equal_token;
+    if (expression)
+        if (unsigned candidate = expression->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned EnumeratorAST::lastToken() const
+{
+    if (expression)
+        if (unsigned candidate = expression->lastToken())
+            return candidate;
+    if (equal_token)
+        return equal_token + 1;
+    if (identifier_token)
+        return identifier_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned ExceptionDeclarationAST::firstToken() const
+{
+    if (type_specifier_list)
+        if (unsigned candidate = type_specifier_list->firstToken())
+            return candidate;
+    if (declarator)
+        if (unsigned candidate = declarator->firstToken())
+            return candidate;
+    if (dot_dot_dot_token)
+        return dot_dot_dot_token;
+    return 0;
+}
+
+/** \generated */
+unsigned ExceptionDeclarationAST::lastToken() const
+{
+    if (dot_dot_dot_token)
+        return dot_dot_dot_token + 1;
+    if (declarator)
+        if (unsigned candidate = declarator->lastToken())
+            return candidate;
+    if (type_specifier_list)
+        if (unsigned candidate = type_specifier_list->lastToken())
+            return candidate;
+    return 1;
+}
+
+/** \generated */
+unsigned DynamicExceptionSpecificationAST::firstToken() const
+{
+    if (throw_token)
+        return throw_token;
+    if (lparen_token)
+        return lparen_token;
+    if (dot_dot_dot_token)
+        return dot_dot_dot_token;
+    if (type_id_list)
+        if (unsigned candidate = type_id_list->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    return 0;
+}
+
+/** \generated */
+unsigned DynamicExceptionSpecificationAST::lastToken() const
+{
+    if (rparen_token)
+        return rparen_token + 1;
+    if (type_id_list)
+        if (unsigned candidate = type_id_list->lastToken())
+            return candidate;
+    if (dot_dot_dot_token)
+        return dot_dot_dot_token + 1;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (throw_token)
+        return throw_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned ExpressionOrDeclarationStatementAST::firstToken() const
+{
+    if (expression)
+        if (unsigned candidate = expression->firstToken())
+            return candidate;
+    if (declaration)
+        if (unsigned candidate = declaration->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned ExpressionOrDeclarationStatementAST::lastToken() const
+{
+    if (declaration)
+        if (unsigned candidate = declaration->lastToken())
+            return candidate;
+    if (expression)
+        if (unsigned candidate = expression->lastToken())
+            return candidate;
+    return 1;
+}
+
+/** \generated */
+unsigned ExpressionStatementAST::firstToken() const
+{
+    if (expression)
+        if (unsigned candidate = expression->firstToken())
+            return candidate;
+    if (semicolon_token)
+        return semicolon_token;
+    return 0;
+}
+
+/** \generated */
+unsigned ExpressionStatementAST::lastToken() const
+{
+    if (semicolon_token)
+        return semicolon_token + 1;
+    if (expression)
+        if (unsigned candidate = expression->lastToken())
+            return candidate;
+    return 1;
+}
+
+/** \generated */
+unsigned ForStatementAST::firstToken() const
+{
+    if (for_token)
+        return for_token;
+    if (lparen_token)
+        return lparen_token;
+    if (initializer)
+        if (unsigned candidate = initializer->firstToken())
+            return candidate;
+    if (condition)
+        if (unsigned candidate = condition->firstToken())
+            return candidate;
+    if (semicolon_token)
+        return semicolon_token;
+    if (expression)
+        if (unsigned candidate = expression->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    if (statement)
+        if (unsigned candidate = statement->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned ForStatementAST::lastToken() const
+{
+    if (statement)
+        if (unsigned candidate = statement->lastToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token + 1;
+    if (expression)
+        if (unsigned candidate = expression->lastToken())
+            return candidate;
+    if (semicolon_token)
+        return semicolon_token + 1;
+    if (condition)
+        if (unsigned candidate = condition->lastToken())
+            return candidate;
+    if (initializer)
+        if (unsigned candidate = initializer->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (for_token)
+        return for_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned ForeachStatementAST::firstToken() const
+{
+    if (foreach_token)
+        return foreach_token;
+    if (lparen_token)
+        return lparen_token;
+    if (type_specifier_list)
+        if (unsigned candidate = type_specifier_list->firstToken())
+            return candidate;
+    if (declarator)
+        if (unsigned candidate = declarator->firstToken())
+            return candidate;
+    if (initializer)
+        if (unsigned candidate = initializer->firstToken())
+            return candidate;
+    if (comma_token)
+        return comma_token;
+    if (expression)
+        if (unsigned candidate = expression->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    if (statement)
+        if (unsigned candidate = statement->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned ForeachStatementAST::lastToken() const
+{
+    if (statement)
+        if (unsigned candidate = statement->lastToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token + 1;
+    if (expression)
+        if (unsigned candidate = expression->lastToken())
+            return candidate;
+    if (comma_token)
+        return comma_token + 1;
+    if (initializer)
+        if (unsigned candidate = initializer->lastToken())
+            return candidate;
+    if (declarator)
+        if (unsigned candidate = declarator->lastToken())
+            return candidate;
+    if (type_specifier_list)
+        if (unsigned candidate = type_specifier_list->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (foreach_token)
+        return foreach_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned FunctionDeclaratorAST::firstToken() const
+{
+    if (lparen_token)
+        return lparen_token;
+    if (parameter_declaration_clause)
+        if (unsigned candidate = parameter_declaration_clause->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    if (cv_qualifier_list)
+        if (unsigned candidate = cv_qualifier_list->firstToken())
+            return candidate;
+    if (ref_qualifier_token)
+        return ref_qualifier_token;
+    if (exception_specification)
+        if (unsigned candidate = exception_specification->firstToken())
+            return candidate;
+    if (trailing_return_type)
+        if (unsigned candidate = trailing_return_type->firstToken())
+            return candidate;
+    if (as_cpp_initializer)
+        if (unsigned candidate = as_cpp_initializer->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned FunctionDeclaratorAST::lastToken() const
+{
+    if (as_cpp_initializer)
+        if (unsigned candidate = as_cpp_initializer->lastToken())
+            return candidate;
+    if (trailing_return_type)
+        if (unsigned candidate = trailing_return_type->lastToken())
+            return candidate;
+    if (exception_specification)
+        if (unsigned candidate = exception_specification->lastToken())
+            return candidate;
+    if (ref_qualifier_token)
+        return ref_qualifier_token + 1;
+    if (cv_qualifier_list)
+        if (unsigned candidate = cv_qualifier_list->lastToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token + 1;
+    if (parameter_declaration_clause)
+        if (unsigned candidate = parameter_declaration_clause->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned FunctionDefinitionAST::firstToken() const
+{
+    if (qt_invokable_token)
+        return qt_invokable_token;
+    if (decl_specifier_list)
+        if (unsigned candidate = decl_specifier_list->firstToken())
+            return candidate;
+    if (declarator)
+        if (unsigned candidate = declarator->firstToken())
+            return candidate;
+    if (ctor_initializer)
+        if (unsigned candidate = ctor_initializer->firstToken())
+            return candidate;
+    if (function_body)
+        if (unsigned candidate = function_body->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned FunctionDefinitionAST::lastToken() const
+{
+    if (function_body)
+        if (unsigned candidate = function_body->lastToken())
+            return candidate;
+    if (ctor_initializer)
+        if (unsigned candidate = ctor_initializer->lastToken())
+            return candidate;
+    if (declarator)
+        if (unsigned candidate = declarator->lastToken())
+            return candidate;
+    if (decl_specifier_list)
+        if (unsigned candidate = decl_specifier_list->lastToken())
+            return candidate;
+    if (qt_invokable_token)
+        return qt_invokable_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned GotoStatementAST::firstToken() const
+{
+    if (goto_token)
+        return goto_token;
+    if (identifier_token)
+        return identifier_token;
+    if (semicolon_token)
+        return semicolon_token;
+    return 0;
+}
+
+/** \generated */
+unsigned GotoStatementAST::lastToken() const
+{
+    if (semicolon_token)
+        return semicolon_token + 1;
+    if (identifier_token)
+        return identifier_token + 1;
+    if (goto_token)
+        return goto_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned IdExpressionAST::firstToken() const
+{
+    if (name)
+        if (unsigned candidate = name->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned IdExpressionAST::lastToken() const
+{
+    if (name)
+        if (unsigned candidate = name->lastToken())
+            return candidate;
+    return 1;
+}
+
+/** \generated */
+unsigned IfStatementAST::firstToken() const
+{
+    if (if_token)
+        return if_token;
+    if (lparen_token)
+        return lparen_token;
+    if (condition)
+        if (unsigned candidate = condition->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    if (statement)
+        if (unsigned candidate = statement->firstToken())
+            return candidate;
+    if (else_token)
+        return else_token;
+    if (else_statement)
+        if (unsigned candidate = else_statement->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned IfStatementAST::lastToken() const
+{
+    if (else_statement)
+        if (unsigned candidate = else_statement->lastToken())
+            return candidate;
+    if (else_token)
+        return else_token + 1;
+    if (statement)
+        if (unsigned candidate = statement->lastToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token + 1;
+    if (condition)
+        if (unsigned candidate = condition->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (if_token)
+        return if_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned LabeledStatementAST::firstToken() const
+{
+    if (label_token)
+        return label_token;
+    if (colon_token)
+        return colon_token;
+    if (statement)
+        if (unsigned candidate = statement->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned LabeledStatementAST::lastToken() const
+{
+    if (statement)
+        if (unsigned candidate = statement->lastToken())
+            return candidate;
+    if (colon_token)
+        return colon_token + 1;
+    if (label_token)
+        return label_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned LambdaCaptureAST::firstToken() const
+{
+    if (default_capture_token)
+        return default_capture_token;
+    if (capture_list)
+        if (unsigned candidate = capture_list->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned LambdaCaptureAST::lastToken() const
+{
+    if (capture_list)
+        if (unsigned candidate = capture_list->lastToken())
+            return candidate;
+    if (default_capture_token)
+        return default_capture_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned LambdaDeclaratorAST::firstToken() const
+{
+    if (lparen_token)
+        return lparen_token;
+    if (parameter_declaration_clause)
+        if (unsigned candidate = parameter_declaration_clause->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    if (attributes)
+        if (unsigned candidate = attributes->firstToken())
+            return candidate;
+    if (mutable_token)
+        return mutable_token;
+    if (exception_specification)
+        if (unsigned candidate = exception_specification->firstToken())
+            return candidate;
+    if (trailing_return_type)
+        if (unsigned candidate = trailing_return_type->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned LambdaDeclaratorAST::lastToken() const
+{
+    if (trailing_return_type)
+        if (unsigned candidate = trailing_return_type->lastToken())
+            return candidate;
+    if (exception_specification)
+        if (unsigned candidate = exception_specification->lastToken())
+            return candidate;
+    if (mutable_token)
+        return mutable_token + 1;
+    if (attributes)
+        if (unsigned candidate = attributes->lastToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token + 1;
+    if (parameter_declaration_clause)
+        if (unsigned candidate = parameter_declaration_clause->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned LambdaExpressionAST::firstToken() const
+{
+    if (lambda_introducer)
+        if (unsigned candidate = lambda_introducer->firstToken())
+            return candidate;
+    if (lambda_declarator)
+        if (unsigned candidate = lambda_declarator->firstToken())
+            return candidate;
+    if (statement)
+        if (unsigned candidate = statement->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned LambdaExpressionAST::lastToken() const
+{
+    if (statement)
+        if (unsigned candidate = statement->lastToken())
+            return candidate;
+    if (lambda_declarator)
+        if (unsigned candidate = lambda_declarator->lastToken())
+            return candidate;
+    if (lambda_introducer)
+        if (unsigned candidate = lambda_introducer->lastToken())
+            return candidate;
+    return 1;
+}
+
+/** \generated */
+unsigned LambdaIntroducerAST::firstToken() const
+{
+    if (lbracket_token)
+        return lbracket_token;
+    if (lambda_capture)
+        if (unsigned candidate = lambda_capture->firstToken())
+            return candidate;
+    if (rbracket_token)
+        return rbracket_token;
+    return 0;
+}
+
+/** \generated */
+unsigned LambdaIntroducerAST::lastToken() const
+{
+    if (rbracket_token)
+        return rbracket_token + 1;
+    if (lambda_capture)
+        if (unsigned candidate = lambda_capture->lastToken())
+            return candidate;
+    if (lbracket_token)
+        return lbracket_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned LinkageBodyAST::firstToken() const
+{
+    if (lbrace_token)
+        return lbrace_token;
+    if (declaration_list)
+        if (unsigned candidate = declaration_list->firstToken())
+            return candidate;
+    if (rbrace_token)
+        return rbrace_token;
+    return 0;
+}
+
+/** \generated */
+unsigned LinkageBodyAST::lastToken() const
+{
+    if (rbrace_token)
+        return rbrace_token + 1;
+    if (declaration_list)
+        if (unsigned candidate = declaration_list->lastToken())
+            return candidate;
+    if (lbrace_token)
+        return lbrace_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned LinkageSpecificationAST::firstToken() const
+{
+    if (extern_token)
+        return extern_token;
+    if (extern_type_token)
+        return extern_type_token;
+    if (declaration)
+        if (unsigned candidate = declaration->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned LinkageSpecificationAST::lastToken() const
+{
+    if (declaration)
+        if (unsigned candidate = declaration->lastToken())
+            return candidate;
+    if (extern_type_token)
+        return extern_type_token + 1;
+    if (extern_token)
+        return extern_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned MemInitializerAST::firstToken() const
+{
+    if (name)
+        if (unsigned candidate = name->firstToken())
+            return candidate;
+    if (expression)
+        if (unsigned candidate = expression->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned MemInitializerAST::lastToken() const
+{
+    if (expression)
+        if (unsigned candidate = expression->lastToken())
+            return candidate;
+    if (name)
+        if (unsigned candidate = name->lastToken())
+            return candidate;
+    return 1;
+}
+
+/** \generated */
+unsigned MemberAccessAST::firstToken() const
+{
+    if (base_expression)
+        if (unsigned candidate = base_expression->firstToken())
+            return candidate;
+    if (access_token)
+        return access_token;
+    if (template_token)
+        return template_token;
+    if (member_name)
+        if (unsigned candidate = member_name->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned MemberAccessAST::lastToken() const
+{
+    if (member_name)
+        if (unsigned candidate = member_name->lastToken())
+            return candidate;
+    if (template_token)
+        return template_token + 1;
+    if (access_token)
+        return access_token + 1;
+    if (base_expression)
+        if (unsigned candidate = base_expression->lastToken())
+            return candidate;
+    return 1;
+}
+
+/** \generated */
+unsigned NamedTypeSpecifierAST::firstToken() const
+{
+    if (name)
+        if (unsigned candidate = name->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned NamedTypeSpecifierAST::lastToken() const
+{
+    if (name)
+        if (unsigned candidate = name->lastToken())
+            return candidate;
+    return 1;
+}
+
+/** \generated */
+unsigned NamespaceAST::firstToken() const
+{
+    if (inline_token)
+        return inline_token;
+    if (namespace_token)
+        return namespace_token;
+    if (identifier_token)
+        return identifier_token;
+    if (attribute_list)
+        if (unsigned candidate = attribute_list->firstToken())
+            return candidate;
+    if (linkage_body)
+        if (unsigned candidate = linkage_body->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned NamespaceAST::lastToken() const
+{
+    if (linkage_body)
+        if (unsigned candidate = linkage_body->lastToken())
+            return candidate;
+    if (attribute_list)
+        if (unsigned candidate = attribute_list->lastToken())
+            return candidate;
+    if (identifier_token)
+        return identifier_token + 1;
+    if (namespace_token)
+        return namespace_token + 1;
+    if (inline_token)
+        return inline_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned NamespaceAliasDefinitionAST::firstToken() const
+{
+    if (namespace_token)
+        return namespace_token;
+    if (namespace_name_token)
+        return namespace_name_token;
+    if (equal_token)
+        return equal_token;
+    if (name)
+        if (unsigned candidate = name->firstToken())
+            return candidate;
+    if (semicolon_token)
+        return semicolon_token;
+    return 0;
+}
+
+/** \generated */
+unsigned NamespaceAliasDefinitionAST::lastToken() const
+{
+    if (semicolon_token)
+        return semicolon_token + 1;
+    if (name)
+        if (unsigned candidate = name->lastToken())
+            return candidate;
+    if (equal_token)
+        return equal_token + 1;
+    if (namespace_name_token)
+        return namespace_name_token + 1;
+    if (namespace_token)
+        return namespace_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned NestedDeclaratorAST::firstToken() const
+{
+    if (lparen_token)
+        return lparen_token;
+    if (declarator)
+        if (unsigned candidate = declarator->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    return 0;
+}
+
+/** \generated */
+unsigned NestedDeclaratorAST::lastToken() const
+{
+    if (rparen_token)
+        return rparen_token + 1;
+    if (declarator)
+        if (unsigned candidate = declarator->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned NestedExpressionAST::firstToken() const
+{
+    if (lparen_token)
+        return lparen_token;
+    if (expression)
+        if (unsigned candidate = expression->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    return 0;
+}
+
+/** \generated */
+unsigned NestedExpressionAST::lastToken() const
+{
+    if (rparen_token)
+        return rparen_token + 1;
+    if (expression)
+        if (unsigned candidate = expression->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned NestedNameSpecifierAST::firstToken() const
+{
+    if (class_or_namespace_name)
+        if (unsigned candidate = class_or_namespace_name->firstToken())
+            return candidate;
+    if (scope_token)
+        return scope_token;
+    return 0;
+}
+
+/** \generated */
+unsigned NestedNameSpecifierAST::lastToken() const
+{
+    if (scope_token)
+        return scope_token + 1;
+    if (class_or_namespace_name)
+        if (unsigned candidate = class_or_namespace_name->lastToken())
+            return candidate;
+    return 1;
+}
+
+/** \generated */
+unsigned NewArrayDeclaratorAST::firstToken() const
+{
+    if (lbracket_token)
+        return lbracket_token;
+    if (expression)
+        if (unsigned candidate = expression->firstToken())
+            return candidate;
+    if (rbracket_token)
+        return rbracket_token;
+    return 0;
+}
+
+/** \generated */
+unsigned NewArrayDeclaratorAST::lastToken() const
+{
+    if (rbracket_token)
+        return rbracket_token + 1;
+    if (expression)
+        if (unsigned candidate = expression->lastToken())
+            return candidate;
+    if (lbracket_token)
+        return lbracket_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned NewExpressionAST::firstToken() const
+{
+    if (scope_token)
+        return scope_token;
+    if (new_token)
+        return new_token;
+    if (new_placement)
+        if (unsigned candidate = new_placement->firstToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token;
+    if (type_id)
+        if (unsigned candidate = type_id->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    if (new_type_id)
+        if (unsigned candidate = new_type_id->firstToken())
+            return candidate;
+    if (new_initializer)
+        if (unsigned candidate = new_initializer->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned NewExpressionAST::lastToken() const
+{
+    if (new_initializer)
+        if (unsigned candidate = new_initializer->lastToken())
+            return candidate;
+    if (new_type_id)
+        if (unsigned candidate = new_type_id->lastToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token + 1;
+    if (type_id)
+        if (unsigned candidate = type_id->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (new_placement)
+        if (unsigned candidate = new_placement->lastToken())
+            return candidate;
+    if (new_token)
+        return new_token + 1;
+    if (scope_token)
+        return scope_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned ExpressionListParenAST::firstToken() const
+{
+    if (lparen_token)
+        return lparen_token;
+    if (expression_list)
+        if (unsigned candidate = expression_list->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    return 0;
+}
+
+/** \generated */
+unsigned ExpressionListParenAST::lastToken() const
+{
+    if (rparen_token)
+        return rparen_token + 1;
+    if (expression_list)
+        if (unsigned candidate = expression_list->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned NewTypeIdAST::firstToken() const
+{
+    if (type_specifier_list)
+        if (unsigned candidate = type_specifier_list->firstToken())
+            return candidate;
+    if (ptr_operator_list)
+        if (unsigned candidate = ptr_operator_list->firstToken())
+            return candidate;
+    if (new_array_declarator_list)
+        if (unsigned candidate = new_array_declarator_list->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned NewTypeIdAST::lastToken() const
+{
+    if (new_array_declarator_list)
+        if (unsigned candidate = new_array_declarator_list->lastToken())
+            return candidate;
+    if (ptr_operator_list)
+        if (unsigned candidate = ptr_operator_list->lastToken())
+            return candidate;
+    if (type_specifier_list)
+        if (unsigned candidate = type_specifier_list->lastToken())
+            return candidate;
+    return 1;
+}
+
+/** \generated */
+unsigned NumericLiteralAST::firstToken() const
+{
+    if (literal_token)
+        return literal_token;
+    return 0;
+}
+
+/** \generated */
+unsigned NumericLiteralAST::lastToken() const
+{
+    if (literal_token)
+        return literal_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned ObjCClassDeclarationAST::firstToken() const
+{
+    if (attribute_list)
+        if (unsigned candidate = attribute_list->firstToken())
+            return candidate;
+    if (interface_token)
+        return interface_token;
+    if (implementation_token)
+        return implementation_token;
+    if (class_name)
+        if (unsigned candidate = class_name->firstToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token;
+    if (category_name)
+        if (unsigned candidate = category_name->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    if (colon_token)
+        return colon_token;
+    if (superclass)
+        if (unsigned candidate = superclass->firstToken())
+            return candidate;
+    if (protocol_refs)
+        if (unsigned candidate = protocol_refs->firstToken())
+            return candidate;
+    if (inst_vars_decl)
+        if (unsigned candidate = inst_vars_decl->firstToken())
+            return candidate;
+    if (member_declaration_list)
+        if (unsigned candidate = member_declaration_list->firstToken())
+            return candidate;
+    if (end_token)
+        return end_token;
+    return 0;
+}
+
+/** \generated */
+unsigned ObjCClassDeclarationAST::lastToken() const
+{
+    if (end_token)
+        return end_token + 1;
+    if (member_declaration_list)
+        if (unsigned candidate = member_declaration_list->lastToken())
+            return candidate;
+    if (inst_vars_decl)
+        if (unsigned candidate = inst_vars_decl->lastToken())
+            return candidate;
+    if (protocol_refs)
+        if (unsigned candidate = protocol_refs->lastToken())
+            return candidate;
+    if (superclass)
+        if (unsigned candidate = superclass->lastToken())
+            return candidate;
+    if (colon_token)
+        return colon_token + 1;
+    if (rparen_token)
+        return rparen_token + 1;
+    if (category_name)
+        if (unsigned candidate = category_name->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (class_name)
+        if (unsigned candidate = class_name->lastToken())
+            return candidate;
+    if (implementation_token)
+        return implementation_token + 1;
+    if (interface_token)
+        return interface_token + 1;
+    if (attribute_list)
+        if (unsigned candidate = attribute_list->lastToken())
+            return candidate;
+    return 1;
+}
+
+/** \generated */
+unsigned ObjCClassForwardDeclarationAST::firstToken() const
+{
+    if (attribute_list)
+        if (unsigned candidate = attribute_list->firstToken())
+            return candidate;
+    if (class_token)
+        return class_token;
+    if (identifier_list)
+        if (unsigned candidate = identifier_list->firstToken())
+            return candidate;
+    if (semicolon_token)
+        return semicolon_token;
+    return 0;
+}
+
+/** \generated */
+unsigned ObjCClassForwardDeclarationAST::lastToken() const
+{
+    if (semicolon_token)
+        return semicolon_token + 1;
+    if (identifier_list)
+        if (unsigned candidate = identifier_list->lastToken())
+            return candidate;
+    if (class_token)
+        return class_token + 1;
+    if (attribute_list)
+        if (unsigned candidate = attribute_list->lastToken())
+            return candidate;
+    return 1;
+}
+
+/** \generated */
+unsigned ObjCDynamicPropertiesDeclarationAST::firstToken() const
+{
+    if (dynamic_token)
+        return dynamic_token;
+    if (property_identifier_list)
+        if (unsigned candidate = property_identifier_list->firstToken())
+            return candidate;
+    if (semicolon_token)
+        return semicolon_token;
+    return 0;
+}
+
+/** \generated */
+unsigned ObjCDynamicPropertiesDeclarationAST::lastToken() const
+{
+    if (semicolon_token)
+        return semicolon_token + 1;
+    if (property_identifier_list)
+        if (unsigned candidate = property_identifier_list->lastToken())
+            return candidate;
+    if (dynamic_token)
+        return dynamic_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned ObjCEncodeExpressionAST::firstToken() const
+{
+    if (encode_token)
+        return encode_token;
+    if (type_name)
+        if (unsigned candidate = type_name->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned ObjCEncodeExpressionAST::lastToken() const
+{
+    if (type_name)
+        if (unsigned candidate = type_name->lastToken())
+            return candidate;
+    if (encode_token)
+        return encode_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned ObjCFastEnumerationAST::firstToken() const
+{
+    if (for_token)
+        return for_token;
+    if (lparen_token)
+        return lparen_token;
+    if (type_specifier_list)
+        if (unsigned candidate = type_specifier_list->firstToken())
+            return candidate;
+    if (declarator)
+        if (unsigned candidate = declarator->firstToken())
+            return candidate;
+    if (initializer)
+        if (unsigned candidate = initializer->firstToken())
+            return candidate;
+    if (in_token)
+        return in_token;
+    if (fast_enumeratable_expression)
+        if (unsigned candidate = fast_enumeratable_expression->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    if (statement)
+        if (unsigned candidate = statement->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned ObjCFastEnumerationAST::lastToken() const
+{
+    if (statement)
+        if (unsigned candidate = statement->lastToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token + 1;
+    if (fast_enumeratable_expression)
+        if (unsigned candidate = fast_enumeratable_expression->lastToken())
+            return candidate;
+    if (in_token)
+        return in_token + 1;
+    if (initializer)
+        if (unsigned candidate = initializer->lastToken())
+            return candidate;
+    if (declarator)
+        if (unsigned candidate = declarator->lastToken())
+            return candidate;
+    if (type_specifier_list)
+        if (unsigned candidate = type_specifier_list->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (for_token)
+        return for_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned ObjCInstanceVariablesDeclarationAST::firstToken() const
+{
+    if (lbrace_token)
+        return lbrace_token;
+    if (instance_variable_list)
+        if (unsigned candidate = instance_variable_list->firstToken())
+            return candidate;
+    if (rbrace_token)
+        return rbrace_token;
+    return 0;
+}
+
+/** \generated */
+unsigned ObjCInstanceVariablesDeclarationAST::lastToken() const
+{
+    if (rbrace_token)
+        return rbrace_token + 1;
+    if (instance_variable_list)
+        if (unsigned candidate = instance_variable_list->lastToken())
+            return candidate;
+    if (lbrace_token)
+        return lbrace_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned ObjCMessageArgumentAST::firstToken() const
+{
+    if (parameter_value_expression)
+        if (unsigned candidate = parameter_value_expression->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned ObjCMessageArgumentAST::lastToken() const
+{
+    if (parameter_value_expression)
+        if (unsigned candidate = parameter_value_expression->lastToken())
+            return candidate;
+    return 1;
+}
+
+/** \generated */
+unsigned ObjCMessageArgumentDeclarationAST::firstToken() const
+{
+    if (type_name)
+        if (unsigned candidate = type_name->firstToken())
+            return candidate;
+    if (attribute_list)
+        if (unsigned candidate = attribute_list->firstToken())
+            return candidate;
+    if (param_name)
+        if (unsigned candidate = param_name->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned ObjCMessageArgumentDeclarationAST::lastToken() const
+{
+    if (param_name)
+        if (unsigned candidate = param_name->lastToken())
+            return candidate;
+    if (attribute_list)
+        if (unsigned candidate = attribute_list->lastToken())
+            return candidate;
+    if (type_name)
+        if (unsigned candidate = type_name->lastToken())
+            return candidate;
+    return 1;
+}
+
+/** \generated */
+unsigned ObjCMessageExpressionAST::firstToken() const
+{
+    if (lbracket_token)
+        return lbracket_token;
+    if (receiver_expression)
+        if (unsigned candidate = receiver_expression->firstToken())
+            return candidate;
+    if (selector)
+        if (unsigned candidate = selector->firstToken())
+            return candidate;
+    if (argument_list)
+        if (unsigned candidate = argument_list->firstToken())
+            return candidate;
+    if (rbracket_token)
+        return rbracket_token;
+    return 0;
+}
+
+/** \generated */
+unsigned ObjCMessageExpressionAST::lastToken() const
+{
+    if (rbracket_token)
+        return rbracket_token + 1;
+    if (argument_list)
+        if (unsigned candidate = argument_list->lastToken())
+            return candidate;
+    if (selector)
+        if (unsigned candidate = selector->lastToken())
+            return candidate;
+    if (receiver_expression)
+        if (unsigned candidate = receiver_expression->lastToken())
+            return candidate;
+    if (lbracket_token)
+        return lbracket_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned ObjCMethodDeclarationAST::firstToken() const
+{
+    if (method_prototype)
+        if (unsigned candidate = method_prototype->firstToken())
+            return candidate;
+    if (function_body)
+        if (unsigned candidate = function_body->firstToken())
+            return candidate;
+    if (semicolon_token)
+        return semicolon_token;
+    return 0;
+}
+
+/** \generated */
+unsigned ObjCMethodDeclarationAST::lastToken() const
+{
+    if (semicolon_token)
+        return semicolon_token + 1;
+    if (function_body)
+        if (unsigned candidate = function_body->lastToken())
+            return candidate;
+    if (method_prototype)
+        if (unsigned candidate = method_prototype->lastToken())
+            return candidate;
+    return 1;
+}
+
+/** \generated */
+unsigned ObjCMethodPrototypeAST::firstToken() const
+{
+    if (method_type_token)
+        return method_type_token;
+    if (type_name)
+        if (unsigned candidate = type_name->firstToken())
+            return candidate;
+    if (selector)
+        if (unsigned candidate = selector->firstToken())
+            return candidate;
+    if (argument_list)
+        if (unsigned candidate = argument_list->firstToken())
+            return candidate;
+    if (dot_dot_dot_token)
+        return dot_dot_dot_token;
+    if (attribute_list)
+        if (unsigned candidate = attribute_list->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned ObjCMethodPrototypeAST::lastToken() const
+{
+    if (attribute_list)
+        if (unsigned candidate = attribute_list->lastToken())
+            return candidate;
+    if (dot_dot_dot_token)
+        return dot_dot_dot_token + 1;
+    if (argument_list)
+        if (unsigned candidate = argument_list->lastToken())
+            return candidate;
+    if (selector)
+        if (unsigned candidate = selector->lastToken())
+            return candidate;
+    if (type_name)
+        if (unsigned candidate = type_name->lastToken())
+            return candidate;
+    if (method_type_token)
+        return method_type_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned ObjCPropertyAttributeAST::firstToken() const
+{
+    if (attribute_identifier_token)
+        return attribute_identifier_token;
+    if (equals_token)
+        return equals_token;
+    if (method_selector)
+        if (unsigned candidate = method_selector->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned ObjCPropertyAttributeAST::lastToken() const
+{
+    if (method_selector)
+        if (unsigned candidate = method_selector->lastToken())
+            return candidate;
+    if (equals_token)
+        return equals_token + 1;
+    if (attribute_identifier_token)
+        return attribute_identifier_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned ObjCPropertyDeclarationAST::firstToken() const
+{
+    if (attribute_list)
+        if (unsigned candidate = attribute_list->firstToken())
+            return candidate;
+    if (property_token)
+        return property_token;
+    if (lparen_token)
+        return lparen_token;
+    if (property_attribute_list)
+        if (unsigned candidate = property_attribute_list->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    if (simple_declaration)
+        if (unsigned candidate = simple_declaration->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned ObjCPropertyDeclarationAST::lastToken() const
+{
+    if (simple_declaration)
+        if (unsigned candidate = simple_declaration->lastToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token + 1;
+    if (property_attribute_list)
+        if (unsigned candidate = property_attribute_list->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (property_token)
+        return property_token + 1;
+    if (attribute_list)
+        if (unsigned candidate = attribute_list->lastToken())
+            return candidate;
+    return 1;
+}
+
+/** \generated */
+unsigned ObjCProtocolDeclarationAST::firstToken() const
+{
+    if (attribute_list)
+        if (unsigned candidate = attribute_list->firstToken())
+            return candidate;
+    if (protocol_token)
+        return protocol_token;
+    if (name)
+        if (unsigned candidate = name->firstToken())
+            return candidate;
+    if (protocol_refs)
+        if (unsigned candidate = protocol_refs->firstToken())
+            return candidate;
+    if (member_declaration_list)
+        if (unsigned candidate = member_declaration_list->firstToken())
+            return candidate;
+    if (end_token)
+        return end_token;
+    return 0;
+}
+
+/** \generated */
+unsigned ObjCProtocolDeclarationAST::lastToken() const
+{
+    if (end_token)
+        return end_token + 1;
+    if (member_declaration_list)
+        if (unsigned candidate = member_declaration_list->lastToken())
+            return candidate;
+    if (protocol_refs)
+        if (unsigned candidate = protocol_refs->lastToken())
+            return candidate;
+    if (name)
+        if (unsigned candidate = name->lastToken())
+            return candidate;
+    if (protocol_token)
+        return protocol_token + 1;
+    if (attribute_list)
+        if (unsigned candidate = attribute_list->lastToken())
+            return candidate;
+    return 1;
+}
+
+/** \generated */
+unsigned ObjCProtocolExpressionAST::firstToken() const
+{
+    if (protocol_token)
+        return protocol_token;
+    if (lparen_token)
+        return lparen_token;
+    if (identifier_token)
+        return identifier_token;
+    if (rparen_token)
+        return rparen_token;
+    return 0;
+}
+
+/** \generated */
+unsigned ObjCProtocolExpressionAST::lastToken() const
+{
+    if (rparen_token)
+        return rparen_token + 1;
+    if (identifier_token)
+        return identifier_token + 1;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (protocol_token)
+        return protocol_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned ObjCProtocolForwardDeclarationAST::firstToken() const
+{
+    if (attribute_list)
+        if (unsigned candidate = attribute_list->firstToken())
+            return candidate;
+    if (protocol_token)
+        return protocol_token;
+    if (identifier_list)
+        if (unsigned candidate = identifier_list->firstToken())
+            return candidate;
+    if (semicolon_token)
+        return semicolon_token;
+    return 0;
+}
+
+/** \generated */
+unsigned ObjCProtocolForwardDeclarationAST::lastToken() const
+{
+    if (semicolon_token)
+        return semicolon_token + 1;
+    if (identifier_list)
+        if (unsigned candidate = identifier_list->lastToken())
+            return candidate;
+    if (protocol_token)
+        return protocol_token + 1;
+    if (attribute_list)
+        if (unsigned candidate = attribute_list->lastToken())
+            return candidate;
+    return 1;
+}
+
+/** \generated */
+unsigned ObjCProtocolRefsAST::firstToken() const
+{
+    if (less_token)
+        return less_token;
+    if (identifier_list)
+        if (unsigned candidate = identifier_list->firstToken())
+            return candidate;
+    if (greater_token)
+        return greater_token;
+    return 0;
+}
+
+/** \generated */
+unsigned ObjCProtocolRefsAST::lastToken() const
+{
+    if (greater_token)
+        return greater_token + 1;
+    if (identifier_list)
+        if (unsigned candidate = identifier_list->lastToken())
+            return candidate;
+    if (less_token)
+        return less_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned ObjCSelectorAST::firstToken() const
+{
+    if (selector_argument_list)
+        if (unsigned candidate = selector_argument_list->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned ObjCSelectorAST::lastToken() const
+{
+    if (selector_argument_list)
+        if (unsigned candidate = selector_argument_list->lastToken())
+            return candidate;
+    return 1;
+}
+
+/** \generated */
+unsigned ObjCSelectorArgumentAST::firstToken() const
+{
+    if (name_token)
+        return name_token;
+    if (colon_token)
+        return colon_token;
+    return 0;
+}
+
+/** \generated */
+unsigned ObjCSelectorArgumentAST::lastToken() const
+{
+    if (colon_token)
+        return colon_token + 1;
+    if (name_token)
+        return name_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned ObjCSelectorExpressionAST::firstToken() const
+{
+    if (selector_token)
+        return selector_token;
+    if (lparen_token)
+        return lparen_token;
+    if (selector)
+        if (unsigned candidate = selector->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    return 0;
+}
+
+/** \generated */
+unsigned ObjCSelectorExpressionAST::lastToken() const
+{
+    if (rparen_token)
+        return rparen_token + 1;
+    if (selector)
+        if (unsigned candidate = selector->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (selector_token)
+        return selector_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned ObjCSynchronizedStatementAST::firstToken() const
+{
+    if (synchronized_token)
+        return synchronized_token;
+    if (lparen_token)
+        return lparen_token;
+    if (synchronized_object)
+        if (unsigned candidate = synchronized_object->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    if (statement)
+        if (unsigned candidate = statement->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned ObjCSynchronizedStatementAST::lastToken() const
+{
+    if (statement)
+        if (unsigned candidate = statement->lastToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token + 1;
+    if (synchronized_object)
+        if (unsigned candidate = synchronized_object->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (synchronized_token)
+        return synchronized_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned ObjCSynthesizedPropertiesDeclarationAST::firstToken() const
+{
+    if (synthesized_token)
+        return synthesized_token;
+    if (property_identifier_list)
+        if (unsigned candidate = property_identifier_list->firstToken())
+            return candidate;
+    if (semicolon_token)
+        return semicolon_token;
+    return 0;
+}
+
+/** \generated */
+unsigned ObjCSynthesizedPropertiesDeclarationAST::lastToken() const
+{
+    if (semicolon_token)
+        return semicolon_token + 1;
+    if (property_identifier_list)
+        if (unsigned candidate = property_identifier_list->lastToken())
+            return candidate;
+    if (synthesized_token)
+        return synthesized_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned ObjCSynthesizedPropertyAST::firstToken() const
+{
+    if (property_identifier_token)
+        return property_identifier_token;
+    if (equals_token)
+        return equals_token;
+    if (alias_identifier_token)
+        return alias_identifier_token;
+    return 0;
+}
+
+/** \generated */
+unsigned ObjCSynthesizedPropertyAST::lastToken() const
+{
+    if (alias_identifier_token)
+        return alias_identifier_token + 1;
+    if (equals_token)
+        return equals_token + 1;
+    if (property_identifier_token)
+        return property_identifier_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned ObjCTypeNameAST::firstToken() const
+{
+    if (lparen_token)
+        return lparen_token;
+    if (type_qualifier_token)
+        return type_qualifier_token;
+    if (type_id)
+        if (unsigned candidate = type_id->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    return 0;
+}
+
+/** \generated */
+unsigned ObjCTypeNameAST::lastToken() const
+{
+    if (rparen_token)
+        return rparen_token + 1;
+    if (type_id)
+        if (unsigned candidate = type_id->lastToken())
+            return candidate;
+    if (type_qualifier_token)
+        return type_qualifier_token + 1;
+    if (lparen_token)
+        return lparen_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned ObjCVisibilityDeclarationAST::firstToken() const
+{
+    if (visibility_token)
+        return visibility_token;
+    return 0;
+}
+
+/** \generated */
+unsigned ObjCVisibilityDeclarationAST::lastToken() const
+{
+    if (visibility_token)
+        return visibility_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned OperatorAST::firstToken() const
+{
+    if (op_token)
+        return op_token;
+    if (open_token)
+        return open_token;
+    if (close_token)
+        return close_token;
+    return 0;
+}
+
+/** \generated */
+unsigned OperatorAST::lastToken() const
+{
+    if (close_token)
+        return close_token + 1;
+    if (open_token)
+        return open_token + 1;
+    if (op_token)
+        return op_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned OperatorFunctionIdAST::firstToken() const
+{
+    if (operator_token)
+        return operator_token;
+    if (op)
+        if (unsigned candidate = op->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned OperatorFunctionIdAST::lastToken() const
+{
+    if (op)
+        if (unsigned candidate = op->lastToken())
+            return candidate;
+    if (operator_token)
+        return operator_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned ParameterDeclarationAST::firstToken() const
+{
+    if (type_specifier_list)
+        if (unsigned candidate = type_specifier_list->firstToken())
+            return candidate;
+    if (declarator)
+        if (unsigned candidate = declarator->firstToken())
+            return candidate;
+    if (equal_token)
+        return equal_token;
+    if (expression)
+        if (unsigned candidate = expression->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned ParameterDeclarationAST::lastToken() const
+{
+    if (expression)
+        if (unsigned candidate = expression->lastToken())
+            return candidate;
+    if (equal_token)
+        return equal_token + 1;
+    if (declarator)
+        if (unsigned candidate = declarator->lastToken())
+            return candidate;
+    if (type_specifier_list)
+        if (unsigned candidate = type_specifier_list->lastToken())
+            return candidate;
+    return 1;
+}
+
+/** \generated */
+unsigned ParameterDeclarationClauseAST::firstToken() const
+{
+    if (parameter_declaration_list)
+        if (unsigned candidate = parameter_declaration_list->firstToken())
+            return candidate;
+    if (dot_dot_dot_token)
+        return dot_dot_dot_token;
+    return 0;
+}
+
+/** \generated */
+unsigned ParameterDeclarationClauseAST::lastToken() const
+{
+    if (dot_dot_dot_token)
+        return dot_dot_dot_token + 1;
+    if (parameter_declaration_list)
+        if (unsigned candidate = parameter_declaration_list->lastToken())
+            return candidate;
+    return 1;
+}
+
+/** \generated */
+unsigned PointerAST::firstToken() const
+{
+    if (star_token)
+        return star_token;
+    if (cv_qualifier_list)
+        if (unsigned candidate = cv_qualifier_list->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned PointerAST::lastToken() const
+{
+    if (cv_qualifier_list)
+        if (unsigned candidate = cv_qualifier_list->lastToken())
+            return candidate;
+    if (star_token)
+        return star_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned PointerToMemberAST::firstToken() const
+{
+    if (global_scope_token)
+        return global_scope_token;
+    if (nested_name_specifier_list)
+        if (unsigned candidate = nested_name_specifier_list->firstToken())
+            return candidate;
+    if (star_token)
+        return star_token;
+    if (cv_qualifier_list)
+        if (unsigned candidate = cv_qualifier_list->firstToken())
+            return candidate;
+    if (ref_qualifier_token)
+        return ref_qualifier_token;
+    return 0;
+}
+
+/** \generated */
+unsigned PointerToMemberAST::lastToken() const
+{
+    if (ref_qualifier_token)
+        return ref_qualifier_token + 1;
+    if (cv_qualifier_list)
+        if (unsigned candidate = cv_qualifier_list->lastToken())
+            return candidate;
+    if (star_token)
+        return star_token + 1;
+    if (nested_name_specifier_list)
+        if (unsigned candidate = nested_name_specifier_list->lastToken())
+            return candidate;
+    if (global_scope_token)
+        return global_scope_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned PostIncrDecrAST::firstToken() const
+{
+    if (base_expression)
+        if (unsigned candidate = base_expression->firstToken())
+            return candidate;
+    if (incr_decr_token)
+        return incr_decr_token;
+    return 0;
+}
+
+/** \generated */
+unsigned PostIncrDecrAST::lastToken() const
+{
+    if (incr_decr_token)
+        return incr_decr_token + 1;
+    if (base_expression)
+        if (unsigned candidate = base_expression->lastToken())
+            return candidate;
+    return 1;
+}
+
+/** \generated */
+unsigned QtEnumDeclarationAST::firstToken() const
+{
+    if (enum_specifier_token)
+        return enum_specifier_token;
+    if (lparen_token)
+        return lparen_token;
+    if (enumerator_list)
+        if (unsigned candidate = enumerator_list->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    return 0;
+}
+
+/** \generated */
+unsigned QtEnumDeclarationAST::lastToken() const
+{
+    if (rparen_token)
+        return rparen_token + 1;
+    if (enumerator_list)
+        if (unsigned candidate = enumerator_list->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (enum_specifier_token)
+        return enum_specifier_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned QtFlagsDeclarationAST::firstToken() const
+{
+    if (flags_specifier_token)
+        return flags_specifier_token;
+    if (lparen_token)
+        return lparen_token;
+    if (flag_enums_list)
+        if (unsigned candidate = flag_enums_list->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    return 0;
+}
+
+/** \generated */
+unsigned QtFlagsDeclarationAST::lastToken() const
+{
+    if (rparen_token)
+        return rparen_token + 1;
+    if (flag_enums_list)
+        if (unsigned candidate = flag_enums_list->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (flags_specifier_token)
+        return flags_specifier_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned QtInterfaceNameAST::firstToken() const
+{
+    if (interface_name)
+        if (unsigned candidate = interface_name->firstToken())
+            return candidate;
+    if (constraint_list)
+        if (unsigned candidate = constraint_list->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned QtInterfaceNameAST::lastToken() const
+{
+    if (constraint_list)
+        if (unsigned candidate = constraint_list->lastToken())
+            return candidate;
+    if (interface_name)
+        if (unsigned candidate = interface_name->lastToken())
+            return candidate;
+    return 1;
+}
+
+/** \generated */
+unsigned QtInterfacesDeclarationAST::firstToken() const
+{
+    if (interfaces_token)
+        return interfaces_token;
+    if (lparen_token)
+        return lparen_token;
+    if (interface_name_list)
+        if (unsigned candidate = interface_name_list->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    return 0;
+}
+
+/** \generated */
+unsigned QtInterfacesDeclarationAST::lastToken() const
+{
+    if (rparen_token)
+        return rparen_token + 1;
+    if (interface_name_list)
+        if (unsigned candidate = interface_name_list->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (interfaces_token)
+        return interfaces_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned QtMemberDeclarationAST::firstToken() const
+{
+    if (q_token)
+        return q_token;
+    if (lparen_token)
+        return lparen_token;
+    if (type_id)
+        if (unsigned candidate = type_id->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    return 0;
+}
+
+/** \generated */
+unsigned QtMemberDeclarationAST::lastToken() const
+{
+    if (rparen_token)
+        return rparen_token + 1;
+    if (type_id)
+        if (unsigned candidate = type_id->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (q_token)
+        return q_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned QtMethodAST::firstToken() const
+{
+    if (method_token)
+        return method_token;
+    if (lparen_token)
+        return lparen_token;
+    if (declarator)
+        if (unsigned candidate = declarator->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    return 0;
+}
+
+/** \generated */
+unsigned QtMethodAST::lastToken() const
+{
+    if (rparen_token)
+        return rparen_token + 1;
+    if (declarator)
+        if (unsigned candidate = declarator->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (method_token)
+        return method_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned QtObjectTagAST::firstToken() const
+{
+    if (q_object_token)
+        return q_object_token;
+    return 0;
+}
+
+/** \generated */
+unsigned QtObjectTagAST::lastToken() const
+{
+    if (q_object_token)
+        return q_object_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned QtPrivateSlotAST::firstToken() const
+{
+    if (q_private_slot_token)
+        return q_private_slot_token;
+    if (lparen_token)
+        return lparen_token;
+    if (dptr_token)
+        return dptr_token;
+    if (dptr_lparen_token)
+        return dptr_lparen_token;
+    if (dptr_rparen_token)
+        return dptr_rparen_token;
+    if (comma_token)
+        return comma_token;
+    if (type_specifier_list)
+        if (unsigned candidate = type_specifier_list->firstToken())
+            return candidate;
+    if (declarator)
+        if (unsigned candidate = declarator->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    return 0;
+}
+
+/** \generated */
+unsigned QtPrivateSlotAST::lastToken() const
+{
+    if (rparen_token)
+        return rparen_token + 1;
+    if (declarator)
+        if (unsigned candidate = declarator->lastToken())
+            return candidate;
+    if (type_specifier_list)
+        if (unsigned candidate = type_specifier_list->lastToken())
+            return candidate;
+    if (comma_token)
+        return comma_token + 1;
+    if (dptr_rparen_token)
+        return dptr_rparen_token + 1;
+    if (dptr_lparen_token)
+        return dptr_lparen_token + 1;
+    if (dptr_token)
+        return dptr_token + 1;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (q_private_slot_token)
+        return q_private_slot_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned QtPropertyDeclarationAST::firstToken() const
+{
+    if (property_specifier_token)
+        return property_specifier_token;
+    if (lparen_token)
+        return lparen_token;
+    if (expression)
+        if (unsigned candidate = expression->firstToken())
+            return candidate;
+    if (comma_token)
+        return comma_token;
+    if (type_id)
+        if (unsigned candidate = type_id->firstToken())
+            return candidate;
+    if (property_name)
+        if (unsigned candidate = property_name->firstToken())
+            return candidate;
+    if (property_declaration_item_list)
+        if (unsigned candidate = property_declaration_item_list->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    return 0;
+}
+
+/** \generated */
+unsigned QtPropertyDeclarationAST::lastToken() const
+{
+    if (rparen_token)
+        return rparen_token + 1;
+    if (property_declaration_item_list)
+        if (unsigned candidate = property_declaration_item_list->lastToken())
+            return candidate;
+    if (property_name)
+        if (unsigned candidate = property_name->lastToken())
+            return candidate;
+    if (type_id)
+        if (unsigned candidate = type_id->lastToken())
+            return candidate;
+    if (comma_token)
+        return comma_token + 1;
+    if (expression)
+        if (unsigned candidate = expression->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (property_specifier_token)
+        return property_specifier_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned QtPropertyDeclarationItemAST::firstToken() const
+{
+    if (item_name_token)
+        return item_name_token;
+    if (expression)
+        if (unsigned candidate = expression->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned QtPropertyDeclarationItemAST::lastToken() const
+{
+    if (expression)
+        if (unsigned candidate = expression->lastToken())
+            return candidate;
+    if (item_name_token)
+        return item_name_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned QualifiedNameAST::firstToken() const
+{
+    if (global_scope_token)
+        return global_scope_token;
+    if (nested_name_specifier_list)
+        if (unsigned candidate = nested_name_specifier_list->firstToken())
+            return candidate;
+    if (unqualified_name)
+        if (unsigned candidate = unqualified_name->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned QualifiedNameAST::lastToken() const
+{
+    if (unqualified_name)
+        if (unsigned candidate = unqualified_name->lastToken())
+            return candidate;
+    if (nested_name_specifier_list)
+        if (unsigned candidate = nested_name_specifier_list->lastToken())
+            return candidate;
+    if (global_scope_token)
+        return global_scope_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned ReferenceAST::firstToken() const
+{
+    if (reference_token)
+        return reference_token;
+    return 0;
+}
+
+/** \generated */
+unsigned ReferenceAST::lastToken() const
+{
+    if (reference_token)
+        return reference_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned ReturnStatementAST::firstToken() const
+{
+    if (return_token)
+        return return_token;
+    if (expression)
+        if (unsigned candidate = expression->firstToken())
+            return candidate;
+    if (semicolon_token)
+        return semicolon_token;
+    return 0;
+}
+
+/** \generated */
+unsigned ReturnStatementAST::lastToken() const
+{
+    if (semicolon_token)
+        return semicolon_token + 1;
+    if (expression)
+        if (unsigned candidate = expression->lastToken())
+            return candidate;
+    if (return_token)
+        return return_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned SimpleDeclarationAST::firstToken() const
+{
+    if (qt_invokable_token)
+        return qt_invokable_token;
+    if (decl_specifier_list)
+        if (unsigned candidate = decl_specifier_list->firstToken())
+            return candidate;
+    if (declarator_list)
+        if (unsigned candidate = declarator_list->firstToken())
+            return candidate;
+    if (semicolon_token)
+        return semicolon_token;
+    return 0;
+}
+
+/** \generated */
+unsigned SimpleDeclarationAST::lastToken() const
+{
+    if (semicolon_token)
+        return semicolon_token + 1;
+    if (declarator_list)
+        if (unsigned candidate = declarator_list->lastToken())
+            return candidate;
+    if (decl_specifier_list)
+        if (unsigned candidate = decl_specifier_list->lastToken())
+            return candidate;
+    if (qt_invokable_token)
+        return qt_invokable_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned SimpleNameAST::firstToken() const
+{
+    if (identifier_token)
+        return identifier_token;
+    return 0;
+}
+
+/** \generated */
+unsigned SimpleNameAST::lastToken() const
+{
+    if (identifier_token)
+        return identifier_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned SimpleSpecifierAST::firstToken() const
+{
+    if (specifier_token)
+        return specifier_token;
+    return 0;
+}
+
+/** \generated */
+unsigned SimpleSpecifierAST::lastToken() const
+{
+    if (specifier_token)
+        return specifier_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned SizeofExpressionAST::firstToken() const
+{
+    if (sizeof_token)
+        return sizeof_token;
+    if (dot_dot_dot_token)
+        return dot_dot_dot_token;
+    if (lparen_token)
+        return lparen_token;
+    if (expression)
+        if (unsigned candidate = expression->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    return 0;
+}
+
+/** \generated */
+unsigned SizeofExpressionAST::lastToken() const
+{
+    if (rparen_token)
+        return rparen_token + 1;
+    if (expression)
+        if (unsigned candidate = expression->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (dot_dot_dot_token)
+        return dot_dot_dot_token + 1;
+    if (sizeof_token)
+        return sizeof_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned StringLiteralAST::firstToken() const
+{
+    if (literal_token)
+        return literal_token;
+    if (next)
+        if (unsigned candidate = next->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned StringLiteralAST::lastToken() const
+{
+    if (next)
+        if (unsigned candidate = next->lastToken())
+            return candidate;
+    if (literal_token)
+        return literal_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned SwitchStatementAST::firstToken() const
+{
+    if (switch_token)
+        return switch_token;
+    if (lparen_token)
+        return lparen_token;
+    if (condition)
+        if (unsigned candidate = condition->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    if (statement)
+        if (unsigned candidate = statement->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned SwitchStatementAST::lastToken() const
+{
+    if (statement)
+        if (unsigned candidate = statement->lastToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token + 1;
+    if (condition)
+        if (unsigned candidate = condition->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (switch_token)
+        return switch_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned TemplateDeclarationAST::firstToken() const
+{
+    if (export_token)
+        return export_token;
+    if (template_token)
+        return template_token;
+    if (less_token)
+        return less_token;
+    if (template_parameter_list)
+        if (unsigned candidate = template_parameter_list->firstToken())
+            return candidate;
+    if (greater_token)
+        return greater_token;
+    if (declaration)
+        if (unsigned candidate = declaration->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned TemplateDeclarationAST::lastToken() const
+{
+    if (declaration)
+        if (unsigned candidate = declaration->lastToken())
+            return candidate;
+    if (greater_token)
+        return greater_token + 1;
+    if (template_parameter_list)
+        if (unsigned candidate = template_parameter_list->lastToken())
+            return candidate;
+    if (less_token)
+        return less_token + 1;
+    if (template_token)
+        return template_token + 1;
+    if (export_token)
+        return export_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned TemplateIdAST::firstToken() const
+{
+    if (template_token)
+        return template_token;
+    if (identifier_token)
+        return identifier_token;
+    if (less_token)
+        return less_token;
+    if (template_argument_list)
+        if (unsigned candidate = template_argument_list->firstToken())
+            return candidate;
+    if (greater_token)
+        return greater_token;
+    return 0;
+}
+
+/** \generated */
+unsigned TemplateIdAST::lastToken() const
+{
+    if (greater_token)
+        return greater_token + 1;
+    if (template_argument_list)
+        if (unsigned candidate = template_argument_list->lastToken())
+            return candidate;
+    if (less_token)
+        return less_token + 1;
+    if (identifier_token)
+        return identifier_token + 1;
+    if (template_token)
+        return template_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned TemplateTypeParameterAST::firstToken() const
+{
+    if (template_token)
+        return template_token;
+    if (less_token)
+        return less_token;
+    if (template_parameter_list)
+        if (unsigned candidate = template_parameter_list->firstToken())
+            return candidate;
+    if (greater_token)
+        return greater_token;
+    if (class_token)
+        return class_token;
+    if (dot_dot_dot_token)
+        return dot_dot_dot_token;
+    if (name)
+        if (unsigned candidate = name->firstToken())
+            return candidate;
+    if (equal_token)
+        return equal_token;
+    if (type_id)
+        if (unsigned candidate = type_id->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned TemplateTypeParameterAST::lastToken() const
+{
+    if (type_id)
+        if (unsigned candidate = type_id->lastToken())
+            return candidate;
+    if (equal_token)
+        return equal_token + 1;
+    if (name)
+        if (unsigned candidate = name->lastToken())
+            return candidate;
+    if (dot_dot_dot_token)
+        return dot_dot_dot_token + 1;
+    if (class_token)
+        return class_token + 1;
+    if (greater_token)
+        return greater_token + 1;
+    if (template_parameter_list)
+        if (unsigned candidate = template_parameter_list->lastToken())
+            return candidate;
+    if (less_token)
+        return less_token + 1;
+    if (template_token)
+        return template_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned ThisExpressionAST::firstToken() const
+{
+    if (this_token)
+        return this_token;
+    return 0;
+}
+
+/** \generated */
+unsigned ThisExpressionAST::lastToken() const
+{
+    if (this_token)
+        return this_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned ThrowExpressionAST::firstToken() const
+{
+    if (throw_token)
+        return throw_token;
+    if (expression)
+        if (unsigned candidate = expression->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned ThrowExpressionAST::lastToken() const
+{
+    if (expression)
+        if (unsigned candidate = expression->lastToken())
+            return candidate;
+    if (throw_token)
+        return throw_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned TrailingReturnTypeAST::firstToken() const
+{
+    if (arrow_token)
+        return arrow_token;
+    if (attributes)
+        if (unsigned candidate = attributes->firstToken())
+            return candidate;
+    if (type_specifier_list)
+        if (unsigned candidate = type_specifier_list->firstToken())
+            return candidate;
+    if (declarator)
+        if (unsigned candidate = declarator->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned TrailingReturnTypeAST::lastToken() const
+{
+    if (declarator)
+        if (unsigned candidate = declarator->lastToken())
+            return candidate;
+    if (type_specifier_list)
+        if (unsigned candidate = type_specifier_list->lastToken())
+            return candidate;
+    if (attributes)
+        if (unsigned candidate = attributes->lastToken())
+            return candidate;
+    if (arrow_token)
+        return arrow_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned TranslationUnitAST::firstToken() const
+{
+    if (declaration_list)
+        if (unsigned candidate = declaration_list->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned TranslationUnitAST::lastToken() const
+{
+    if (declaration_list)
+        if (unsigned candidate = declaration_list->lastToken())
+            return candidate;
+    return 1;
+}
+
+/** \generated */
+unsigned TryBlockStatementAST::firstToken() const
+{
+    if (try_token)
+        return try_token;
+    if (statement)
+        if (unsigned candidate = statement->firstToken())
+            return candidate;
+    if (catch_clause_list)
+        if (unsigned candidate = catch_clause_list->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned TryBlockStatementAST::lastToken() const
+{
+    if (catch_clause_list)
+        if (unsigned candidate = catch_clause_list->lastToken())
+            return candidate;
+    if (statement)
+        if (unsigned candidate = statement->lastToken())
+            return candidate;
+    if (try_token)
+        return try_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned TypeConstructorCallAST::firstToken() const
+{
+    if (type_specifier_list)
+        if (unsigned candidate = type_specifier_list->firstToken())
+            return candidate;
+    if (expression)
+        if (unsigned candidate = expression->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned TypeConstructorCallAST::lastToken() const
+{
+    if (expression)
+        if (unsigned candidate = expression->lastToken())
+            return candidate;
+    if (type_specifier_list)
+        if (unsigned candidate = type_specifier_list->lastToken())
+            return candidate;
+    return 1;
+}
+
+/** \generated */
+unsigned TypeIdAST::firstToken() const
+{
+    if (type_specifier_list)
+        if (unsigned candidate = type_specifier_list->firstToken())
+            return candidate;
+    if (declarator)
+        if (unsigned candidate = declarator->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned TypeIdAST::lastToken() const
+{
+    if (declarator)
+        if (unsigned candidate = declarator->lastToken())
+            return candidate;
+    if (type_specifier_list)
+        if (unsigned candidate = type_specifier_list->lastToken())
+            return candidate;
+    return 1;
+}
+
+/** \generated */
+unsigned TypeidExpressionAST::firstToken() const
+{
+    if (typeid_token)
+        return typeid_token;
+    if (lparen_token)
+        return lparen_token;
+    if (expression)
+        if (unsigned candidate = expression->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    return 0;
+}
+
+/** \generated */
+unsigned TypeidExpressionAST::lastToken() const
+{
+    if (rparen_token)
+        return rparen_token + 1;
+    if (expression)
+        if (unsigned candidate = expression->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (typeid_token)
+        return typeid_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned TypenameCallExpressionAST::firstToken() const
+{
+    if (typename_token)
+        return typename_token;
+    if (name)
+        if (unsigned candidate = name->firstToken())
+            return candidate;
+    if (expression)
+        if (unsigned candidate = expression->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned TypenameCallExpressionAST::lastToken() const
+{
+    if (expression)
+        if (unsigned candidate = expression->lastToken())
+            return candidate;
+    if (name)
+        if (unsigned candidate = name->lastToken())
+            return candidate;
+    if (typename_token)
+        return typename_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned TypenameTypeParameterAST::firstToken() const
+{
+    if (classkey_token)
+        return classkey_token;
+    if (dot_dot_dot_token)
+        return dot_dot_dot_token;
+    if (name)
+        if (unsigned candidate = name->firstToken())
+            return candidate;
+    if (equal_token)
+        return equal_token;
+    if (type_id)
+        if (unsigned candidate = type_id->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned TypenameTypeParameterAST::lastToken() const
+{
+    if (type_id)
+        if (unsigned candidate = type_id->lastToken())
+            return candidate;
+    if (equal_token)
+        return equal_token + 1;
+    if (name)
+        if (unsigned candidate = name->lastToken())
+            return candidate;
+    if (dot_dot_dot_token)
+        return dot_dot_dot_token + 1;
+    if (classkey_token)
+        return classkey_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned TypeofSpecifierAST::firstToken() const
+{
+    if (typeof_token)
+        return typeof_token;
+    if (lparen_token)
+        return lparen_token;
+    if (expression)
+        if (unsigned candidate = expression->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    return 0;
+}
+
+/** \generated */
+unsigned TypeofSpecifierAST::lastToken() const
+{
+    if (rparen_token)
+        return rparen_token + 1;
+    if (expression)
+        if (unsigned candidate = expression->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (typeof_token)
+        return typeof_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned UnaryExpressionAST::firstToken() const
+{
+    if (unary_op_token)
+        return unary_op_token;
+    if (expression)
+        if (unsigned candidate = expression->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned UnaryExpressionAST::lastToken() const
+{
+    if (expression)
+        if (unsigned candidate = expression->lastToken())
+            return candidate;
+    if (unary_op_token)
+        return unary_op_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned UsingAST::firstToken() const
+{
+    if (using_token)
+        return using_token;
+    if (typename_token)
+        return typename_token;
+    if (name)
+        if (unsigned candidate = name->firstToken())
+            return candidate;
+    if (semicolon_token)
+        return semicolon_token;
+    return 0;
+}
+
+/** \generated */
+unsigned UsingAST::lastToken() const
+{
+    if (semicolon_token)
+        return semicolon_token + 1;
+    if (name)
+        if (unsigned candidate = name->lastToken())
+            return candidate;
+    if (typename_token)
+        return typename_token + 1;
+    if (using_token)
+        return using_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned UsingDirectiveAST::firstToken() const
+{
+    if (using_token)
+        return using_token;
+    if (namespace_token)
+        return namespace_token;
+    if (name)
+        if (unsigned candidate = name->firstToken())
+            return candidate;
+    if (semicolon_token)
+        return semicolon_token;
+    return 0;
+}
+
+/** \generated */
+unsigned UsingDirectiveAST::lastToken() const
+{
+    if (semicolon_token)
+        return semicolon_token + 1;
+    if (name)
+        if (unsigned candidate = name->lastToken())
+            return candidate;
+    if (namespace_token)
+        return namespace_token + 1;
+    if (using_token)
+        return using_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned WhileStatementAST::firstToken() const
+{
+    if (while_token)
+        return while_token;
+    if (lparen_token)
+        return lparen_token;
+    if (condition)
+        if (unsigned candidate = condition->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    if (statement)
+        if (unsigned candidate = statement->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned WhileStatementAST::lastToken() const
+{
+    if (statement)
+        if (unsigned candidate = statement->lastToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token + 1;
+    if (condition)
+        if (unsigned candidate = condition->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (while_token)
+        return while_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned GnuAttributeSpecifierAST::lastToken() const
+{
+    if (second_rparen_token)
+        return second_rparen_token + 1;
+    if (first_rparen_token)
+        return first_rparen_token + 1;
+    if (attribute_list)
+        if (unsigned candidate = attribute_list->lastToken())
+            return candidate;
+    if (second_lparen_token)
+        return second_lparen_token + 1;
+    if (first_lparen_token)
+        return first_lparen_token + 1;
+    if (attribute_token)
+        return attribute_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned PointerLiteralAST::firstToken() const
+{
+    if (literal_token)
+        return literal_token;
+    return 0;
+}
+
+/** \generated */
+unsigned PointerLiteralAST::lastToken() const
+{
+    if (literal_token)
+        return literal_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned NoExceptSpecificationAST::firstToken() const
+{
+    if (noexcept_token)
+        return noexcept_token;
+    if (lparen_token)
+        return lparen_token;
+    if (expression)
+        if (unsigned candidate = expression->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    return 0;
+}
+
+/** \generated */
+unsigned NoExceptSpecificationAST::lastToken() const
+{
+    if (rparen_token)
+        return rparen_token + 1;
+    if (expression)
+        if (unsigned candidate = expression->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (noexcept_token)
+        return noexcept_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned StaticAssertDeclarationAST::firstToken() const
+{
+    if (static_assert_token)
+        return static_assert_token;
+    if (lparen_token)
+        return lparen_token;
+    if (expression)
+        if (unsigned candidate = expression->firstToken())
+            return candidate;
+    if (comma_token)
+        return comma_token;
+    if (string_literal)
+        if (unsigned candidate = string_literal->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    if (semicolon_token)
+        return semicolon_token;
+    return 0;
+}
+
+/** \generated */
+unsigned StaticAssertDeclarationAST::lastToken() const
+{
+    if (semicolon_token)
+        return semicolon_token + 1;
+    if (rparen_token)
+        return rparen_token + 1;
+    if (string_literal)
+        if (unsigned candidate = string_literal->lastToken())
+            return candidate;
+    if (comma_token)
+        return comma_token + 1;
+    if (expression)
+        if (unsigned candidate = expression->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (static_assert_token)
+        return static_assert_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned DecltypeSpecifierAST::firstToken() const
+{
+    if (decltype_token)
+        return decltype_token;
+    if (lparen_token)
+        return lparen_token;
+    if (expression)
+        if (unsigned candidate = expression->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    return 0;
+}
+
+/** \generated */
+unsigned DecltypeSpecifierAST::lastToken() const
+{
+    if (rparen_token)
+        return rparen_token + 1;
+    if (expression)
+        if (unsigned candidate = expression->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (decltype_token)
+        return decltype_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned RangeBasedForStatementAST::firstToken() const
+{
+    if (for_token)
+        return for_token;
+    if (lparen_token)
+        return lparen_token;
+    if (type_specifier_list)
+        if (unsigned candidate = type_specifier_list->firstToken())
+            return candidate;
+    if (declarator)
+        if (unsigned candidate = declarator->firstToken())
+            return candidate;
+    if (colon_token)
+        return colon_token;
+    if (expression)
+        if (unsigned candidate = expression->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    if (statement)
+        if (unsigned candidate = statement->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned RangeBasedForStatementAST::lastToken() const
+{
+    if (statement)
+        if (unsigned candidate = statement->lastToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token + 1;
+    if (expression)
+        if (unsigned candidate = expression->lastToken())
+            return candidate;
+    if (colon_token)
+        return colon_token + 1;
+    if (declarator)
+        if (unsigned candidate = declarator->lastToken())
+            return candidate;
+    if (type_specifier_list)
+        if (unsigned candidate = type_specifier_list->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (for_token)
+        return for_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned AlignofExpressionAST::firstToken() const
+{
+    if (alignof_token)
+        return alignof_token;
+    if (lparen_token)
+        return lparen_token;
+    if (typeId)
+        if (unsigned candidate = typeId->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    return 0;
+}
+
+/** \generated */
+unsigned AlignofExpressionAST::lastToken() const
+{
+    if (rparen_token)
+        return rparen_token + 1;
+    if (typeId)
+        if (unsigned candidate = typeId->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (alignof_token)
+        return alignof_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned AliasDeclarationAST::firstToken() const
+{
+    if (using_token)
+        return using_token;
+    if (name)
+        if (unsigned candidate = name->firstToken())
+            return candidate;
+    if (equal_token)
+        return equal_token;
+    if (typeId)
+        if (unsigned candidate = typeId->firstToken())
+            return candidate;
+    if (semicolon_token)
+        return semicolon_token;
+    return 0;
+}
+
+/** \generated */
+unsigned AliasDeclarationAST::lastToken() const
+{
+    if (semicolon_token)
+        return semicolon_token + 1;
+    if (typeId)
+        if (unsigned candidate = typeId->lastToken())
+            return candidate;
+    if (equal_token)
+        return equal_token + 1;
+    if (name)
+        if (unsigned candidate = name->lastToken())
+            return candidate;
+    if (using_token)
+        return using_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned DesignatedInitializerAST::firstToken() const
+{
+    if (designator_list)
+        if (unsigned candidate = designator_list->firstToken())
+            return candidate;
+    if (equal_token)
+        return equal_token;
+    if (initializer)
+        if (unsigned candidate = initializer->firstToken())
+            return candidate;
+    return 0;
+}
+
+/** \generated */
+unsigned DesignatedInitializerAST::lastToken() const
+{
+    if (initializer)
+        if (unsigned candidate = initializer->lastToken())
+            return candidate;
+    if (equal_token)
+        return equal_token + 1;
+    if (designator_list)
+        if (unsigned candidate = designator_list->lastToken())
+            return candidate;
+    return 1;
+}
+
+/** \generated */
+unsigned BracketDesignatorAST::firstToken() const
+{
+    if (lbracket_token)
+        return lbracket_token;
+    if (expression)
+        if (unsigned candidate = expression->firstToken())
+            return candidate;
+    if (rbracket_token)
+        return rbracket_token;
+    return 0;
+}
+
+/** \generated */
+unsigned BracketDesignatorAST::lastToken() const
+{
+    if (rbracket_token)
+        return rbracket_token + 1;
+    if (expression)
+        if (unsigned candidate = expression->lastToken())
+            return candidate;
+    if (lbracket_token)
+        return lbracket_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned DotDesignatorAST::firstToken() const
+{
+    if (dot_token)
+        return dot_token;
+    if (identifier_token)
+        return identifier_token;
+    return 0;
+}
+
+/** \generated */
+unsigned DotDesignatorAST::lastToken() const
+{
+    if (identifier_token)
+        return identifier_token + 1;
+    if (dot_token)
+        return dot_token + 1;
+    return 1;
+}
+
+/** \generated */
+unsigned AlignmentSpecifierAST::firstToken() const
+{
+    if (align_token)
+        return align_token;
+    if (lparen_token)
+        return lparen_token;
+    if (typeIdExprOrAlignmentExpr)
+        if (unsigned candidate = typeIdExprOrAlignmentExpr->firstToken())
+            return candidate;
+    if (ellipses_token)
+        return ellipses_token;
+    if (rparen_token)
+        return rparen_token;
+    return 0;
+}
+
+/** \generated */
+unsigned AlignmentSpecifierAST::lastToken() const
+{
+    if (rparen_token)
+        return rparen_token + 1;
+    if (ellipses_token)
+        return ellipses_token + 1;
+    if (typeIdExprOrAlignmentExpr)
+        if (unsigned candidate = typeIdExprOrAlignmentExpr->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (align_token)
+        return align_token + 1;
+    return 1;
+}
+

+ 4665 - 0
Source/ToolCore/JSBind/cplusplus/AST.h

@@ -0,0 +1,4665 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_AST_H
+#define CPLUSPLUS_AST_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include "ASTfwd.h"
+#include "MemoryPool.h"
+
+namespace CPlusPlus {
+
+template <typename Tptr>
+class CPLUSPLUS_EXPORT List: public Managed
+{
+    List(const List &other);
+    void operator =(const List &other);
+
+public:
+    List()
+        : value(Tptr()), next(0)
+    { }
+
+    List(const Tptr &value)
+        : value(value), next(0)
+    { }
+
+    unsigned firstToken() const
+    {
+        if (value)
+            return value->firstToken();
+
+        // ### CPP_CHECK(0);
+        return 0;
+    }
+
+    unsigned lastToken() const
+    {
+        Tptr lv = lastValue();
+
+        if (lv)
+            return lv->lastToken();
+
+        // ### CPP_CHECK(0);
+        return 0;
+    }
+
+    Tptr lastValue() const
+    {
+        Tptr lastValue = 0;
+
+        for (const List *it = this; it; it = it->next) {
+            if (it->value)
+                lastValue = it->value;
+        }
+
+        return lastValue;
+    }
+
+    Tptr value;
+    List *next;
+};
+
+class CPLUSPLUS_EXPORT AST: public Managed
+{
+    AST(const AST &other);
+    void operator =(const AST &other);
+
+public:
+    AST();
+    virtual ~AST();
+
+    void accept(ASTVisitor *visitor);
+
+    static void accept(AST *ast, ASTVisitor *visitor)
+    { if (ast) ast->accept(visitor); }
+
+    template <typename Tptr>
+    static void accept(List<Tptr> *it, ASTVisitor *visitor)
+    {
+        for (; it; it = it->next)
+            accept(it->value, visitor);
+    }
+
+    static bool match(AST *ast, AST *pattern, ASTMatcher *matcher);
+    bool match(AST *pattern, ASTMatcher *matcher);
+
+    template <typename Tptr>
+    static bool match(List<Tptr> *it, List<Tptr> *patternIt, ASTMatcher *matcher)
+    {
+        while (it && patternIt) {
+            if (! match(it->value, patternIt->value, matcher))
+                return false;
+
+            it = it->next;
+            patternIt = patternIt->next;
+        }
+
+        if (! it && ! patternIt)
+            return true;
+
+        return false;
+    }
+
+    virtual unsigned firstToken() const = 0;
+    virtual unsigned lastToken() const = 0;
+
+    virtual AST *clone(MemoryPool *pool) const = 0;
+
+    virtual AccessDeclarationAST *asAccessDeclaration() { return 0; }
+    virtual AliasDeclarationAST *asAliasDeclaration() { return 0; }
+    virtual AlignmentSpecifierAST *asAlignmentSpecifier() { return 0; }
+    virtual AlignofExpressionAST *asAlignofExpression() { return 0; }
+    virtual AnonymousNameAST *asAnonymousName() { return 0; }
+    virtual ArrayAccessAST *asArrayAccess() { return 0; }
+    virtual ArrayDeclaratorAST *asArrayDeclarator() { return 0; }
+    virtual ArrayInitializerAST *asArrayInitializer() { return 0; }
+    virtual AsmDefinitionAST *asAsmDefinition() { return 0; }
+    virtual AttributeSpecifierAST *asAttributeSpecifier() { return 0; }
+    virtual BaseSpecifierAST *asBaseSpecifier() { return 0; }
+    virtual BinaryExpressionAST *asBinaryExpression() { return 0; }
+    virtual BoolLiteralAST *asBoolLiteral() { return 0; }
+    virtual BracedInitializerAST *asBracedInitializer() { return 0; }
+    virtual BracketDesignatorAST *asBracketDesignator() { return 0; }
+    virtual BreakStatementAST *asBreakStatement() { return 0; }
+    virtual CallAST *asCall() { return 0; }
+    virtual CaptureAST *asCapture() { return 0; }
+    virtual CaseStatementAST *asCaseStatement() { return 0; }
+    virtual CastExpressionAST *asCastExpression() { return 0; }
+    virtual CatchClauseAST *asCatchClause() { return 0; }
+    virtual ClassSpecifierAST *asClassSpecifier() { return 0; }
+    virtual CompoundExpressionAST *asCompoundExpression() { return 0; }
+    virtual CompoundLiteralAST *asCompoundLiteral() { return 0; }
+    virtual CompoundStatementAST *asCompoundStatement() { return 0; }
+    virtual ConditionAST *asCondition() { return 0; }
+    virtual ConditionalExpressionAST *asConditionalExpression() { return 0; }
+    virtual ContinueStatementAST *asContinueStatement() { return 0; }
+    virtual ConversionFunctionIdAST *asConversionFunctionId() { return 0; }
+    virtual CoreDeclaratorAST *asCoreDeclarator() { return 0; }
+    virtual CppCastExpressionAST *asCppCastExpression() { return 0; }
+    virtual CtorInitializerAST *asCtorInitializer() { return 0; }
+    virtual DeclarationAST *asDeclaration() { return 0; }
+    virtual DeclarationStatementAST *asDeclarationStatement() { return 0; }
+    virtual DeclaratorAST *asDeclarator() { return 0; }
+    virtual DeclaratorIdAST *asDeclaratorId() { return 0; }
+    virtual DecltypeSpecifierAST *asDecltypeSpecifier() { return 0; }
+    virtual DeleteExpressionAST *asDeleteExpression() { return 0; }
+    virtual DesignatedInitializerAST *asDesignatedInitializer() { return 0; }
+    virtual DesignatorAST *asDesignator() { return 0; }
+    virtual DestructorNameAST *asDestructorName() { return 0; }
+    virtual DoStatementAST *asDoStatement() { return 0; }
+    virtual DotDesignatorAST *asDotDesignator() { return 0; }
+    virtual DynamicExceptionSpecificationAST *asDynamicExceptionSpecification() { return 0; }
+    virtual ElaboratedTypeSpecifierAST *asElaboratedTypeSpecifier() { return 0; }
+    virtual EmptyDeclarationAST *asEmptyDeclaration() { return 0; }
+    virtual EnumSpecifierAST *asEnumSpecifier() { return 0; }
+    virtual EnumeratorAST *asEnumerator() { return 0; }
+    virtual ExceptionDeclarationAST *asExceptionDeclaration() { return 0; }
+    virtual ExceptionSpecificationAST *asExceptionSpecification() { return 0; }
+    virtual ExpressionAST *asExpression() { return 0; }
+    virtual ExpressionListParenAST *asExpressionListParen() { return 0; }
+    virtual ExpressionOrDeclarationStatementAST *asExpressionOrDeclarationStatement() { return 0; }
+    virtual ExpressionStatementAST *asExpressionStatement() { return 0; }
+    virtual ForStatementAST *asForStatement() { return 0; }
+    virtual ForeachStatementAST *asForeachStatement() { return 0; }
+    virtual FunctionDeclaratorAST *asFunctionDeclarator() { return 0; }
+    virtual FunctionDefinitionAST *asFunctionDefinition() { return 0; }
+    virtual GnuAttributeAST *asGnuAttribute() { return 0; }
+    virtual GnuAttributeSpecifierAST *asGnuAttributeSpecifier() { return 0; }
+    virtual GotoStatementAST *asGotoStatement() { return 0; }
+    virtual IdExpressionAST *asIdExpression() { return 0; }
+    virtual IfStatementAST *asIfStatement() { return 0; }
+    virtual LabeledStatementAST *asLabeledStatement() { return 0; }
+    virtual LambdaCaptureAST *asLambdaCapture() { return 0; }
+    virtual LambdaDeclaratorAST *asLambdaDeclarator() { return 0; }
+    virtual LambdaExpressionAST *asLambdaExpression() { return 0; }
+    virtual LambdaIntroducerAST *asLambdaIntroducer() { return 0; }
+    virtual LinkageBodyAST *asLinkageBody() { return 0; }
+    virtual LinkageSpecificationAST *asLinkageSpecification() { return 0; }
+    virtual MemInitializerAST *asMemInitializer() { return 0; }
+    virtual MemberAccessAST *asMemberAccess() { return 0; }
+    virtual NameAST *asName() { return 0; }
+    virtual NamedTypeSpecifierAST *asNamedTypeSpecifier() { return 0; }
+    virtual NamespaceAST *asNamespace() { return 0; }
+    virtual NamespaceAliasDefinitionAST *asNamespaceAliasDefinition() { return 0; }
+    virtual NestedDeclaratorAST *asNestedDeclarator() { return 0; }
+    virtual NestedExpressionAST *asNestedExpression() { return 0; }
+    virtual NestedNameSpecifierAST *asNestedNameSpecifier() { return 0; }
+    virtual NewArrayDeclaratorAST *asNewArrayDeclarator() { return 0; }
+    virtual NewExpressionAST *asNewExpression() { return 0; }
+    virtual NewTypeIdAST *asNewTypeId() { return 0; }
+    virtual NoExceptSpecificationAST *asNoExceptSpecification() { return 0; }
+    virtual NumericLiteralAST *asNumericLiteral() { return 0; }
+    virtual ObjCClassDeclarationAST *asObjCClassDeclaration() { return 0; }
+    virtual ObjCClassForwardDeclarationAST *asObjCClassForwardDeclaration() { return 0; }
+    virtual ObjCDynamicPropertiesDeclarationAST *asObjCDynamicPropertiesDeclaration() { return 0; }
+    virtual ObjCEncodeExpressionAST *asObjCEncodeExpression() { return 0; }
+    virtual ObjCFastEnumerationAST *asObjCFastEnumeration() { return 0; }
+    virtual ObjCInstanceVariablesDeclarationAST *asObjCInstanceVariablesDeclaration() { return 0; }
+    virtual ObjCMessageArgumentAST *asObjCMessageArgument() { return 0; }
+    virtual ObjCMessageArgumentDeclarationAST *asObjCMessageArgumentDeclaration() { return 0; }
+    virtual ObjCMessageExpressionAST *asObjCMessageExpression() { return 0; }
+    virtual ObjCMethodDeclarationAST *asObjCMethodDeclaration() { return 0; }
+    virtual ObjCMethodPrototypeAST *asObjCMethodPrototype() { return 0; }
+    virtual ObjCPropertyAttributeAST *asObjCPropertyAttribute() { return 0; }
+    virtual ObjCPropertyDeclarationAST *asObjCPropertyDeclaration() { return 0; }
+    virtual ObjCProtocolDeclarationAST *asObjCProtocolDeclaration() { return 0; }
+    virtual ObjCProtocolExpressionAST *asObjCProtocolExpression() { return 0; }
+    virtual ObjCProtocolForwardDeclarationAST *asObjCProtocolForwardDeclaration() { return 0; }
+    virtual ObjCProtocolRefsAST *asObjCProtocolRefs() { return 0; }
+    virtual ObjCSelectorAST *asObjCSelector() { return 0; }
+    virtual ObjCSelectorArgumentAST *asObjCSelectorArgument() { return 0; }
+    virtual ObjCSelectorExpressionAST *asObjCSelectorExpression() { return 0; }
+    virtual ObjCSynchronizedStatementAST *asObjCSynchronizedStatement() { return 0; }
+    virtual ObjCSynthesizedPropertiesDeclarationAST *asObjCSynthesizedPropertiesDeclaration() { return 0; }
+    virtual ObjCSynthesizedPropertyAST *asObjCSynthesizedProperty() { return 0; }
+    virtual ObjCTypeNameAST *asObjCTypeName() { return 0; }
+    virtual ObjCVisibilityDeclarationAST *asObjCVisibilityDeclaration() { return 0; }
+    virtual OperatorAST *asOperator() { return 0; }
+    virtual OperatorFunctionIdAST *asOperatorFunctionId() { return 0; }
+    virtual ParameterDeclarationAST *asParameterDeclaration() { return 0; }
+    virtual ParameterDeclarationClauseAST *asParameterDeclarationClause() { return 0; }
+    virtual PointerAST *asPointer() { return 0; }
+    virtual PointerLiteralAST *asPointerLiteral() { return 0; }
+    virtual PointerToMemberAST *asPointerToMember() { return 0; }
+    virtual PostIncrDecrAST *asPostIncrDecr() { return 0; }
+    virtual PostfixAST *asPostfix() { return 0; }
+    virtual PostfixDeclaratorAST *asPostfixDeclarator() { return 0; }
+    virtual PtrOperatorAST *asPtrOperator() { return 0; }
+    virtual QtEnumDeclarationAST *asQtEnumDeclaration() { return 0; }
+    virtual QtFlagsDeclarationAST *asQtFlagsDeclaration() { return 0; }
+    virtual QtInterfaceNameAST *asQtInterfaceName() { return 0; }
+    virtual QtInterfacesDeclarationAST *asQtInterfacesDeclaration() { return 0; }
+    virtual QtMemberDeclarationAST *asQtMemberDeclaration() { return 0; }
+    virtual QtMethodAST *asQtMethod() { return 0; }
+    virtual QtObjectTagAST *asQtObjectTag() { return 0; }
+    virtual QtPrivateSlotAST *asQtPrivateSlot() { return 0; }
+    virtual QtPropertyDeclarationAST *asQtPropertyDeclaration() { return 0; }
+    virtual QtPropertyDeclarationItemAST *asQtPropertyDeclarationItem() { return 0; }
+    virtual QualifiedNameAST *asQualifiedName() { return 0; }
+    virtual RangeBasedForStatementAST *asRangeBasedForStatement() { return 0; }
+    virtual ReferenceAST *asReference() { return 0; }
+    virtual ReturnStatementAST *asReturnStatement() { return 0; }
+    virtual SimpleDeclarationAST *asSimpleDeclaration() { return 0; }
+    virtual SimpleNameAST *asSimpleName() { return 0; }
+    virtual SimpleSpecifierAST *asSimpleSpecifier() { return 0; }
+    virtual SizeofExpressionAST *asSizeofExpression() { return 0; }
+    virtual SpecifierAST *asSpecifier() { return 0; }
+    virtual StatementAST *asStatement() { return 0; }
+    virtual StaticAssertDeclarationAST *asStaticAssertDeclaration() { return 0; }
+    virtual StringLiteralAST *asStringLiteral() { return 0; }
+    virtual SwitchStatementAST *asSwitchStatement() { return 0; }
+    virtual TemplateDeclarationAST *asTemplateDeclaration() { return 0; }
+    virtual TemplateIdAST *asTemplateId() { return 0; }
+    virtual TemplateTypeParameterAST *asTemplateTypeParameter() { return 0; }
+    virtual ThisExpressionAST *asThisExpression() { return 0; }
+    virtual ThrowExpressionAST *asThrowExpression() { return 0; }
+    virtual TrailingReturnTypeAST *asTrailingReturnType() { return 0; }
+    virtual TranslationUnitAST *asTranslationUnit() { return 0; }
+    virtual TryBlockStatementAST *asTryBlockStatement() { return 0; }
+    virtual TypeConstructorCallAST *asTypeConstructorCall() { return 0; }
+    virtual TypeIdAST *asTypeId() { return 0; }
+    virtual TypeidExpressionAST *asTypeidExpression() { return 0; }
+    virtual TypenameCallExpressionAST *asTypenameCallExpression() { return 0; }
+    virtual TypenameTypeParameterAST *asTypenameTypeParameter() { return 0; }
+    virtual TypeofSpecifierAST *asTypeofSpecifier() { return 0; }
+    virtual UnaryExpressionAST *asUnaryExpression() { return 0; }
+    virtual UsingAST *asUsing() { return 0; }
+    virtual UsingDirectiveAST *asUsingDirective() { return 0; }
+    virtual WhileStatementAST *asWhileStatement() { return 0; }
+
+protected:
+    virtual void accept0(ASTVisitor *visitor) = 0;
+    virtual bool match0(AST *, ASTMatcher *) = 0;
+};
+
+class CPLUSPLUS_EXPORT StatementAST: public AST
+{
+public:
+    StatementAST()
+    {}
+
+    virtual StatementAST *asStatement() { return this; }
+
+    virtual StatementAST *clone(MemoryPool *pool) const = 0;
+};
+
+class CPLUSPLUS_EXPORT ExpressionAST: public AST
+{
+public:
+    ExpressionAST()
+    {}
+
+    virtual ExpressionAST *asExpression() { return this; }
+
+    virtual ExpressionAST *clone(MemoryPool *pool) const = 0;
+};
+
+class CPLUSPLUS_EXPORT DeclarationAST: public AST
+{
+public:
+    DeclarationAST()
+    {}
+
+    virtual DeclarationAST *asDeclaration() { return this; }
+
+    virtual DeclarationAST *clone(MemoryPool *pool) const = 0;
+};
+
+class CPLUSPLUS_EXPORT NameAST: public AST
+{
+public: // annotations
+    const Name *name;
+
+public:
+    NameAST()
+        : name(0)
+    {}
+
+    virtual NameAST *asName() { return this; }
+
+    virtual NameAST *clone(MemoryPool *pool) const = 0;
+};
+
+class CPLUSPLUS_EXPORT SpecifierAST: public AST
+{
+public:
+    SpecifierAST()
+    {}
+
+    virtual SpecifierAST *asSpecifier() { return this; }
+
+    virtual SpecifierAST *clone(MemoryPool *pool) const = 0;
+};
+
+class CPLUSPLUS_EXPORT PtrOperatorAST: public AST
+{
+public:
+    PtrOperatorAST()
+    {}
+
+    virtual PtrOperatorAST *asPtrOperator() { return this; }
+
+    virtual PtrOperatorAST *clone(MemoryPool *pool) const = 0;
+};
+
+class CPLUSPLUS_EXPORT PostfixAST: public ExpressionAST
+{
+public:
+    PostfixAST()
+    {}
+
+    virtual PostfixAST *asPostfix() { return this; }
+
+    virtual PostfixAST *clone(MemoryPool *pool) const = 0;
+};
+
+class CPLUSPLUS_EXPORT CoreDeclaratorAST: public AST
+{
+public:
+    CoreDeclaratorAST()
+    {}
+
+    virtual CoreDeclaratorAST *asCoreDeclarator() { return this; }
+
+    virtual CoreDeclaratorAST *clone(MemoryPool *pool) const = 0;
+};
+
+class CPLUSPLUS_EXPORT PostfixDeclaratorAST: public AST
+{
+public:
+    PostfixDeclaratorAST()
+    {}
+
+    virtual PostfixDeclaratorAST *asPostfixDeclarator() { return this; }
+
+    virtual PostfixDeclaratorAST *clone(MemoryPool *pool) const = 0;
+};
+
+class CPLUSPLUS_EXPORT ObjCSelectorArgumentAST: public AST
+{
+public:
+    unsigned name_token;
+    unsigned colon_token;
+
+public:
+    ObjCSelectorArgumentAST()
+        : name_token(0)
+        , colon_token(0)
+    {}
+
+    virtual ObjCSelectorArgumentAST *asObjCSelectorArgument() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCSelectorArgumentAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ObjCSelectorAST: public NameAST
+{
+public:
+    ObjCSelectorArgumentListAST *selector_argument_list;
+
+public:
+    ObjCSelectorAST()
+        : selector_argument_list(0)
+    {}
+
+    virtual ObjCSelectorAST *asObjCSelector() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCSelectorAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT SimpleSpecifierAST: public SpecifierAST
+{
+public:
+    unsigned specifier_token;
+
+public:
+    SimpleSpecifierAST()
+        : specifier_token(0)
+    {}
+
+    virtual SimpleSpecifierAST *asSimpleSpecifier() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual SimpleSpecifierAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT AttributeSpecifierAST: public SpecifierAST
+{
+public:
+    AttributeSpecifierAST()
+    {}
+
+    virtual AttributeSpecifierAST *asAttributeSpecifier() { return this; }
+
+    virtual AttributeSpecifierAST *clone(MemoryPool *pool) const = 0;
+};
+
+class CPLUSPLUS_EXPORT AlignmentSpecifierAST: public AttributeSpecifierAST
+{
+public:
+    unsigned align_token;
+    unsigned lparen_token;
+    ExpressionAST *typeIdExprOrAlignmentExpr;
+    unsigned ellipses_token;
+    unsigned rparen_token;
+
+public:
+    AlignmentSpecifierAST()
+        : align_token(0)
+        , lparen_token(0)
+        , typeIdExprOrAlignmentExpr(0)
+        , ellipses_token(0)
+        , rparen_token(0)
+    {}
+
+    virtual AlignmentSpecifierAST *asAlignmentSpecifier() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual AlignmentSpecifierAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+
+class CPLUSPLUS_EXPORT GnuAttributeSpecifierAST: public AttributeSpecifierAST
+{
+public:
+    unsigned attribute_token;
+    unsigned first_lparen_token;
+    unsigned second_lparen_token;
+    GnuAttributeListAST *attribute_list;
+    unsigned first_rparen_token;
+    unsigned second_rparen_token;
+
+public:
+    GnuAttributeSpecifierAST()
+        : attribute_token(0)
+        , first_lparen_token(0)
+        , second_lparen_token(0)
+        , attribute_list(0)
+        , first_rparen_token(0)
+        , second_rparen_token(0)
+    {}
+
+    virtual GnuAttributeSpecifierAST *asGnuAttributeSpecifier() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual GnuAttributeSpecifierAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT GnuAttributeAST: public AST
+{
+public:
+    unsigned identifier_token;
+    unsigned lparen_token;
+    unsigned tag_token;
+    ExpressionListAST *expression_list;
+    unsigned rparen_token;
+
+public:
+    GnuAttributeAST()
+        : identifier_token(0)
+        , lparen_token(0)
+        , tag_token(0)
+        , expression_list(0)
+        , rparen_token(0)
+    {}
+
+    virtual GnuAttributeAST *asGnuAttribute() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual GnuAttributeAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT TypeofSpecifierAST: public SpecifierAST
+{
+public:
+    unsigned typeof_token;
+    unsigned lparen_token;
+    ExpressionAST *expression;
+    unsigned rparen_token;
+
+public:
+    TypeofSpecifierAST()
+        : typeof_token(0)
+        , lparen_token(0)
+        , expression(0)
+        , rparen_token(0)
+    {}
+
+    virtual TypeofSpecifierAST *asTypeofSpecifier() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual TypeofSpecifierAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT DecltypeSpecifierAST: public SpecifierAST
+{
+public:
+    unsigned decltype_token;
+    unsigned lparen_token;
+    ExpressionAST *expression;
+    unsigned rparen_token;
+
+public:
+    DecltypeSpecifierAST()
+        : decltype_token(0)
+        , lparen_token(0)
+        , expression(0)
+        , rparen_token(0)
+    {}
+
+    virtual DecltypeSpecifierAST *asDecltypeSpecifier() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual DecltypeSpecifierAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT DeclaratorAST: public AST
+{
+public:
+    SpecifierListAST *attribute_list;
+    PtrOperatorListAST *ptr_operator_list;
+    CoreDeclaratorAST *core_declarator;
+    PostfixDeclaratorListAST *postfix_declarator_list;
+    SpecifierListAST *post_attribute_list;
+    unsigned equal_token;
+    ExpressionAST *initializer;
+
+public:
+    DeclaratorAST()
+        : attribute_list(0)
+        , ptr_operator_list(0)
+        , core_declarator(0)
+        , postfix_declarator_list(0)
+        , post_attribute_list(0)
+        , equal_token(0)
+        , initializer(0)
+    {}
+
+    virtual DeclaratorAST *asDeclarator() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual DeclaratorAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT SimpleDeclarationAST: public DeclarationAST
+{
+public:
+    unsigned qt_invokable_token;
+    SpecifierListAST *decl_specifier_list;
+    DeclaratorListAST *declarator_list;
+    unsigned semicolon_token;
+
+public:
+    List<Symbol *> *symbols;
+
+public:
+    SimpleDeclarationAST()
+        : qt_invokable_token(0)
+        , decl_specifier_list(0)
+        , declarator_list(0)
+        , semicolon_token(0)
+        , symbols(0)
+    {}
+
+    virtual SimpleDeclarationAST *asSimpleDeclaration() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual SimpleDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT EmptyDeclarationAST: public DeclarationAST
+{
+public:
+    unsigned semicolon_token;
+
+public:
+    EmptyDeclarationAST()
+        : semicolon_token(0)
+    {}
+
+    virtual EmptyDeclarationAST *asEmptyDeclaration() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual EmptyDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT AccessDeclarationAST: public DeclarationAST
+{
+public:
+    unsigned access_specifier_token;
+    unsigned slots_token;
+    unsigned colon_token;
+
+public:
+    AccessDeclarationAST()
+        : access_specifier_token(0)
+        , slots_token(0)
+        , colon_token(0)
+    {}
+
+    virtual AccessDeclarationAST *asAccessDeclaration() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual AccessDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT QtObjectTagAST: public DeclarationAST
+{
+public:
+    unsigned q_object_token;
+
+public:
+    QtObjectTagAST()
+        : q_object_token(0)
+    {}
+
+    virtual QtObjectTagAST *asQtObjectTag() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual QtObjectTagAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT QtPrivateSlotAST: public DeclarationAST
+{
+public:
+    unsigned q_private_slot_token;
+    unsigned lparen_token;
+    unsigned dptr_token;
+    unsigned dptr_lparen_token;
+    unsigned dptr_rparen_token;
+    unsigned comma_token;
+    SpecifierListAST *type_specifier_list;
+    DeclaratorAST *declarator;
+    unsigned rparen_token;
+
+public:
+    QtPrivateSlotAST()
+        : q_private_slot_token(0)
+        , lparen_token(0)
+        , dptr_token(0)
+        , dptr_lparen_token(0)
+        , dptr_rparen_token(0)
+        , comma_token(0)
+        , type_specifier_list(0)
+        , declarator(0)
+        , rparen_token(0)
+    {}
+
+    virtual QtPrivateSlotAST *asQtPrivateSlot() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual QtPrivateSlotAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class QtPropertyDeclarationItemAST: public AST
+{
+public:
+    unsigned item_name_token;
+    ExpressionAST *expression;
+
+public:
+    QtPropertyDeclarationItemAST()
+        : item_name_token(0)
+        , expression(0)
+    {}
+
+    virtual QtPropertyDeclarationItemAST *asQtPropertyDeclarationItem() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual QtPropertyDeclarationItemAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT QtPropertyDeclarationAST: public DeclarationAST
+{
+public:
+    unsigned property_specifier_token;
+    unsigned lparen_token;
+    ExpressionAST *expression; // for Q_PRIVATE_PROPERTY(expression, ...)
+    unsigned comma_token;
+    ExpressionAST *type_id;
+    NameAST *property_name;
+    QtPropertyDeclarationItemListAST *property_declaration_item_list;
+    unsigned rparen_token;
+
+public:
+    QtPropertyDeclarationAST()
+        : property_specifier_token(0)
+        , lparen_token(0)
+        , expression(0)
+        , comma_token(0)
+        , type_id(0)
+        , property_name(0)
+        , property_declaration_item_list(0)
+        , rparen_token(0)
+    {}
+
+    virtual QtPropertyDeclarationAST *asQtPropertyDeclaration() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual QtPropertyDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT QtEnumDeclarationAST: public DeclarationAST
+{
+public:
+    unsigned enum_specifier_token;
+    unsigned lparen_token;
+    NameListAST *enumerator_list;
+    unsigned rparen_token;
+
+public:
+    QtEnumDeclarationAST()
+        : enum_specifier_token(0)
+        , lparen_token(0)
+        , enumerator_list(0)
+        , rparen_token(0)
+    {}
+
+    virtual QtEnumDeclarationAST *asQtEnumDeclaration() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual QtEnumDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT QtFlagsDeclarationAST: public DeclarationAST
+{
+public:
+    unsigned flags_specifier_token;
+    unsigned lparen_token;
+    NameListAST *flag_enums_list;
+    unsigned rparen_token;
+
+public:
+    QtFlagsDeclarationAST()
+        : flags_specifier_token(0)
+        , lparen_token(0)
+        , flag_enums_list(0)
+        , rparen_token(0)
+    {}
+
+    virtual QtFlagsDeclarationAST *asQtFlagsDeclaration() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual QtFlagsDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT QtInterfaceNameAST: public AST
+{
+public:
+    NameAST *interface_name;
+    NameListAST *constraint_list;
+
+public:
+    QtInterfaceNameAST()
+        : interface_name(0)
+        , constraint_list(0)
+    {}
+
+    virtual QtInterfaceNameAST *asQtInterfaceName() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual QtInterfaceNameAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT QtInterfacesDeclarationAST: public DeclarationAST
+{
+public:
+    unsigned interfaces_token;
+    unsigned lparen_token;
+    QtInterfaceNameListAST *interface_name_list;
+    unsigned rparen_token;
+
+public:
+    QtInterfacesDeclarationAST()
+        : interfaces_token(0)
+        , lparen_token(0)
+        , interface_name_list(0)
+        , rparen_token(0)
+    {}
+
+    virtual QtInterfacesDeclarationAST *asQtInterfacesDeclaration() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual QtInterfacesDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT AsmDefinitionAST: public DeclarationAST
+{
+public:
+    unsigned asm_token;
+    unsigned volatile_token;
+    unsigned lparen_token;
+    // ### string literals
+    // ### asm operand list
+    unsigned rparen_token;
+    unsigned semicolon_token;
+
+public:
+    AsmDefinitionAST()
+        : asm_token(0)
+        , volatile_token(0)
+        , lparen_token(0)
+        , rparen_token(0)
+        , semicolon_token(0)
+    {}
+
+    virtual AsmDefinitionAST *asAsmDefinition() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual AsmDefinitionAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT BaseSpecifierAST: public AST
+{
+public:
+    unsigned virtual_token;
+    unsigned access_specifier_token;
+    NameAST *name;
+
+public: // annotations
+    BaseClass *symbol;
+
+public:
+    BaseSpecifierAST()
+        : virtual_token(0)
+        , access_specifier_token(0)
+        , name(0)
+        , symbol(0)
+    {}
+
+    virtual BaseSpecifierAST *asBaseSpecifier() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual BaseSpecifierAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT IdExpressionAST: public ExpressionAST
+{
+public:
+    NameAST *name;
+
+public:
+    IdExpressionAST()
+        : name(0)
+    {}
+
+    virtual IdExpressionAST *asIdExpression() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual IdExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT CompoundExpressionAST: public ExpressionAST
+{
+public:
+    unsigned lparen_token;
+    CompoundStatementAST *statement;
+    unsigned rparen_token;
+
+public:
+    CompoundExpressionAST()
+        : lparen_token(0)
+        , statement(0)
+        , rparen_token(0)
+    {}
+
+    virtual CompoundExpressionAST *asCompoundExpression() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual CompoundExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT CompoundLiteralAST: public ExpressionAST
+{
+public:
+    unsigned lparen_token;
+    ExpressionAST *type_id;
+    unsigned rparen_token;
+    ExpressionAST *initializer;
+
+public:
+    CompoundLiteralAST()
+        : lparen_token(0)
+        , type_id(0)
+        , rparen_token(0)
+        , initializer(0)
+    {}
+
+    virtual CompoundLiteralAST *asCompoundLiteral() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual CompoundLiteralAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT QtMethodAST: public ExpressionAST
+{
+public:
+    unsigned method_token;
+    unsigned lparen_token;
+    DeclaratorAST *declarator;
+    unsigned rparen_token;
+
+public:
+    QtMethodAST()
+        : method_token(0)
+        , lparen_token(0)
+        , declarator(0)
+        , rparen_token(0)
+    {}
+
+    virtual QtMethodAST *asQtMethod() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual QtMethodAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT QtMemberDeclarationAST: public StatementAST
+{
+public:
+    unsigned q_token;
+    unsigned lparen_token;
+    ExpressionAST *type_id;
+    unsigned rparen_token;
+
+public:
+    QtMemberDeclarationAST()
+        : q_token(0)
+        , lparen_token(0)
+        , type_id(0)
+        , rparen_token(0)
+    {}
+
+    virtual QtMemberDeclarationAST *asQtMemberDeclaration() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual QtMemberDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT BinaryExpressionAST: public ExpressionAST
+{
+public:
+    ExpressionAST *left_expression;
+    unsigned binary_op_token;
+    ExpressionAST *right_expression;
+
+public:
+    BinaryExpressionAST()
+        : left_expression(0)
+        , binary_op_token(0)
+        , right_expression(0)
+    {}
+
+    virtual BinaryExpressionAST *asBinaryExpression() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual BinaryExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT CastExpressionAST: public ExpressionAST
+{
+public:
+    unsigned lparen_token;
+    ExpressionAST *type_id;
+    unsigned rparen_token;
+    ExpressionAST *expression;
+
+public:
+    CastExpressionAST()
+        : lparen_token(0)
+        , type_id(0)
+        , rparen_token(0)
+        , expression(0)
+    {}
+
+    virtual CastExpressionAST *asCastExpression() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual CastExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ClassSpecifierAST: public SpecifierAST
+{
+public:
+    unsigned classkey_token;
+    SpecifierListAST *attribute_list;
+    NameAST *name;
+    unsigned final_token;
+    unsigned colon_token;
+    BaseSpecifierListAST *base_clause_list;
+    unsigned dot_dot_dot_token;
+    unsigned lbrace_token;
+    DeclarationListAST *member_specifier_list;
+    unsigned rbrace_token;
+
+public: // annotations
+    Class *symbol;
+
+public:
+    ClassSpecifierAST()
+        : classkey_token(0)
+        , attribute_list(0)
+        , name(0)
+        , final_token(0)
+        , colon_token(0)
+        , base_clause_list(0)
+        , dot_dot_dot_token(0)
+        , lbrace_token(0)
+        , member_specifier_list(0)
+        , rbrace_token(0)
+        , symbol(0)
+    {}
+
+    virtual ClassSpecifierAST *asClassSpecifier() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ClassSpecifierAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT CaseStatementAST: public StatementAST
+{
+public:
+    unsigned case_token;
+    ExpressionAST *expression;
+    unsigned colon_token;
+    StatementAST *statement;
+
+public:
+    CaseStatementAST()
+        : case_token(0)
+        , expression(0)
+        , colon_token(0)
+        , statement(0)
+    {}
+
+    virtual CaseStatementAST *asCaseStatement() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual CaseStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT CompoundStatementAST: public StatementAST
+{
+public:
+    unsigned lbrace_token;
+    StatementListAST *statement_list;
+    unsigned rbrace_token;
+
+public: // annotations
+    Block *symbol;
+
+public:
+    CompoundStatementAST()
+        : lbrace_token(0)
+        , statement_list(0)
+        , rbrace_token(0)
+        , symbol(0)
+    {}
+
+    virtual CompoundStatementAST *asCompoundStatement() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual CompoundStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ConditionAST: public ExpressionAST
+{
+public:
+    SpecifierListAST *type_specifier_list;
+    DeclaratorAST *declarator;
+
+public:
+    ConditionAST()
+        : type_specifier_list(0)
+        , declarator(0)
+    {}
+
+    virtual ConditionAST *asCondition() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ConditionAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ConditionalExpressionAST: public ExpressionAST
+{
+public:
+    ExpressionAST *condition;
+    unsigned question_token;
+    ExpressionAST *left_expression;
+    unsigned colon_token;
+    ExpressionAST *right_expression;
+
+public:
+    ConditionalExpressionAST()
+        : condition(0)
+        , question_token(0)
+        , left_expression(0)
+        , colon_token(0)
+        , right_expression(0)
+    {}
+
+    virtual ConditionalExpressionAST *asConditionalExpression() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ConditionalExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT CppCastExpressionAST: public ExpressionAST
+{
+public:
+    unsigned cast_token;
+    unsigned less_token;
+    ExpressionAST *type_id;
+    unsigned greater_token;
+    unsigned lparen_token;
+    ExpressionAST *expression;
+    unsigned rparen_token;
+
+public:
+    CppCastExpressionAST()
+        : cast_token(0)
+        , less_token(0)
+        , type_id(0)
+        , greater_token(0)
+        , lparen_token(0)
+        , expression(0)
+        , rparen_token(0)
+    {}
+
+    virtual CppCastExpressionAST *asCppCastExpression() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual CppCastExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT CtorInitializerAST: public AST
+{
+public:
+    unsigned colon_token;
+    MemInitializerListAST *member_initializer_list;
+    unsigned dot_dot_dot_token;
+
+public:
+    CtorInitializerAST()
+        : colon_token(0)
+        , member_initializer_list(0)
+        , dot_dot_dot_token(0)
+    {}
+
+    virtual CtorInitializerAST *asCtorInitializer() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual CtorInitializerAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT DeclarationStatementAST: public StatementAST
+{
+public:
+    DeclarationAST *declaration;
+
+public:
+    DeclarationStatementAST()
+        : declaration(0)
+    {}
+
+    virtual DeclarationStatementAST *asDeclarationStatement() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual DeclarationStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT DeclaratorIdAST: public CoreDeclaratorAST
+{
+public:
+    unsigned dot_dot_dot_token;
+    NameAST *name;
+
+public:
+    DeclaratorIdAST()
+        : dot_dot_dot_token(0)
+        , name(0)
+    {}
+
+    virtual DeclaratorIdAST *asDeclaratorId() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual DeclaratorIdAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT NestedDeclaratorAST: public CoreDeclaratorAST
+{
+public:
+    unsigned lparen_token;
+    DeclaratorAST *declarator;
+    unsigned rparen_token;
+
+public:
+    NestedDeclaratorAST()
+        : lparen_token(0)
+        , declarator(0)
+        , rparen_token(0)
+    {}
+
+    virtual NestedDeclaratorAST *asNestedDeclarator() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual NestedDeclaratorAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT FunctionDeclaratorAST: public PostfixDeclaratorAST
+{
+public:
+    unsigned lparen_token;
+    ParameterDeclarationClauseAST *parameter_declaration_clause;
+    unsigned rparen_token;
+    SpecifierListAST *cv_qualifier_list;
+    unsigned ref_qualifier_token;
+    ExceptionSpecificationAST *exception_specification;
+    TrailingReturnTypeAST *trailing_return_type;
+    // Some FunctionDeclarators can also be interpreted as an initializer, like for 'A b(c);'
+    ExpressionAST *as_cpp_initializer;
+
+public: // annotations
+    Function *symbol;
+
+public:
+    FunctionDeclaratorAST()
+        : lparen_token(0)
+        , parameter_declaration_clause(0)
+        , rparen_token(0)
+        , cv_qualifier_list(0)
+        , ref_qualifier_token(0)
+        , exception_specification(0)
+        , trailing_return_type(0)
+        , as_cpp_initializer(0)
+        , symbol(0)
+    {}
+
+    virtual FunctionDeclaratorAST *asFunctionDeclarator() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual FunctionDeclaratorAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ArrayDeclaratorAST: public PostfixDeclaratorAST
+{
+public:
+    unsigned lbracket_token;
+    ExpressionAST *expression;
+    unsigned rbracket_token;
+
+public:
+    ArrayDeclaratorAST()
+        : lbracket_token(0)
+        , expression(0)
+        , rbracket_token(0)
+    {}
+
+    virtual ArrayDeclaratorAST *asArrayDeclarator() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ArrayDeclaratorAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT DeleteExpressionAST: public ExpressionAST
+{
+public:
+    unsigned scope_token;
+    unsigned delete_token;
+    unsigned lbracket_token;
+    unsigned rbracket_token;
+    ExpressionAST *expression;
+
+public:
+    DeleteExpressionAST()
+        : scope_token(0)
+        , delete_token(0)
+        , lbracket_token(0)
+        , rbracket_token(0)
+        , expression(0)
+    {}
+
+    virtual DeleteExpressionAST *asDeleteExpression() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual DeleteExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT DoStatementAST: public StatementAST
+{
+public:
+    unsigned do_token;
+    StatementAST *statement;
+    unsigned while_token;
+    unsigned lparen_token;
+    ExpressionAST *expression;
+    unsigned rparen_token;
+    unsigned semicolon_token;
+
+public:
+    DoStatementAST()
+        : do_token(0)
+        , statement(0)
+        , while_token(0)
+        , lparen_token(0)
+        , expression(0)
+        , rparen_token(0)
+        , semicolon_token(0)
+    {}
+
+    virtual DoStatementAST *asDoStatement() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual DoStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT NamedTypeSpecifierAST: public SpecifierAST
+{
+public:
+    NameAST *name;
+
+public:
+    NamedTypeSpecifierAST()
+        : name(0)
+    {}
+
+    virtual NamedTypeSpecifierAST *asNamedTypeSpecifier() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual NamedTypeSpecifierAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ElaboratedTypeSpecifierAST: public SpecifierAST
+{
+public:
+    unsigned classkey_token;
+    SpecifierListAST *attribute_list;
+    NameAST *name;
+
+public:
+    ElaboratedTypeSpecifierAST()
+        : classkey_token(0)
+        , attribute_list(0)
+        , name(0)
+    {}
+
+    virtual ElaboratedTypeSpecifierAST *asElaboratedTypeSpecifier() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ElaboratedTypeSpecifierAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT EnumSpecifierAST: public SpecifierAST
+{
+public:
+    unsigned enum_token;
+    unsigned key_token; // struct, class or 0
+    NameAST *name;
+    unsigned colon_token; // can be 0 if there is no enum-base
+    SpecifierListAST *type_specifier_list; // ditto
+    unsigned lbrace_token;
+    EnumeratorListAST *enumerator_list;
+    unsigned stray_comma_token;
+    unsigned rbrace_token;
+
+public: // annotations
+    Enum *symbol;
+
+public:
+    EnumSpecifierAST()
+        : enum_token(0)
+        , key_token(0)
+        , name(0)
+        , colon_token(0)
+        , type_specifier_list(0)
+        , lbrace_token(0)
+        , enumerator_list(0)
+        , stray_comma_token(0)
+        , rbrace_token(0)
+        , symbol(0)
+    {}
+
+    virtual EnumSpecifierAST *asEnumSpecifier() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual EnumSpecifierAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT EnumeratorAST: public AST
+{
+public:
+    unsigned identifier_token;
+    unsigned equal_token;
+    ExpressionAST *expression;
+
+public:
+    EnumeratorAST()
+        : identifier_token(0)
+        , equal_token(0)
+        , expression(0)
+    {}
+
+    virtual EnumeratorAST *asEnumerator() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual EnumeratorAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ExceptionDeclarationAST: public DeclarationAST
+{
+public:
+    SpecifierListAST *type_specifier_list;
+    DeclaratorAST *declarator;
+    unsigned dot_dot_dot_token;
+
+public:
+    ExceptionDeclarationAST()
+        : type_specifier_list(0)
+        , declarator(0)
+        , dot_dot_dot_token(0)
+    {}
+
+    virtual ExceptionDeclarationAST *asExceptionDeclaration() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ExceptionDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ExceptionSpecificationAST: public AST
+{
+public:
+    ExceptionSpecificationAST()
+    {}
+
+    virtual ExceptionSpecificationAST *asExceptionSpecification() { return this; }
+
+    virtual ExceptionSpecificationAST *clone(MemoryPool *pool) const = 0;
+};
+
+class CPLUSPLUS_EXPORT DynamicExceptionSpecificationAST: public ExceptionSpecificationAST
+{
+public:
+    unsigned throw_token;
+    unsigned lparen_token;
+    unsigned dot_dot_dot_token;
+    ExpressionListAST *type_id_list;
+    unsigned rparen_token;
+
+public:
+    DynamicExceptionSpecificationAST()
+        : throw_token(0)
+        , lparen_token(0)
+        , dot_dot_dot_token(0)
+        , type_id_list(0)
+        , rparen_token(0)
+    {}
+
+    virtual DynamicExceptionSpecificationAST *asDynamicExceptionSpecification() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual DynamicExceptionSpecificationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT NoExceptSpecificationAST: public ExceptionSpecificationAST
+{
+public:
+    unsigned noexcept_token;
+    unsigned lparen_token;
+    ExpressionAST *expression;
+    unsigned rparen_token;
+
+public:
+    NoExceptSpecificationAST()
+        : noexcept_token(0)
+        , lparen_token(0)
+        , expression(0)
+        , rparen_token(0)
+    {}
+
+    virtual NoExceptSpecificationAST *asNoExceptSpecification() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual NoExceptSpecificationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ExpressionOrDeclarationStatementAST: public StatementAST
+{
+public:
+    ExpressionStatementAST *expression;
+    DeclarationStatementAST *declaration;
+
+public:
+    ExpressionOrDeclarationStatementAST()
+        : expression(0)
+        , declaration(0)
+    {}
+
+    virtual ExpressionOrDeclarationStatementAST *asExpressionOrDeclarationStatement() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ExpressionOrDeclarationStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ExpressionStatementAST: public StatementAST
+{
+public:
+    ExpressionAST *expression;
+    unsigned semicolon_token;
+
+public:
+    ExpressionStatementAST()
+        : expression(0)
+        , semicolon_token(0)
+    {}
+
+    virtual ExpressionStatementAST *asExpressionStatement() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ExpressionStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT FunctionDefinitionAST: public DeclarationAST
+{
+public:
+    unsigned qt_invokable_token;
+    SpecifierListAST *decl_specifier_list;
+    DeclaratorAST *declarator;
+    CtorInitializerAST *ctor_initializer;
+    StatementAST *function_body;
+
+public: // annotations
+    Function *symbol;
+
+public:
+    FunctionDefinitionAST()
+        : qt_invokable_token(0)
+        , decl_specifier_list(0)
+        , declarator(0)
+        , ctor_initializer(0)
+        , function_body(0)
+        , symbol(0)
+    {}
+
+    virtual FunctionDefinitionAST *asFunctionDefinition() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual FunctionDefinitionAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ForeachStatementAST: public StatementAST
+{
+public:
+    unsigned foreach_token;
+    unsigned lparen_token;
+    // declaration
+    SpecifierListAST *type_specifier_list;
+    DeclaratorAST *declarator;
+    // or an expression
+    ExpressionAST *initializer;
+    unsigned comma_token;
+    ExpressionAST *expression;
+    unsigned rparen_token;
+    StatementAST *statement;
+
+public: // annotations
+    Block *symbol;
+
+public:
+    ForeachStatementAST()
+        : foreach_token(0)
+        , lparen_token(0)
+        , type_specifier_list(0)
+        , declarator(0)
+        , initializer(0)
+        , comma_token(0)
+        , expression(0)
+        , rparen_token(0)
+        , statement(0)
+        , symbol(0)
+    {}
+
+    virtual ForeachStatementAST *asForeachStatement() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ForeachStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT RangeBasedForStatementAST : public StatementAST
+{
+public:
+    unsigned for_token;
+    unsigned lparen_token;
+    // declaration
+    SpecifierListAST *type_specifier_list;
+    DeclaratorAST *declarator;
+    // or an expression
+    unsigned colon_token;
+    ExpressionAST *expression;
+    unsigned rparen_token;
+    StatementAST *statement;
+
+public: // annotations
+    Block *symbol;
+
+public:
+    RangeBasedForStatementAST()
+        : for_token(0)
+        , lparen_token(0)
+        , type_specifier_list(0)
+        , declarator(0)
+        , colon_token(0)
+        , expression(0)
+        , rparen_token(0)
+        , statement(0)
+        , symbol(0)
+    {}
+
+    virtual RangeBasedForStatementAST *asRangeBasedForStatement() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual RangeBasedForStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ForStatementAST: public StatementAST
+{
+public:
+    unsigned for_token;
+    unsigned lparen_token;
+    StatementAST *initializer;
+    ExpressionAST *condition;
+    unsigned semicolon_token;
+    ExpressionAST *expression;
+    unsigned rparen_token;
+    StatementAST *statement;
+
+public: // annotations
+    Block *symbol;
+
+public:
+    ForStatementAST()
+        : for_token(0)
+        , lparen_token(0)
+        , initializer(0)
+        , condition(0)
+        , semicolon_token(0)
+        , expression(0)
+        , rparen_token(0)
+        , statement(0)
+        , symbol(0)
+    {}
+
+    virtual ForStatementAST *asForStatement() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ForStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT IfStatementAST: public StatementAST
+{
+public:
+    unsigned if_token;
+    unsigned lparen_token;
+    ExpressionAST *condition;
+    unsigned rparen_token;
+    StatementAST *statement;
+    unsigned else_token;
+    StatementAST *else_statement;
+
+public: // annotations
+    Block *symbol;
+
+public:
+    IfStatementAST()
+        : if_token(0)
+        , lparen_token(0)
+        , condition(0)
+        , rparen_token(0)
+        , statement(0)
+        , else_token(0)
+        , else_statement(0)
+        , symbol(0)
+    {}
+
+    virtual IfStatementAST *asIfStatement() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual IfStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ArrayInitializerAST: public ExpressionAST
+{
+public:
+    unsigned lbrace_token;
+    ExpressionListAST *expression_list;
+    unsigned rbrace_token;
+
+public:
+    ArrayInitializerAST()
+        : lbrace_token(0)
+        , expression_list(0)
+        , rbrace_token(0)
+    {}
+
+    virtual ArrayInitializerAST *asArrayInitializer() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ArrayInitializerAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT LabeledStatementAST: public StatementAST
+{
+public:
+    unsigned label_token;
+    unsigned colon_token;
+    StatementAST *statement;
+
+public:
+    LabeledStatementAST()
+        : label_token(0)
+        , colon_token(0)
+        , statement(0)
+    {}
+
+    virtual LabeledStatementAST *asLabeledStatement() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual LabeledStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT LinkageBodyAST: public DeclarationAST
+{
+public:
+    unsigned lbrace_token;
+    DeclarationListAST *declaration_list;
+    unsigned rbrace_token;
+
+public:
+    LinkageBodyAST()
+        : lbrace_token(0)
+        , declaration_list(0)
+        , rbrace_token(0)
+    {}
+
+    virtual LinkageBodyAST *asLinkageBody() { return this; }
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual LinkageBodyAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT LinkageSpecificationAST: public DeclarationAST
+{
+public:
+    unsigned extern_token;
+    unsigned extern_type_token;
+    DeclarationAST *declaration;
+
+public:
+    LinkageSpecificationAST()
+        : extern_token(0)
+        , extern_type_token(0)
+        , declaration(0)
+    {}
+
+    virtual LinkageSpecificationAST *asLinkageSpecification() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual LinkageSpecificationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT MemInitializerAST: public AST
+{
+public:
+    NameAST *name;
+    // either a BracedInitializerAST or a ExpressionListParenAST
+    ExpressionAST *expression;
+
+public:
+    MemInitializerAST()
+        : name(0)
+        , expression(0)
+    {}
+
+    virtual MemInitializerAST *asMemInitializer() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual MemInitializerAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT NestedNameSpecifierAST: public AST
+{
+public:
+    NameAST *class_or_namespace_name;
+    unsigned scope_token;
+
+public:
+    NestedNameSpecifierAST()
+        : class_or_namespace_name(0)
+        , scope_token(0)
+    {}
+
+    virtual NestedNameSpecifierAST *asNestedNameSpecifier() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual NestedNameSpecifierAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT QualifiedNameAST: public NameAST
+{
+public:
+    unsigned global_scope_token;
+    NestedNameSpecifierListAST *nested_name_specifier_list;
+    NameAST *unqualified_name;
+
+public:
+    QualifiedNameAST()
+        : global_scope_token(0)
+        , nested_name_specifier_list(0)
+        , unqualified_name(0)
+    {}
+
+    virtual QualifiedNameAST *asQualifiedName() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual QualifiedNameAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT OperatorFunctionIdAST: public NameAST
+{
+public:
+    unsigned operator_token;
+    OperatorAST *op;
+
+public:
+    OperatorFunctionIdAST()
+        : operator_token(0)
+        , op(0)
+    {}
+
+    virtual OperatorFunctionIdAST *asOperatorFunctionId() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual OperatorFunctionIdAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ConversionFunctionIdAST: public NameAST
+{
+public:
+    unsigned operator_token;
+    SpecifierListAST *type_specifier_list;
+    PtrOperatorListAST *ptr_operator_list;
+
+public:
+    ConversionFunctionIdAST()
+        : operator_token(0)
+        , type_specifier_list(0)
+        , ptr_operator_list(0)
+    {}
+
+    virtual ConversionFunctionIdAST *asConversionFunctionId() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ConversionFunctionIdAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT AnonymousNameAST: public NameAST
+{
+public:
+    unsigned class_token;
+public:
+    AnonymousNameAST()
+        : class_token(0)
+    {}
+
+    virtual AnonymousNameAST *asAnonymousName() { return this; }
+    virtual unsigned firstToken() const { return 0; }
+    virtual unsigned lastToken() const { return 0; }
+
+    virtual AnonymousNameAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT SimpleNameAST: public NameAST
+{
+public:
+    unsigned identifier_token;
+
+public:
+    SimpleNameAST()
+        : identifier_token(0)
+    {}
+
+    virtual SimpleNameAST *asSimpleName() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual SimpleNameAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT DestructorNameAST: public NameAST
+{
+public:
+    unsigned tilde_token;
+    NameAST *unqualified_name;
+
+public:
+    DestructorNameAST()
+        : tilde_token(0)
+        , unqualified_name(0)
+    {}
+
+    virtual DestructorNameAST *asDestructorName() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual DestructorNameAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT TemplateIdAST: public NameAST
+{
+public:
+    unsigned template_token;
+    unsigned identifier_token;
+    unsigned less_token;
+    ExpressionListAST *template_argument_list;
+    unsigned greater_token;
+
+public:
+    TemplateIdAST()
+        : template_token(0)
+        , identifier_token(0)
+        , less_token(0)
+        , template_argument_list(0)
+        , greater_token(0)
+    {}
+
+    virtual TemplateIdAST *asTemplateId() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual TemplateIdAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT NamespaceAST: public DeclarationAST
+{
+public:
+    unsigned inline_token;
+    unsigned namespace_token;
+    unsigned identifier_token;
+    SpecifierListAST *attribute_list;
+    DeclarationAST *linkage_body;
+
+public: // annotations
+    Namespace *symbol;
+
+public:
+    NamespaceAST()
+        : inline_token(0)
+        , namespace_token(0)
+        , identifier_token(0)
+        , attribute_list(0)
+        , linkage_body(0)
+        , symbol(0)
+    {}
+
+    virtual NamespaceAST *asNamespace() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual NamespaceAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT NamespaceAliasDefinitionAST: public DeclarationAST
+{
+public:
+    unsigned namespace_token;
+    unsigned namespace_name_token;
+    unsigned equal_token;
+    NameAST *name;
+    unsigned semicolon_token;
+
+public:
+    NamespaceAliasDefinitionAST()
+        : namespace_token(0)
+        , namespace_name_token(0)
+        , equal_token(0)
+        , name(0)
+        , semicolon_token(0)
+    {}
+
+    virtual NamespaceAliasDefinitionAST *asNamespaceAliasDefinition() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual NamespaceAliasDefinitionAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT AliasDeclarationAST: public DeclarationAST
+{
+public:
+    unsigned using_token;
+    NameAST *name;
+    unsigned equal_token;
+    TypeIdAST *typeId;
+    unsigned semicolon_token;
+
+public: // annotations
+    Declaration *symbol;
+
+public:
+    AliasDeclarationAST()
+        : using_token(0)
+        , name(0)
+        , equal_token(0)
+        , typeId(0)
+        , semicolon_token(0)
+        , symbol(0)
+    {}
+
+    virtual AliasDeclarationAST *asAliasDeclaration() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual AliasDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ExpressionListParenAST: public ExpressionAST
+{
+public:
+    unsigned lparen_token;
+    ExpressionListAST *expression_list;
+    unsigned rparen_token;
+
+public:
+    ExpressionListParenAST()
+        : lparen_token(0)
+        , expression_list(0)
+        , rparen_token(0)
+    {}
+
+    virtual ExpressionListParenAST *asExpressionListParen() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ExpressionListParenAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT NewArrayDeclaratorAST: public AST
+{
+public:
+    unsigned lbracket_token;
+    ExpressionAST *expression;
+    unsigned rbracket_token;
+
+public:
+    NewArrayDeclaratorAST()
+        : lbracket_token(0)
+        , expression(0)
+        , rbracket_token(0)
+    {}
+
+    virtual NewArrayDeclaratorAST *asNewArrayDeclarator() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual NewArrayDeclaratorAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT NewExpressionAST: public ExpressionAST
+{
+public:
+    unsigned scope_token;
+    unsigned new_token;
+    ExpressionListParenAST *new_placement;
+
+    unsigned lparen_token;
+    ExpressionAST *type_id;
+    unsigned rparen_token;
+
+    NewTypeIdAST *new_type_id;
+
+    ExpressionAST *new_initializer; // either ExpressionListParenAST or BracedInitializerAST
+
+public:
+    NewExpressionAST()
+        : scope_token(0)
+        , new_token(0)
+        , new_placement(0)
+        , lparen_token(0)
+        , type_id(0)
+        , rparen_token(0)
+        , new_type_id(0)
+        , new_initializer(0)
+    {}
+
+    virtual NewExpressionAST *asNewExpression() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual NewExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT NewTypeIdAST: public AST
+{
+public:
+    SpecifierListAST *type_specifier_list;
+    PtrOperatorListAST *ptr_operator_list;
+    NewArrayDeclaratorListAST *new_array_declarator_list;
+
+public:
+    NewTypeIdAST()
+        : type_specifier_list(0)
+        , ptr_operator_list(0)
+        , new_array_declarator_list(0)
+    {}
+
+    virtual NewTypeIdAST *asNewTypeId() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual NewTypeIdAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT OperatorAST: public AST
+{
+public:
+    unsigned op_token;
+    unsigned open_token;
+    unsigned close_token;
+
+public:
+    OperatorAST()
+        : op_token(0)
+        , open_token(0)
+        , close_token(0)
+    {}
+
+    virtual OperatorAST *asOperator() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual OperatorAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ParameterDeclarationAST: public DeclarationAST
+{
+public:
+    SpecifierListAST *type_specifier_list;
+    DeclaratorAST *declarator;
+    unsigned equal_token;
+    ExpressionAST *expression;
+
+public: // annotations
+    Argument *symbol;
+
+public:
+    ParameterDeclarationAST()
+        : type_specifier_list(0)
+        , declarator(0)
+        , equal_token(0)
+        , expression(0)
+        , symbol(0)
+    {}
+
+    virtual ParameterDeclarationAST *asParameterDeclaration() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ParameterDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ParameterDeclarationClauseAST: public AST
+{
+public:
+    ParameterDeclarationListAST *parameter_declaration_list;
+    unsigned dot_dot_dot_token;
+
+public:
+    ParameterDeclarationClauseAST()
+        : parameter_declaration_list(0)
+        , dot_dot_dot_token(0)
+    {}
+
+    virtual ParameterDeclarationClauseAST *asParameterDeclarationClause() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ParameterDeclarationClauseAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT CallAST: public PostfixAST
+{
+public:
+    ExpressionAST *base_expression;
+    unsigned lparen_token;
+    ExpressionListAST *expression_list;
+    unsigned rparen_token;
+
+public:
+    CallAST()
+        : base_expression(0)
+        , lparen_token(0)
+        , expression_list(0)
+        , rparen_token(0)
+    {}
+
+    virtual CallAST *asCall() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual CallAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ArrayAccessAST: public PostfixAST
+{
+public:
+    ExpressionAST *base_expression;
+    unsigned lbracket_token;
+    ExpressionAST *expression;
+    unsigned rbracket_token;
+
+public:
+    ArrayAccessAST()
+        : base_expression(0)
+        , lbracket_token(0)
+        , expression(0)
+        , rbracket_token(0)
+    {}
+
+    virtual ArrayAccessAST *asArrayAccess() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ArrayAccessAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT PostIncrDecrAST: public PostfixAST
+{
+public:
+    ExpressionAST *base_expression;
+    unsigned incr_decr_token;
+
+public:
+    PostIncrDecrAST()
+        : base_expression(0)
+        , incr_decr_token(0)
+    {}
+
+    virtual PostIncrDecrAST *asPostIncrDecr() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual PostIncrDecrAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT MemberAccessAST: public PostfixAST
+{
+public:
+    ExpressionAST *base_expression;
+    unsigned access_token;
+    unsigned template_token;
+    NameAST *member_name;
+
+public:
+    MemberAccessAST()
+        : base_expression(0)
+        , access_token(0)
+        , template_token(0)
+        , member_name(0)
+    {}
+
+    virtual MemberAccessAST *asMemberAccess() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual MemberAccessAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT TypeidExpressionAST: public ExpressionAST
+{
+public:
+    unsigned typeid_token;
+    unsigned lparen_token;
+    ExpressionAST *expression;
+    unsigned rparen_token;
+
+public:
+    TypeidExpressionAST()
+        : typeid_token(0)
+        , lparen_token(0)
+        , expression(0)
+        , rparen_token(0)
+    {}
+
+    virtual TypeidExpressionAST *asTypeidExpression() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual TypeidExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT TypenameCallExpressionAST: public ExpressionAST
+{
+public:
+    unsigned typename_token;
+    NameAST *name;
+    ExpressionAST *expression; // either ExpressionListParenAST or BracedInitializerAST
+
+public:
+    TypenameCallExpressionAST()
+        : typename_token(0)
+        , name(0)
+        , expression(0)
+    {}
+
+    virtual TypenameCallExpressionAST *asTypenameCallExpression() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual TypenameCallExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT TypeConstructorCallAST: public ExpressionAST
+{
+public:
+    SpecifierListAST *type_specifier_list;
+    ExpressionAST *expression; // either ExpressionListParenAST or BracedInitializerAST
+
+public:
+    TypeConstructorCallAST()
+        : type_specifier_list(0)
+        , expression(0)
+    {}
+
+    virtual TypeConstructorCallAST *asTypeConstructorCall() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual TypeConstructorCallAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT PointerToMemberAST: public PtrOperatorAST
+{
+public:
+    unsigned global_scope_token;
+    NestedNameSpecifierListAST *nested_name_specifier_list;
+    unsigned star_token;
+    SpecifierListAST *cv_qualifier_list;
+    unsigned ref_qualifier_token;
+
+public:
+    PointerToMemberAST()
+        : global_scope_token(0)
+        , nested_name_specifier_list(0)
+        , star_token(0)
+        , cv_qualifier_list(0)
+        , ref_qualifier_token(0)
+    {}
+
+    virtual PointerToMemberAST *asPointerToMember() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual PointerToMemberAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT PointerAST: public PtrOperatorAST
+{
+public:
+    unsigned star_token;
+    SpecifierListAST *cv_qualifier_list;
+
+public:
+    PointerAST()
+        : star_token(0)
+        , cv_qualifier_list(0)
+    {}
+
+    virtual PointerAST *asPointer() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual PointerAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ReferenceAST: public PtrOperatorAST
+{
+public:
+    unsigned reference_token;
+
+public:
+    ReferenceAST()
+        : reference_token(0)
+    {}
+
+    virtual ReferenceAST *asReference() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ReferenceAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT BreakStatementAST: public StatementAST
+{
+public:
+    unsigned break_token;
+    unsigned semicolon_token;
+
+public:
+    BreakStatementAST()
+        : break_token(0)
+        , semicolon_token(0)
+    {}
+
+    virtual BreakStatementAST *asBreakStatement() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual BreakStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ContinueStatementAST: public StatementAST
+{
+public:
+    unsigned continue_token;
+    unsigned semicolon_token;
+
+public:
+    ContinueStatementAST()
+        : continue_token(0)
+        , semicolon_token(0)
+    {}
+
+    virtual ContinueStatementAST *asContinueStatement() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ContinueStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT GotoStatementAST: public StatementAST
+{
+public:
+    unsigned goto_token;
+    unsigned identifier_token;
+    unsigned semicolon_token;
+
+public:
+    GotoStatementAST()
+        : goto_token(0)
+        , identifier_token(0)
+        , semicolon_token(0)
+    {}
+
+    virtual GotoStatementAST *asGotoStatement() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual GotoStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ReturnStatementAST: public StatementAST
+{
+public:
+    unsigned return_token;
+    ExpressionAST *expression;
+    unsigned semicolon_token;
+
+public:
+    ReturnStatementAST()
+        : return_token(0)
+        , expression(0)
+        , semicolon_token(0)
+    {}
+
+    virtual ReturnStatementAST *asReturnStatement() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ReturnStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT SizeofExpressionAST: public ExpressionAST
+{
+public:
+    unsigned sizeof_token;
+    unsigned dot_dot_dot_token;
+    unsigned lparen_token;
+    ExpressionAST *expression;
+    unsigned rparen_token;
+
+public:
+    SizeofExpressionAST()
+        : sizeof_token(0)
+        , dot_dot_dot_token(0)
+        , lparen_token(0)
+        , expression(0)
+        , rparen_token(0)
+    {}
+
+    virtual SizeofExpressionAST *asSizeofExpression() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual SizeofExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT AlignofExpressionAST: public ExpressionAST
+{
+public:
+    unsigned alignof_token;
+    unsigned lparen_token;
+    TypeIdAST *typeId;
+    unsigned rparen_token;
+
+public:
+    AlignofExpressionAST()
+        : alignof_token(0)
+        , lparen_token(0)
+        , typeId(0)
+        , rparen_token(0)
+    {}
+
+    virtual AlignofExpressionAST *asAlignofExpression() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual AlignofExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT PointerLiteralAST: public ExpressionAST
+{
+public:
+    unsigned literal_token;
+
+public:
+    PointerLiteralAST()
+        : literal_token(0)
+    {}
+
+    virtual PointerLiteralAST *asPointerLiteral() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual PointerLiteralAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT NumericLiteralAST: public ExpressionAST
+{
+public:
+    unsigned literal_token;
+
+public:
+    NumericLiteralAST()
+        : literal_token(0)
+    {}
+
+    virtual NumericLiteralAST *asNumericLiteral() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual NumericLiteralAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT BoolLiteralAST: public ExpressionAST
+{
+public:
+    unsigned literal_token;
+
+public:
+    BoolLiteralAST()
+        : literal_token(0)
+    {}
+
+    virtual BoolLiteralAST *asBoolLiteral() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual BoolLiteralAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ThisExpressionAST: public ExpressionAST
+{
+public:
+    unsigned this_token;
+
+public:
+    ThisExpressionAST()
+        : this_token(0)
+    {}
+
+    virtual ThisExpressionAST *asThisExpression() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ThisExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT NestedExpressionAST: public ExpressionAST
+{
+public:
+    unsigned lparen_token;
+    ExpressionAST *expression;
+    unsigned rparen_token;
+
+public:
+    NestedExpressionAST()
+        : lparen_token(0)
+        , expression(0)
+        , rparen_token(0)
+    {}
+
+    virtual NestedExpressionAST *asNestedExpression() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual NestedExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT StaticAssertDeclarationAST: public DeclarationAST
+{
+public:
+    unsigned static_assert_token;
+    unsigned lparen_token;
+    ExpressionAST *expression;
+    unsigned comma_token;
+    ExpressionAST *string_literal;
+    unsigned rparen_token;
+    unsigned semicolon_token;
+
+public:
+    StaticAssertDeclarationAST()
+        : static_assert_token(0)
+        , lparen_token(0)
+        , expression(0)
+        , comma_token(0)
+        , string_literal(0)
+        , rparen_token(0)
+        , semicolon_token(0)
+    {}
+
+    virtual StaticAssertDeclarationAST *asStaticAssertDeclaration() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual StaticAssertDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT StringLiteralAST: public ExpressionAST
+{
+public:
+    unsigned literal_token;
+    StringLiteralAST *next;
+
+public:
+    StringLiteralAST()
+        : literal_token(0)
+        , next(0)
+    {}
+
+    virtual StringLiteralAST *asStringLiteral() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual StringLiteralAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT SwitchStatementAST: public StatementAST
+{
+public:
+    unsigned switch_token;
+    unsigned lparen_token;
+    ExpressionAST *condition;
+    unsigned rparen_token;
+    StatementAST *statement;
+
+public: // annotations
+    Block *symbol;
+
+public:
+    SwitchStatementAST()
+        : switch_token(0)
+        , lparen_token(0)
+        , condition(0)
+        , rparen_token(0)
+        , statement(0)
+        , symbol(0)
+    {}
+
+    virtual SwitchStatementAST *asSwitchStatement() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual SwitchStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT TemplateDeclarationAST: public DeclarationAST
+{
+public:
+    unsigned export_token;
+    unsigned template_token;
+    unsigned less_token;
+    DeclarationListAST *template_parameter_list;
+    unsigned greater_token;
+    DeclarationAST *declaration;
+
+public: // annotations
+    Template *symbol;
+
+public:
+    TemplateDeclarationAST()
+        : export_token(0)
+        , template_token(0)
+        , less_token(0)
+        , template_parameter_list(0)
+        , greater_token(0)
+        , declaration(0)
+        , symbol(0)
+    {}
+
+    virtual TemplateDeclarationAST *asTemplateDeclaration() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual TemplateDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ThrowExpressionAST: public ExpressionAST
+{
+public:
+    unsigned throw_token;
+    ExpressionAST *expression;
+
+public:
+    ThrowExpressionAST()
+        : throw_token(0)
+        , expression(0)
+    {}
+
+    virtual ThrowExpressionAST *asThrowExpression() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ThrowExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT TranslationUnitAST: public AST
+{
+public:
+    DeclarationListAST *declaration_list;
+
+public:
+    TranslationUnitAST()
+        : declaration_list(0)
+    {}
+
+    virtual TranslationUnitAST *asTranslationUnit() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual TranslationUnitAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT TryBlockStatementAST: public StatementAST
+{
+public:
+    unsigned try_token;
+    StatementAST *statement;
+    CatchClauseListAST *catch_clause_list;
+
+public:
+    TryBlockStatementAST()
+        : try_token(0)
+        , statement(0)
+        , catch_clause_list(0)
+    {}
+
+    virtual TryBlockStatementAST *asTryBlockStatement() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual TryBlockStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT CatchClauseAST: public StatementAST
+{
+public:
+    unsigned catch_token;
+    unsigned lparen_token;
+    ExceptionDeclarationAST *exception_declaration;
+    unsigned rparen_token;
+    StatementAST *statement;
+
+public: // annotations
+    Block *symbol;
+
+public:
+    CatchClauseAST()
+        : catch_token(0)
+        , lparen_token(0)
+        , exception_declaration(0)
+        , rparen_token(0)
+        , statement(0)
+        , symbol(0)
+    {}
+
+    virtual CatchClauseAST *asCatchClause() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual CatchClauseAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT TypeIdAST: public ExpressionAST
+{
+public:
+    SpecifierListAST *type_specifier_list;
+    DeclaratorAST *declarator;
+
+public:
+    TypeIdAST()
+        : type_specifier_list(0)
+        , declarator(0)
+    {}
+
+    virtual TypeIdAST *asTypeId() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual TypeIdAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT TypenameTypeParameterAST: public DeclarationAST
+{
+public:
+    unsigned classkey_token;
+    unsigned dot_dot_dot_token;
+    NameAST *name;
+    unsigned equal_token;
+    ExpressionAST *type_id;
+
+public: // annotations
+    TypenameArgument *symbol;
+
+public:
+    TypenameTypeParameterAST()
+        : classkey_token(0)
+        , dot_dot_dot_token(0)
+        , name(0)
+        , equal_token(0)
+        , type_id(0)
+        , symbol(0)
+    {}
+
+    virtual TypenameTypeParameterAST *asTypenameTypeParameter() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual TypenameTypeParameterAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT TemplateTypeParameterAST: public DeclarationAST
+{
+public:
+    unsigned template_token;
+    unsigned less_token;
+    DeclarationListAST *template_parameter_list;
+    unsigned greater_token;
+    unsigned class_token;
+    unsigned dot_dot_dot_token;
+    NameAST *name;
+    unsigned equal_token;
+    ExpressionAST *type_id;
+
+public:
+    TypenameArgument *symbol;
+
+public:
+    TemplateTypeParameterAST()
+        : template_token(0)
+        , less_token(0)
+        , template_parameter_list(0)
+        , greater_token(0)
+        , class_token(0)
+        , dot_dot_dot_token(0)
+        , name(0)
+        , equal_token(0)
+        , type_id(0)
+        , symbol(0)
+    {}
+
+    virtual TemplateTypeParameterAST *asTemplateTypeParameter() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual TemplateTypeParameterAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT UnaryExpressionAST: public ExpressionAST
+{
+public:
+    unsigned unary_op_token;
+    ExpressionAST *expression;
+
+public:
+    UnaryExpressionAST()
+        : unary_op_token(0)
+        , expression(0)
+    {}
+
+    virtual UnaryExpressionAST *asUnaryExpression() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual UnaryExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT UsingAST: public DeclarationAST
+{
+public:
+    unsigned using_token;
+    unsigned typename_token;
+    NameAST *name;
+    unsigned semicolon_token;
+
+public: // annotations
+    UsingDeclaration *symbol;
+
+public:
+    UsingAST()
+        : using_token(0)
+        , typename_token(0)
+        , name(0)
+        , semicolon_token(0)
+        , symbol(0)
+    {}
+
+    virtual UsingAST *asUsing() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual UsingAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT UsingDirectiveAST: public DeclarationAST
+{
+public:
+    unsigned using_token;
+    unsigned namespace_token;
+    NameAST *name;
+    unsigned semicolon_token;
+
+public:
+    UsingNamespaceDirective *symbol;
+
+public:
+    UsingDirectiveAST()
+        : using_token(0)
+        , namespace_token(0)
+        , name(0)
+        , semicolon_token(0)
+        , symbol(0)
+    {}
+
+    virtual UsingDirectiveAST *asUsingDirective() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual UsingDirectiveAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT WhileStatementAST: public StatementAST
+{
+public:
+    unsigned while_token;
+    unsigned lparen_token;
+    ExpressionAST *condition;
+    unsigned rparen_token;
+    StatementAST *statement;
+
+public: // annotations
+    Block *symbol;
+
+public:
+    WhileStatementAST()
+        : while_token(0)
+        , lparen_token(0)
+        , condition(0)
+        , rparen_token(0)
+        , statement(0)
+        , symbol(0)
+    {}
+
+    virtual WhileStatementAST *asWhileStatement() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual WhileStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ObjCClassForwardDeclarationAST: public DeclarationAST
+{
+public:
+    SpecifierListAST *attribute_list;
+    unsigned class_token;
+    NameListAST *identifier_list;
+    unsigned semicolon_token;
+
+public: // annotations
+    List<ObjCForwardClassDeclaration *> *symbols;
+
+public:
+    ObjCClassForwardDeclarationAST()
+        : attribute_list(0)
+        , class_token(0)
+        , identifier_list(0)
+        , semicolon_token(0)
+        , symbols(0)
+    {}
+
+    virtual ObjCClassForwardDeclarationAST *asObjCClassForwardDeclaration() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCClassForwardDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ObjCClassDeclarationAST: public DeclarationAST
+{
+public:
+    SpecifierListAST *attribute_list;
+    unsigned interface_token;
+    unsigned implementation_token;
+    NameAST *class_name;
+    unsigned lparen_token;
+    NameAST *category_name;
+    unsigned rparen_token;
+    unsigned colon_token;
+    NameAST *superclass;
+    ObjCProtocolRefsAST *protocol_refs;
+    ObjCInstanceVariablesDeclarationAST *inst_vars_decl;
+    DeclarationListAST *member_declaration_list;
+    unsigned end_token;
+
+public: // annotations
+    ObjCClass *symbol;
+
+public:
+    ObjCClassDeclarationAST()
+        : attribute_list(0)
+        , interface_token(0)
+        , implementation_token(0)
+        , class_name(0)
+        , lparen_token(0)
+        , category_name(0)
+        , rparen_token(0)
+        , colon_token(0)
+        , superclass(0)
+        , protocol_refs(0)
+        , inst_vars_decl(0)
+        , member_declaration_list(0)
+        , end_token(0)
+        , symbol(0)
+    {}
+
+    virtual ObjCClassDeclarationAST *asObjCClassDeclaration() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCClassDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ObjCProtocolForwardDeclarationAST: public DeclarationAST
+{
+public:
+    SpecifierListAST *attribute_list;
+    unsigned protocol_token;
+    NameListAST *identifier_list;
+    unsigned semicolon_token;
+
+public: // annotations
+    List<ObjCForwardProtocolDeclaration *> *symbols;
+
+public:
+    ObjCProtocolForwardDeclarationAST()
+        : attribute_list(0)
+        , protocol_token(0)
+        , identifier_list(0)
+        , semicolon_token(0)
+        , symbols(0)
+    {}
+
+    virtual ObjCProtocolForwardDeclarationAST *asObjCProtocolForwardDeclaration() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCProtocolForwardDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ObjCProtocolDeclarationAST: public DeclarationAST
+{
+public:
+    SpecifierListAST *attribute_list;
+    unsigned protocol_token;
+    NameAST *name;
+    ObjCProtocolRefsAST *protocol_refs;
+    DeclarationListAST *member_declaration_list;
+    unsigned end_token;
+
+public: // annotations
+    ObjCProtocol *symbol;
+
+public:
+    ObjCProtocolDeclarationAST()
+        : attribute_list(0)
+        , protocol_token(0)
+        , name(0)
+        , protocol_refs(0)
+        , member_declaration_list(0)
+        , end_token(0)
+        , symbol(0)
+    {}
+
+    virtual ObjCProtocolDeclarationAST *asObjCProtocolDeclaration() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCProtocolDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ObjCProtocolRefsAST: public AST
+{
+public:
+    unsigned less_token;
+    NameListAST *identifier_list;
+    unsigned greater_token;
+
+public:
+    ObjCProtocolRefsAST()
+        : less_token(0)
+        , identifier_list(0)
+        , greater_token(0)
+    {}
+
+    virtual ObjCProtocolRefsAST *asObjCProtocolRefs() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCProtocolRefsAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ObjCMessageArgumentAST: public AST
+{
+public:
+    ExpressionAST *parameter_value_expression;
+
+public:
+    ObjCMessageArgumentAST()
+        : parameter_value_expression(0)
+    {}
+
+    virtual ObjCMessageArgumentAST *asObjCMessageArgument() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCMessageArgumentAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ObjCMessageExpressionAST: public ExpressionAST
+{
+public:
+    unsigned lbracket_token;
+    ExpressionAST *receiver_expression;
+    ObjCSelectorAST *selector;
+    ObjCMessageArgumentListAST *argument_list;
+    unsigned rbracket_token;
+
+public:
+    ObjCMessageExpressionAST()
+        : lbracket_token(0)
+        , receiver_expression(0)
+        , selector(0)
+        , argument_list(0)
+        , rbracket_token(0)
+    {}
+
+    virtual ObjCMessageExpressionAST *asObjCMessageExpression() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCMessageExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ObjCProtocolExpressionAST: public ExpressionAST
+{
+public:
+    unsigned protocol_token;
+    unsigned lparen_token;
+    unsigned identifier_token;
+    unsigned rparen_token;
+
+public:
+    ObjCProtocolExpressionAST()
+        : protocol_token(0)
+        , lparen_token(0)
+        , identifier_token(0)
+        , rparen_token(0)
+    {}
+
+    virtual ObjCProtocolExpressionAST *asObjCProtocolExpression() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCProtocolExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ObjCTypeNameAST: public AST
+{
+public:
+    unsigned lparen_token;
+    unsigned type_qualifier_token;
+    ExpressionAST *type_id;
+    unsigned rparen_token;
+
+public:
+    ObjCTypeNameAST()
+        : lparen_token(0)
+        , type_qualifier_token(0)
+        , type_id(0)
+        , rparen_token(0)
+    {}
+
+    virtual ObjCTypeNameAST *asObjCTypeName() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCTypeNameAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ObjCEncodeExpressionAST: public ExpressionAST
+{
+public:
+    unsigned encode_token;
+    ObjCTypeNameAST *type_name;
+
+public:
+    ObjCEncodeExpressionAST()
+        : encode_token(0)
+        , type_name(0)
+    {}
+
+    virtual ObjCEncodeExpressionAST *asObjCEncodeExpression() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCEncodeExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ObjCSelectorExpressionAST: public ExpressionAST
+{
+public:
+    unsigned selector_token;
+    unsigned lparen_token;
+    ObjCSelectorAST *selector;
+    unsigned rparen_token;
+
+public:
+    ObjCSelectorExpressionAST()
+        : selector_token(0)
+        , lparen_token(0)
+        , selector(0)
+        , rparen_token(0)
+    {}
+
+    virtual ObjCSelectorExpressionAST *asObjCSelectorExpression() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCSelectorExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ObjCInstanceVariablesDeclarationAST: public AST
+{
+public:
+    unsigned lbrace_token;
+    DeclarationListAST *instance_variable_list;
+    unsigned rbrace_token;
+
+public:
+    ObjCInstanceVariablesDeclarationAST()
+        : lbrace_token(0)
+        , instance_variable_list(0)
+        , rbrace_token(0)
+    {}
+
+    virtual ObjCInstanceVariablesDeclarationAST *asObjCInstanceVariablesDeclaration() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCInstanceVariablesDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ObjCVisibilityDeclarationAST: public DeclarationAST
+{
+public:
+    unsigned visibility_token;
+
+public:
+    ObjCVisibilityDeclarationAST()
+        : visibility_token(0)
+    {}
+
+    virtual ObjCVisibilityDeclarationAST *asObjCVisibilityDeclaration() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCVisibilityDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ObjCPropertyAttributeAST: public AST
+{
+public:
+    unsigned attribute_identifier_token;
+    unsigned equals_token;
+    ObjCSelectorAST *method_selector;
+
+public:
+    ObjCPropertyAttributeAST()
+        : attribute_identifier_token(0)
+        , equals_token(0)
+        , method_selector(0)
+    {}
+
+    virtual ObjCPropertyAttributeAST *asObjCPropertyAttribute() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCPropertyAttributeAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ObjCPropertyDeclarationAST: public DeclarationAST
+{
+public:
+    SpecifierListAST *attribute_list;
+    unsigned property_token;
+    unsigned lparen_token;
+    ObjCPropertyAttributeListAST *property_attribute_list;
+    unsigned rparen_token;
+    DeclarationAST *simple_declaration;
+
+public: // annotations
+    List<ObjCPropertyDeclaration *> *symbols;
+
+public:
+    ObjCPropertyDeclarationAST()
+        : attribute_list(0)
+        , property_token(0)
+        , lparen_token(0)
+        , property_attribute_list(0)
+        , rparen_token(0)
+        , simple_declaration(0)
+        , symbols(0)
+    {}
+
+    virtual ObjCPropertyDeclarationAST *asObjCPropertyDeclaration() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCPropertyDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ObjCMessageArgumentDeclarationAST: public AST
+{
+public:
+    ObjCTypeNameAST* type_name;
+    SpecifierListAST *attribute_list;
+    NameAST *param_name;
+
+public: // annotations
+    Argument *argument;
+
+public:
+    ObjCMessageArgumentDeclarationAST()
+        : type_name(0)
+        , attribute_list(0)
+        , param_name(0)
+        , argument(0)
+    {}
+
+    virtual ObjCMessageArgumentDeclarationAST *asObjCMessageArgumentDeclaration() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCMessageArgumentDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ObjCMethodPrototypeAST: public AST
+{
+public:
+    unsigned method_type_token;
+    ObjCTypeNameAST *type_name;
+    ObjCSelectorAST *selector;
+    ObjCMessageArgumentDeclarationListAST *argument_list;
+    unsigned dot_dot_dot_token;
+    SpecifierListAST *attribute_list;
+
+public: // annotations
+    ObjCMethod *symbol;
+
+public:
+    ObjCMethodPrototypeAST()
+        : method_type_token(0)
+        , type_name(0)
+        , selector(0)
+        , argument_list(0)
+        , dot_dot_dot_token(0)
+        , attribute_list(0)
+        , symbol(0)
+    {}
+
+    virtual ObjCMethodPrototypeAST *asObjCMethodPrototype() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCMethodPrototypeAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ObjCMethodDeclarationAST: public DeclarationAST
+{
+public:
+    ObjCMethodPrototypeAST *method_prototype;
+    StatementAST *function_body;
+    unsigned semicolon_token;
+
+public:
+    ObjCMethodDeclarationAST()
+        : method_prototype(0)
+        , function_body(0)
+        , semicolon_token(0)
+    {}
+
+    virtual ObjCMethodDeclarationAST *asObjCMethodDeclaration() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCMethodDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ObjCSynthesizedPropertyAST: public AST
+{
+public:
+    unsigned property_identifier_token;
+    unsigned equals_token;
+    unsigned alias_identifier_token;
+
+public:
+    ObjCSynthesizedPropertyAST()
+        : property_identifier_token(0)
+        , equals_token(0)
+        , alias_identifier_token(0)
+    {}
+
+    virtual ObjCSynthesizedPropertyAST *asObjCSynthesizedProperty() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCSynthesizedPropertyAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ObjCSynthesizedPropertiesDeclarationAST: public DeclarationAST
+{
+public:
+    unsigned synthesized_token;
+    ObjCSynthesizedPropertyListAST *property_identifier_list;
+    unsigned semicolon_token;
+
+public:
+    ObjCSynthesizedPropertiesDeclarationAST()
+        : synthesized_token(0)
+        , property_identifier_list(0)
+        , semicolon_token(0)
+    {}
+
+    virtual ObjCSynthesizedPropertiesDeclarationAST *asObjCSynthesizedPropertiesDeclaration() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCSynthesizedPropertiesDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ObjCDynamicPropertiesDeclarationAST: public DeclarationAST
+{
+public:
+    unsigned dynamic_token;
+    NameListAST *property_identifier_list;
+    unsigned semicolon_token;
+
+public:
+    ObjCDynamicPropertiesDeclarationAST()
+        : dynamic_token(0)
+        , property_identifier_list(0)
+        , semicolon_token(0)
+    {}
+
+    virtual ObjCDynamicPropertiesDeclarationAST *asObjCDynamicPropertiesDeclaration() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCDynamicPropertiesDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ObjCFastEnumerationAST: public StatementAST
+{
+public:
+    unsigned for_token;
+    unsigned lparen_token;
+
+    // declaration
+    SpecifierListAST *type_specifier_list;
+    DeclaratorAST *declarator;
+    // or an expression
+    ExpressionAST *initializer;
+
+    unsigned in_token;
+    ExpressionAST *fast_enumeratable_expression;
+    unsigned rparen_token;
+    StatementAST *statement;
+
+public: // annotations
+    Block *symbol;
+
+public:
+    ObjCFastEnumerationAST()
+        : for_token(0)
+        , lparen_token(0)
+        , type_specifier_list(0)
+        , declarator(0)
+        , initializer(0)
+        , in_token(0)
+        , fast_enumeratable_expression(0)
+        , rparen_token(0)
+        , statement(0)
+        , symbol(0)
+    {}
+
+    virtual ObjCFastEnumerationAST *asObjCFastEnumeration() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCFastEnumerationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT ObjCSynchronizedStatementAST: public StatementAST
+{
+public:
+    unsigned synchronized_token;
+    unsigned lparen_token;
+    ExpressionAST *synchronized_object;
+    unsigned rparen_token;
+    StatementAST *statement;
+
+public:
+    ObjCSynchronizedStatementAST()
+        : synchronized_token(0)
+        , lparen_token(0)
+        , synchronized_object(0)
+        , rparen_token(0)
+        , statement(0)
+    {}
+
+    virtual ObjCSynchronizedStatementAST *asObjCSynchronizedStatement() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCSynchronizedStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+
+class LambdaExpressionAST: public ExpressionAST
+{
+public:
+    LambdaIntroducerAST *lambda_introducer;
+    LambdaDeclaratorAST *lambda_declarator;
+    StatementAST *statement;
+
+public:
+    LambdaExpressionAST()
+        : lambda_introducer(0)
+        , lambda_declarator(0)
+        , statement(0)
+    {}
+
+    virtual LambdaExpressionAST *asLambdaExpression() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+    virtual LambdaExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class LambdaIntroducerAST: public AST
+{
+public:
+    unsigned lbracket_token;
+    LambdaCaptureAST *lambda_capture;
+    unsigned rbracket_token;
+
+public:
+    LambdaIntroducerAST()
+        : lbracket_token(0)
+        , lambda_capture(0)
+        , rbracket_token(0)
+    {}
+
+    virtual LambdaIntroducerAST *asLambdaIntroducer() { return this; }
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual LambdaIntroducerAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class LambdaCaptureAST: public AST
+{
+public:
+    unsigned default_capture_token;
+    CaptureListAST *capture_list;
+
+public:
+    LambdaCaptureAST()
+        : default_capture_token(0)
+        , capture_list(0)
+    {}
+
+    virtual LambdaCaptureAST *asLambdaCapture() { return this; }
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual LambdaCaptureAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CaptureAST: public AST
+{
+public:
+    unsigned amper_token;
+    NameAST *identifier;
+
+public:
+    CaptureAST()
+        : amper_token(0)
+        , identifier(0)
+    {}
+
+    virtual CaptureAST *asCapture() { return this; }
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual CaptureAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class LambdaDeclaratorAST: public AST
+{
+public:
+    unsigned lparen_token;
+    ParameterDeclarationClauseAST *parameter_declaration_clause;
+    unsigned rparen_token;
+    SpecifierListAST *attributes;
+    unsigned mutable_token;
+    ExceptionSpecificationAST *exception_specification;
+    TrailingReturnTypeAST *trailing_return_type;
+
+public: // annotations
+    Function *symbol;
+
+public:
+    LambdaDeclaratorAST()
+        : lparen_token(0)
+        , parameter_declaration_clause(0)
+        , rparen_token(0)
+        , attributes(0)
+        , mutable_token(0)
+        , exception_specification(0)
+        , trailing_return_type(0)
+        , symbol(0)
+    {}
+
+    virtual LambdaDeclaratorAST *asLambdaDeclarator() { return this; }
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual LambdaDeclaratorAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class TrailingReturnTypeAST: public AST
+{
+public:
+    unsigned arrow_token;
+    SpecifierListAST *attributes;
+    SpecifierListAST *type_specifier_list;
+    DeclaratorAST *declarator;
+
+public:
+    TrailingReturnTypeAST()
+        : arrow_token(0)
+        , attributes(0)
+        , type_specifier_list(0)
+        , declarator(0)
+    {}
+
+    virtual TrailingReturnTypeAST *asTrailingReturnType() { return this; }
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual TrailingReturnTypeAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class BracedInitializerAST: public ExpressionAST
+{
+public:
+    unsigned lbrace_token;
+    ExpressionListAST *expression_list;
+    unsigned comma_token;
+    unsigned rbrace_token;
+
+public:
+    BracedInitializerAST()
+        : lbrace_token(0)
+        , expression_list(0)
+        , comma_token(0)
+        , rbrace_token(0)
+    {}
+
+    virtual BracedInitializerAST *asBracedInitializer() { return this; }
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual BracedInitializerAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class DesignatorAST: public AST
+{
+public:
+    DesignatorAST()
+    {}
+
+    virtual DesignatorAST *asDesignator() { return this; }
+    virtual DesignatorAST *clone(MemoryPool *pool) const = 0;
+};
+
+class DotDesignatorAST: public DesignatorAST
+{
+public:
+    unsigned dot_token;
+    unsigned identifier_token;
+public:
+    DotDesignatorAST()
+        : dot_token(0)
+        , identifier_token(0)
+    {}
+
+    virtual DotDesignatorAST *asDotDesignator() { return this; }
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual DotDesignatorAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class BracketDesignatorAST: public DesignatorAST
+{
+public:
+    unsigned lbracket_token;
+    ExpressionAST *expression;
+    unsigned rbracket_token;
+public:
+    BracketDesignatorAST()
+        : lbracket_token(0)
+        , expression(0)
+        , rbracket_token(0)
+    {}
+
+    virtual BracketDesignatorAST *asBracketDesignator() { return this; }
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual BracketDesignatorAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class DesignatedInitializerAST: public ExpressionAST
+{
+public:
+    DesignatorListAST *designator_list;
+    unsigned equal_token;
+    ExpressionAST *initializer;
+
+public:
+    DesignatedInitializerAST()
+        : designator_list(0)
+        , equal_token(0)
+        , initializer(0)
+    {}
+
+    virtual DesignatedInitializerAST *asDesignatedInitializer() { return this; }
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual DesignatedInitializerAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+} // namespace CPlusPlus
+
+#endif // CPLUSPLUS_AST_H

+ 1806 - 0
Source/ToolCore/JSBind/cplusplus/ASTClone.cpp

@@ -0,0 +1,1806 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is automatically generated by "cplusplus-update-frontend".
+// Changes will be lost.
+//
+
+#include "AST.h"
+#include "MemoryPool.h"
+
+using namespace CPlusPlus;
+
+ObjCSelectorArgumentAST *ObjCSelectorArgumentAST::clone(MemoryPool *pool) const
+{
+    ObjCSelectorArgumentAST *ast = new (pool) ObjCSelectorArgumentAST;
+    ast->name_token = name_token;
+    ast->colon_token = colon_token;
+    return ast;
+}
+
+ObjCSelectorAST *ObjCSelectorAST::clone(MemoryPool *pool) const
+{
+    ObjCSelectorAST *ast = new (pool) ObjCSelectorAST;
+    for (ObjCSelectorArgumentListAST *iter = selector_argument_list, **ast_iter = &ast->selector_argument_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) ObjCSelectorArgumentListAST((iter->value) ? iter->value->clone(pool) : 0);
+    return ast;
+}
+
+SimpleSpecifierAST *SimpleSpecifierAST::clone(MemoryPool *pool) const
+{
+    SimpleSpecifierAST *ast = new (pool) SimpleSpecifierAST;
+    ast->specifier_token = specifier_token;
+    return ast;
+}
+
+AlignmentSpecifierAST *AlignmentSpecifierAST::clone(MemoryPool *pool) const
+{
+    AlignmentSpecifierAST *ast = new (pool) AlignmentSpecifierAST;
+    ast->align_token = align_token;
+    ast->lparen_token = lparen_token;
+    if (typeIdExprOrAlignmentExpr)
+        ast->typeIdExprOrAlignmentExpr = typeIdExprOrAlignmentExpr->clone(pool);
+    ast->ellipses_token = ellipses_token;
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
+GnuAttributeSpecifierAST *GnuAttributeSpecifierAST::clone(MemoryPool *pool) const
+{
+    GnuAttributeSpecifierAST *ast = new (pool) GnuAttributeSpecifierAST;
+    ast->attribute_token = attribute_token;
+    ast->first_lparen_token = first_lparen_token;
+    ast->second_lparen_token = second_lparen_token;
+    for (GnuAttributeListAST *iter = attribute_list, **ast_iter = &ast->attribute_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) GnuAttributeListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->first_rparen_token = first_rparen_token;
+    ast->second_rparen_token = second_rparen_token;
+    return ast;
+}
+
+GnuAttributeAST *GnuAttributeAST::clone(MemoryPool *pool) const
+{
+    GnuAttributeAST *ast = new (pool) GnuAttributeAST;
+    ast->identifier_token = identifier_token;
+    ast->lparen_token = lparen_token;
+    ast->tag_token = tag_token;
+    for (ExpressionListAST *iter = expression_list, **ast_iter = &ast->expression_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) ExpressionListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
+TypeofSpecifierAST *TypeofSpecifierAST::clone(MemoryPool *pool) const
+{
+    TypeofSpecifierAST *ast = new (pool) TypeofSpecifierAST;
+    ast->typeof_token = typeof_token;
+    ast->lparen_token = lparen_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
+DecltypeSpecifierAST *DecltypeSpecifierAST::clone(MemoryPool *pool) const
+{
+    DecltypeSpecifierAST *ast = new (pool) DecltypeSpecifierAST;
+    ast->decltype_token = decltype_token;
+    ast->lparen_token = lparen_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
+DeclaratorAST *DeclaratorAST::clone(MemoryPool *pool) const
+{
+    DeclaratorAST *ast = new (pool) DeclaratorAST;
+    for (SpecifierListAST *iter = attribute_list, **ast_iter = &ast->attribute_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    for (PtrOperatorListAST *iter = ptr_operator_list, **ast_iter = &ast->ptr_operator_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) PtrOperatorListAST((iter->value) ? iter->value->clone(pool) : 0);
+    if (core_declarator)
+        ast->core_declarator = core_declarator->clone(pool);
+    for (PostfixDeclaratorListAST *iter = postfix_declarator_list, **ast_iter = &ast->postfix_declarator_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) PostfixDeclaratorListAST((iter->value) ? iter->value->clone(pool) : 0);
+    for (SpecifierListAST *iter = post_attribute_list, **ast_iter = &ast->post_attribute_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->equal_token = equal_token;
+    if (initializer)
+        ast->initializer = initializer->clone(pool);
+    return ast;
+}
+
+SimpleDeclarationAST *SimpleDeclarationAST::clone(MemoryPool *pool) const
+{
+    SimpleDeclarationAST *ast = new (pool) SimpleDeclarationAST;
+    ast->qt_invokable_token = qt_invokable_token;
+    for (SpecifierListAST *iter = decl_specifier_list, **ast_iter = &ast->decl_specifier_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    for (DeclaratorListAST *iter = declarator_list, **ast_iter = &ast->declarator_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) DeclaratorListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->semicolon_token = semicolon_token;
+    return ast;
+}
+
+EmptyDeclarationAST *EmptyDeclarationAST::clone(MemoryPool *pool) const
+{
+    EmptyDeclarationAST *ast = new (pool) EmptyDeclarationAST;
+    ast->semicolon_token = semicolon_token;
+    return ast;
+}
+
+AccessDeclarationAST *AccessDeclarationAST::clone(MemoryPool *pool) const
+{
+    AccessDeclarationAST *ast = new (pool) AccessDeclarationAST;
+    ast->access_specifier_token = access_specifier_token;
+    ast->slots_token = slots_token;
+    ast->colon_token = colon_token;
+    return ast;
+}
+
+QtObjectTagAST *QtObjectTagAST::clone(MemoryPool *pool) const
+{
+    QtObjectTagAST *ast = new (pool) QtObjectTagAST;
+    ast->q_object_token = q_object_token;
+    return ast;
+}
+
+QtPrivateSlotAST *QtPrivateSlotAST::clone(MemoryPool *pool) const
+{
+    QtPrivateSlotAST *ast = new (pool) QtPrivateSlotAST;
+    ast->q_private_slot_token = q_private_slot_token;
+    ast->lparen_token = lparen_token;
+    ast->dptr_token = dptr_token;
+    ast->dptr_lparen_token = dptr_lparen_token;
+    ast->dptr_rparen_token = dptr_rparen_token;
+    ast->comma_token = comma_token;
+    for (SpecifierListAST *iter = type_specifier_list, **ast_iter = &ast->type_specifier_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    if (declarator)
+        ast->declarator = declarator->clone(pool);
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
+QtPropertyDeclarationItemAST *QtPropertyDeclarationItemAST::clone(MemoryPool *pool) const
+{
+    QtPropertyDeclarationItemAST *ast = new (pool) QtPropertyDeclarationItemAST;
+    ast->item_name_token = item_name_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    return ast;
+}
+
+QtPropertyDeclarationAST *QtPropertyDeclarationAST::clone(MemoryPool *pool) const
+{
+    QtPropertyDeclarationAST *ast = new (pool) QtPropertyDeclarationAST;
+    ast->property_specifier_token = property_specifier_token;
+    ast->lparen_token = lparen_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    ast->comma_token = comma_token;
+    if (type_id)
+        ast->type_id = type_id->clone(pool);
+    if (property_name)
+        ast->property_name = property_name->clone(pool);
+    for (QtPropertyDeclarationItemListAST *iter = property_declaration_item_list, **ast_iter = &ast->property_declaration_item_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) QtPropertyDeclarationItemListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
+QtEnumDeclarationAST *QtEnumDeclarationAST::clone(MemoryPool *pool) const
+{
+    QtEnumDeclarationAST *ast = new (pool) QtEnumDeclarationAST;
+    ast->enum_specifier_token = enum_specifier_token;
+    ast->lparen_token = lparen_token;
+    for (NameListAST *iter = enumerator_list, **ast_iter = &ast->enumerator_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) NameListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
+QtFlagsDeclarationAST *QtFlagsDeclarationAST::clone(MemoryPool *pool) const
+{
+    QtFlagsDeclarationAST *ast = new (pool) QtFlagsDeclarationAST;
+    ast->flags_specifier_token = flags_specifier_token;
+    ast->lparen_token = lparen_token;
+    for (NameListAST *iter = flag_enums_list, **ast_iter = &ast->flag_enums_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) NameListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
+QtInterfaceNameAST *QtInterfaceNameAST::clone(MemoryPool *pool) const
+{
+    QtInterfaceNameAST *ast = new (pool) QtInterfaceNameAST;
+    if (interface_name)
+        ast->interface_name = interface_name->clone(pool);
+    for (NameListAST *iter = constraint_list, **ast_iter = &ast->constraint_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) NameListAST((iter->value) ? iter->value->clone(pool) : 0);
+    return ast;
+}
+
+QtInterfacesDeclarationAST *QtInterfacesDeclarationAST::clone(MemoryPool *pool) const
+{
+    QtInterfacesDeclarationAST *ast = new (pool) QtInterfacesDeclarationAST;
+    ast->interfaces_token = interfaces_token;
+    ast->lparen_token = lparen_token;
+    for (QtInterfaceNameListAST *iter = interface_name_list, **ast_iter = &ast->interface_name_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) QtInterfaceNameListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
+AsmDefinitionAST *AsmDefinitionAST::clone(MemoryPool *pool) const
+{
+    AsmDefinitionAST *ast = new (pool) AsmDefinitionAST;
+    ast->asm_token = asm_token;
+    ast->volatile_token = volatile_token;
+    ast->lparen_token = lparen_token;
+    ast->rparen_token = rparen_token;
+    ast->semicolon_token = semicolon_token;
+    return ast;
+}
+
+BaseSpecifierAST *BaseSpecifierAST::clone(MemoryPool *pool) const
+{
+    BaseSpecifierAST *ast = new (pool) BaseSpecifierAST;
+    ast->virtual_token = virtual_token;
+    ast->access_specifier_token = access_specifier_token;
+    if (name)
+        ast->name = name->clone(pool);
+    return ast;
+}
+
+IdExpressionAST *IdExpressionAST::clone(MemoryPool *pool) const
+{
+    IdExpressionAST *ast = new (pool) IdExpressionAST;
+    if (name)
+        ast->name = name->clone(pool);
+    return ast;
+}
+
+CompoundExpressionAST *CompoundExpressionAST::clone(MemoryPool *pool) const
+{
+    CompoundExpressionAST *ast = new (pool) CompoundExpressionAST;
+    ast->lparen_token = lparen_token;
+    if (statement)
+        ast->statement = statement->clone(pool);
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
+CompoundLiteralAST *CompoundLiteralAST::clone(MemoryPool *pool) const
+{
+    CompoundLiteralAST *ast = new (pool) CompoundLiteralAST;
+    ast->lparen_token = lparen_token;
+    if (type_id)
+        ast->type_id = type_id->clone(pool);
+    ast->rparen_token = rparen_token;
+    if (initializer)
+        ast->initializer = initializer->clone(pool);
+    return ast;
+}
+
+QtMethodAST *QtMethodAST::clone(MemoryPool *pool) const
+{
+    QtMethodAST *ast = new (pool) QtMethodAST;
+    ast->method_token = method_token;
+    ast->lparen_token = lparen_token;
+    if (declarator)
+        ast->declarator = declarator->clone(pool);
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
+QtMemberDeclarationAST *QtMemberDeclarationAST::clone(MemoryPool *pool) const
+{
+    QtMemberDeclarationAST *ast = new (pool) QtMemberDeclarationAST;
+    ast->q_token = q_token;
+    ast->lparen_token = lparen_token;
+    if (type_id)
+        ast->type_id = type_id->clone(pool);
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
+BinaryExpressionAST *BinaryExpressionAST::clone(MemoryPool *pool) const
+{
+    BinaryExpressionAST *ast = new (pool) BinaryExpressionAST;
+    if (left_expression)
+        ast->left_expression = left_expression->clone(pool);
+    ast->binary_op_token = binary_op_token;
+    if (right_expression)
+        ast->right_expression = right_expression->clone(pool);
+    return ast;
+}
+
+CastExpressionAST *CastExpressionAST::clone(MemoryPool *pool) const
+{
+    CastExpressionAST *ast = new (pool) CastExpressionAST;
+    ast->lparen_token = lparen_token;
+    if (type_id)
+        ast->type_id = type_id->clone(pool);
+    ast->rparen_token = rparen_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    return ast;
+}
+
+ClassSpecifierAST *ClassSpecifierAST::clone(MemoryPool *pool) const
+{
+    ClassSpecifierAST *ast = new (pool) ClassSpecifierAST;
+    ast->classkey_token = classkey_token;
+    for (SpecifierListAST *iter = attribute_list, **ast_iter = &ast->attribute_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    if (name)
+        ast->name = name->clone(pool);
+    ast->final_token = final_token;
+    ast->colon_token = colon_token;
+    for (BaseSpecifierListAST *iter = base_clause_list, **ast_iter = &ast->base_clause_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) BaseSpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->dot_dot_dot_token = dot_dot_dot_token;
+    ast->lbrace_token = lbrace_token;
+    for (DeclarationListAST *iter = member_specifier_list, **ast_iter = &ast->member_specifier_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) DeclarationListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->rbrace_token = rbrace_token;
+    return ast;
+}
+
+CaseStatementAST *CaseStatementAST::clone(MemoryPool *pool) const
+{
+    CaseStatementAST *ast = new (pool) CaseStatementAST;
+    ast->case_token = case_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    ast->colon_token = colon_token;
+    if (statement)
+        ast->statement = statement->clone(pool);
+    return ast;
+}
+
+CompoundStatementAST *CompoundStatementAST::clone(MemoryPool *pool) const
+{
+    CompoundStatementAST *ast = new (pool) CompoundStatementAST;
+    ast->lbrace_token = lbrace_token;
+    for (StatementListAST *iter = statement_list, **ast_iter = &ast->statement_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) StatementListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->rbrace_token = rbrace_token;
+    return ast;
+}
+
+ConditionAST *ConditionAST::clone(MemoryPool *pool) const
+{
+    ConditionAST *ast = new (pool) ConditionAST;
+    for (SpecifierListAST *iter = type_specifier_list, **ast_iter = &ast->type_specifier_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    if (declarator)
+        ast->declarator = declarator->clone(pool);
+    return ast;
+}
+
+ConditionalExpressionAST *ConditionalExpressionAST::clone(MemoryPool *pool) const
+{
+    ConditionalExpressionAST *ast = new (pool) ConditionalExpressionAST;
+    if (condition)
+        ast->condition = condition->clone(pool);
+    ast->question_token = question_token;
+    if (left_expression)
+        ast->left_expression = left_expression->clone(pool);
+    ast->colon_token = colon_token;
+    if (right_expression)
+        ast->right_expression = right_expression->clone(pool);
+    return ast;
+}
+
+CppCastExpressionAST *CppCastExpressionAST::clone(MemoryPool *pool) const
+{
+    CppCastExpressionAST *ast = new (pool) CppCastExpressionAST;
+    ast->cast_token = cast_token;
+    ast->less_token = less_token;
+    if (type_id)
+        ast->type_id = type_id->clone(pool);
+    ast->greater_token = greater_token;
+    ast->lparen_token = lparen_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
+CtorInitializerAST *CtorInitializerAST::clone(MemoryPool *pool) const
+{
+    CtorInitializerAST *ast = new (pool) CtorInitializerAST;
+    ast->colon_token = colon_token;
+    for (MemInitializerListAST *iter = member_initializer_list, **ast_iter = &ast->member_initializer_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) MemInitializerListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->dot_dot_dot_token = dot_dot_dot_token;
+    return ast;
+}
+
+DeclarationStatementAST *DeclarationStatementAST::clone(MemoryPool *pool) const
+{
+    DeclarationStatementAST *ast = new (pool) DeclarationStatementAST;
+    if (declaration)
+        ast->declaration = declaration->clone(pool);
+    return ast;
+}
+
+DeclaratorIdAST *DeclaratorIdAST::clone(MemoryPool *pool) const
+{
+    DeclaratorIdAST *ast = new (pool) DeclaratorIdAST;
+    ast->dot_dot_dot_token = dot_dot_dot_token;
+    if (name)
+        ast->name = name->clone(pool);
+    return ast;
+}
+
+NestedDeclaratorAST *NestedDeclaratorAST::clone(MemoryPool *pool) const
+{
+    NestedDeclaratorAST *ast = new (pool) NestedDeclaratorAST;
+    ast->lparen_token = lparen_token;
+    if (declarator)
+        ast->declarator = declarator->clone(pool);
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
+FunctionDeclaratorAST *FunctionDeclaratorAST::clone(MemoryPool *pool) const
+{
+    FunctionDeclaratorAST *ast = new (pool) FunctionDeclaratorAST;
+    ast->lparen_token = lparen_token;
+    if (parameter_declaration_clause)
+        ast->parameter_declaration_clause = parameter_declaration_clause->clone(pool);
+    ast->rparen_token = rparen_token;
+    for (SpecifierListAST *iter = cv_qualifier_list, **ast_iter = &ast->cv_qualifier_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->ref_qualifier_token = ref_qualifier_token;
+    if (exception_specification)
+        ast->exception_specification = exception_specification->clone(pool);
+    if (trailing_return_type)
+        ast->trailing_return_type = trailing_return_type->clone(pool);
+    if (as_cpp_initializer)
+        ast->as_cpp_initializer = as_cpp_initializer->clone(pool);
+    return ast;
+}
+
+ArrayDeclaratorAST *ArrayDeclaratorAST::clone(MemoryPool *pool) const
+{
+    ArrayDeclaratorAST *ast = new (pool) ArrayDeclaratorAST;
+    ast->lbracket_token = lbracket_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    ast->rbracket_token = rbracket_token;
+    return ast;
+}
+
+DeleteExpressionAST *DeleteExpressionAST::clone(MemoryPool *pool) const
+{
+    DeleteExpressionAST *ast = new (pool) DeleteExpressionAST;
+    ast->scope_token = scope_token;
+    ast->delete_token = delete_token;
+    ast->lbracket_token = lbracket_token;
+    ast->rbracket_token = rbracket_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    return ast;
+}
+
+DoStatementAST *DoStatementAST::clone(MemoryPool *pool) const
+{
+    DoStatementAST *ast = new (pool) DoStatementAST;
+    ast->do_token = do_token;
+    if (statement)
+        ast->statement = statement->clone(pool);
+    ast->while_token = while_token;
+    ast->lparen_token = lparen_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    ast->rparen_token = rparen_token;
+    ast->semicolon_token = semicolon_token;
+    return ast;
+}
+
+NamedTypeSpecifierAST *NamedTypeSpecifierAST::clone(MemoryPool *pool) const
+{
+    NamedTypeSpecifierAST *ast = new (pool) NamedTypeSpecifierAST;
+    if (name)
+        ast->name = name->clone(pool);
+    return ast;
+}
+
+ElaboratedTypeSpecifierAST *ElaboratedTypeSpecifierAST::clone(MemoryPool *pool) const
+{
+    ElaboratedTypeSpecifierAST *ast = new (pool) ElaboratedTypeSpecifierAST;
+    ast->classkey_token = classkey_token;
+    for (SpecifierListAST *iter = attribute_list, **ast_iter = &ast->attribute_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    if (name)
+        ast->name = name->clone(pool);
+    return ast;
+}
+
+EnumSpecifierAST *EnumSpecifierAST::clone(MemoryPool *pool) const
+{
+    EnumSpecifierAST *ast = new (pool) EnumSpecifierAST;
+    ast->enum_token = enum_token;
+    ast->key_token = key_token;
+    if (name)
+        ast->name = name->clone(pool);
+    ast->colon_token = colon_token;
+    for (SpecifierListAST *iter = type_specifier_list, **ast_iter = &ast->type_specifier_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->lbrace_token = lbrace_token;
+    for (EnumeratorListAST *iter = enumerator_list, **ast_iter = &ast->enumerator_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) EnumeratorListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->stray_comma_token = stray_comma_token;
+    ast->rbrace_token = rbrace_token;
+    return ast;
+}
+
+EnumeratorAST *EnumeratorAST::clone(MemoryPool *pool) const
+{
+    EnumeratorAST *ast = new (pool) EnumeratorAST;
+    ast->identifier_token = identifier_token;
+    ast->equal_token = equal_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    return ast;
+}
+
+ExceptionDeclarationAST *ExceptionDeclarationAST::clone(MemoryPool *pool) const
+{
+    ExceptionDeclarationAST *ast = new (pool) ExceptionDeclarationAST;
+    for (SpecifierListAST *iter = type_specifier_list, **ast_iter = &ast->type_specifier_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    if (declarator)
+        ast->declarator = declarator->clone(pool);
+    ast->dot_dot_dot_token = dot_dot_dot_token;
+    return ast;
+}
+
+DynamicExceptionSpecificationAST *DynamicExceptionSpecificationAST::clone(MemoryPool *pool) const
+{
+    DynamicExceptionSpecificationAST *ast = new (pool) DynamicExceptionSpecificationAST;
+    ast->throw_token = throw_token;
+    ast->lparen_token = lparen_token;
+    ast->dot_dot_dot_token = dot_dot_dot_token;
+    for (ExpressionListAST *iter = type_id_list, **ast_iter = &ast->type_id_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) ExpressionListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
+NoExceptSpecificationAST *NoExceptSpecificationAST::clone(MemoryPool *pool) const
+{
+    NoExceptSpecificationAST *ast = new (pool) NoExceptSpecificationAST;
+    ast->noexcept_token = noexcept_token;
+    ast->lparen_token = lparen_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
+ExpressionOrDeclarationStatementAST *ExpressionOrDeclarationStatementAST::clone(MemoryPool *pool) const
+{
+    ExpressionOrDeclarationStatementAST *ast = new (pool) ExpressionOrDeclarationStatementAST;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    if (declaration)
+        ast->declaration = declaration->clone(pool);
+    return ast;
+}
+
+ExpressionStatementAST *ExpressionStatementAST::clone(MemoryPool *pool) const
+{
+    ExpressionStatementAST *ast = new (pool) ExpressionStatementAST;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    ast->semicolon_token = semicolon_token;
+    return ast;
+}
+
+FunctionDefinitionAST *FunctionDefinitionAST::clone(MemoryPool *pool) const
+{
+    FunctionDefinitionAST *ast = new (pool) FunctionDefinitionAST;
+    ast->qt_invokable_token = qt_invokable_token;
+    for (SpecifierListAST *iter = decl_specifier_list, **ast_iter = &ast->decl_specifier_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    if (declarator)
+        ast->declarator = declarator->clone(pool);
+    if (ctor_initializer)
+        ast->ctor_initializer = ctor_initializer->clone(pool);
+    if (function_body)
+        ast->function_body = function_body->clone(pool);
+    return ast;
+}
+
+ForeachStatementAST *ForeachStatementAST::clone(MemoryPool *pool) const
+{
+    ForeachStatementAST *ast = new (pool) ForeachStatementAST;
+    ast->foreach_token = foreach_token;
+    ast->lparen_token = lparen_token;
+    for (SpecifierListAST *iter = type_specifier_list, **ast_iter = &ast->type_specifier_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    if (declarator)
+        ast->declarator = declarator->clone(pool);
+    if (initializer)
+        ast->initializer = initializer->clone(pool);
+    ast->comma_token = comma_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    ast->rparen_token = rparen_token;
+    if (statement)
+        ast->statement = statement->clone(pool);
+    return ast;
+}
+
+RangeBasedForStatementAST *RangeBasedForStatementAST::clone(MemoryPool *pool) const
+{
+    RangeBasedForStatementAST *ast = new (pool) RangeBasedForStatementAST;
+    ast->for_token = for_token;
+    ast->lparen_token = lparen_token;
+    for (SpecifierListAST *iter = type_specifier_list, **ast_iter = &ast->type_specifier_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    if (declarator)
+        ast->declarator = declarator->clone(pool);
+    ast->colon_token = colon_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    ast->rparen_token = rparen_token;
+    if (statement)
+        ast->statement = statement->clone(pool);
+    return ast;
+}
+
+ForStatementAST *ForStatementAST::clone(MemoryPool *pool) const
+{
+    ForStatementAST *ast = new (pool) ForStatementAST;
+    ast->for_token = for_token;
+    ast->lparen_token = lparen_token;
+    if (initializer)
+        ast->initializer = initializer->clone(pool);
+    if (condition)
+        ast->condition = condition->clone(pool);
+    ast->semicolon_token = semicolon_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    ast->rparen_token = rparen_token;
+    if (statement)
+        ast->statement = statement->clone(pool);
+    return ast;
+}
+
+IfStatementAST *IfStatementAST::clone(MemoryPool *pool) const
+{
+    IfStatementAST *ast = new (pool) IfStatementAST;
+    ast->if_token = if_token;
+    ast->lparen_token = lparen_token;
+    if (condition)
+        ast->condition = condition->clone(pool);
+    ast->rparen_token = rparen_token;
+    if (statement)
+        ast->statement = statement->clone(pool);
+    ast->else_token = else_token;
+    if (else_statement)
+        ast->else_statement = else_statement->clone(pool);
+    return ast;
+}
+
+ArrayInitializerAST *ArrayInitializerAST::clone(MemoryPool *pool) const
+{
+    ArrayInitializerAST *ast = new (pool) ArrayInitializerAST;
+    ast->lbrace_token = lbrace_token;
+    for (ExpressionListAST *iter = expression_list, **ast_iter = &ast->expression_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) ExpressionListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->rbrace_token = rbrace_token;
+    return ast;
+}
+
+LabeledStatementAST *LabeledStatementAST::clone(MemoryPool *pool) const
+{
+    LabeledStatementAST *ast = new (pool) LabeledStatementAST;
+    ast->label_token = label_token;
+    ast->colon_token = colon_token;
+    if (statement)
+        ast->statement = statement->clone(pool);
+    return ast;
+}
+
+LinkageBodyAST *LinkageBodyAST::clone(MemoryPool *pool) const
+{
+    LinkageBodyAST *ast = new (pool) LinkageBodyAST;
+    ast->lbrace_token = lbrace_token;
+    for (DeclarationListAST *iter = declaration_list, **ast_iter = &ast->declaration_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) DeclarationListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->rbrace_token = rbrace_token;
+    return ast;
+}
+
+LinkageSpecificationAST *LinkageSpecificationAST::clone(MemoryPool *pool) const
+{
+    LinkageSpecificationAST *ast = new (pool) LinkageSpecificationAST;
+    ast->extern_token = extern_token;
+    ast->extern_type_token = extern_type_token;
+    if (declaration)
+        ast->declaration = declaration->clone(pool);
+    return ast;
+}
+
+MemInitializerAST *MemInitializerAST::clone(MemoryPool *pool) const
+{
+    MemInitializerAST *ast = new (pool) MemInitializerAST;
+    if (name)
+        ast->name = name->clone(pool);
+    if (expression)
+        ast->expression = expression->clone(pool);
+    return ast;
+}
+
+NestedNameSpecifierAST *NestedNameSpecifierAST::clone(MemoryPool *pool) const
+{
+    NestedNameSpecifierAST *ast = new (pool) NestedNameSpecifierAST;
+    if (class_or_namespace_name)
+        ast->class_or_namespace_name = class_or_namespace_name->clone(pool);
+    ast->scope_token = scope_token;
+    return ast;
+}
+
+QualifiedNameAST *QualifiedNameAST::clone(MemoryPool *pool) const
+{
+    QualifiedNameAST *ast = new (pool) QualifiedNameAST;
+    ast->global_scope_token = global_scope_token;
+    for (NestedNameSpecifierListAST *iter = nested_name_specifier_list, **ast_iter = &ast->nested_name_specifier_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) NestedNameSpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    if (unqualified_name)
+        ast->unqualified_name = unqualified_name->clone(pool);
+    return ast;
+}
+
+OperatorFunctionIdAST *OperatorFunctionIdAST::clone(MemoryPool *pool) const
+{
+    OperatorFunctionIdAST *ast = new (pool) OperatorFunctionIdAST;
+    ast->operator_token = operator_token;
+    if (op)
+        ast->op = op->clone(pool);
+    return ast;
+}
+
+ConversionFunctionIdAST *ConversionFunctionIdAST::clone(MemoryPool *pool) const
+{
+    ConversionFunctionIdAST *ast = new (pool) ConversionFunctionIdAST;
+    ast->operator_token = operator_token;
+    for (SpecifierListAST *iter = type_specifier_list, **ast_iter = &ast->type_specifier_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    for (PtrOperatorListAST *iter = ptr_operator_list, **ast_iter = &ast->ptr_operator_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) PtrOperatorListAST((iter->value) ? iter->value->clone(pool) : 0);
+    return ast;
+}
+
+AnonymousNameAST *AnonymousNameAST::clone(MemoryPool *pool) const
+{
+    AnonymousNameAST *ast = new (pool) AnonymousNameAST;
+    ast->class_token = class_token;
+    return ast;
+}
+
+SimpleNameAST *SimpleNameAST::clone(MemoryPool *pool) const
+{
+    SimpleNameAST *ast = new (pool) SimpleNameAST;
+    ast->identifier_token = identifier_token;
+    return ast;
+}
+
+DestructorNameAST *DestructorNameAST::clone(MemoryPool *pool) const
+{
+    DestructorNameAST *ast = new (pool) DestructorNameAST;
+    ast->tilde_token = tilde_token;
+    if (unqualified_name)
+        ast->unqualified_name = unqualified_name->clone(pool);
+    return ast;
+}
+
+TemplateIdAST *TemplateIdAST::clone(MemoryPool *pool) const
+{
+    TemplateIdAST *ast = new (pool) TemplateIdAST;
+    ast->template_token = template_token;
+    ast->identifier_token = identifier_token;
+    ast->less_token = less_token;
+    for (ExpressionListAST *iter = template_argument_list, **ast_iter = &ast->template_argument_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) ExpressionListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->greater_token = greater_token;
+    return ast;
+}
+
+NamespaceAST *NamespaceAST::clone(MemoryPool *pool) const
+{
+    NamespaceAST *ast = new (pool) NamespaceAST;
+    ast->inline_token = inline_token;
+    ast->namespace_token = namespace_token;
+    ast->identifier_token = identifier_token;
+    for (SpecifierListAST *iter = attribute_list, **ast_iter = &ast->attribute_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    if (linkage_body)
+        ast->linkage_body = linkage_body->clone(pool);
+    return ast;
+}
+
+NamespaceAliasDefinitionAST *NamespaceAliasDefinitionAST::clone(MemoryPool *pool) const
+{
+    NamespaceAliasDefinitionAST *ast = new (pool) NamespaceAliasDefinitionAST;
+    ast->namespace_token = namespace_token;
+    ast->namespace_name_token = namespace_name_token;
+    ast->equal_token = equal_token;
+    if (name)
+        ast->name = name->clone(pool);
+    ast->semicolon_token = semicolon_token;
+    return ast;
+}
+
+AliasDeclarationAST *AliasDeclarationAST::clone(MemoryPool *pool) const
+{
+    AliasDeclarationAST *ast = new (pool) AliasDeclarationAST;
+    ast->using_token = using_token;
+    if (name)
+        ast->name = name->clone(pool);
+    ast->equal_token = equal_token;
+    if (typeId)
+        ast->typeId = typeId->clone(pool);
+    ast->semicolon_token = semicolon_token;
+    return ast;
+}
+
+ExpressionListParenAST *ExpressionListParenAST::clone(MemoryPool *pool) const
+{
+    ExpressionListParenAST *ast = new (pool) ExpressionListParenAST;
+    ast->lparen_token = lparen_token;
+    for (ExpressionListAST *iter = expression_list, **ast_iter = &ast->expression_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) ExpressionListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
+NewArrayDeclaratorAST *NewArrayDeclaratorAST::clone(MemoryPool *pool) const
+{
+    NewArrayDeclaratorAST *ast = new (pool) NewArrayDeclaratorAST;
+    ast->lbracket_token = lbracket_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    ast->rbracket_token = rbracket_token;
+    return ast;
+}
+
+NewExpressionAST *NewExpressionAST::clone(MemoryPool *pool) const
+{
+    NewExpressionAST *ast = new (pool) NewExpressionAST;
+    ast->scope_token = scope_token;
+    ast->new_token = new_token;
+    if (new_placement)
+        ast->new_placement = new_placement->clone(pool);
+    ast->lparen_token = lparen_token;
+    if (type_id)
+        ast->type_id = type_id->clone(pool);
+    ast->rparen_token = rparen_token;
+    if (new_type_id)
+        ast->new_type_id = new_type_id->clone(pool);
+    if (new_initializer)
+        ast->new_initializer = new_initializer->clone(pool);
+    return ast;
+}
+
+NewTypeIdAST *NewTypeIdAST::clone(MemoryPool *pool) const
+{
+    NewTypeIdAST *ast = new (pool) NewTypeIdAST;
+    for (SpecifierListAST *iter = type_specifier_list, **ast_iter = &ast->type_specifier_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    for (PtrOperatorListAST *iter = ptr_operator_list, **ast_iter = &ast->ptr_operator_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) PtrOperatorListAST((iter->value) ? iter->value->clone(pool) : 0);
+    for (NewArrayDeclaratorListAST *iter = new_array_declarator_list, **ast_iter = &ast->new_array_declarator_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) NewArrayDeclaratorListAST((iter->value) ? iter->value->clone(pool) : 0);
+    return ast;
+}
+
+OperatorAST *OperatorAST::clone(MemoryPool *pool) const
+{
+    OperatorAST *ast = new (pool) OperatorAST;
+    ast->op_token = op_token;
+    ast->open_token = open_token;
+    ast->close_token = close_token;
+    return ast;
+}
+
+ParameterDeclarationAST *ParameterDeclarationAST::clone(MemoryPool *pool) const
+{
+    ParameterDeclarationAST *ast = new (pool) ParameterDeclarationAST;
+    for (SpecifierListAST *iter = type_specifier_list, **ast_iter = &ast->type_specifier_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    if (declarator)
+        ast->declarator = declarator->clone(pool);
+    ast->equal_token = equal_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    return ast;
+}
+
+ParameterDeclarationClauseAST *ParameterDeclarationClauseAST::clone(MemoryPool *pool) const
+{
+    ParameterDeclarationClauseAST *ast = new (pool) ParameterDeclarationClauseAST;
+    for (ParameterDeclarationListAST *iter = parameter_declaration_list, **ast_iter = &ast->parameter_declaration_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) ParameterDeclarationListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->dot_dot_dot_token = dot_dot_dot_token;
+    return ast;
+}
+
+CallAST *CallAST::clone(MemoryPool *pool) const
+{
+    CallAST *ast = new (pool) CallAST;
+    if (base_expression)
+        ast->base_expression = base_expression->clone(pool);
+    ast->lparen_token = lparen_token;
+    for (ExpressionListAST *iter = expression_list, **ast_iter = &ast->expression_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) ExpressionListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
+ArrayAccessAST *ArrayAccessAST::clone(MemoryPool *pool) const
+{
+    ArrayAccessAST *ast = new (pool) ArrayAccessAST;
+    if (base_expression)
+        ast->base_expression = base_expression->clone(pool);
+    ast->lbracket_token = lbracket_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    ast->rbracket_token = rbracket_token;
+    return ast;
+}
+
+PostIncrDecrAST *PostIncrDecrAST::clone(MemoryPool *pool) const
+{
+    PostIncrDecrAST *ast = new (pool) PostIncrDecrAST;
+    if (base_expression)
+        ast->base_expression = base_expression->clone(pool);
+    ast->incr_decr_token = incr_decr_token;
+    return ast;
+}
+
+MemberAccessAST *MemberAccessAST::clone(MemoryPool *pool) const
+{
+    MemberAccessAST *ast = new (pool) MemberAccessAST;
+    if (base_expression)
+        ast->base_expression = base_expression->clone(pool);
+    ast->access_token = access_token;
+    ast->template_token = template_token;
+    if (member_name)
+        ast->member_name = member_name->clone(pool);
+    return ast;
+}
+
+TypeidExpressionAST *TypeidExpressionAST::clone(MemoryPool *pool) const
+{
+    TypeidExpressionAST *ast = new (pool) TypeidExpressionAST;
+    ast->typeid_token = typeid_token;
+    ast->lparen_token = lparen_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
+TypenameCallExpressionAST *TypenameCallExpressionAST::clone(MemoryPool *pool) const
+{
+    TypenameCallExpressionAST *ast = new (pool) TypenameCallExpressionAST;
+    ast->typename_token = typename_token;
+    if (name)
+        ast->name = name->clone(pool);
+    if (expression)
+        ast->expression = expression->clone(pool);
+    return ast;
+}
+
+TypeConstructorCallAST *TypeConstructorCallAST::clone(MemoryPool *pool) const
+{
+    TypeConstructorCallAST *ast = new (pool) TypeConstructorCallAST;
+    for (SpecifierListAST *iter = type_specifier_list, **ast_iter = &ast->type_specifier_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    if (expression)
+        ast->expression = expression->clone(pool);
+    return ast;
+}
+
+PointerToMemberAST *PointerToMemberAST::clone(MemoryPool *pool) const
+{
+    PointerToMemberAST *ast = new (pool) PointerToMemberAST;
+    ast->global_scope_token = global_scope_token;
+    for (NestedNameSpecifierListAST *iter = nested_name_specifier_list, **ast_iter = &ast->nested_name_specifier_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) NestedNameSpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->star_token = star_token;
+    for (SpecifierListAST *iter = cv_qualifier_list, **ast_iter = &ast->cv_qualifier_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->ref_qualifier_token = ref_qualifier_token;
+    return ast;
+}
+
+PointerAST *PointerAST::clone(MemoryPool *pool) const
+{
+    PointerAST *ast = new (pool) PointerAST;
+    ast->star_token = star_token;
+    for (SpecifierListAST *iter = cv_qualifier_list, **ast_iter = &ast->cv_qualifier_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    return ast;
+}
+
+ReferenceAST *ReferenceAST::clone(MemoryPool *pool) const
+{
+    ReferenceAST *ast = new (pool) ReferenceAST;
+    ast->reference_token = reference_token;
+    return ast;
+}
+
+BreakStatementAST *BreakStatementAST::clone(MemoryPool *pool) const
+{
+    BreakStatementAST *ast = new (pool) BreakStatementAST;
+    ast->break_token = break_token;
+    ast->semicolon_token = semicolon_token;
+    return ast;
+}
+
+ContinueStatementAST *ContinueStatementAST::clone(MemoryPool *pool) const
+{
+    ContinueStatementAST *ast = new (pool) ContinueStatementAST;
+    ast->continue_token = continue_token;
+    ast->semicolon_token = semicolon_token;
+    return ast;
+}
+
+GotoStatementAST *GotoStatementAST::clone(MemoryPool *pool) const
+{
+    GotoStatementAST *ast = new (pool) GotoStatementAST;
+    ast->goto_token = goto_token;
+    ast->identifier_token = identifier_token;
+    ast->semicolon_token = semicolon_token;
+    return ast;
+}
+
+ReturnStatementAST *ReturnStatementAST::clone(MemoryPool *pool) const
+{
+    ReturnStatementAST *ast = new (pool) ReturnStatementAST;
+    ast->return_token = return_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    ast->semicolon_token = semicolon_token;
+    return ast;
+}
+
+SizeofExpressionAST *SizeofExpressionAST::clone(MemoryPool *pool) const
+{
+    SizeofExpressionAST *ast = new (pool) SizeofExpressionAST;
+    ast->sizeof_token = sizeof_token;
+    ast->dot_dot_dot_token = dot_dot_dot_token;
+    ast->lparen_token = lparen_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
+AlignofExpressionAST *AlignofExpressionAST::clone(MemoryPool *pool) const
+{
+    AlignofExpressionAST *ast = new (pool) AlignofExpressionAST;
+    ast->alignof_token = alignof_token;
+    ast->lparen_token = lparen_token;
+    if (typeId)
+        ast->typeId = typeId->clone(pool);
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
+PointerLiteralAST *PointerLiteralAST::clone(MemoryPool *pool) const
+{
+    PointerLiteralAST *ast = new (pool) PointerLiteralAST;
+    ast->literal_token = literal_token;
+    return ast;
+}
+
+NumericLiteralAST *NumericLiteralAST::clone(MemoryPool *pool) const
+{
+    NumericLiteralAST *ast = new (pool) NumericLiteralAST;
+    ast->literal_token = literal_token;
+    return ast;
+}
+
+BoolLiteralAST *BoolLiteralAST::clone(MemoryPool *pool) const
+{
+    BoolLiteralAST *ast = new (pool) BoolLiteralAST;
+    ast->literal_token = literal_token;
+    return ast;
+}
+
+ThisExpressionAST *ThisExpressionAST::clone(MemoryPool *pool) const
+{
+    ThisExpressionAST *ast = new (pool) ThisExpressionAST;
+    ast->this_token = this_token;
+    return ast;
+}
+
+NestedExpressionAST *NestedExpressionAST::clone(MemoryPool *pool) const
+{
+    NestedExpressionAST *ast = new (pool) NestedExpressionAST;
+    ast->lparen_token = lparen_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
+StaticAssertDeclarationAST *StaticAssertDeclarationAST::clone(MemoryPool *pool) const
+{
+    StaticAssertDeclarationAST *ast = new (pool) StaticAssertDeclarationAST;
+    ast->static_assert_token = static_assert_token;
+    ast->lparen_token = lparen_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    ast->comma_token = comma_token;
+    if (string_literal)
+        ast->string_literal = string_literal->clone(pool);
+    ast->rparen_token = rparen_token;
+    ast->semicolon_token = semicolon_token;
+    return ast;
+}
+
+StringLiteralAST *StringLiteralAST::clone(MemoryPool *pool) const
+{
+    StringLiteralAST *ast = new (pool) StringLiteralAST;
+    ast->literal_token = literal_token;
+    if (next)
+        ast->next = next->clone(pool);
+    return ast;
+}
+
+SwitchStatementAST *SwitchStatementAST::clone(MemoryPool *pool) const
+{
+    SwitchStatementAST *ast = new (pool) SwitchStatementAST;
+    ast->switch_token = switch_token;
+    ast->lparen_token = lparen_token;
+    if (condition)
+        ast->condition = condition->clone(pool);
+    ast->rparen_token = rparen_token;
+    if (statement)
+        ast->statement = statement->clone(pool);
+    return ast;
+}
+
+TemplateDeclarationAST *TemplateDeclarationAST::clone(MemoryPool *pool) const
+{
+    TemplateDeclarationAST *ast = new (pool) TemplateDeclarationAST;
+    ast->export_token = export_token;
+    ast->template_token = template_token;
+    ast->less_token = less_token;
+    for (DeclarationListAST *iter = template_parameter_list, **ast_iter = &ast->template_parameter_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) DeclarationListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->greater_token = greater_token;
+    if (declaration)
+        ast->declaration = declaration->clone(pool);
+    return ast;
+}
+
+ThrowExpressionAST *ThrowExpressionAST::clone(MemoryPool *pool) const
+{
+    ThrowExpressionAST *ast = new (pool) ThrowExpressionAST;
+    ast->throw_token = throw_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    return ast;
+}
+
+TranslationUnitAST *TranslationUnitAST::clone(MemoryPool *pool) const
+{
+    TranslationUnitAST *ast = new (pool) TranslationUnitAST;
+    for (DeclarationListAST *iter = declaration_list, **ast_iter = &ast->declaration_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) DeclarationListAST((iter->value) ? iter->value->clone(pool) : 0);
+    return ast;
+}
+
+TryBlockStatementAST *TryBlockStatementAST::clone(MemoryPool *pool) const
+{
+    TryBlockStatementAST *ast = new (pool) TryBlockStatementAST;
+    ast->try_token = try_token;
+    if (statement)
+        ast->statement = statement->clone(pool);
+    for (CatchClauseListAST *iter = catch_clause_list, **ast_iter = &ast->catch_clause_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) CatchClauseListAST((iter->value) ? iter->value->clone(pool) : 0);
+    return ast;
+}
+
+CatchClauseAST *CatchClauseAST::clone(MemoryPool *pool) const
+{
+    CatchClauseAST *ast = new (pool) CatchClauseAST;
+    ast->catch_token = catch_token;
+    ast->lparen_token = lparen_token;
+    if (exception_declaration)
+        ast->exception_declaration = exception_declaration->clone(pool);
+    ast->rparen_token = rparen_token;
+    if (statement)
+        ast->statement = statement->clone(pool);
+    return ast;
+}
+
+TypeIdAST *TypeIdAST::clone(MemoryPool *pool) const
+{
+    TypeIdAST *ast = new (pool) TypeIdAST;
+    for (SpecifierListAST *iter = type_specifier_list, **ast_iter = &ast->type_specifier_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    if (declarator)
+        ast->declarator = declarator->clone(pool);
+    return ast;
+}
+
+TypenameTypeParameterAST *TypenameTypeParameterAST::clone(MemoryPool *pool) const
+{
+    TypenameTypeParameterAST *ast = new (pool) TypenameTypeParameterAST;
+    ast->classkey_token = classkey_token;
+    ast->dot_dot_dot_token = dot_dot_dot_token;
+    if (name)
+        ast->name = name->clone(pool);
+    ast->equal_token = equal_token;
+    if (type_id)
+        ast->type_id = type_id->clone(pool);
+    return ast;
+}
+
+TemplateTypeParameterAST *TemplateTypeParameterAST::clone(MemoryPool *pool) const
+{
+    TemplateTypeParameterAST *ast = new (pool) TemplateTypeParameterAST;
+    ast->template_token = template_token;
+    ast->less_token = less_token;
+    for (DeclarationListAST *iter = template_parameter_list, **ast_iter = &ast->template_parameter_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) DeclarationListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->greater_token = greater_token;
+    ast->class_token = class_token;
+    ast->dot_dot_dot_token = dot_dot_dot_token;
+    if (name)
+        ast->name = name->clone(pool);
+    ast->equal_token = equal_token;
+    if (type_id)
+        ast->type_id = type_id->clone(pool);
+    return ast;
+}
+
+UnaryExpressionAST *UnaryExpressionAST::clone(MemoryPool *pool) const
+{
+    UnaryExpressionAST *ast = new (pool) UnaryExpressionAST;
+    ast->unary_op_token = unary_op_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    return ast;
+}
+
+UsingAST *UsingAST::clone(MemoryPool *pool) const
+{
+    UsingAST *ast = new (pool) UsingAST;
+    ast->using_token = using_token;
+    ast->typename_token = typename_token;
+    if (name)
+        ast->name = name->clone(pool);
+    ast->semicolon_token = semicolon_token;
+    return ast;
+}
+
+UsingDirectiveAST *UsingDirectiveAST::clone(MemoryPool *pool) const
+{
+    UsingDirectiveAST *ast = new (pool) UsingDirectiveAST;
+    ast->using_token = using_token;
+    ast->namespace_token = namespace_token;
+    if (name)
+        ast->name = name->clone(pool);
+    ast->semicolon_token = semicolon_token;
+    return ast;
+}
+
+WhileStatementAST *WhileStatementAST::clone(MemoryPool *pool) const
+{
+    WhileStatementAST *ast = new (pool) WhileStatementAST;
+    ast->while_token = while_token;
+    ast->lparen_token = lparen_token;
+    if (condition)
+        ast->condition = condition->clone(pool);
+    ast->rparen_token = rparen_token;
+    if (statement)
+        ast->statement = statement->clone(pool);
+    return ast;
+}
+
+ObjCClassForwardDeclarationAST *ObjCClassForwardDeclarationAST::clone(MemoryPool *pool) const
+{
+    ObjCClassForwardDeclarationAST *ast = new (pool) ObjCClassForwardDeclarationAST;
+    for (SpecifierListAST *iter = attribute_list, **ast_iter = &ast->attribute_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->class_token = class_token;
+    for (NameListAST *iter = identifier_list, **ast_iter = &ast->identifier_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) NameListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->semicolon_token = semicolon_token;
+    return ast;
+}
+
+ObjCClassDeclarationAST *ObjCClassDeclarationAST::clone(MemoryPool *pool) const
+{
+    ObjCClassDeclarationAST *ast = new (pool) ObjCClassDeclarationAST;
+    for (SpecifierListAST *iter = attribute_list, **ast_iter = &ast->attribute_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->interface_token = interface_token;
+    ast->implementation_token = implementation_token;
+    if (class_name)
+        ast->class_name = class_name->clone(pool);
+    ast->lparen_token = lparen_token;
+    if (category_name)
+        ast->category_name = category_name->clone(pool);
+    ast->rparen_token = rparen_token;
+    ast->colon_token = colon_token;
+    if (superclass)
+        ast->superclass = superclass->clone(pool);
+    if (protocol_refs)
+        ast->protocol_refs = protocol_refs->clone(pool);
+    if (inst_vars_decl)
+        ast->inst_vars_decl = inst_vars_decl->clone(pool);
+    for (DeclarationListAST *iter = member_declaration_list, **ast_iter = &ast->member_declaration_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) DeclarationListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->end_token = end_token;
+    return ast;
+}
+
+ObjCProtocolForwardDeclarationAST *ObjCProtocolForwardDeclarationAST::clone(MemoryPool *pool) const
+{
+    ObjCProtocolForwardDeclarationAST *ast = new (pool) ObjCProtocolForwardDeclarationAST;
+    for (SpecifierListAST *iter = attribute_list, **ast_iter = &ast->attribute_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->protocol_token = protocol_token;
+    for (NameListAST *iter = identifier_list, **ast_iter = &ast->identifier_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) NameListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->semicolon_token = semicolon_token;
+    return ast;
+}
+
+ObjCProtocolDeclarationAST *ObjCProtocolDeclarationAST::clone(MemoryPool *pool) const
+{
+    ObjCProtocolDeclarationAST *ast = new (pool) ObjCProtocolDeclarationAST;
+    for (SpecifierListAST *iter = attribute_list, **ast_iter = &ast->attribute_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->protocol_token = protocol_token;
+    if (name)
+        ast->name = name->clone(pool);
+    if (protocol_refs)
+        ast->protocol_refs = protocol_refs->clone(pool);
+    for (DeclarationListAST *iter = member_declaration_list, **ast_iter = &ast->member_declaration_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) DeclarationListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->end_token = end_token;
+    return ast;
+}
+
+ObjCProtocolRefsAST *ObjCProtocolRefsAST::clone(MemoryPool *pool) const
+{
+    ObjCProtocolRefsAST *ast = new (pool) ObjCProtocolRefsAST;
+    ast->less_token = less_token;
+    for (NameListAST *iter = identifier_list, **ast_iter = &ast->identifier_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) NameListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->greater_token = greater_token;
+    return ast;
+}
+
+ObjCMessageArgumentAST *ObjCMessageArgumentAST::clone(MemoryPool *pool) const
+{
+    ObjCMessageArgumentAST *ast = new (pool) ObjCMessageArgumentAST;
+    if (parameter_value_expression)
+        ast->parameter_value_expression = parameter_value_expression->clone(pool);
+    return ast;
+}
+
+ObjCMessageExpressionAST *ObjCMessageExpressionAST::clone(MemoryPool *pool) const
+{
+    ObjCMessageExpressionAST *ast = new (pool) ObjCMessageExpressionAST;
+    ast->lbracket_token = lbracket_token;
+    if (receiver_expression)
+        ast->receiver_expression = receiver_expression->clone(pool);
+    if (selector)
+        ast->selector = selector->clone(pool);
+    for (ObjCMessageArgumentListAST *iter = argument_list, **ast_iter = &ast->argument_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) ObjCMessageArgumentListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->rbracket_token = rbracket_token;
+    return ast;
+}
+
+ObjCProtocolExpressionAST *ObjCProtocolExpressionAST::clone(MemoryPool *pool) const
+{
+    ObjCProtocolExpressionAST *ast = new (pool) ObjCProtocolExpressionAST;
+    ast->protocol_token = protocol_token;
+    ast->lparen_token = lparen_token;
+    ast->identifier_token = identifier_token;
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
+ObjCTypeNameAST *ObjCTypeNameAST::clone(MemoryPool *pool) const
+{
+    ObjCTypeNameAST *ast = new (pool) ObjCTypeNameAST;
+    ast->lparen_token = lparen_token;
+    ast->type_qualifier_token = type_qualifier_token;
+    if (type_id)
+        ast->type_id = type_id->clone(pool);
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
+ObjCEncodeExpressionAST *ObjCEncodeExpressionAST::clone(MemoryPool *pool) const
+{
+    ObjCEncodeExpressionAST *ast = new (pool) ObjCEncodeExpressionAST;
+    ast->encode_token = encode_token;
+    if (type_name)
+        ast->type_name = type_name->clone(pool);
+    return ast;
+}
+
+ObjCSelectorExpressionAST *ObjCSelectorExpressionAST::clone(MemoryPool *pool) const
+{
+    ObjCSelectorExpressionAST *ast = new (pool) ObjCSelectorExpressionAST;
+    ast->selector_token = selector_token;
+    ast->lparen_token = lparen_token;
+    if (selector)
+        ast->selector = selector->clone(pool);
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
+ObjCInstanceVariablesDeclarationAST *ObjCInstanceVariablesDeclarationAST::clone(MemoryPool *pool) const
+{
+    ObjCInstanceVariablesDeclarationAST *ast = new (pool) ObjCInstanceVariablesDeclarationAST;
+    ast->lbrace_token = lbrace_token;
+    for (DeclarationListAST *iter = instance_variable_list, **ast_iter = &ast->instance_variable_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) DeclarationListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->rbrace_token = rbrace_token;
+    return ast;
+}
+
+ObjCVisibilityDeclarationAST *ObjCVisibilityDeclarationAST::clone(MemoryPool *pool) const
+{
+    ObjCVisibilityDeclarationAST *ast = new (pool) ObjCVisibilityDeclarationAST;
+    ast->visibility_token = visibility_token;
+    return ast;
+}
+
+ObjCPropertyAttributeAST *ObjCPropertyAttributeAST::clone(MemoryPool *pool) const
+{
+    ObjCPropertyAttributeAST *ast = new (pool) ObjCPropertyAttributeAST;
+    ast->attribute_identifier_token = attribute_identifier_token;
+    ast->equals_token = equals_token;
+    if (method_selector)
+        ast->method_selector = method_selector->clone(pool);
+    return ast;
+}
+
+ObjCPropertyDeclarationAST *ObjCPropertyDeclarationAST::clone(MemoryPool *pool) const
+{
+    ObjCPropertyDeclarationAST *ast = new (pool) ObjCPropertyDeclarationAST;
+    for (SpecifierListAST *iter = attribute_list, **ast_iter = &ast->attribute_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->property_token = property_token;
+    ast->lparen_token = lparen_token;
+    for (ObjCPropertyAttributeListAST *iter = property_attribute_list, **ast_iter = &ast->property_attribute_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) ObjCPropertyAttributeListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->rparen_token = rparen_token;
+    if (simple_declaration)
+        ast->simple_declaration = simple_declaration->clone(pool);
+    return ast;
+}
+
+ObjCMessageArgumentDeclarationAST *ObjCMessageArgumentDeclarationAST::clone(MemoryPool *pool) const
+{
+    ObjCMessageArgumentDeclarationAST *ast = new (pool) ObjCMessageArgumentDeclarationAST;
+    if (type_name)
+        ast->type_name = type_name->clone(pool);
+    for (SpecifierListAST *iter = attribute_list, **ast_iter = &ast->attribute_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    if (param_name)
+        ast->param_name = param_name->clone(pool);
+    return ast;
+}
+
+ObjCMethodPrototypeAST *ObjCMethodPrototypeAST::clone(MemoryPool *pool) const
+{
+    ObjCMethodPrototypeAST *ast = new (pool) ObjCMethodPrototypeAST;
+    ast->method_type_token = method_type_token;
+    if (type_name)
+        ast->type_name = type_name->clone(pool);
+    if (selector)
+        ast->selector = selector->clone(pool);
+    for (ObjCMessageArgumentDeclarationListAST *iter = argument_list, **ast_iter = &ast->argument_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) ObjCMessageArgumentDeclarationListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->dot_dot_dot_token = dot_dot_dot_token;
+    for (SpecifierListAST *iter = attribute_list, **ast_iter = &ast->attribute_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    return ast;
+}
+
+ObjCMethodDeclarationAST *ObjCMethodDeclarationAST::clone(MemoryPool *pool) const
+{
+    ObjCMethodDeclarationAST *ast = new (pool) ObjCMethodDeclarationAST;
+    if (method_prototype)
+        ast->method_prototype = method_prototype->clone(pool);
+    if (function_body)
+        ast->function_body = function_body->clone(pool);
+    ast->semicolon_token = semicolon_token;
+    return ast;
+}
+
+ObjCSynthesizedPropertyAST *ObjCSynthesizedPropertyAST::clone(MemoryPool *pool) const
+{
+    ObjCSynthesizedPropertyAST *ast = new (pool) ObjCSynthesizedPropertyAST;
+    ast->property_identifier_token = property_identifier_token;
+    ast->equals_token = equals_token;
+    ast->alias_identifier_token = alias_identifier_token;
+    return ast;
+}
+
+ObjCSynthesizedPropertiesDeclarationAST *ObjCSynthesizedPropertiesDeclarationAST::clone(MemoryPool *pool) const
+{
+    ObjCSynthesizedPropertiesDeclarationAST *ast = new (pool) ObjCSynthesizedPropertiesDeclarationAST;
+    ast->synthesized_token = synthesized_token;
+    for (ObjCSynthesizedPropertyListAST *iter = property_identifier_list, **ast_iter = &ast->property_identifier_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) ObjCSynthesizedPropertyListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->semicolon_token = semicolon_token;
+    return ast;
+}
+
+ObjCDynamicPropertiesDeclarationAST *ObjCDynamicPropertiesDeclarationAST::clone(MemoryPool *pool) const
+{
+    ObjCDynamicPropertiesDeclarationAST *ast = new (pool) ObjCDynamicPropertiesDeclarationAST;
+    ast->dynamic_token = dynamic_token;
+    for (NameListAST *iter = property_identifier_list, **ast_iter = &ast->property_identifier_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) NameListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->semicolon_token = semicolon_token;
+    return ast;
+}
+
+ObjCFastEnumerationAST *ObjCFastEnumerationAST::clone(MemoryPool *pool) const
+{
+    ObjCFastEnumerationAST *ast = new (pool) ObjCFastEnumerationAST;
+    ast->for_token = for_token;
+    ast->lparen_token = lparen_token;
+    for (SpecifierListAST *iter = type_specifier_list, **ast_iter = &ast->type_specifier_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    if (declarator)
+        ast->declarator = declarator->clone(pool);
+    if (initializer)
+        ast->initializer = initializer->clone(pool);
+    ast->in_token = in_token;
+    if (fast_enumeratable_expression)
+        ast->fast_enumeratable_expression = fast_enumeratable_expression->clone(pool);
+    ast->rparen_token = rparen_token;
+    if (statement)
+        ast->statement = statement->clone(pool);
+    return ast;
+}
+
+ObjCSynchronizedStatementAST *ObjCSynchronizedStatementAST::clone(MemoryPool *pool) const
+{
+    ObjCSynchronizedStatementAST *ast = new (pool) ObjCSynchronizedStatementAST;
+    ast->synchronized_token = synchronized_token;
+    ast->lparen_token = lparen_token;
+    if (synchronized_object)
+        ast->synchronized_object = synchronized_object->clone(pool);
+    ast->rparen_token = rparen_token;
+    if (statement)
+        ast->statement = statement->clone(pool);
+    return ast;
+}
+
+LambdaExpressionAST *LambdaExpressionAST::clone(MemoryPool *pool) const
+{
+    LambdaExpressionAST *ast = new (pool) LambdaExpressionAST;
+    if (lambda_introducer)
+        ast->lambda_introducer = lambda_introducer->clone(pool);
+    if (lambda_declarator)
+        ast->lambda_declarator = lambda_declarator->clone(pool);
+    if (statement)
+        ast->statement = statement->clone(pool);
+    return ast;
+}
+
+LambdaIntroducerAST *LambdaIntroducerAST::clone(MemoryPool *pool) const
+{
+    LambdaIntroducerAST *ast = new (pool) LambdaIntroducerAST;
+    ast->lbracket_token = lbracket_token;
+    if (lambda_capture)
+        ast->lambda_capture = lambda_capture->clone(pool);
+    ast->rbracket_token = rbracket_token;
+    return ast;
+}
+
+LambdaCaptureAST *LambdaCaptureAST::clone(MemoryPool *pool) const
+{
+    LambdaCaptureAST *ast = new (pool) LambdaCaptureAST;
+    ast->default_capture_token = default_capture_token;
+    for (CaptureListAST *iter = capture_list, **ast_iter = &ast->capture_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) CaptureListAST((iter->value) ? iter->value->clone(pool) : 0);
+    return ast;
+}
+
+CaptureAST *CaptureAST::clone(MemoryPool *pool) const
+{
+    CaptureAST *ast = new (pool) CaptureAST;
+    ast->amper_token = amper_token;
+    if (identifier)
+        ast->identifier = identifier->clone(pool);
+    return ast;
+}
+
+LambdaDeclaratorAST *LambdaDeclaratorAST::clone(MemoryPool *pool) const
+{
+    LambdaDeclaratorAST *ast = new (pool) LambdaDeclaratorAST;
+    ast->lparen_token = lparen_token;
+    if (parameter_declaration_clause)
+        ast->parameter_declaration_clause = parameter_declaration_clause->clone(pool);
+    ast->rparen_token = rparen_token;
+    for (SpecifierListAST *iter = attributes, **ast_iter = &ast->attributes;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->mutable_token = mutable_token;
+    if (exception_specification)
+        ast->exception_specification = exception_specification->clone(pool);
+    if (trailing_return_type)
+        ast->trailing_return_type = trailing_return_type->clone(pool);
+    return ast;
+}
+
+TrailingReturnTypeAST *TrailingReturnTypeAST::clone(MemoryPool *pool) const
+{
+    TrailingReturnTypeAST *ast = new (pool) TrailingReturnTypeAST;
+    ast->arrow_token = arrow_token;
+    for (SpecifierListAST *iter = attributes, **ast_iter = &ast->attributes;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    for (SpecifierListAST *iter = type_specifier_list, **ast_iter = &ast->type_specifier_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    if (declarator)
+        ast->declarator = declarator->clone(pool);
+    return ast;
+}
+
+BracedInitializerAST *BracedInitializerAST::clone(MemoryPool *pool) const
+{
+    BracedInitializerAST *ast = new (pool) BracedInitializerAST;
+    ast->lbrace_token = lbrace_token;
+    for (ExpressionListAST *iter = expression_list, **ast_iter = &ast->expression_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) ExpressionListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->comma_token = comma_token;
+    ast->rbrace_token = rbrace_token;
+    return ast;
+}
+
+DotDesignatorAST *DotDesignatorAST::clone(MemoryPool *pool) const
+{
+    DotDesignatorAST *ast = new (pool) DotDesignatorAST;
+    ast->dot_token = dot_token;
+    ast->identifier_token = identifier_token;
+    return ast;
+}
+
+BracketDesignatorAST *BracketDesignatorAST::clone(MemoryPool *pool) const
+{
+    BracketDesignatorAST *ast = new (pool) BracketDesignatorAST;
+    ast->lbracket_token = lbracket_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    ast->rbracket_token = rbracket_token;
+    return ast;
+}
+
+DesignatedInitializerAST *DesignatedInitializerAST::clone(MemoryPool *pool) const
+{
+    DesignatedInitializerAST *ast = new (pool) DesignatedInitializerAST;
+    for (DesignatorListAST *iter = designator_list, **ast_iter = &ast->designator_list;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) DesignatorListAST((iter->value) ? iter->value->clone(pool) : 0);
+    ast->equal_token = equal_token;
+    if (initializer)
+        ast->initializer = initializer->clone(pool);
+    return ast;
+}
+

+ 1226 - 0
Source/ToolCore/JSBind/cplusplus/ASTMatch0.cpp

@@ -0,0 +1,1226 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is automatically generated by "cplusplus-update-frontend".
+// Changes will be lost.
+//
+
+
+#include "AST.h"
+#include "ASTMatcher.h"
+
+using namespace CPlusPlus;
+
+bool ObjCSelectorArgumentAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ObjCSelectorArgumentAST *_other = pattern->asObjCSelectorArgument())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ObjCSelectorAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ObjCSelectorAST *_other = pattern->asObjCSelector())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool SimpleSpecifierAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (SimpleSpecifierAST *_other = pattern->asSimpleSpecifier())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool AlignmentSpecifierAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (AlignmentSpecifierAST *_other = pattern->asAlignmentSpecifier())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool GnuAttributeSpecifierAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (GnuAttributeSpecifierAST *_other = pattern->asGnuAttributeSpecifier())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool GnuAttributeAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (GnuAttributeAST *_other = pattern->asGnuAttribute())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool TypeofSpecifierAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (TypeofSpecifierAST *_other = pattern->asTypeofSpecifier())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool DecltypeSpecifierAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (DecltypeSpecifierAST *_other = pattern->asDecltypeSpecifier())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool DeclaratorAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (DeclaratorAST *_other = pattern->asDeclarator())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool SimpleDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (SimpleDeclarationAST *_other = pattern->asSimpleDeclaration())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool EmptyDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (EmptyDeclarationAST *_other = pattern->asEmptyDeclaration())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool AccessDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (AccessDeclarationAST *_other = pattern->asAccessDeclaration())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool QtObjectTagAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (QtObjectTagAST *_other = pattern->asQtObjectTag())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool QtPrivateSlotAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (QtPrivateSlotAST *_other = pattern->asQtPrivateSlot())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool QtPropertyDeclarationItemAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (QtPropertyDeclarationItemAST *_other = pattern->asQtPropertyDeclarationItem())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool QtPropertyDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (QtPropertyDeclarationAST *_other = pattern->asQtPropertyDeclaration())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool QtEnumDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (QtEnumDeclarationAST *_other = pattern->asQtEnumDeclaration())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool QtFlagsDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (QtFlagsDeclarationAST *_other = pattern->asQtFlagsDeclaration())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool QtInterfaceNameAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (QtInterfaceNameAST *_other = pattern->asQtInterfaceName())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool QtInterfacesDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (QtInterfacesDeclarationAST *_other = pattern->asQtInterfacesDeclaration())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool AsmDefinitionAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (AsmDefinitionAST *_other = pattern->asAsmDefinition())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool BaseSpecifierAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (BaseSpecifierAST *_other = pattern->asBaseSpecifier())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool IdExpressionAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (IdExpressionAST *_other = pattern->asIdExpression())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool CompoundExpressionAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (CompoundExpressionAST *_other = pattern->asCompoundExpression())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool CompoundLiteralAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (CompoundLiteralAST *_other = pattern->asCompoundLiteral())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool QtMethodAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (QtMethodAST *_other = pattern->asQtMethod())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool QtMemberDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (QtMemberDeclarationAST *_other = pattern->asQtMemberDeclaration())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool BinaryExpressionAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (BinaryExpressionAST *_other = pattern->asBinaryExpression())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool CastExpressionAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (CastExpressionAST *_other = pattern->asCastExpression())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ClassSpecifierAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ClassSpecifierAST *_other = pattern->asClassSpecifier())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool CaseStatementAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (CaseStatementAST *_other = pattern->asCaseStatement())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool CompoundStatementAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (CompoundStatementAST *_other = pattern->asCompoundStatement())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ConditionAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ConditionAST *_other = pattern->asCondition())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ConditionalExpressionAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ConditionalExpressionAST *_other = pattern->asConditionalExpression())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool CppCastExpressionAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (CppCastExpressionAST *_other = pattern->asCppCastExpression())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool CtorInitializerAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (CtorInitializerAST *_other = pattern->asCtorInitializer())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool DeclarationStatementAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (DeclarationStatementAST *_other = pattern->asDeclarationStatement())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool DeclaratorIdAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (DeclaratorIdAST *_other = pattern->asDeclaratorId())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool NestedDeclaratorAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (NestedDeclaratorAST *_other = pattern->asNestedDeclarator())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool FunctionDeclaratorAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (FunctionDeclaratorAST *_other = pattern->asFunctionDeclarator())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ArrayDeclaratorAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ArrayDeclaratorAST *_other = pattern->asArrayDeclarator())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool DeleteExpressionAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (DeleteExpressionAST *_other = pattern->asDeleteExpression())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool DoStatementAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (DoStatementAST *_other = pattern->asDoStatement())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool NamedTypeSpecifierAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (NamedTypeSpecifierAST *_other = pattern->asNamedTypeSpecifier())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ElaboratedTypeSpecifierAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ElaboratedTypeSpecifierAST *_other = pattern->asElaboratedTypeSpecifier())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool EnumSpecifierAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (EnumSpecifierAST *_other = pattern->asEnumSpecifier())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool EnumeratorAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (EnumeratorAST *_other = pattern->asEnumerator())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ExceptionDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ExceptionDeclarationAST *_other = pattern->asExceptionDeclaration())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool DynamicExceptionSpecificationAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (DynamicExceptionSpecificationAST *_other = pattern->asDynamicExceptionSpecification())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool NoExceptSpecificationAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (NoExceptSpecificationAST *_other = pattern->asNoExceptSpecification())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ExpressionOrDeclarationStatementAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ExpressionOrDeclarationStatementAST *_other = pattern->asExpressionOrDeclarationStatement())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ExpressionStatementAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ExpressionStatementAST *_other = pattern->asExpressionStatement())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool FunctionDefinitionAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (FunctionDefinitionAST *_other = pattern->asFunctionDefinition())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ForeachStatementAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ForeachStatementAST *_other = pattern->asForeachStatement())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool RangeBasedForStatementAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (RangeBasedForStatementAST *_other = pattern->asRangeBasedForStatement())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ForStatementAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ForStatementAST *_other = pattern->asForStatement())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool IfStatementAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (IfStatementAST *_other = pattern->asIfStatement())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ArrayInitializerAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ArrayInitializerAST *_other = pattern->asArrayInitializer())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool LabeledStatementAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (LabeledStatementAST *_other = pattern->asLabeledStatement())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool LinkageBodyAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (LinkageBodyAST *_other = pattern->asLinkageBody())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool LinkageSpecificationAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (LinkageSpecificationAST *_other = pattern->asLinkageSpecification())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool MemInitializerAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (MemInitializerAST *_other = pattern->asMemInitializer())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool NestedNameSpecifierAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (NestedNameSpecifierAST *_other = pattern->asNestedNameSpecifier())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool QualifiedNameAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (QualifiedNameAST *_other = pattern->asQualifiedName())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool OperatorFunctionIdAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (OperatorFunctionIdAST *_other = pattern->asOperatorFunctionId())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ConversionFunctionIdAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ConversionFunctionIdAST *_other = pattern->asConversionFunctionId())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool AnonymousNameAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (AnonymousNameAST *_other = pattern->asAnonymousName())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool SimpleNameAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (SimpleNameAST *_other = pattern->asSimpleName())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool DestructorNameAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (DestructorNameAST *_other = pattern->asDestructorName())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool TemplateIdAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (TemplateIdAST *_other = pattern->asTemplateId())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool NamespaceAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (NamespaceAST *_other = pattern->asNamespace())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool NamespaceAliasDefinitionAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (NamespaceAliasDefinitionAST *_other = pattern->asNamespaceAliasDefinition())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool AliasDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (AliasDeclarationAST *_other = pattern->asAliasDeclaration())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ExpressionListParenAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ExpressionListParenAST *_other = pattern->asExpressionListParen())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool NewArrayDeclaratorAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (NewArrayDeclaratorAST *_other = pattern->asNewArrayDeclarator())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool NewExpressionAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (NewExpressionAST *_other = pattern->asNewExpression())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool NewTypeIdAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (NewTypeIdAST *_other = pattern->asNewTypeId())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool OperatorAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (OperatorAST *_other = pattern->asOperator())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ParameterDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ParameterDeclarationAST *_other = pattern->asParameterDeclaration())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ParameterDeclarationClauseAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ParameterDeclarationClauseAST *_other = pattern->asParameterDeclarationClause())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool CallAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (CallAST *_other = pattern->asCall())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ArrayAccessAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ArrayAccessAST *_other = pattern->asArrayAccess())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool PostIncrDecrAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (PostIncrDecrAST *_other = pattern->asPostIncrDecr())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool MemberAccessAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (MemberAccessAST *_other = pattern->asMemberAccess())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool TypeidExpressionAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (TypeidExpressionAST *_other = pattern->asTypeidExpression())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool TypenameCallExpressionAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (TypenameCallExpressionAST *_other = pattern->asTypenameCallExpression())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool TypeConstructorCallAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (TypeConstructorCallAST *_other = pattern->asTypeConstructorCall())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool PointerToMemberAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (PointerToMemberAST *_other = pattern->asPointerToMember())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool PointerAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (PointerAST *_other = pattern->asPointer())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ReferenceAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ReferenceAST *_other = pattern->asReference())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool BreakStatementAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (BreakStatementAST *_other = pattern->asBreakStatement())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ContinueStatementAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ContinueStatementAST *_other = pattern->asContinueStatement())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool GotoStatementAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (GotoStatementAST *_other = pattern->asGotoStatement())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ReturnStatementAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ReturnStatementAST *_other = pattern->asReturnStatement())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool SizeofExpressionAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (SizeofExpressionAST *_other = pattern->asSizeofExpression())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool AlignofExpressionAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (AlignofExpressionAST *_other = pattern->asAlignofExpression())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool PointerLiteralAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (PointerLiteralAST *_other = pattern->asPointerLiteral())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool NumericLiteralAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (NumericLiteralAST *_other = pattern->asNumericLiteral())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool BoolLiteralAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (BoolLiteralAST *_other = pattern->asBoolLiteral())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ThisExpressionAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ThisExpressionAST *_other = pattern->asThisExpression())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool NestedExpressionAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (NestedExpressionAST *_other = pattern->asNestedExpression())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool StaticAssertDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (StaticAssertDeclarationAST *_other = pattern->asStaticAssertDeclaration())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool StringLiteralAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (StringLiteralAST *_other = pattern->asStringLiteral())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool SwitchStatementAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (SwitchStatementAST *_other = pattern->asSwitchStatement())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool TemplateDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (TemplateDeclarationAST *_other = pattern->asTemplateDeclaration())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ThrowExpressionAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ThrowExpressionAST *_other = pattern->asThrowExpression())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool TranslationUnitAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (TranslationUnitAST *_other = pattern->asTranslationUnit())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool TryBlockStatementAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (TryBlockStatementAST *_other = pattern->asTryBlockStatement())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool CatchClauseAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (CatchClauseAST *_other = pattern->asCatchClause())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool TypeIdAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (TypeIdAST *_other = pattern->asTypeId())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool TypenameTypeParameterAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (TypenameTypeParameterAST *_other = pattern->asTypenameTypeParameter())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool TemplateTypeParameterAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (TemplateTypeParameterAST *_other = pattern->asTemplateTypeParameter())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool UnaryExpressionAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (UnaryExpressionAST *_other = pattern->asUnaryExpression())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool UsingAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (UsingAST *_other = pattern->asUsing())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool UsingDirectiveAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (UsingDirectiveAST *_other = pattern->asUsingDirective())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool WhileStatementAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (WhileStatementAST *_other = pattern->asWhileStatement())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ObjCClassForwardDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ObjCClassForwardDeclarationAST *_other = pattern->asObjCClassForwardDeclaration())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ObjCClassDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ObjCClassDeclarationAST *_other = pattern->asObjCClassDeclaration())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ObjCProtocolForwardDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ObjCProtocolForwardDeclarationAST *_other = pattern->asObjCProtocolForwardDeclaration())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ObjCProtocolDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ObjCProtocolDeclarationAST *_other = pattern->asObjCProtocolDeclaration())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ObjCProtocolRefsAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ObjCProtocolRefsAST *_other = pattern->asObjCProtocolRefs())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ObjCMessageArgumentAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ObjCMessageArgumentAST *_other = pattern->asObjCMessageArgument())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ObjCMessageExpressionAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ObjCMessageExpressionAST *_other = pattern->asObjCMessageExpression())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ObjCProtocolExpressionAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ObjCProtocolExpressionAST *_other = pattern->asObjCProtocolExpression())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ObjCTypeNameAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ObjCTypeNameAST *_other = pattern->asObjCTypeName())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ObjCEncodeExpressionAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ObjCEncodeExpressionAST *_other = pattern->asObjCEncodeExpression())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ObjCSelectorExpressionAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ObjCSelectorExpressionAST *_other = pattern->asObjCSelectorExpression())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ObjCInstanceVariablesDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ObjCInstanceVariablesDeclarationAST *_other = pattern->asObjCInstanceVariablesDeclaration())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ObjCVisibilityDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ObjCVisibilityDeclarationAST *_other = pattern->asObjCVisibilityDeclaration())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ObjCPropertyAttributeAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ObjCPropertyAttributeAST *_other = pattern->asObjCPropertyAttribute())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ObjCPropertyDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ObjCPropertyDeclarationAST *_other = pattern->asObjCPropertyDeclaration())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ObjCMessageArgumentDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ObjCMessageArgumentDeclarationAST *_other = pattern->asObjCMessageArgumentDeclaration())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ObjCMethodPrototypeAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ObjCMethodPrototypeAST *_other = pattern->asObjCMethodPrototype())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ObjCMethodDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ObjCMethodDeclarationAST *_other = pattern->asObjCMethodDeclaration())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ObjCSynthesizedPropertyAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ObjCSynthesizedPropertyAST *_other = pattern->asObjCSynthesizedProperty())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ObjCSynthesizedPropertiesDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ObjCSynthesizedPropertiesDeclarationAST *_other = pattern->asObjCSynthesizedPropertiesDeclaration())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ObjCDynamicPropertiesDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ObjCDynamicPropertiesDeclarationAST *_other = pattern->asObjCDynamicPropertiesDeclaration())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ObjCFastEnumerationAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ObjCFastEnumerationAST *_other = pattern->asObjCFastEnumeration())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool ObjCSynchronizedStatementAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (ObjCSynchronizedStatementAST *_other = pattern->asObjCSynchronizedStatement())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool LambdaExpressionAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (LambdaExpressionAST *_other = pattern->asLambdaExpression())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool LambdaIntroducerAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (LambdaIntroducerAST *_other = pattern->asLambdaIntroducer())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool LambdaCaptureAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (LambdaCaptureAST *_other = pattern->asLambdaCapture())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool CaptureAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (CaptureAST *_other = pattern->asCapture())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool LambdaDeclaratorAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (LambdaDeclaratorAST *_other = pattern->asLambdaDeclarator())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool TrailingReturnTypeAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (TrailingReturnTypeAST *_other = pattern->asTrailingReturnType())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool BracedInitializerAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (BracedInitializerAST *_other = pattern->asBracedInitializer())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool DotDesignatorAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (DotDesignatorAST *_other = pattern->asDotDesignator())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool BracketDesignatorAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (BracketDesignatorAST *_other = pattern->asBracketDesignator())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool DesignatedInitializerAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (DesignatedInitializerAST *_other = pattern->asDesignatedInitializer())
+        return matcher->match(this, _other);
+
+    return false;
+}
+

+ 3071 - 0
Source/ToolCore/JSBind/cplusplus/ASTMatcher.cpp

@@ -0,0 +1,3071 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is automatically generated by "cplusplus-update-frontend".
+// Changes will be lost.
+//
+
+#include "AST.h"
+#include "ASTMatcher.h"
+
+using namespace CPlusPlus;
+
+ASTMatcher::ASTMatcher()
+{ }
+
+ASTMatcher::~ASTMatcher()
+{ }
+
+bool ASTMatcher::match(ObjCSelectorArgumentAST *node, ObjCSelectorArgumentAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->name_token = node->name_token;
+
+    pattern->colon_token = node->colon_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(ObjCSelectorAST *node, ObjCSelectorAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    if (! pattern->selector_argument_list)
+        pattern->selector_argument_list = node->selector_argument_list;
+    else if (! AST::match(node->selector_argument_list, pattern->selector_argument_list, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(SimpleSpecifierAST *node, SimpleSpecifierAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->specifier_token = node->specifier_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(AlignmentSpecifierAST *node, AlignmentSpecifierAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->align_token = node->align_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->typeIdExprOrAlignmentExpr)
+        pattern->typeIdExprOrAlignmentExpr = node->typeIdExprOrAlignmentExpr;
+    else if (! AST::match(node->typeIdExprOrAlignmentExpr, pattern->typeIdExprOrAlignmentExpr, this))
+        return false;
+
+    pattern->ellipses_token = node->ellipses_token;
+
+    pattern->rparen_token = node->rparen_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(GnuAttributeSpecifierAST *node, GnuAttributeSpecifierAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->attribute_token = node->attribute_token;
+
+    pattern->first_lparen_token = node->first_lparen_token;
+
+    pattern->second_lparen_token = node->second_lparen_token;
+
+    if (! pattern->attribute_list)
+        pattern->attribute_list = node->attribute_list;
+    else if (! AST::match(node->attribute_list, pattern->attribute_list, this))
+        return false;
+
+    pattern->first_rparen_token = node->first_rparen_token;
+
+    pattern->second_rparen_token = node->second_rparen_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(GnuAttributeAST *node, GnuAttributeAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->identifier_token = node->identifier_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    pattern->tag_token = node->tag_token;
+
+    if (! pattern->expression_list)
+        pattern->expression_list = node->expression_list;
+    else if (! AST::match(node->expression_list, pattern->expression_list, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(TypeofSpecifierAST *node, TypeofSpecifierAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->typeof_token = node->typeof_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->expression)
+        pattern->expression = node->expression;
+    else if (! AST::match(node->expression, pattern->expression, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(DecltypeSpecifierAST *node, DecltypeSpecifierAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->decltype_token = node->decltype_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->expression)
+        pattern->expression = node->expression;
+    else if (! AST::match(node->expression, pattern->expression, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(DeclaratorAST *node, DeclaratorAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    if (! pattern->attribute_list)
+        pattern->attribute_list = node->attribute_list;
+    else if (! AST::match(node->attribute_list, pattern->attribute_list, this))
+        return false;
+
+    if (! pattern->ptr_operator_list)
+        pattern->ptr_operator_list = node->ptr_operator_list;
+    else if (! AST::match(node->ptr_operator_list, pattern->ptr_operator_list, this))
+        return false;
+
+    if (! pattern->core_declarator)
+        pattern->core_declarator = node->core_declarator;
+    else if (! AST::match(node->core_declarator, pattern->core_declarator, this))
+        return false;
+
+    if (! pattern->postfix_declarator_list)
+        pattern->postfix_declarator_list = node->postfix_declarator_list;
+    else if (! AST::match(node->postfix_declarator_list, pattern->postfix_declarator_list, this))
+        return false;
+
+    if (! pattern->post_attribute_list)
+        pattern->post_attribute_list = node->post_attribute_list;
+    else if (! AST::match(node->post_attribute_list, pattern->post_attribute_list, this))
+        return false;
+
+    pattern->equal_token = node->equal_token;
+
+    if (! pattern->initializer)
+        pattern->initializer = node->initializer;
+    else if (! AST::match(node->initializer, pattern->initializer, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(SimpleDeclarationAST *node, SimpleDeclarationAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->qt_invokable_token = node->qt_invokable_token;
+
+    if (! pattern->decl_specifier_list)
+        pattern->decl_specifier_list = node->decl_specifier_list;
+    else if (! AST::match(node->decl_specifier_list, pattern->decl_specifier_list, this))
+        return false;
+
+    if (! pattern->declarator_list)
+        pattern->declarator_list = node->declarator_list;
+    else if (! AST::match(node->declarator_list, pattern->declarator_list, this))
+        return false;
+
+    pattern->semicolon_token = node->semicolon_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(EmptyDeclarationAST *node, EmptyDeclarationAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->semicolon_token = node->semicolon_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(AccessDeclarationAST *node, AccessDeclarationAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->access_specifier_token = node->access_specifier_token;
+
+    pattern->slots_token = node->slots_token;
+
+    pattern->colon_token = node->colon_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(QtObjectTagAST *node, QtObjectTagAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->q_object_token = node->q_object_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(QtPrivateSlotAST *node, QtPrivateSlotAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->q_private_slot_token = node->q_private_slot_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    pattern->dptr_token = node->dptr_token;
+
+    pattern->dptr_lparen_token = node->dptr_lparen_token;
+
+    pattern->dptr_rparen_token = node->dptr_rparen_token;
+
+    pattern->comma_token = node->comma_token;
+
+    if (! pattern->type_specifier_list)
+        pattern->type_specifier_list = node->type_specifier_list;
+    else if (! AST::match(node->type_specifier_list, pattern->type_specifier_list, this))
+        return false;
+
+    if (! pattern->declarator)
+        pattern->declarator = node->declarator;
+    else if (! AST::match(node->declarator, pattern->declarator, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(QtPropertyDeclarationItemAST *node, QtPropertyDeclarationItemAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->item_name_token = node->item_name_token;
+
+    if (! pattern->expression)
+        pattern->expression = node->expression;
+    else if (! AST::match(node->expression, pattern->expression, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(QtPropertyDeclarationAST *node, QtPropertyDeclarationAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->property_specifier_token = node->property_specifier_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->expression)
+        pattern->expression = node->expression;
+    else if (! AST::match(node->expression, pattern->expression, this))
+        return false;
+
+    pattern->comma_token = node->comma_token;
+
+    if (! pattern->type_id)
+        pattern->type_id = node->type_id;
+    else if (! AST::match(node->type_id, pattern->type_id, this))
+        return false;
+
+    if (! pattern->property_name)
+        pattern->property_name = node->property_name;
+    else if (! AST::match(node->property_name, pattern->property_name, this))
+        return false;
+
+    if (! pattern->property_declaration_item_list)
+        pattern->property_declaration_item_list = node->property_declaration_item_list;
+    else if (! AST::match(node->property_declaration_item_list, pattern->property_declaration_item_list, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(QtEnumDeclarationAST *node, QtEnumDeclarationAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->enum_specifier_token = node->enum_specifier_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->enumerator_list)
+        pattern->enumerator_list = node->enumerator_list;
+    else if (! AST::match(node->enumerator_list, pattern->enumerator_list, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(QtFlagsDeclarationAST *node, QtFlagsDeclarationAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->flags_specifier_token = node->flags_specifier_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->flag_enums_list)
+        pattern->flag_enums_list = node->flag_enums_list;
+    else if (! AST::match(node->flag_enums_list, pattern->flag_enums_list, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(QtInterfaceNameAST *node, QtInterfaceNameAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    if (! pattern->interface_name)
+        pattern->interface_name = node->interface_name;
+    else if (! AST::match(node->interface_name, pattern->interface_name, this))
+        return false;
+
+    if (! pattern->constraint_list)
+        pattern->constraint_list = node->constraint_list;
+    else if (! AST::match(node->constraint_list, pattern->constraint_list, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(QtInterfacesDeclarationAST *node, QtInterfacesDeclarationAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->interfaces_token = node->interfaces_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->interface_name_list)
+        pattern->interface_name_list = node->interface_name_list;
+    else if (! AST::match(node->interface_name_list, pattern->interface_name_list, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(AsmDefinitionAST *node, AsmDefinitionAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->asm_token = node->asm_token;
+
+    pattern->volatile_token = node->volatile_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    pattern->rparen_token = node->rparen_token;
+
+    pattern->semicolon_token = node->semicolon_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(BaseSpecifierAST *node, BaseSpecifierAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->virtual_token = node->virtual_token;
+
+    pattern->access_specifier_token = node->access_specifier_token;
+
+    if (! pattern->name)
+        pattern->name = node->name;
+    else if (! AST::match(node->name, pattern->name, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(IdExpressionAST *node, IdExpressionAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    if (! pattern->name)
+        pattern->name = node->name;
+    else if (! AST::match(node->name, pattern->name, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(CompoundExpressionAST *node, CompoundExpressionAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->statement)
+        pattern->statement = node->statement;
+    else if (! AST::match(node->statement, pattern->statement, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(CompoundLiteralAST *node, CompoundLiteralAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->type_id)
+        pattern->type_id = node->type_id;
+    else if (! AST::match(node->type_id, pattern->type_id, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    if (! pattern->initializer)
+        pattern->initializer = node->initializer;
+    else if (! AST::match(node->initializer, pattern->initializer, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(QtMethodAST *node, QtMethodAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->method_token = node->method_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->declarator)
+        pattern->declarator = node->declarator;
+    else if (! AST::match(node->declarator, pattern->declarator, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(QtMemberDeclarationAST *node, QtMemberDeclarationAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->q_token = node->q_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->type_id)
+        pattern->type_id = node->type_id;
+    else if (! AST::match(node->type_id, pattern->type_id, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(BinaryExpressionAST *node, BinaryExpressionAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    if (! pattern->left_expression)
+        pattern->left_expression = node->left_expression;
+    else if (! AST::match(node->left_expression, pattern->left_expression, this))
+        return false;
+
+    pattern->binary_op_token = node->binary_op_token;
+
+    if (! pattern->right_expression)
+        pattern->right_expression = node->right_expression;
+    else if (! AST::match(node->right_expression, pattern->right_expression, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(CastExpressionAST *node, CastExpressionAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->type_id)
+        pattern->type_id = node->type_id;
+    else if (! AST::match(node->type_id, pattern->type_id, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    if (! pattern->expression)
+        pattern->expression = node->expression;
+    else if (! AST::match(node->expression, pattern->expression, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(ClassSpecifierAST *node, ClassSpecifierAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->classkey_token = node->classkey_token;
+
+    if (! pattern->attribute_list)
+        pattern->attribute_list = node->attribute_list;
+    else if (! AST::match(node->attribute_list, pattern->attribute_list, this))
+        return false;
+
+    if (! pattern->name)
+        pattern->name = node->name;
+    else if (! AST::match(node->name, pattern->name, this))
+        return false;
+
+    pattern->final_token = node->final_token;
+
+    pattern->colon_token = node->colon_token;
+
+    if (! pattern->base_clause_list)
+        pattern->base_clause_list = node->base_clause_list;
+    else if (! AST::match(node->base_clause_list, pattern->base_clause_list, this))
+        return false;
+
+    pattern->dot_dot_dot_token = node->dot_dot_dot_token;
+
+    pattern->lbrace_token = node->lbrace_token;
+
+    if (! pattern->member_specifier_list)
+        pattern->member_specifier_list = node->member_specifier_list;
+    else if (! AST::match(node->member_specifier_list, pattern->member_specifier_list, this))
+        return false;
+
+    pattern->rbrace_token = node->rbrace_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(CaseStatementAST *node, CaseStatementAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->case_token = node->case_token;
+
+    if (! pattern->expression)
+        pattern->expression = node->expression;
+    else if (! AST::match(node->expression, pattern->expression, this))
+        return false;
+
+    pattern->colon_token = node->colon_token;
+
+    if (! pattern->statement)
+        pattern->statement = node->statement;
+    else if (! AST::match(node->statement, pattern->statement, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(CompoundStatementAST *node, CompoundStatementAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->lbrace_token = node->lbrace_token;
+
+    if (! pattern->statement_list)
+        pattern->statement_list = node->statement_list;
+    else if (! AST::match(node->statement_list, pattern->statement_list, this))
+        return false;
+
+    pattern->rbrace_token = node->rbrace_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(ConditionAST *node, ConditionAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    if (! pattern->type_specifier_list)
+        pattern->type_specifier_list = node->type_specifier_list;
+    else if (! AST::match(node->type_specifier_list, pattern->type_specifier_list, this))
+        return false;
+
+    if (! pattern->declarator)
+        pattern->declarator = node->declarator;
+    else if (! AST::match(node->declarator, pattern->declarator, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(ConditionalExpressionAST *node, ConditionalExpressionAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    if (! pattern->condition)
+        pattern->condition = node->condition;
+    else if (! AST::match(node->condition, pattern->condition, this))
+        return false;
+
+    pattern->question_token = node->question_token;
+
+    if (! pattern->left_expression)
+        pattern->left_expression = node->left_expression;
+    else if (! AST::match(node->left_expression, pattern->left_expression, this))
+        return false;
+
+    pattern->colon_token = node->colon_token;
+
+    if (! pattern->right_expression)
+        pattern->right_expression = node->right_expression;
+    else if (! AST::match(node->right_expression, pattern->right_expression, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(CppCastExpressionAST *node, CppCastExpressionAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->cast_token = node->cast_token;
+
+    pattern->less_token = node->less_token;
+
+    if (! pattern->type_id)
+        pattern->type_id = node->type_id;
+    else if (! AST::match(node->type_id, pattern->type_id, this))
+        return false;
+
+    pattern->greater_token = node->greater_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->expression)
+        pattern->expression = node->expression;
+    else if (! AST::match(node->expression, pattern->expression, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(CtorInitializerAST *node, CtorInitializerAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->colon_token = node->colon_token;
+
+    if (! pattern->member_initializer_list)
+        pattern->member_initializer_list = node->member_initializer_list;
+    else if (! AST::match(node->member_initializer_list, pattern->member_initializer_list, this))
+        return false;
+
+    pattern->dot_dot_dot_token = node->dot_dot_dot_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(DeclarationStatementAST *node, DeclarationStatementAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    if (! pattern->declaration)
+        pattern->declaration = node->declaration;
+    else if (! AST::match(node->declaration, pattern->declaration, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(DeclaratorIdAST *node, DeclaratorIdAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->dot_dot_dot_token = node->dot_dot_dot_token;
+
+    if (! pattern->name)
+        pattern->name = node->name;
+    else if (! AST::match(node->name, pattern->name, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(NestedDeclaratorAST *node, NestedDeclaratorAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->declarator)
+        pattern->declarator = node->declarator;
+    else if (! AST::match(node->declarator, pattern->declarator, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(FunctionDeclaratorAST *node, FunctionDeclaratorAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->parameter_declaration_clause)
+        pattern->parameter_declaration_clause = node->parameter_declaration_clause;
+    else if (! AST::match(node->parameter_declaration_clause, pattern->parameter_declaration_clause, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    if (! pattern->cv_qualifier_list)
+        pattern->cv_qualifier_list = node->cv_qualifier_list;
+    else if (! AST::match(node->cv_qualifier_list, pattern->cv_qualifier_list, this))
+        return false;
+
+    pattern->ref_qualifier_token = node->ref_qualifier_token;
+
+    if (! pattern->exception_specification)
+        pattern->exception_specification = node->exception_specification;
+    else if (! AST::match(node->exception_specification, pattern->exception_specification, this))
+        return false;
+
+    if (! pattern->trailing_return_type)
+        pattern->trailing_return_type = node->trailing_return_type;
+    else if (! AST::match(node->trailing_return_type, pattern->trailing_return_type, this))
+        return false;
+
+    if (! pattern->as_cpp_initializer)
+        pattern->as_cpp_initializer = node->as_cpp_initializer;
+    else if (! AST::match(node->as_cpp_initializer, pattern->as_cpp_initializer, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(ArrayDeclaratorAST *node, ArrayDeclaratorAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->lbracket_token = node->lbracket_token;
+
+    if (! pattern->expression)
+        pattern->expression = node->expression;
+    else if (! AST::match(node->expression, pattern->expression, this))
+        return false;
+
+    pattern->rbracket_token = node->rbracket_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(DeleteExpressionAST *node, DeleteExpressionAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->scope_token = node->scope_token;
+
+    pattern->delete_token = node->delete_token;
+
+    pattern->lbracket_token = node->lbracket_token;
+
+    pattern->rbracket_token = node->rbracket_token;
+
+    if (! pattern->expression)
+        pattern->expression = node->expression;
+    else if (! AST::match(node->expression, pattern->expression, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(DoStatementAST *node, DoStatementAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->do_token = node->do_token;
+
+    if (! pattern->statement)
+        pattern->statement = node->statement;
+    else if (! AST::match(node->statement, pattern->statement, this))
+        return false;
+
+    pattern->while_token = node->while_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->expression)
+        pattern->expression = node->expression;
+    else if (! AST::match(node->expression, pattern->expression, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    pattern->semicolon_token = node->semicolon_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(NamedTypeSpecifierAST *node, NamedTypeSpecifierAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    if (! pattern->name)
+        pattern->name = node->name;
+    else if (! AST::match(node->name, pattern->name, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(ElaboratedTypeSpecifierAST *node, ElaboratedTypeSpecifierAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->classkey_token = node->classkey_token;
+
+    if (! pattern->attribute_list)
+        pattern->attribute_list = node->attribute_list;
+    else if (! AST::match(node->attribute_list, pattern->attribute_list, this))
+        return false;
+
+    if (! pattern->name)
+        pattern->name = node->name;
+    else if (! AST::match(node->name, pattern->name, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(EnumSpecifierAST *node, EnumSpecifierAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->enum_token = node->enum_token;
+
+    pattern->key_token = node->key_token;
+
+    if (! pattern->name)
+        pattern->name = node->name;
+    else if (! AST::match(node->name, pattern->name, this))
+        return false;
+
+    pattern->colon_token = node->colon_token;
+
+    if (! pattern->type_specifier_list)
+        pattern->type_specifier_list = node->type_specifier_list;
+    else if (! AST::match(node->type_specifier_list, pattern->type_specifier_list, this))
+        return false;
+
+    pattern->lbrace_token = node->lbrace_token;
+
+    if (! pattern->enumerator_list)
+        pattern->enumerator_list = node->enumerator_list;
+    else if (! AST::match(node->enumerator_list, pattern->enumerator_list, this))
+        return false;
+
+    pattern->stray_comma_token = node->stray_comma_token;
+
+    pattern->rbrace_token = node->rbrace_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(EnumeratorAST *node, EnumeratorAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->identifier_token = node->identifier_token;
+
+    pattern->equal_token = node->equal_token;
+
+    if (! pattern->expression)
+        pattern->expression = node->expression;
+    else if (! AST::match(node->expression, pattern->expression, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(ExceptionDeclarationAST *node, ExceptionDeclarationAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    if (! pattern->type_specifier_list)
+        pattern->type_specifier_list = node->type_specifier_list;
+    else if (! AST::match(node->type_specifier_list, pattern->type_specifier_list, this))
+        return false;
+
+    if (! pattern->declarator)
+        pattern->declarator = node->declarator;
+    else if (! AST::match(node->declarator, pattern->declarator, this))
+        return false;
+
+    pattern->dot_dot_dot_token = node->dot_dot_dot_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(DynamicExceptionSpecificationAST *node, DynamicExceptionSpecificationAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->throw_token = node->throw_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    pattern->dot_dot_dot_token = node->dot_dot_dot_token;
+
+    if (! pattern->type_id_list)
+        pattern->type_id_list = node->type_id_list;
+    else if (! AST::match(node->type_id_list, pattern->type_id_list, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(NoExceptSpecificationAST *node, NoExceptSpecificationAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->noexcept_token = node->noexcept_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->expression)
+        pattern->expression = node->expression;
+    else if (! AST::match(node->expression, pattern->expression, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(ExpressionOrDeclarationStatementAST *node, ExpressionOrDeclarationStatementAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    if (! pattern->expression)
+        pattern->expression = node->expression;
+    else if (! AST::match(node->expression, pattern->expression, this))
+        return false;
+
+    if (! pattern->declaration)
+        pattern->declaration = node->declaration;
+    else if (! AST::match(node->declaration, pattern->declaration, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(ExpressionStatementAST *node, ExpressionStatementAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    if (! pattern->expression)
+        pattern->expression = node->expression;
+    else if (! AST::match(node->expression, pattern->expression, this))
+        return false;
+
+    pattern->semicolon_token = node->semicolon_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(FunctionDefinitionAST *node, FunctionDefinitionAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->qt_invokable_token = node->qt_invokable_token;
+
+    if (! pattern->decl_specifier_list)
+        pattern->decl_specifier_list = node->decl_specifier_list;
+    else if (! AST::match(node->decl_specifier_list, pattern->decl_specifier_list, this))
+        return false;
+
+    if (! pattern->declarator)
+        pattern->declarator = node->declarator;
+    else if (! AST::match(node->declarator, pattern->declarator, this))
+        return false;
+
+    if (! pattern->ctor_initializer)
+        pattern->ctor_initializer = node->ctor_initializer;
+    else if (! AST::match(node->ctor_initializer, pattern->ctor_initializer, this))
+        return false;
+
+    if (! pattern->function_body)
+        pattern->function_body = node->function_body;
+    else if (! AST::match(node->function_body, pattern->function_body, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(ForeachStatementAST *node, ForeachStatementAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->foreach_token = node->foreach_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->type_specifier_list)
+        pattern->type_specifier_list = node->type_specifier_list;
+    else if (! AST::match(node->type_specifier_list, pattern->type_specifier_list, this))
+        return false;
+
+    if (! pattern->declarator)
+        pattern->declarator = node->declarator;
+    else if (! AST::match(node->declarator, pattern->declarator, this))
+        return false;
+
+    if (! pattern->initializer)
+        pattern->initializer = node->initializer;
+    else if (! AST::match(node->initializer, pattern->initializer, this))
+        return false;
+
+    pattern->comma_token = node->comma_token;
+
+    if (! pattern->expression)
+        pattern->expression = node->expression;
+    else if (! AST::match(node->expression, pattern->expression, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    if (! pattern->statement)
+        pattern->statement = node->statement;
+    else if (! AST::match(node->statement, pattern->statement, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(RangeBasedForStatementAST *node, RangeBasedForStatementAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->for_token = node->for_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->type_specifier_list)
+        pattern->type_specifier_list = node->type_specifier_list;
+    else if (! AST::match(node->type_specifier_list, pattern->type_specifier_list, this))
+        return false;
+
+    if (! pattern->declarator)
+        pattern->declarator = node->declarator;
+    else if (! AST::match(node->declarator, pattern->declarator, this))
+        return false;
+
+    pattern->colon_token = node->colon_token;
+
+    if (! pattern->expression)
+        pattern->expression = node->expression;
+    else if (! AST::match(node->expression, pattern->expression, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    if (! pattern->statement)
+        pattern->statement = node->statement;
+    else if (! AST::match(node->statement, pattern->statement, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(ForStatementAST *node, ForStatementAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->for_token = node->for_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->initializer)
+        pattern->initializer = node->initializer;
+    else if (! AST::match(node->initializer, pattern->initializer, this))
+        return false;
+
+    if (! pattern->condition)
+        pattern->condition = node->condition;
+    else if (! AST::match(node->condition, pattern->condition, this))
+        return false;
+
+    pattern->semicolon_token = node->semicolon_token;
+
+    if (! pattern->expression)
+        pattern->expression = node->expression;
+    else if (! AST::match(node->expression, pattern->expression, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    if (! pattern->statement)
+        pattern->statement = node->statement;
+    else if (! AST::match(node->statement, pattern->statement, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(IfStatementAST *node, IfStatementAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->if_token = node->if_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->condition)
+        pattern->condition = node->condition;
+    else if (! AST::match(node->condition, pattern->condition, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    if (! pattern->statement)
+        pattern->statement = node->statement;
+    else if (! AST::match(node->statement, pattern->statement, this))
+        return false;
+
+    pattern->else_token = node->else_token;
+
+    if (! pattern->else_statement)
+        pattern->else_statement = node->else_statement;
+    else if (! AST::match(node->else_statement, pattern->else_statement, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(ArrayInitializerAST *node, ArrayInitializerAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->lbrace_token = node->lbrace_token;
+
+    if (! pattern->expression_list)
+        pattern->expression_list = node->expression_list;
+    else if (! AST::match(node->expression_list, pattern->expression_list, this))
+        return false;
+
+    pattern->rbrace_token = node->rbrace_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(LabeledStatementAST *node, LabeledStatementAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->label_token = node->label_token;
+
+    pattern->colon_token = node->colon_token;
+
+    if (! pattern->statement)
+        pattern->statement = node->statement;
+    else if (! AST::match(node->statement, pattern->statement, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(LinkageBodyAST *node, LinkageBodyAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->lbrace_token = node->lbrace_token;
+
+    if (! pattern->declaration_list)
+        pattern->declaration_list = node->declaration_list;
+    else if (! AST::match(node->declaration_list, pattern->declaration_list, this))
+        return false;
+
+    pattern->rbrace_token = node->rbrace_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(LinkageSpecificationAST *node, LinkageSpecificationAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->extern_token = node->extern_token;
+
+    pattern->extern_type_token = node->extern_type_token;
+
+    if (! pattern->declaration)
+        pattern->declaration = node->declaration;
+    else if (! AST::match(node->declaration, pattern->declaration, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(MemInitializerAST *node, MemInitializerAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    if (! pattern->name)
+        pattern->name = node->name;
+    else if (! AST::match(node->name, pattern->name, this))
+        return false;
+
+    if (! pattern->expression)
+        pattern->expression = node->expression;
+    else if (! AST::match(node->expression, pattern->expression, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(NestedNameSpecifierAST *node, NestedNameSpecifierAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    if (! pattern->class_or_namespace_name)
+        pattern->class_or_namespace_name = node->class_or_namespace_name;
+    else if (! AST::match(node->class_or_namespace_name, pattern->class_or_namespace_name, this))
+        return false;
+
+    pattern->scope_token = node->scope_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(QualifiedNameAST *node, QualifiedNameAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->global_scope_token = node->global_scope_token;
+
+    if (! pattern->nested_name_specifier_list)
+        pattern->nested_name_specifier_list = node->nested_name_specifier_list;
+    else if (! AST::match(node->nested_name_specifier_list, pattern->nested_name_specifier_list, this))
+        return false;
+
+    if (! pattern->unqualified_name)
+        pattern->unqualified_name = node->unqualified_name;
+    else if (! AST::match(node->unqualified_name, pattern->unqualified_name, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(OperatorFunctionIdAST *node, OperatorFunctionIdAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->operator_token = node->operator_token;
+
+    if (! pattern->op)
+        pattern->op = node->op;
+    else if (! AST::match(node->op, pattern->op, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(ConversionFunctionIdAST *node, ConversionFunctionIdAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->operator_token = node->operator_token;
+
+    if (! pattern->type_specifier_list)
+        pattern->type_specifier_list = node->type_specifier_list;
+    else if (! AST::match(node->type_specifier_list, pattern->type_specifier_list, this))
+        return false;
+
+    if (! pattern->ptr_operator_list)
+        pattern->ptr_operator_list = node->ptr_operator_list;
+    else if (! AST::match(node->ptr_operator_list, pattern->ptr_operator_list, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(AnonymousNameAST *node, AnonymousNameAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->class_token = node->class_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(SimpleNameAST *node, SimpleNameAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->identifier_token = node->identifier_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(DestructorNameAST *node, DestructorNameAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->tilde_token = node->tilde_token;
+
+    if (! pattern->unqualified_name)
+        pattern->unqualified_name = node->unqualified_name;
+    else if (! AST::match(node->unqualified_name, pattern->unqualified_name, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(TemplateIdAST *node, TemplateIdAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->template_token = node->template_token;
+
+    pattern->identifier_token = node->identifier_token;
+
+    pattern->less_token = node->less_token;
+
+    if (! pattern->template_argument_list)
+        pattern->template_argument_list = node->template_argument_list;
+    else if (! AST::match(node->template_argument_list, pattern->template_argument_list, this))
+        return false;
+
+    pattern->greater_token = node->greater_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(NamespaceAST *node, NamespaceAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->inline_token = node->inline_token;
+
+    pattern->namespace_token = node->namespace_token;
+
+    pattern->identifier_token = node->identifier_token;
+
+    if (! pattern->attribute_list)
+        pattern->attribute_list = node->attribute_list;
+    else if (! AST::match(node->attribute_list, pattern->attribute_list, this))
+        return false;
+
+    if (! pattern->linkage_body)
+        pattern->linkage_body = node->linkage_body;
+    else if (! AST::match(node->linkage_body, pattern->linkage_body, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(NamespaceAliasDefinitionAST *node, NamespaceAliasDefinitionAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->namespace_token = node->namespace_token;
+
+    pattern->namespace_name_token = node->namespace_name_token;
+
+    pattern->equal_token = node->equal_token;
+
+    if (! pattern->name)
+        pattern->name = node->name;
+    else if (! AST::match(node->name, pattern->name, this))
+        return false;
+
+    pattern->semicolon_token = node->semicolon_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(AliasDeclarationAST *node, AliasDeclarationAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->using_token = node->using_token;
+
+    if (! pattern->name)
+        pattern->name = node->name;
+    else if (! AST::match(node->name, pattern->name, this))
+        return false;
+
+    pattern->equal_token = node->equal_token;
+
+    if (! pattern->typeId)
+        pattern->typeId = node->typeId;
+    else if (! AST::match(node->typeId, pattern->typeId, this))
+        return false;
+
+    pattern->semicolon_token = node->semicolon_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(ExpressionListParenAST *node, ExpressionListParenAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->expression_list)
+        pattern->expression_list = node->expression_list;
+    else if (! AST::match(node->expression_list, pattern->expression_list, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(NewArrayDeclaratorAST *node, NewArrayDeclaratorAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->lbracket_token = node->lbracket_token;
+
+    if (! pattern->expression)
+        pattern->expression = node->expression;
+    else if (! AST::match(node->expression, pattern->expression, this))
+        return false;
+
+    pattern->rbracket_token = node->rbracket_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(NewExpressionAST *node, NewExpressionAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->scope_token = node->scope_token;
+
+    pattern->new_token = node->new_token;
+
+    if (! pattern->new_placement)
+        pattern->new_placement = node->new_placement;
+    else if (! AST::match(node->new_placement, pattern->new_placement, this))
+        return false;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->type_id)
+        pattern->type_id = node->type_id;
+    else if (! AST::match(node->type_id, pattern->type_id, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    if (! pattern->new_type_id)
+        pattern->new_type_id = node->new_type_id;
+    else if (! AST::match(node->new_type_id, pattern->new_type_id, this))
+        return false;
+
+    if (! pattern->new_initializer)
+        pattern->new_initializer = node->new_initializer;
+    else if (! AST::match(node->new_initializer, pattern->new_initializer, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(NewTypeIdAST *node, NewTypeIdAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    if (! pattern->type_specifier_list)
+        pattern->type_specifier_list = node->type_specifier_list;
+    else if (! AST::match(node->type_specifier_list, pattern->type_specifier_list, this))
+        return false;
+
+    if (! pattern->ptr_operator_list)
+        pattern->ptr_operator_list = node->ptr_operator_list;
+    else if (! AST::match(node->ptr_operator_list, pattern->ptr_operator_list, this))
+        return false;
+
+    if (! pattern->new_array_declarator_list)
+        pattern->new_array_declarator_list = node->new_array_declarator_list;
+    else if (! AST::match(node->new_array_declarator_list, pattern->new_array_declarator_list, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(OperatorAST *node, OperatorAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->op_token = node->op_token;
+
+    pattern->open_token = node->open_token;
+
+    pattern->close_token = node->close_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(ParameterDeclarationAST *node, ParameterDeclarationAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    if (! pattern->type_specifier_list)
+        pattern->type_specifier_list = node->type_specifier_list;
+    else if (! AST::match(node->type_specifier_list, pattern->type_specifier_list, this))
+        return false;
+
+    if (! pattern->declarator)
+        pattern->declarator = node->declarator;
+    else if (! AST::match(node->declarator, pattern->declarator, this))
+        return false;
+
+    pattern->equal_token = node->equal_token;
+
+    if (! pattern->expression)
+        pattern->expression = node->expression;
+    else if (! AST::match(node->expression, pattern->expression, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(ParameterDeclarationClauseAST *node, ParameterDeclarationClauseAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    if (! pattern->parameter_declaration_list)
+        pattern->parameter_declaration_list = node->parameter_declaration_list;
+    else if (! AST::match(node->parameter_declaration_list, pattern->parameter_declaration_list, this))
+        return false;
+
+    pattern->dot_dot_dot_token = node->dot_dot_dot_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(CallAST *node, CallAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    if (! pattern->base_expression)
+        pattern->base_expression = node->base_expression;
+    else if (! AST::match(node->base_expression, pattern->base_expression, this))
+        return false;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->expression_list)
+        pattern->expression_list = node->expression_list;
+    else if (! AST::match(node->expression_list, pattern->expression_list, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(ArrayAccessAST *node, ArrayAccessAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    if (! pattern->base_expression)
+        pattern->base_expression = node->base_expression;
+    else if (! AST::match(node->base_expression, pattern->base_expression, this))
+        return false;
+
+    pattern->lbracket_token = node->lbracket_token;
+
+    if (! pattern->expression)
+        pattern->expression = node->expression;
+    else if (! AST::match(node->expression, pattern->expression, this))
+        return false;
+
+    pattern->rbracket_token = node->rbracket_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(PostIncrDecrAST *node, PostIncrDecrAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    if (! pattern->base_expression)
+        pattern->base_expression = node->base_expression;
+    else if (! AST::match(node->base_expression, pattern->base_expression, this))
+        return false;
+
+    pattern->incr_decr_token = node->incr_decr_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(MemberAccessAST *node, MemberAccessAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    if (! pattern->base_expression)
+        pattern->base_expression = node->base_expression;
+    else if (! AST::match(node->base_expression, pattern->base_expression, this))
+        return false;
+
+    pattern->access_token = node->access_token;
+
+    pattern->template_token = node->template_token;
+
+    if (! pattern->member_name)
+        pattern->member_name = node->member_name;
+    else if (! AST::match(node->member_name, pattern->member_name, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(TypeidExpressionAST *node, TypeidExpressionAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->typeid_token = node->typeid_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->expression)
+        pattern->expression = node->expression;
+    else if (! AST::match(node->expression, pattern->expression, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(TypenameCallExpressionAST *node, TypenameCallExpressionAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->typename_token = node->typename_token;
+
+    if (! pattern->name)
+        pattern->name = node->name;
+    else if (! AST::match(node->name, pattern->name, this))
+        return false;
+
+    if (! pattern->expression)
+        pattern->expression = node->expression;
+    else if (! AST::match(node->expression, pattern->expression, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(TypeConstructorCallAST *node, TypeConstructorCallAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    if (! pattern->type_specifier_list)
+        pattern->type_specifier_list = node->type_specifier_list;
+    else if (! AST::match(node->type_specifier_list, pattern->type_specifier_list, this))
+        return false;
+
+    if (! pattern->expression)
+        pattern->expression = node->expression;
+    else if (! AST::match(node->expression, pattern->expression, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(PointerToMemberAST *node, PointerToMemberAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->global_scope_token = node->global_scope_token;
+
+    if (! pattern->nested_name_specifier_list)
+        pattern->nested_name_specifier_list = node->nested_name_specifier_list;
+    else if (! AST::match(node->nested_name_specifier_list, pattern->nested_name_specifier_list, this))
+        return false;
+
+    pattern->star_token = node->star_token;
+
+    if (! pattern->cv_qualifier_list)
+        pattern->cv_qualifier_list = node->cv_qualifier_list;
+    else if (! AST::match(node->cv_qualifier_list, pattern->cv_qualifier_list, this))
+        return false;
+
+    pattern->ref_qualifier_token = node->ref_qualifier_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(PointerAST *node, PointerAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->star_token = node->star_token;
+
+    if (! pattern->cv_qualifier_list)
+        pattern->cv_qualifier_list = node->cv_qualifier_list;
+    else if (! AST::match(node->cv_qualifier_list, pattern->cv_qualifier_list, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(ReferenceAST *node, ReferenceAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->reference_token = node->reference_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(BreakStatementAST *node, BreakStatementAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->break_token = node->break_token;
+
+    pattern->semicolon_token = node->semicolon_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(ContinueStatementAST *node, ContinueStatementAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->continue_token = node->continue_token;
+
+    pattern->semicolon_token = node->semicolon_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(GotoStatementAST *node, GotoStatementAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->goto_token = node->goto_token;
+
+    pattern->identifier_token = node->identifier_token;
+
+    pattern->semicolon_token = node->semicolon_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(ReturnStatementAST *node, ReturnStatementAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->return_token = node->return_token;
+
+    if (! pattern->expression)
+        pattern->expression = node->expression;
+    else if (! AST::match(node->expression, pattern->expression, this))
+        return false;
+
+    pattern->semicolon_token = node->semicolon_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(SizeofExpressionAST *node, SizeofExpressionAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->sizeof_token = node->sizeof_token;
+
+    pattern->dot_dot_dot_token = node->dot_dot_dot_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->expression)
+        pattern->expression = node->expression;
+    else if (! AST::match(node->expression, pattern->expression, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(AlignofExpressionAST *node, AlignofExpressionAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->alignof_token = node->alignof_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->typeId)
+        pattern->typeId = node->typeId;
+    else if (! AST::match(node->typeId, pattern->typeId, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(PointerLiteralAST *node, PointerLiteralAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->literal_token = node->literal_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(NumericLiteralAST *node, NumericLiteralAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->literal_token = node->literal_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(BoolLiteralAST *node, BoolLiteralAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->literal_token = node->literal_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(ThisExpressionAST *node, ThisExpressionAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->this_token = node->this_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(NestedExpressionAST *node, NestedExpressionAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->expression)
+        pattern->expression = node->expression;
+    else if (! AST::match(node->expression, pattern->expression, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(StaticAssertDeclarationAST *node, StaticAssertDeclarationAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->static_assert_token = node->static_assert_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->expression)
+        pattern->expression = node->expression;
+    else if (! AST::match(node->expression, pattern->expression, this))
+        return false;
+
+    pattern->comma_token = node->comma_token;
+
+    if (! pattern->string_literal)
+        pattern->string_literal = node->string_literal;
+    else if (! AST::match(node->string_literal, pattern->string_literal, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    pattern->semicolon_token = node->semicolon_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(StringLiteralAST *node, StringLiteralAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->literal_token = node->literal_token;
+
+    if (! pattern->next)
+        pattern->next = node->next;
+    else if (! AST::match(node->next, pattern->next, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(SwitchStatementAST *node, SwitchStatementAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->switch_token = node->switch_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->condition)
+        pattern->condition = node->condition;
+    else if (! AST::match(node->condition, pattern->condition, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    if (! pattern->statement)
+        pattern->statement = node->statement;
+    else if (! AST::match(node->statement, pattern->statement, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(TemplateDeclarationAST *node, TemplateDeclarationAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->export_token = node->export_token;
+
+    pattern->template_token = node->template_token;
+
+    pattern->less_token = node->less_token;
+
+    if (! pattern->template_parameter_list)
+        pattern->template_parameter_list = node->template_parameter_list;
+    else if (! AST::match(node->template_parameter_list, pattern->template_parameter_list, this))
+        return false;
+
+    pattern->greater_token = node->greater_token;
+
+    if (! pattern->declaration)
+        pattern->declaration = node->declaration;
+    else if (! AST::match(node->declaration, pattern->declaration, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(ThrowExpressionAST *node, ThrowExpressionAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->throw_token = node->throw_token;
+
+    if (! pattern->expression)
+        pattern->expression = node->expression;
+    else if (! AST::match(node->expression, pattern->expression, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(TranslationUnitAST *node, TranslationUnitAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    if (! pattern->declaration_list)
+        pattern->declaration_list = node->declaration_list;
+    else if (! AST::match(node->declaration_list, pattern->declaration_list, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(TryBlockStatementAST *node, TryBlockStatementAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->try_token = node->try_token;
+
+    if (! pattern->statement)
+        pattern->statement = node->statement;
+    else if (! AST::match(node->statement, pattern->statement, this))
+        return false;
+
+    if (! pattern->catch_clause_list)
+        pattern->catch_clause_list = node->catch_clause_list;
+    else if (! AST::match(node->catch_clause_list, pattern->catch_clause_list, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(CatchClauseAST *node, CatchClauseAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->catch_token = node->catch_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->exception_declaration)
+        pattern->exception_declaration = node->exception_declaration;
+    else if (! AST::match(node->exception_declaration, pattern->exception_declaration, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    if (! pattern->statement)
+        pattern->statement = node->statement;
+    else if (! AST::match(node->statement, pattern->statement, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(TypeIdAST *node, TypeIdAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    if (! pattern->type_specifier_list)
+        pattern->type_specifier_list = node->type_specifier_list;
+    else if (! AST::match(node->type_specifier_list, pattern->type_specifier_list, this))
+        return false;
+
+    if (! pattern->declarator)
+        pattern->declarator = node->declarator;
+    else if (! AST::match(node->declarator, pattern->declarator, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(TypenameTypeParameterAST *node, TypenameTypeParameterAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->classkey_token = node->classkey_token;
+
+    pattern->dot_dot_dot_token = node->dot_dot_dot_token;
+
+    if (! pattern->name)
+        pattern->name = node->name;
+    else if (! AST::match(node->name, pattern->name, this))
+        return false;
+
+    pattern->equal_token = node->equal_token;
+
+    if (! pattern->type_id)
+        pattern->type_id = node->type_id;
+    else if (! AST::match(node->type_id, pattern->type_id, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(TemplateTypeParameterAST *node, TemplateTypeParameterAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->template_token = node->template_token;
+
+    pattern->less_token = node->less_token;
+
+    if (! pattern->template_parameter_list)
+        pattern->template_parameter_list = node->template_parameter_list;
+    else if (! AST::match(node->template_parameter_list, pattern->template_parameter_list, this))
+        return false;
+
+    pattern->greater_token = node->greater_token;
+
+    pattern->class_token = node->class_token;
+
+    pattern->dot_dot_dot_token = node->dot_dot_dot_token;
+
+    if (! pattern->name)
+        pattern->name = node->name;
+    else if (! AST::match(node->name, pattern->name, this))
+        return false;
+
+    pattern->equal_token = node->equal_token;
+
+    if (! pattern->type_id)
+        pattern->type_id = node->type_id;
+    else if (! AST::match(node->type_id, pattern->type_id, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(UnaryExpressionAST *node, UnaryExpressionAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->unary_op_token = node->unary_op_token;
+
+    if (! pattern->expression)
+        pattern->expression = node->expression;
+    else if (! AST::match(node->expression, pattern->expression, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(UsingAST *node, UsingAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->using_token = node->using_token;
+
+    pattern->typename_token = node->typename_token;
+
+    if (! pattern->name)
+        pattern->name = node->name;
+    else if (! AST::match(node->name, pattern->name, this))
+        return false;
+
+    pattern->semicolon_token = node->semicolon_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(UsingDirectiveAST *node, UsingDirectiveAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->using_token = node->using_token;
+
+    pattern->namespace_token = node->namespace_token;
+
+    if (! pattern->name)
+        pattern->name = node->name;
+    else if (! AST::match(node->name, pattern->name, this))
+        return false;
+
+    pattern->semicolon_token = node->semicolon_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(WhileStatementAST *node, WhileStatementAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->while_token = node->while_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->condition)
+        pattern->condition = node->condition;
+    else if (! AST::match(node->condition, pattern->condition, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    if (! pattern->statement)
+        pattern->statement = node->statement;
+    else if (! AST::match(node->statement, pattern->statement, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(ObjCClassForwardDeclarationAST *node, ObjCClassForwardDeclarationAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    if (! pattern->attribute_list)
+        pattern->attribute_list = node->attribute_list;
+    else if (! AST::match(node->attribute_list, pattern->attribute_list, this))
+        return false;
+
+    pattern->class_token = node->class_token;
+
+    if (! pattern->identifier_list)
+        pattern->identifier_list = node->identifier_list;
+    else if (! AST::match(node->identifier_list, pattern->identifier_list, this))
+        return false;
+
+    pattern->semicolon_token = node->semicolon_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(ObjCClassDeclarationAST *node, ObjCClassDeclarationAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    if (! pattern->attribute_list)
+        pattern->attribute_list = node->attribute_list;
+    else if (! AST::match(node->attribute_list, pattern->attribute_list, this))
+        return false;
+
+    pattern->interface_token = node->interface_token;
+
+    pattern->implementation_token = node->implementation_token;
+
+    if (! pattern->class_name)
+        pattern->class_name = node->class_name;
+    else if (! AST::match(node->class_name, pattern->class_name, this))
+        return false;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->category_name)
+        pattern->category_name = node->category_name;
+    else if (! AST::match(node->category_name, pattern->category_name, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    pattern->colon_token = node->colon_token;
+
+    if (! pattern->superclass)
+        pattern->superclass = node->superclass;
+    else if (! AST::match(node->superclass, pattern->superclass, this))
+        return false;
+
+    if (! pattern->protocol_refs)
+        pattern->protocol_refs = node->protocol_refs;
+    else if (! AST::match(node->protocol_refs, pattern->protocol_refs, this))
+        return false;
+
+    if (! pattern->inst_vars_decl)
+        pattern->inst_vars_decl = node->inst_vars_decl;
+    else if (! AST::match(node->inst_vars_decl, pattern->inst_vars_decl, this))
+        return false;
+
+    if (! pattern->member_declaration_list)
+        pattern->member_declaration_list = node->member_declaration_list;
+    else if (! AST::match(node->member_declaration_list, pattern->member_declaration_list, this))
+        return false;
+
+    pattern->end_token = node->end_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(ObjCProtocolForwardDeclarationAST *node, ObjCProtocolForwardDeclarationAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    if (! pattern->attribute_list)
+        pattern->attribute_list = node->attribute_list;
+    else if (! AST::match(node->attribute_list, pattern->attribute_list, this))
+        return false;
+
+    pattern->protocol_token = node->protocol_token;
+
+    if (! pattern->identifier_list)
+        pattern->identifier_list = node->identifier_list;
+    else if (! AST::match(node->identifier_list, pattern->identifier_list, this))
+        return false;
+
+    pattern->semicolon_token = node->semicolon_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(ObjCProtocolDeclarationAST *node, ObjCProtocolDeclarationAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    if (! pattern->attribute_list)
+        pattern->attribute_list = node->attribute_list;
+    else if (! AST::match(node->attribute_list, pattern->attribute_list, this))
+        return false;
+
+    pattern->protocol_token = node->protocol_token;
+
+    if (! pattern->name)
+        pattern->name = node->name;
+    else if (! AST::match(node->name, pattern->name, this))
+        return false;
+
+    if (! pattern->protocol_refs)
+        pattern->protocol_refs = node->protocol_refs;
+    else if (! AST::match(node->protocol_refs, pattern->protocol_refs, this))
+        return false;
+
+    if (! pattern->member_declaration_list)
+        pattern->member_declaration_list = node->member_declaration_list;
+    else if (! AST::match(node->member_declaration_list, pattern->member_declaration_list, this))
+        return false;
+
+    pattern->end_token = node->end_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(ObjCProtocolRefsAST *node, ObjCProtocolRefsAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->less_token = node->less_token;
+
+    if (! pattern->identifier_list)
+        pattern->identifier_list = node->identifier_list;
+    else if (! AST::match(node->identifier_list, pattern->identifier_list, this))
+        return false;
+
+    pattern->greater_token = node->greater_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(ObjCMessageArgumentAST *node, ObjCMessageArgumentAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    if (! pattern->parameter_value_expression)
+        pattern->parameter_value_expression = node->parameter_value_expression;
+    else if (! AST::match(node->parameter_value_expression, pattern->parameter_value_expression, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(ObjCMessageExpressionAST *node, ObjCMessageExpressionAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->lbracket_token = node->lbracket_token;
+
+    if (! pattern->receiver_expression)
+        pattern->receiver_expression = node->receiver_expression;
+    else if (! AST::match(node->receiver_expression, pattern->receiver_expression, this))
+        return false;
+
+    if (! pattern->selector)
+        pattern->selector = node->selector;
+    else if (! AST::match(node->selector, pattern->selector, this))
+        return false;
+
+    if (! pattern->argument_list)
+        pattern->argument_list = node->argument_list;
+    else if (! AST::match(node->argument_list, pattern->argument_list, this))
+        return false;
+
+    pattern->rbracket_token = node->rbracket_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(ObjCProtocolExpressionAST *node, ObjCProtocolExpressionAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->protocol_token = node->protocol_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    pattern->identifier_token = node->identifier_token;
+
+    pattern->rparen_token = node->rparen_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(ObjCTypeNameAST *node, ObjCTypeNameAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->lparen_token = node->lparen_token;
+
+    pattern->type_qualifier_token = node->type_qualifier_token;
+
+    if (! pattern->type_id)
+        pattern->type_id = node->type_id;
+    else if (! AST::match(node->type_id, pattern->type_id, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(ObjCEncodeExpressionAST *node, ObjCEncodeExpressionAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->encode_token = node->encode_token;
+
+    if (! pattern->type_name)
+        pattern->type_name = node->type_name;
+    else if (! AST::match(node->type_name, pattern->type_name, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(ObjCSelectorExpressionAST *node, ObjCSelectorExpressionAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->selector_token = node->selector_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->selector)
+        pattern->selector = node->selector;
+    else if (! AST::match(node->selector, pattern->selector, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(ObjCInstanceVariablesDeclarationAST *node, ObjCInstanceVariablesDeclarationAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->lbrace_token = node->lbrace_token;
+
+    if (! pattern->instance_variable_list)
+        pattern->instance_variable_list = node->instance_variable_list;
+    else if (! AST::match(node->instance_variable_list, pattern->instance_variable_list, this))
+        return false;
+
+    pattern->rbrace_token = node->rbrace_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(ObjCVisibilityDeclarationAST *node, ObjCVisibilityDeclarationAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->visibility_token = node->visibility_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(ObjCPropertyAttributeAST *node, ObjCPropertyAttributeAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->attribute_identifier_token = node->attribute_identifier_token;
+
+    pattern->equals_token = node->equals_token;
+
+    if (! pattern->method_selector)
+        pattern->method_selector = node->method_selector;
+    else if (! AST::match(node->method_selector, pattern->method_selector, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(ObjCPropertyDeclarationAST *node, ObjCPropertyDeclarationAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    if (! pattern->attribute_list)
+        pattern->attribute_list = node->attribute_list;
+    else if (! AST::match(node->attribute_list, pattern->attribute_list, this))
+        return false;
+
+    pattern->property_token = node->property_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->property_attribute_list)
+        pattern->property_attribute_list = node->property_attribute_list;
+    else if (! AST::match(node->property_attribute_list, pattern->property_attribute_list, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    if (! pattern->simple_declaration)
+        pattern->simple_declaration = node->simple_declaration;
+    else if (! AST::match(node->simple_declaration, pattern->simple_declaration, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(ObjCMessageArgumentDeclarationAST *node, ObjCMessageArgumentDeclarationAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    if (! pattern->type_name)
+        pattern->type_name = node->type_name;
+    else if (! AST::match(node->type_name, pattern->type_name, this))
+        return false;
+
+    if (! pattern->attribute_list)
+        pattern->attribute_list = node->attribute_list;
+    else if (! AST::match(node->attribute_list, pattern->attribute_list, this))
+        return false;
+
+    if (! pattern->param_name)
+        pattern->param_name = node->param_name;
+    else if (! AST::match(node->param_name, pattern->param_name, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(ObjCMethodPrototypeAST *node, ObjCMethodPrototypeAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->method_type_token = node->method_type_token;
+
+    if (! pattern->type_name)
+        pattern->type_name = node->type_name;
+    else if (! AST::match(node->type_name, pattern->type_name, this))
+        return false;
+
+    if (! pattern->selector)
+        pattern->selector = node->selector;
+    else if (! AST::match(node->selector, pattern->selector, this))
+        return false;
+
+    if (! pattern->argument_list)
+        pattern->argument_list = node->argument_list;
+    else if (! AST::match(node->argument_list, pattern->argument_list, this))
+        return false;
+
+    pattern->dot_dot_dot_token = node->dot_dot_dot_token;
+
+    if (! pattern->attribute_list)
+        pattern->attribute_list = node->attribute_list;
+    else if (! AST::match(node->attribute_list, pattern->attribute_list, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(ObjCMethodDeclarationAST *node, ObjCMethodDeclarationAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    if (! pattern->method_prototype)
+        pattern->method_prototype = node->method_prototype;
+    else if (! AST::match(node->method_prototype, pattern->method_prototype, this))
+        return false;
+
+    if (! pattern->function_body)
+        pattern->function_body = node->function_body;
+    else if (! AST::match(node->function_body, pattern->function_body, this))
+        return false;
+
+    pattern->semicolon_token = node->semicolon_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(ObjCSynthesizedPropertyAST *node, ObjCSynthesizedPropertyAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->property_identifier_token = node->property_identifier_token;
+
+    pattern->equals_token = node->equals_token;
+
+    pattern->alias_identifier_token = node->alias_identifier_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(ObjCSynthesizedPropertiesDeclarationAST *node, ObjCSynthesizedPropertiesDeclarationAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->synthesized_token = node->synthesized_token;
+
+    if (! pattern->property_identifier_list)
+        pattern->property_identifier_list = node->property_identifier_list;
+    else if (! AST::match(node->property_identifier_list, pattern->property_identifier_list, this))
+        return false;
+
+    pattern->semicolon_token = node->semicolon_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(ObjCDynamicPropertiesDeclarationAST *node, ObjCDynamicPropertiesDeclarationAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->dynamic_token = node->dynamic_token;
+
+    if (! pattern->property_identifier_list)
+        pattern->property_identifier_list = node->property_identifier_list;
+    else if (! AST::match(node->property_identifier_list, pattern->property_identifier_list, this))
+        return false;
+
+    pattern->semicolon_token = node->semicolon_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(ObjCFastEnumerationAST *node, ObjCFastEnumerationAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->for_token = node->for_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->type_specifier_list)
+        pattern->type_specifier_list = node->type_specifier_list;
+    else if (! AST::match(node->type_specifier_list, pattern->type_specifier_list, this))
+        return false;
+
+    if (! pattern->declarator)
+        pattern->declarator = node->declarator;
+    else if (! AST::match(node->declarator, pattern->declarator, this))
+        return false;
+
+    if (! pattern->initializer)
+        pattern->initializer = node->initializer;
+    else if (! AST::match(node->initializer, pattern->initializer, this))
+        return false;
+
+    pattern->in_token = node->in_token;
+
+    if (! pattern->fast_enumeratable_expression)
+        pattern->fast_enumeratable_expression = node->fast_enumeratable_expression;
+    else if (! AST::match(node->fast_enumeratable_expression, pattern->fast_enumeratable_expression, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    if (! pattern->statement)
+        pattern->statement = node->statement;
+    else if (! AST::match(node->statement, pattern->statement, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(ObjCSynchronizedStatementAST *node, ObjCSynchronizedStatementAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->synchronized_token = node->synchronized_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->synchronized_object)
+        pattern->synchronized_object = node->synchronized_object;
+    else if (! AST::match(node->synchronized_object, pattern->synchronized_object, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    if (! pattern->statement)
+        pattern->statement = node->statement;
+    else if (! AST::match(node->statement, pattern->statement, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(LambdaExpressionAST *node, LambdaExpressionAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    if (! pattern->lambda_introducer)
+        pattern->lambda_introducer = node->lambda_introducer;
+    else if (! AST::match(node->lambda_introducer, pattern->lambda_introducer, this))
+        return false;
+
+    if (! pattern->lambda_declarator)
+        pattern->lambda_declarator = node->lambda_declarator;
+    else if (! AST::match(node->lambda_declarator, pattern->lambda_declarator, this))
+        return false;
+
+    if (! pattern->statement)
+        pattern->statement = node->statement;
+    else if (! AST::match(node->statement, pattern->statement, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(LambdaIntroducerAST *node, LambdaIntroducerAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->lbracket_token = node->lbracket_token;
+
+    if (! pattern->lambda_capture)
+        pattern->lambda_capture = node->lambda_capture;
+    else if (! AST::match(node->lambda_capture, pattern->lambda_capture, this))
+        return false;
+
+    pattern->rbracket_token = node->rbracket_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(LambdaCaptureAST *node, LambdaCaptureAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->default_capture_token = node->default_capture_token;
+
+    if (! pattern->capture_list)
+        pattern->capture_list = node->capture_list;
+    else if (! AST::match(node->capture_list, pattern->capture_list, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(CaptureAST *node, CaptureAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->amper_token = node->amper_token;
+
+    if (! pattern->identifier)
+        pattern->identifier = node->identifier;
+    else if (! AST::match(node->identifier, pattern->identifier, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(LambdaDeclaratorAST *node, LambdaDeclaratorAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->parameter_declaration_clause)
+        pattern->parameter_declaration_clause = node->parameter_declaration_clause;
+    else if (! AST::match(node->parameter_declaration_clause, pattern->parameter_declaration_clause, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    if (! pattern->attributes)
+        pattern->attributes = node->attributes;
+    else if (! AST::match(node->attributes, pattern->attributes, this))
+        return false;
+
+    pattern->mutable_token = node->mutable_token;
+
+    if (! pattern->exception_specification)
+        pattern->exception_specification = node->exception_specification;
+    else if (! AST::match(node->exception_specification, pattern->exception_specification, this))
+        return false;
+
+    if (! pattern->trailing_return_type)
+        pattern->trailing_return_type = node->trailing_return_type;
+    else if (! AST::match(node->trailing_return_type, pattern->trailing_return_type, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(TrailingReturnTypeAST *node, TrailingReturnTypeAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->arrow_token = node->arrow_token;
+
+    if (! pattern->attributes)
+        pattern->attributes = node->attributes;
+    else if (! AST::match(node->attributes, pattern->attributes, this))
+        return false;
+
+    if (! pattern->type_specifier_list)
+        pattern->type_specifier_list = node->type_specifier_list;
+    else if (! AST::match(node->type_specifier_list, pattern->type_specifier_list, this))
+        return false;
+
+    if (! pattern->declarator)
+        pattern->declarator = node->declarator;
+    else if (! AST::match(node->declarator, pattern->declarator, this))
+        return false;
+
+    return true;
+}
+
+bool ASTMatcher::match(BracedInitializerAST *node, BracedInitializerAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->lbrace_token = node->lbrace_token;
+
+    if (! pattern->expression_list)
+        pattern->expression_list = node->expression_list;
+    else if (! AST::match(node->expression_list, pattern->expression_list, this))
+        return false;
+
+    pattern->comma_token = node->comma_token;
+
+    pattern->rbrace_token = node->rbrace_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(DotDesignatorAST *node, DotDesignatorAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->dot_token = node->dot_token;
+
+    pattern->identifier_token = node->identifier_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(BracketDesignatorAST *node, BracketDesignatorAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->lbracket_token = node->lbracket_token;
+
+    if (! pattern->expression)
+        pattern->expression = node->expression;
+    else if (! AST::match(node->expression, pattern->expression, this))
+        return false;
+
+    pattern->rbracket_token = node->rbracket_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(DesignatedInitializerAST *node, DesignatedInitializerAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    if (! pattern->designator_list)
+        pattern->designator_list = node->designator_list;
+    else if (! AST::match(node->designator_list, pattern->designator_list, this))
+        return false;
+
+    pattern->equal_token = node->equal_token;
+
+    if (! pattern->initializer)
+        pattern->initializer = node->initializer;
+    else if (! AST::match(node->initializer, pattern->initializer, this))
+        return false;
+
+    return true;
+}
+

+ 187 - 0
Source/ToolCore/JSBind/cplusplus/ASTMatcher.h

@@ -0,0 +1,187 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef ASTMATCHER_H
+#define ASTMATCHER_H
+
+#include "ASTfwd.h"
+
+namespace CPlusPlus {
+
+class CPLUSPLUS_EXPORT ASTMatcher
+{
+public:
+    ASTMatcher();
+    virtual ~ASTMatcher();
+
+    virtual bool match(AccessDeclarationAST *node, AccessDeclarationAST *pattern);
+    virtual bool match(AliasDeclarationAST *node, AliasDeclarationAST *pattern);
+    virtual bool match(AlignmentSpecifierAST *node, AlignmentSpecifierAST *pattern);
+    virtual bool match(AlignofExpressionAST *node, AlignofExpressionAST *pattern);
+    virtual bool match(AnonymousNameAST *node, AnonymousNameAST *pattern);
+    virtual bool match(ArrayAccessAST *node, ArrayAccessAST *pattern);
+    virtual bool match(ArrayDeclaratorAST *node, ArrayDeclaratorAST *pattern);
+    virtual bool match(ArrayInitializerAST *node, ArrayInitializerAST *pattern);
+    virtual bool match(AsmDefinitionAST *node, AsmDefinitionAST *pattern);
+    virtual bool match(BaseSpecifierAST *node, BaseSpecifierAST *pattern);
+    virtual bool match(BinaryExpressionAST *node, BinaryExpressionAST *pattern);
+    virtual bool match(BoolLiteralAST *node, BoolLiteralAST *pattern);
+    virtual bool match(BracedInitializerAST *node, BracedInitializerAST *pattern);
+    virtual bool match(BracketDesignatorAST *node, BracketDesignatorAST *pattern);
+    virtual bool match(BreakStatementAST *node, BreakStatementAST *pattern);
+    virtual bool match(CallAST *node, CallAST *pattern);
+    virtual bool match(CaptureAST *node, CaptureAST *pattern);
+    virtual bool match(CaseStatementAST *node, CaseStatementAST *pattern);
+    virtual bool match(CastExpressionAST *node, CastExpressionAST *pattern);
+    virtual bool match(CatchClauseAST *node, CatchClauseAST *pattern);
+    virtual bool match(ClassSpecifierAST *node, ClassSpecifierAST *pattern);
+    virtual bool match(CompoundExpressionAST *node, CompoundExpressionAST *pattern);
+    virtual bool match(CompoundLiteralAST *node, CompoundLiteralAST *pattern);
+    virtual bool match(CompoundStatementAST *node, CompoundStatementAST *pattern);
+    virtual bool match(ConditionAST *node, ConditionAST *pattern);
+    virtual bool match(ConditionalExpressionAST *node, ConditionalExpressionAST *pattern);
+    virtual bool match(ContinueStatementAST *node, ContinueStatementAST *pattern);
+    virtual bool match(ConversionFunctionIdAST *node, ConversionFunctionIdAST *pattern);
+    virtual bool match(CppCastExpressionAST *node, CppCastExpressionAST *pattern);
+    virtual bool match(CtorInitializerAST *node, CtorInitializerAST *pattern);
+    virtual bool match(DeclarationStatementAST *node, DeclarationStatementAST *pattern);
+    virtual bool match(DeclaratorAST *node, DeclaratorAST *pattern);
+    virtual bool match(DeclaratorIdAST *node, DeclaratorIdAST *pattern);
+    virtual bool match(DecltypeSpecifierAST *node, DecltypeSpecifierAST *pattern);
+    virtual bool match(DeleteExpressionAST *node, DeleteExpressionAST *pattern);
+    virtual bool match(DesignatedInitializerAST *node, DesignatedInitializerAST *pattern);
+    virtual bool match(DestructorNameAST *node, DestructorNameAST *pattern);
+    virtual bool match(DoStatementAST *node, DoStatementAST *pattern);
+    virtual bool match(DotDesignatorAST *node, DotDesignatorAST *pattern);
+    virtual bool match(DynamicExceptionSpecificationAST *node, DynamicExceptionSpecificationAST *pattern);
+    virtual bool match(ElaboratedTypeSpecifierAST *node, ElaboratedTypeSpecifierAST *pattern);
+    virtual bool match(EmptyDeclarationAST *node, EmptyDeclarationAST *pattern);
+    virtual bool match(EnumSpecifierAST *node, EnumSpecifierAST *pattern);
+    virtual bool match(EnumeratorAST *node, EnumeratorAST *pattern);
+    virtual bool match(ExceptionDeclarationAST *node, ExceptionDeclarationAST *pattern);
+    virtual bool match(ExpressionListParenAST *node, ExpressionListParenAST *pattern);
+    virtual bool match(ExpressionOrDeclarationStatementAST *node, ExpressionOrDeclarationStatementAST *pattern);
+    virtual bool match(ExpressionStatementAST *node, ExpressionStatementAST *pattern);
+    virtual bool match(ForStatementAST *node, ForStatementAST *pattern);
+    virtual bool match(ForeachStatementAST *node, ForeachStatementAST *pattern);
+    virtual bool match(FunctionDeclaratorAST *node, FunctionDeclaratorAST *pattern);
+    virtual bool match(FunctionDefinitionAST *node, FunctionDefinitionAST *pattern);
+    virtual bool match(GnuAttributeAST *node, GnuAttributeAST *pattern);
+    virtual bool match(GnuAttributeSpecifierAST *node, GnuAttributeSpecifierAST *pattern);
+    virtual bool match(GotoStatementAST *node, GotoStatementAST *pattern);
+    virtual bool match(IdExpressionAST *node, IdExpressionAST *pattern);
+    virtual bool match(IfStatementAST *node, IfStatementAST *pattern);
+    virtual bool match(LabeledStatementAST *node, LabeledStatementAST *pattern);
+    virtual bool match(LambdaCaptureAST *node, LambdaCaptureAST *pattern);
+    virtual bool match(LambdaDeclaratorAST *node, LambdaDeclaratorAST *pattern);
+    virtual bool match(LambdaExpressionAST *node, LambdaExpressionAST *pattern);
+    virtual bool match(LambdaIntroducerAST *node, LambdaIntroducerAST *pattern);
+    virtual bool match(LinkageBodyAST *node, LinkageBodyAST *pattern);
+    virtual bool match(LinkageSpecificationAST *node, LinkageSpecificationAST *pattern);
+    virtual bool match(MemInitializerAST *node, MemInitializerAST *pattern);
+    virtual bool match(MemberAccessAST *node, MemberAccessAST *pattern);
+    virtual bool match(NamedTypeSpecifierAST *node, NamedTypeSpecifierAST *pattern);
+    virtual bool match(NamespaceAST *node, NamespaceAST *pattern);
+    virtual bool match(NamespaceAliasDefinitionAST *node, NamespaceAliasDefinitionAST *pattern);
+    virtual bool match(NestedDeclaratorAST *node, NestedDeclaratorAST *pattern);
+    virtual bool match(NestedExpressionAST *node, NestedExpressionAST *pattern);
+    virtual bool match(NestedNameSpecifierAST *node, NestedNameSpecifierAST *pattern);
+    virtual bool match(NewArrayDeclaratorAST *node, NewArrayDeclaratorAST *pattern);
+    virtual bool match(NewExpressionAST *node, NewExpressionAST *pattern);
+    virtual bool match(NewTypeIdAST *node, NewTypeIdAST *pattern);
+    virtual bool match(NoExceptSpecificationAST *node, NoExceptSpecificationAST *pattern);
+    virtual bool match(NumericLiteralAST *node, NumericLiteralAST *pattern);
+    virtual bool match(ObjCClassDeclarationAST *node, ObjCClassDeclarationAST *pattern);
+    virtual bool match(ObjCClassForwardDeclarationAST *node, ObjCClassForwardDeclarationAST *pattern);
+    virtual bool match(ObjCDynamicPropertiesDeclarationAST *node, ObjCDynamicPropertiesDeclarationAST *pattern);
+    virtual bool match(ObjCEncodeExpressionAST *node, ObjCEncodeExpressionAST *pattern);
+    virtual bool match(ObjCFastEnumerationAST *node, ObjCFastEnumerationAST *pattern);
+    virtual bool match(ObjCInstanceVariablesDeclarationAST *node, ObjCInstanceVariablesDeclarationAST *pattern);
+    virtual bool match(ObjCMessageArgumentAST *node, ObjCMessageArgumentAST *pattern);
+    virtual bool match(ObjCMessageArgumentDeclarationAST *node, ObjCMessageArgumentDeclarationAST *pattern);
+    virtual bool match(ObjCMessageExpressionAST *node, ObjCMessageExpressionAST *pattern);
+    virtual bool match(ObjCMethodDeclarationAST *node, ObjCMethodDeclarationAST *pattern);
+    virtual bool match(ObjCMethodPrototypeAST *node, ObjCMethodPrototypeAST *pattern);
+    virtual bool match(ObjCPropertyAttributeAST *node, ObjCPropertyAttributeAST *pattern);
+    virtual bool match(ObjCPropertyDeclarationAST *node, ObjCPropertyDeclarationAST *pattern);
+    virtual bool match(ObjCProtocolDeclarationAST *node, ObjCProtocolDeclarationAST *pattern);
+    virtual bool match(ObjCProtocolExpressionAST *node, ObjCProtocolExpressionAST *pattern);
+    virtual bool match(ObjCProtocolForwardDeclarationAST *node, ObjCProtocolForwardDeclarationAST *pattern);
+    virtual bool match(ObjCProtocolRefsAST *node, ObjCProtocolRefsAST *pattern);
+    virtual bool match(ObjCSelectorAST *node, ObjCSelectorAST *pattern);
+    virtual bool match(ObjCSelectorArgumentAST *node, ObjCSelectorArgumentAST *pattern);
+    virtual bool match(ObjCSelectorExpressionAST *node, ObjCSelectorExpressionAST *pattern);
+    virtual bool match(ObjCSynchronizedStatementAST *node, ObjCSynchronizedStatementAST *pattern);
+    virtual bool match(ObjCSynthesizedPropertiesDeclarationAST *node, ObjCSynthesizedPropertiesDeclarationAST *pattern);
+    virtual bool match(ObjCSynthesizedPropertyAST *node, ObjCSynthesizedPropertyAST *pattern);
+    virtual bool match(ObjCTypeNameAST *node, ObjCTypeNameAST *pattern);
+    virtual bool match(ObjCVisibilityDeclarationAST *node, ObjCVisibilityDeclarationAST *pattern);
+    virtual bool match(OperatorAST *node, OperatorAST *pattern);
+    virtual bool match(OperatorFunctionIdAST *node, OperatorFunctionIdAST *pattern);
+    virtual bool match(ParameterDeclarationAST *node, ParameterDeclarationAST *pattern);
+    virtual bool match(ParameterDeclarationClauseAST *node, ParameterDeclarationClauseAST *pattern);
+    virtual bool match(PointerAST *node, PointerAST *pattern);
+    virtual bool match(PointerLiteralAST *node, PointerLiteralAST *pattern);
+    virtual bool match(PointerToMemberAST *node, PointerToMemberAST *pattern);
+    virtual bool match(PostIncrDecrAST *node, PostIncrDecrAST *pattern);
+    virtual bool match(QtEnumDeclarationAST *node, QtEnumDeclarationAST *pattern);
+    virtual bool match(QtFlagsDeclarationAST *node, QtFlagsDeclarationAST *pattern);
+    virtual bool match(QtInterfaceNameAST *node, QtInterfaceNameAST *pattern);
+    virtual bool match(QtInterfacesDeclarationAST *node, QtInterfacesDeclarationAST *pattern);
+    virtual bool match(QtMemberDeclarationAST *node, QtMemberDeclarationAST *pattern);
+    virtual bool match(QtMethodAST *node, QtMethodAST *pattern);
+    virtual bool match(QtObjectTagAST *node, QtObjectTagAST *pattern);
+    virtual bool match(QtPrivateSlotAST *node, QtPrivateSlotAST *pattern);
+    virtual bool match(QtPropertyDeclarationAST *node, QtPropertyDeclarationAST *pattern);
+    virtual bool match(QtPropertyDeclarationItemAST *node, QtPropertyDeclarationItemAST *pattern);
+    virtual bool match(QualifiedNameAST *node, QualifiedNameAST *pattern);
+    virtual bool match(RangeBasedForStatementAST *node, RangeBasedForStatementAST *pattern);
+    virtual bool match(ReferenceAST *node, ReferenceAST *pattern);
+    virtual bool match(ReturnStatementAST *node, ReturnStatementAST *pattern);
+    virtual bool match(SimpleDeclarationAST *node, SimpleDeclarationAST *pattern);
+    virtual bool match(SimpleNameAST *node, SimpleNameAST *pattern);
+    virtual bool match(SimpleSpecifierAST *node, SimpleSpecifierAST *pattern);
+    virtual bool match(SizeofExpressionAST *node, SizeofExpressionAST *pattern);
+    virtual bool match(StaticAssertDeclarationAST *node, StaticAssertDeclarationAST *pattern);
+    virtual bool match(StringLiteralAST *node, StringLiteralAST *pattern);
+    virtual bool match(SwitchStatementAST *node, SwitchStatementAST *pattern);
+    virtual bool match(TemplateDeclarationAST *node, TemplateDeclarationAST *pattern);
+    virtual bool match(TemplateIdAST *node, TemplateIdAST *pattern);
+    virtual bool match(TemplateTypeParameterAST *node, TemplateTypeParameterAST *pattern);
+    virtual bool match(ThisExpressionAST *node, ThisExpressionAST *pattern);
+    virtual bool match(ThrowExpressionAST *node, ThrowExpressionAST *pattern);
+    virtual bool match(TrailingReturnTypeAST *node, TrailingReturnTypeAST *pattern);
+    virtual bool match(TranslationUnitAST *node, TranslationUnitAST *pattern);
+    virtual bool match(TryBlockStatementAST *node, TryBlockStatementAST *pattern);
+    virtual bool match(TypeConstructorCallAST *node, TypeConstructorCallAST *pattern);
+    virtual bool match(TypeIdAST *node, TypeIdAST *pattern);
+    virtual bool match(TypeidExpressionAST *node, TypeidExpressionAST *pattern);
+    virtual bool match(TypenameCallExpressionAST *node, TypenameCallExpressionAST *pattern);
+    virtual bool match(TypenameTypeParameterAST *node, TypenameTypeParameterAST *pattern);
+    virtual bool match(TypeofSpecifierAST *node, TypeofSpecifierAST *pattern);
+    virtual bool match(UnaryExpressionAST *node, UnaryExpressionAST *pattern);
+    virtual bool match(UsingAST *node, UsingAST *pattern);
+    virtual bool match(UsingDirectiveAST *node, UsingDirectiveAST *pattern);
+    virtual bool match(WhileStatementAST *node, WhileStatementAST *pattern);
+};
+
+} // namespace CPlusPlus
+
+#endif // CPLUSPLUS_ASTMATCHER_H

+ 2 - 0
Source/ToolCore/JSBind/cplusplus/ASTPatternBuilder.cpp

@@ -0,0 +1,2 @@
+
+#include "ASTPatternBuilder.h"

+ 1382 - 0
Source/ToolCore/JSBind/cplusplus/ASTPatternBuilder.h

@@ -0,0 +1,1382 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is automatically generated by "cplusplus-update-frontend".
+// Changes will be lost.
+//
+
+#ifndef CPLUSPLUS_AST_PATTERN_BUILDER_H
+#define CPLUSPLUS_AST_PATTERN_BUILDER_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include "AST.h"
+#include "MemoryPool.h"
+
+namespace CPlusPlus {
+
+class CPLUSPLUS_EXPORT ASTPatternBuilder
+{
+    MemoryPool pool;
+
+public:
+    ASTPatternBuilder() {}
+
+    void reset() { pool.reset(); }
+
+    ObjCSelectorArgumentAST *ObjCSelectorArgument()
+    {
+        ObjCSelectorArgumentAST *ast = new (&pool) ObjCSelectorArgumentAST;
+        return ast;
+    }
+
+    ObjCSelectorAST *ObjCSelector(ObjCSelectorArgumentListAST *selector_argument_list = 0)
+    {
+        ObjCSelectorAST *ast = new (&pool) ObjCSelectorAST;
+        ast->selector_argument_list = selector_argument_list;
+        return ast;
+    }
+
+    SimpleSpecifierAST *SimpleSpecifier()
+    {
+        SimpleSpecifierAST *ast = new (&pool) SimpleSpecifierAST;
+        return ast;
+    }
+
+    AlignmentSpecifierAST *AlignmentSpecifier(ExpressionAST *typeIdExprOrAlignmentExpr = 0)
+    {
+        AlignmentSpecifierAST *ast = new (&pool) AlignmentSpecifierAST;
+        ast->typeIdExprOrAlignmentExpr = typeIdExprOrAlignmentExpr;
+        return ast;
+    }
+
+    GnuAttributeSpecifierAST *GnuAttributeSpecifier(GnuAttributeListAST *attribute_list = 0)
+    {
+        GnuAttributeSpecifierAST *ast = new (&pool) GnuAttributeSpecifierAST;
+        ast->attribute_list = attribute_list;
+        return ast;
+    }
+
+    GnuAttributeAST *GnuAttribute(ExpressionListAST *expression_list = 0)
+    {
+        GnuAttributeAST *ast = new (&pool) GnuAttributeAST;
+        ast->expression_list = expression_list;
+        return ast;
+    }
+
+    TypeofSpecifierAST *TypeofSpecifier(ExpressionAST *expression = 0)
+    {
+        TypeofSpecifierAST *ast = new (&pool) TypeofSpecifierAST;
+        ast->expression = expression;
+        return ast;
+    }
+
+    DecltypeSpecifierAST *DecltypeSpecifier(ExpressionAST *expression = 0)
+    {
+        DecltypeSpecifierAST *ast = new (&pool) DecltypeSpecifierAST;
+        ast->expression = expression;
+        return ast;
+    }
+
+    DeclaratorAST *Declarator(SpecifierListAST *attribute_list = 0, PtrOperatorListAST *ptr_operator_list = 0, CoreDeclaratorAST *core_declarator = 0, PostfixDeclaratorListAST *postfix_declarator_list = 0, SpecifierListAST *post_attribute_list = 0, ExpressionAST *initializer = 0)
+    {
+        DeclaratorAST *ast = new (&pool) DeclaratorAST;
+        ast->attribute_list = attribute_list;
+        ast->ptr_operator_list = ptr_operator_list;
+        ast->core_declarator = core_declarator;
+        ast->postfix_declarator_list = postfix_declarator_list;
+        ast->post_attribute_list = post_attribute_list;
+        ast->initializer = initializer;
+        return ast;
+    }
+
+    SimpleDeclarationAST *SimpleDeclaration(SpecifierListAST *decl_specifier_list = 0, DeclaratorListAST *declarator_list = 0)
+    {
+        SimpleDeclarationAST *ast = new (&pool) SimpleDeclarationAST;
+        ast->decl_specifier_list = decl_specifier_list;
+        ast->declarator_list = declarator_list;
+        return ast;
+    }
+
+    EmptyDeclarationAST *EmptyDeclaration()
+    {
+        EmptyDeclarationAST *ast = new (&pool) EmptyDeclarationAST;
+        return ast;
+    }
+
+    AccessDeclarationAST *AccessDeclaration()
+    {
+        AccessDeclarationAST *ast = new (&pool) AccessDeclarationAST;
+        return ast;
+    }
+
+    QtObjectTagAST *QtObjectTag()
+    {
+        QtObjectTagAST *ast = new (&pool) QtObjectTagAST;
+        return ast;
+    }
+
+    QtPrivateSlotAST *QtPrivateSlot(SpecifierListAST *type_specifier_list = 0, DeclaratorAST *declarator = 0)
+    {
+        QtPrivateSlotAST *ast = new (&pool) QtPrivateSlotAST;
+        ast->type_specifier_list = type_specifier_list;
+        ast->declarator = declarator;
+        return ast;
+    }
+
+    QtPropertyDeclarationItemAST *QtPropertyDeclarationItem(ExpressionAST *expression = 0)
+    {
+        QtPropertyDeclarationItemAST *ast = new (&pool) QtPropertyDeclarationItemAST;
+        ast->expression = expression;
+        return ast;
+    }
+
+    QtPropertyDeclarationAST *QtPropertyDeclaration(ExpressionAST *expression = 0, ExpressionAST *type_id = 0, NameAST *property_name = 0, QtPropertyDeclarationItemListAST *property_declaration_item_list = 0)
+    {
+        QtPropertyDeclarationAST *ast = new (&pool) QtPropertyDeclarationAST;
+        ast->expression = expression;
+        ast->type_id = type_id;
+        ast->property_name = property_name;
+        ast->property_declaration_item_list = property_declaration_item_list;
+        return ast;
+    }
+
+    QtEnumDeclarationAST *QtEnumDeclaration(NameListAST *enumerator_list = 0)
+    {
+        QtEnumDeclarationAST *ast = new (&pool) QtEnumDeclarationAST;
+        ast->enumerator_list = enumerator_list;
+        return ast;
+    }
+
+    QtFlagsDeclarationAST *QtFlagsDeclaration(NameListAST *flag_enums_list = 0)
+    {
+        QtFlagsDeclarationAST *ast = new (&pool) QtFlagsDeclarationAST;
+        ast->flag_enums_list = flag_enums_list;
+        return ast;
+    }
+
+    QtInterfaceNameAST *QtInterfaceName(NameAST *interface_name = 0, NameListAST *constraint_list = 0)
+    {
+        QtInterfaceNameAST *ast = new (&pool) QtInterfaceNameAST;
+        ast->interface_name = interface_name;
+        ast->constraint_list = constraint_list;
+        return ast;
+    }
+
+    QtInterfacesDeclarationAST *QtInterfacesDeclaration(QtInterfaceNameListAST *interface_name_list = 0)
+    {
+        QtInterfacesDeclarationAST *ast = new (&pool) QtInterfacesDeclarationAST;
+        ast->interface_name_list = interface_name_list;
+        return ast;
+    }
+
+    AsmDefinitionAST *AsmDefinition()
+    {
+        AsmDefinitionAST *ast = new (&pool) AsmDefinitionAST;
+        return ast;
+    }
+
+    BaseSpecifierAST *BaseSpecifier(NameAST *name = 0)
+    {
+        BaseSpecifierAST *ast = new (&pool) BaseSpecifierAST;
+        ast->name = name;
+        return ast;
+    }
+
+    IdExpressionAST *IdExpression(NameAST *name = 0)
+    {
+        IdExpressionAST *ast = new (&pool) IdExpressionAST;
+        ast->name = name;
+        return ast;
+    }
+
+    CompoundExpressionAST *CompoundExpression(CompoundStatementAST *statement = 0)
+    {
+        CompoundExpressionAST *ast = new (&pool) CompoundExpressionAST;
+        ast->statement = statement;
+        return ast;
+    }
+
+    CompoundLiteralAST *CompoundLiteral(ExpressionAST *type_id = 0, ExpressionAST *initializer = 0)
+    {
+        CompoundLiteralAST *ast = new (&pool) CompoundLiteralAST;
+        ast->type_id = type_id;
+        ast->initializer = initializer;
+        return ast;
+    }
+
+    QtMethodAST *QtMethod(DeclaratorAST *declarator = 0)
+    {
+        QtMethodAST *ast = new (&pool) QtMethodAST;
+        ast->declarator = declarator;
+        return ast;
+    }
+
+    QtMemberDeclarationAST *QtMemberDeclaration(ExpressionAST *type_id = 0)
+    {
+        QtMemberDeclarationAST *ast = new (&pool) QtMemberDeclarationAST;
+        ast->type_id = type_id;
+        return ast;
+    }
+
+    BinaryExpressionAST *BinaryExpression(ExpressionAST *left_expression = 0, ExpressionAST *right_expression = 0)
+    {
+        BinaryExpressionAST *ast = new (&pool) BinaryExpressionAST;
+        ast->left_expression = left_expression;
+        ast->right_expression = right_expression;
+        return ast;
+    }
+
+    CastExpressionAST *CastExpression(ExpressionAST *type_id = 0, ExpressionAST *expression = 0)
+    {
+        CastExpressionAST *ast = new (&pool) CastExpressionAST;
+        ast->type_id = type_id;
+        ast->expression = expression;
+        return ast;
+    }
+
+    ClassSpecifierAST *ClassSpecifier(SpecifierListAST *attribute_list = 0, NameAST *name = 0, BaseSpecifierListAST *base_clause_list = 0, DeclarationListAST *member_specifier_list = 0)
+    {
+        ClassSpecifierAST *ast = new (&pool) ClassSpecifierAST;
+        ast->attribute_list = attribute_list;
+        ast->name = name;
+        ast->base_clause_list = base_clause_list;
+        ast->member_specifier_list = member_specifier_list;
+        return ast;
+    }
+
+    CaseStatementAST *CaseStatement(ExpressionAST *expression = 0, StatementAST *statement = 0)
+    {
+        CaseStatementAST *ast = new (&pool) CaseStatementAST;
+        ast->expression = expression;
+        ast->statement = statement;
+        return ast;
+    }
+
+    CompoundStatementAST *CompoundStatement(StatementListAST *statement_list = 0)
+    {
+        CompoundStatementAST *ast = new (&pool) CompoundStatementAST;
+        ast->statement_list = statement_list;
+        return ast;
+    }
+
+    ConditionAST *Condition(SpecifierListAST *type_specifier_list = 0, DeclaratorAST *declarator = 0)
+    {
+        ConditionAST *ast = new (&pool) ConditionAST;
+        ast->type_specifier_list = type_specifier_list;
+        ast->declarator = declarator;
+        return ast;
+    }
+
+    ConditionalExpressionAST *ConditionalExpression(ExpressionAST *condition = 0, ExpressionAST *left_expression = 0, ExpressionAST *right_expression = 0)
+    {
+        ConditionalExpressionAST *ast = new (&pool) ConditionalExpressionAST;
+        ast->condition = condition;
+        ast->left_expression = left_expression;
+        ast->right_expression = right_expression;
+        return ast;
+    }
+
+    CppCastExpressionAST *CppCastExpression(ExpressionAST *type_id = 0, ExpressionAST *expression = 0)
+    {
+        CppCastExpressionAST *ast = new (&pool) CppCastExpressionAST;
+        ast->type_id = type_id;
+        ast->expression = expression;
+        return ast;
+    }
+
+    CtorInitializerAST *CtorInitializer(MemInitializerListAST *member_initializer_list = 0)
+    {
+        CtorInitializerAST *ast = new (&pool) CtorInitializerAST;
+        ast->member_initializer_list = member_initializer_list;
+        return ast;
+    }
+
+    DeclarationStatementAST *DeclarationStatement(DeclarationAST *declaration = 0)
+    {
+        DeclarationStatementAST *ast = new (&pool) DeclarationStatementAST;
+        ast->declaration = declaration;
+        return ast;
+    }
+
+    DeclaratorIdAST *DeclaratorId(NameAST *name = 0)
+    {
+        DeclaratorIdAST *ast = new (&pool) DeclaratorIdAST;
+        ast->name = name;
+        return ast;
+    }
+
+    NestedDeclaratorAST *NestedDeclarator(DeclaratorAST *declarator = 0)
+    {
+        NestedDeclaratorAST *ast = new (&pool) NestedDeclaratorAST;
+        ast->declarator = declarator;
+        return ast;
+    }
+
+    FunctionDeclaratorAST *FunctionDeclarator(ParameterDeclarationClauseAST *parameter_declaration_clause = 0, SpecifierListAST *cv_qualifier_list = 0, ExceptionSpecificationAST *exception_specification = 0, TrailingReturnTypeAST *trailing_return_type = 0, ExpressionAST *as_cpp_initializer = 0)
+    {
+        FunctionDeclaratorAST *ast = new (&pool) FunctionDeclaratorAST;
+        ast->parameter_declaration_clause = parameter_declaration_clause;
+        ast->cv_qualifier_list = cv_qualifier_list;
+        ast->exception_specification = exception_specification;
+        ast->trailing_return_type = trailing_return_type;
+        ast->as_cpp_initializer = as_cpp_initializer;
+        return ast;
+    }
+
+    ArrayDeclaratorAST *ArrayDeclarator(ExpressionAST *expression = 0)
+    {
+        ArrayDeclaratorAST *ast = new (&pool) ArrayDeclaratorAST;
+        ast->expression = expression;
+        return ast;
+    }
+
+    DeleteExpressionAST *DeleteExpression(ExpressionAST *expression = 0)
+    {
+        DeleteExpressionAST *ast = new (&pool) DeleteExpressionAST;
+        ast->expression = expression;
+        return ast;
+    }
+
+    DoStatementAST *DoStatement(StatementAST *statement = 0, ExpressionAST *expression = 0)
+    {
+        DoStatementAST *ast = new (&pool) DoStatementAST;
+        ast->statement = statement;
+        ast->expression = expression;
+        return ast;
+    }
+
+    NamedTypeSpecifierAST *NamedTypeSpecifier(NameAST *name = 0)
+    {
+        NamedTypeSpecifierAST *ast = new (&pool) NamedTypeSpecifierAST;
+        ast->name = name;
+        return ast;
+    }
+
+    ElaboratedTypeSpecifierAST *ElaboratedTypeSpecifier(SpecifierListAST *attribute_list = 0, NameAST *name = 0)
+    {
+        ElaboratedTypeSpecifierAST *ast = new (&pool) ElaboratedTypeSpecifierAST;
+        ast->attribute_list = attribute_list;
+        ast->name = name;
+        return ast;
+    }
+
+    EnumSpecifierAST *EnumSpecifier(NameAST *name = 0, SpecifierListAST *type_specifier_list = 0, EnumeratorListAST *enumerator_list = 0)
+    {
+        EnumSpecifierAST *ast = new (&pool) EnumSpecifierAST;
+        ast->name = name;
+        ast->type_specifier_list = type_specifier_list;
+        ast->enumerator_list = enumerator_list;
+        return ast;
+    }
+
+    EnumeratorAST *Enumerator(ExpressionAST *expression = 0)
+    {
+        EnumeratorAST *ast = new (&pool) EnumeratorAST;
+        ast->expression = expression;
+        return ast;
+    }
+
+    ExceptionDeclarationAST *ExceptionDeclaration(SpecifierListAST *type_specifier_list = 0, DeclaratorAST *declarator = 0)
+    {
+        ExceptionDeclarationAST *ast = new (&pool) ExceptionDeclarationAST;
+        ast->type_specifier_list = type_specifier_list;
+        ast->declarator = declarator;
+        return ast;
+    }
+
+    DynamicExceptionSpecificationAST *DynamicExceptionSpecification(ExpressionListAST *type_id_list = 0)
+    {
+        DynamicExceptionSpecificationAST *ast = new (&pool) DynamicExceptionSpecificationAST;
+        ast->type_id_list = type_id_list;
+        return ast;
+    }
+
+    NoExceptSpecificationAST *NoExceptSpecification(ExpressionAST *expression = 0)
+    {
+        NoExceptSpecificationAST *ast = new (&pool) NoExceptSpecificationAST;
+        ast->expression = expression;
+        return ast;
+    }
+
+    ExpressionOrDeclarationStatementAST *ExpressionOrDeclarationStatement(ExpressionStatementAST *expression = 0, DeclarationStatementAST *declaration = 0)
+    {
+        ExpressionOrDeclarationStatementAST *ast = new (&pool) ExpressionOrDeclarationStatementAST;
+        ast->expression = expression;
+        ast->declaration = declaration;
+        return ast;
+    }
+
+    ExpressionStatementAST *ExpressionStatement(ExpressionAST *expression = 0)
+    {
+        ExpressionStatementAST *ast = new (&pool) ExpressionStatementAST;
+        ast->expression = expression;
+        return ast;
+    }
+
+    FunctionDefinitionAST *FunctionDefinition(SpecifierListAST *decl_specifier_list = 0, DeclaratorAST *declarator = 0, CtorInitializerAST *ctor_initializer = 0, StatementAST *function_body = 0)
+    {
+        FunctionDefinitionAST *ast = new (&pool) FunctionDefinitionAST;
+        ast->decl_specifier_list = decl_specifier_list;
+        ast->declarator = declarator;
+        ast->ctor_initializer = ctor_initializer;
+        ast->function_body = function_body;
+        return ast;
+    }
+
+    ForeachStatementAST *ForeachStatement(SpecifierListAST *type_specifier_list = 0, DeclaratorAST *declarator = 0, ExpressionAST *initializer = 0, ExpressionAST *expression = 0, StatementAST *statement = 0)
+    {
+        ForeachStatementAST *ast = new (&pool) ForeachStatementAST;
+        ast->type_specifier_list = type_specifier_list;
+        ast->declarator = declarator;
+        ast->initializer = initializer;
+        ast->expression = expression;
+        ast->statement = statement;
+        return ast;
+    }
+
+    RangeBasedForStatementAST *RangeBasedForStatement(SpecifierListAST *type_specifier_list = 0, DeclaratorAST *declarator = 0, ExpressionAST *expression = 0, StatementAST *statement = 0)
+    {
+        RangeBasedForStatementAST *ast = new (&pool) RangeBasedForStatementAST;
+        ast->type_specifier_list = type_specifier_list;
+        ast->declarator = declarator;
+        ast->expression = expression;
+        ast->statement = statement;
+        return ast;
+    }
+
+    ForStatementAST *ForStatement(StatementAST *initializer = 0, ExpressionAST *condition = 0, ExpressionAST *expression = 0, StatementAST *statement = 0)
+    {
+        ForStatementAST *ast = new (&pool) ForStatementAST;
+        ast->initializer = initializer;
+        ast->condition = condition;
+        ast->expression = expression;
+        ast->statement = statement;
+        return ast;
+    }
+
+    IfStatementAST *IfStatement(ExpressionAST *condition = 0, StatementAST *statement = 0, StatementAST *else_statement = 0)
+    {
+        IfStatementAST *ast = new (&pool) IfStatementAST;
+        ast->condition = condition;
+        ast->statement = statement;
+        ast->else_statement = else_statement;
+        return ast;
+    }
+
+    ArrayInitializerAST *ArrayInitializer(ExpressionListAST *expression_list = 0)
+    {
+        ArrayInitializerAST *ast = new (&pool) ArrayInitializerAST;
+        ast->expression_list = expression_list;
+        return ast;
+    }
+
+    LabeledStatementAST *LabeledStatement(StatementAST *statement = 0)
+    {
+        LabeledStatementAST *ast = new (&pool) LabeledStatementAST;
+        ast->statement = statement;
+        return ast;
+    }
+
+    LinkageBodyAST *LinkageBody(DeclarationListAST *declaration_list = 0)
+    {
+        LinkageBodyAST *ast = new (&pool) LinkageBodyAST;
+        ast->declaration_list = declaration_list;
+        return ast;
+    }
+
+    LinkageSpecificationAST *LinkageSpecification(DeclarationAST *declaration = 0)
+    {
+        LinkageSpecificationAST *ast = new (&pool) LinkageSpecificationAST;
+        ast->declaration = declaration;
+        return ast;
+    }
+
+    MemInitializerAST *MemInitializer(NameAST *name = 0, ExpressionAST *expression = 0)
+    {
+        MemInitializerAST *ast = new (&pool) MemInitializerAST;
+        ast->name = name;
+        ast->expression = expression;
+        return ast;
+    }
+
+    NestedNameSpecifierAST *NestedNameSpecifier(NameAST *class_or_namespace_name = 0)
+    {
+        NestedNameSpecifierAST *ast = new (&pool) NestedNameSpecifierAST;
+        ast->class_or_namespace_name = class_or_namespace_name;
+        return ast;
+    }
+
+    QualifiedNameAST *QualifiedName(NestedNameSpecifierListAST *nested_name_specifier_list = 0, NameAST *unqualified_name = 0)
+    {
+        QualifiedNameAST *ast = new (&pool) QualifiedNameAST;
+        ast->nested_name_specifier_list = nested_name_specifier_list;
+        ast->unqualified_name = unqualified_name;
+        return ast;
+    }
+
+    OperatorFunctionIdAST *OperatorFunctionId(OperatorAST *op = 0)
+    {
+        OperatorFunctionIdAST *ast = new (&pool) OperatorFunctionIdAST;
+        ast->op = op;
+        return ast;
+    }
+
+    ConversionFunctionIdAST *ConversionFunctionId(SpecifierListAST *type_specifier_list = 0, PtrOperatorListAST *ptr_operator_list = 0)
+    {
+        ConversionFunctionIdAST *ast = new (&pool) ConversionFunctionIdAST;
+        ast->type_specifier_list = type_specifier_list;
+        ast->ptr_operator_list = ptr_operator_list;
+        return ast;
+    }
+
+    AnonymousNameAST *AnonymousName()
+    {
+        AnonymousNameAST *ast = new (&pool) AnonymousNameAST;
+        return ast;
+    }
+
+    SimpleNameAST *SimpleName()
+    {
+        SimpleNameAST *ast = new (&pool) SimpleNameAST;
+        return ast;
+    }
+
+    DestructorNameAST *DestructorName(NameAST *unqualified_name = 0)
+    {
+        DestructorNameAST *ast = new (&pool) DestructorNameAST;
+        ast->unqualified_name = unqualified_name;
+        return ast;
+    }
+
+    TemplateIdAST *TemplateId(ExpressionListAST *template_argument_list = 0)
+    {
+        TemplateIdAST *ast = new (&pool) TemplateIdAST;
+        ast->template_argument_list = template_argument_list;
+        return ast;
+    }
+
+    NamespaceAST *Namespace(SpecifierListAST *attribute_list = 0, DeclarationAST *linkage_body = 0)
+    {
+        NamespaceAST *ast = new (&pool) NamespaceAST;
+        ast->attribute_list = attribute_list;
+        ast->linkage_body = linkage_body;
+        return ast;
+    }
+
+    NamespaceAliasDefinitionAST *NamespaceAliasDefinition(NameAST *name = 0)
+    {
+        NamespaceAliasDefinitionAST *ast = new (&pool) NamespaceAliasDefinitionAST;
+        ast->name = name;
+        return ast;
+    }
+
+    AliasDeclarationAST *AliasDeclaration(NameAST *name = 0, TypeIdAST *typeId = 0)
+    {
+        AliasDeclarationAST *ast = new (&pool) AliasDeclarationAST;
+        ast->name = name;
+        ast->typeId = typeId;
+        return ast;
+    }
+
+    ExpressionListParenAST *ExpressionListParen(ExpressionListAST *expression_list = 0)
+    {
+        ExpressionListParenAST *ast = new (&pool) ExpressionListParenAST;
+        ast->expression_list = expression_list;
+        return ast;
+    }
+
+    NewArrayDeclaratorAST *NewArrayDeclarator(ExpressionAST *expression = 0)
+    {
+        NewArrayDeclaratorAST *ast = new (&pool) NewArrayDeclaratorAST;
+        ast->expression = expression;
+        return ast;
+    }
+
+    NewExpressionAST *NewExpression(ExpressionListParenAST *new_placement = 0, ExpressionAST *type_id = 0, NewTypeIdAST *new_type_id = 0, ExpressionAST *new_initializer = 0)
+    {
+        NewExpressionAST *ast = new (&pool) NewExpressionAST;
+        ast->new_placement = new_placement;
+        ast->type_id = type_id;
+        ast->new_type_id = new_type_id;
+        ast->new_initializer = new_initializer;
+        return ast;
+    }
+
+    NewTypeIdAST *NewTypeId(SpecifierListAST *type_specifier_list = 0, PtrOperatorListAST *ptr_operator_list = 0, NewArrayDeclaratorListAST *new_array_declarator_list = 0)
+    {
+        NewTypeIdAST *ast = new (&pool) NewTypeIdAST;
+        ast->type_specifier_list = type_specifier_list;
+        ast->ptr_operator_list = ptr_operator_list;
+        ast->new_array_declarator_list = new_array_declarator_list;
+        return ast;
+    }
+
+    OperatorAST *Operator()
+    {
+        OperatorAST *ast = new (&pool) OperatorAST;
+        return ast;
+    }
+
+    ParameterDeclarationAST *ParameterDeclaration(SpecifierListAST *type_specifier_list = 0, DeclaratorAST *declarator = 0, ExpressionAST *expression = 0)
+    {
+        ParameterDeclarationAST *ast = new (&pool) ParameterDeclarationAST;
+        ast->type_specifier_list = type_specifier_list;
+        ast->declarator = declarator;
+        ast->expression = expression;
+        return ast;
+    }
+
+    ParameterDeclarationClauseAST *ParameterDeclarationClause(ParameterDeclarationListAST *parameter_declaration_list = 0)
+    {
+        ParameterDeclarationClauseAST *ast = new (&pool) ParameterDeclarationClauseAST;
+        ast->parameter_declaration_list = parameter_declaration_list;
+        return ast;
+    }
+
+    CallAST *Call(ExpressionAST *base_expression = 0, ExpressionListAST *expression_list = 0)
+    {
+        CallAST *ast = new (&pool) CallAST;
+        ast->base_expression = base_expression;
+        ast->expression_list = expression_list;
+        return ast;
+    }
+
+    ArrayAccessAST *ArrayAccess(ExpressionAST *base_expression = 0, ExpressionAST *expression = 0)
+    {
+        ArrayAccessAST *ast = new (&pool) ArrayAccessAST;
+        ast->base_expression = base_expression;
+        ast->expression = expression;
+        return ast;
+    }
+
+    PostIncrDecrAST *PostIncrDecr(ExpressionAST *base_expression = 0)
+    {
+        PostIncrDecrAST *ast = new (&pool) PostIncrDecrAST;
+        ast->base_expression = base_expression;
+        return ast;
+    }
+
+    MemberAccessAST *MemberAccess(ExpressionAST *base_expression = 0, NameAST *member_name = 0)
+    {
+        MemberAccessAST *ast = new (&pool) MemberAccessAST;
+        ast->base_expression = base_expression;
+        ast->member_name = member_name;
+        return ast;
+    }
+
+    TypeidExpressionAST *TypeidExpression(ExpressionAST *expression = 0)
+    {
+        TypeidExpressionAST *ast = new (&pool) TypeidExpressionAST;
+        ast->expression = expression;
+        return ast;
+    }
+
+    TypenameCallExpressionAST *TypenameCallExpression(NameAST *name = 0, ExpressionAST *expression = 0)
+    {
+        TypenameCallExpressionAST *ast = new (&pool) TypenameCallExpressionAST;
+        ast->name = name;
+        ast->expression = expression;
+        return ast;
+    }
+
+    TypeConstructorCallAST *TypeConstructorCall(SpecifierListAST *type_specifier_list = 0, ExpressionAST *expression = 0)
+    {
+        TypeConstructorCallAST *ast = new (&pool) TypeConstructorCallAST;
+        ast->type_specifier_list = type_specifier_list;
+        ast->expression = expression;
+        return ast;
+    }
+
+    PointerToMemberAST *PointerToMember(NestedNameSpecifierListAST *nested_name_specifier_list = 0, SpecifierListAST *cv_qualifier_list = 0)
+    {
+        PointerToMemberAST *ast = new (&pool) PointerToMemberAST;
+        ast->nested_name_specifier_list = nested_name_specifier_list;
+        ast->cv_qualifier_list = cv_qualifier_list;
+        return ast;
+    }
+
+    PointerAST *Pointer(SpecifierListAST *cv_qualifier_list = 0)
+    {
+        PointerAST *ast = new (&pool) PointerAST;
+        ast->cv_qualifier_list = cv_qualifier_list;
+        return ast;
+    }
+
+    ReferenceAST *Reference()
+    {
+        ReferenceAST *ast = new (&pool) ReferenceAST;
+        return ast;
+    }
+
+    BreakStatementAST *BreakStatement()
+    {
+        BreakStatementAST *ast = new (&pool) BreakStatementAST;
+        return ast;
+    }
+
+    ContinueStatementAST *ContinueStatement()
+    {
+        ContinueStatementAST *ast = new (&pool) ContinueStatementAST;
+        return ast;
+    }
+
+    GotoStatementAST *GotoStatement()
+    {
+        GotoStatementAST *ast = new (&pool) GotoStatementAST;
+        return ast;
+    }
+
+    ReturnStatementAST *ReturnStatement(ExpressionAST *expression = 0)
+    {
+        ReturnStatementAST *ast = new (&pool) ReturnStatementAST;
+        ast->expression = expression;
+        return ast;
+    }
+
+    SizeofExpressionAST *SizeofExpression(ExpressionAST *expression = 0)
+    {
+        SizeofExpressionAST *ast = new (&pool) SizeofExpressionAST;
+        ast->expression = expression;
+        return ast;
+    }
+
+    AlignofExpressionAST *AlignofExpression(TypeIdAST *typeId = 0)
+    {
+        AlignofExpressionAST *ast = new (&pool) AlignofExpressionAST;
+        ast->typeId = typeId;
+        return ast;
+    }
+
+    PointerLiteralAST *PointerLiteral()
+    {
+        PointerLiteralAST *ast = new (&pool) PointerLiteralAST;
+        return ast;
+    }
+
+    NumericLiteralAST *NumericLiteral()
+    {
+        NumericLiteralAST *ast = new (&pool) NumericLiteralAST;
+        return ast;
+    }
+
+    BoolLiteralAST *BoolLiteral()
+    {
+        BoolLiteralAST *ast = new (&pool) BoolLiteralAST;
+        return ast;
+    }
+
+    ThisExpressionAST *ThisExpression()
+    {
+        ThisExpressionAST *ast = new (&pool) ThisExpressionAST;
+        return ast;
+    }
+
+    NestedExpressionAST *NestedExpression(ExpressionAST *expression = 0)
+    {
+        NestedExpressionAST *ast = new (&pool) NestedExpressionAST;
+        ast->expression = expression;
+        return ast;
+    }
+
+    StaticAssertDeclarationAST *StaticAssertDeclaration(ExpressionAST *expression = 0, ExpressionAST *string_literal = 0)
+    {
+        StaticAssertDeclarationAST *ast = new (&pool) StaticAssertDeclarationAST;
+        ast->expression = expression;
+        ast->string_literal = string_literal;
+        return ast;
+    }
+
+    StringLiteralAST *StringLiteral(StringLiteralAST *next = 0)
+    {
+        StringLiteralAST *ast = new (&pool) StringLiteralAST;
+        ast->next = next;
+        return ast;
+    }
+
+    SwitchStatementAST *SwitchStatement(ExpressionAST *condition = 0, StatementAST *statement = 0)
+    {
+        SwitchStatementAST *ast = new (&pool) SwitchStatementAST;
+        ast->condition = condition;
+        ast->statement = statement;
+        return ast;
+    }
+
+    TemplateDeclarationAST *TemplateDeclaration(DeclarationListAST *template_parameter_list = 0, DeclarationAST *declaration = 0)
+    {
+        TemplateDeclarationAST *ast = new (&pool) TemplateDeclarationAST;
+        ast->template_parameter_list = template_parameter_list;
+        ast->declaration = declaration;
+        return ast;
+    }
+
+    ThrowExpressionAST *ThrowExpression(ExpressionAST *expression = 0)
+    {
+        ThrowExpressionAST *ast = new (&pool) ThrowExpressionAST;
+        ast->expression = expression;
+        return ast;
+    }
+
+    TranslationUnitAST *TranslationUnit(DeclarationListAST *declaration_list = 0)
+    {
+        TranslationUnitAST *ast = new (&pool) TranslationUnitAST;
+        ast->declaration_list = declaration_list;
+        return ast;
+    }
+
+    TryBlockStatementAST *TryBlockStatement(StatementAST *statement = 0, CatchClauseListAST *catch_clause_list = 0)
+    {
+        TryBlockStatementAST *ast = new (&pool) TryBlockStatementAST;
+        ast->statement = statement;
+        ast->catch_clause_list = catch_clause_list;
+        return ast;
+    }
+
+    CatchClauseAST *CatchClause(ExceptionDeclarationAST *exception_declaration = 0, StatementAST *statement = 0)
+    {
+        CatchClauseAST *ast = new (&pool) CatchClauseAST;
+        ast->exception_declaration = exception_declaration;
+        ast->statement = statement;
+        return ast;
+    }
+
+    TypeIdAST *TypeId(SpecifierListAST *type_specifier_list = 0, DeclaratorAST *declarator = 0)
+    {
+        TypeIdAST *ast = new (&pool) TypeIdAST;
+        ast->type_specifier_list = type_specifier_list;
+        ast->declarator = declarator;
+        return ast;
+    }
+
+    TypenameTypeParameterAST *TypenameTypeParameter(NameAST *name = 0, ExpressionAST *type_id = 0)
+    {
+        TypenameTypeParameterAST *ast = new (&pool) TypenameTypeParameterAST;
+        ast->name = name;
+        ast->type_id = type_id;
+        return ast;
+    }
+
+    TemplateTypeParameterAST *TemplateTypeParameter(DeclarationListAST *template_parameter_list = 0, NameAST *name = 0, ExpressionAST *type_id = 0)
+    {
+        TemplateTypeParameterAST *ast = new (&pool) TemplateTypeParameterAST;
+        ast->template_parameter_list = template_parameter_list;
+        ast->name = name;
+        ast->type_id = type_id;
+        return ast;
+    }
+
+    UnaryExpressionAST *UnaryExpression(ExpressionAST *expression = 0)
+    {
+        UnaryExpressionAST *ast = new (&pool) UnaryExpressionAST;
+        ast->expression = expression;
+        return ast;
+    }
+
+    UsingAST *Using(NameAST *name = 0)
+    {
+        UsingAST *ast = new (&pool) UsingAST;
+        ast->name = name;
+        return ast;
+    }
+
+    UsingDirectiveAST *UsingDirective(NameAST *name = 0)
+    {
+        UsingDirectiveAST *ast = new (&pool) UsingDirectiveAST;
+        ast->name = name;
+        return ast;
+    }
+
+    WhileStatementAST *WhileStatement(ExpressionAST *condition = 0, StatementAST *statement = 0)
+    {
+        WhileStatementAST *ast = new (&pool) WhileStatementAST;
+        ast->condition = condition;
+        ast->statement = statement;
+        return ast;
+    }
+
+    ObjCClassForwardDeclarationAST *ObjCClassForwardDeclaration(SpecifierListAST *attribute_list = 0, NameListAST *identifier_list = 0)
+    {
+        ObjCClassForwardDeclarationAST *ast = new (&pool) ObjCClassForwardDeclarationAST;
+        ast->attribute_list = attribute_list;
+        ast->identifier_list = identifier_list;
+        return ast;
+    }
+
+    ObjCClassDeclarationAST *ObjCClassDeclaration(SpecifierListAST *attribute_list = 0, NameAST *class_name = 0, NameAST *category_name = 0, NameAST *superclass = 0, ObjCProtocolRefsAST *protocol_refs = 0, ObjCInstanceVariablesDeclarationAST *inst_vars_decl = 0, DeclarationListAST *member_declaration_list = 0)
+    {
+        ObjCClassDeclarationAST *ast = new (&pool) ObjCClassDeclarationAST;
+        ast->attribute_list = attribute_list;
+        ast->class_name = class_name;
+        ast->category_name = category_name;
+        ast->superclass = superclass;
+        ast->protocol_refs = protocol_refs;
+        ast->inst_vars_decl = inst_vars_decl;
+        ast->member_declaration_list = member_declaration_list;
+        return ast;
+    }
+
+    ObjCProtocolForwardDeclarationAST *ObjCProtocolForwardDeclaration(SpecifierListAST *attribute_list = 0, NameListAST *identifier_list = 0)
+    {
+        ObjCProtocolForwardDeclarationAST *ast = new (&pool) ObjCProtocolForwardDeclarationAST;
+        ast->attribute_list = attribute_list;
+        ast->identifier_list = identifier_list;
+        return ast;
+    }
+
+    ObjCProtocolDeclarationAST *ObjCProtocolDeclaration(SpecifierListAST *attribute_list = 0, NameAST *name = 0, ObjCProtocolRefsAST *protocol_refs = 0, DeclarationListAST *member_declaration_list = 0)
+    {
+        ObjCProtocolDeclarationAST *ast = new (&pool) ObjCProtocolDeclarationAST;
+        ast->attribute_list = attribute_list;
+        ast->name = name;
+        ast->protocol_refs = protocol_refs;
+        ast->member_declaration_list = member_declaration_list;
+        return ast;
+    }
+
+    ObjCProtocolRefsAST *ObjCProtocolRefs(NameListAST *identifier_list = 0)
+    {
+        ObjCProtocolRefsAST *ast = new (&pool) ObjCProtocolRefsAST;
+        ast->identifier_list = identifier_list;
+        return ast;
+    }
+
+    ObjCMessageArgumentAST *ObjCMessageArgument(ExpressionAST *parameter_value_expression = 0)
+    {
+        ObjCMessageArgumentAST *ast = new (&pool) ObjCMessageArgumentAST;
+        ast->parameter_value_expression = parameter_value_expression;
+        return ast;
+    }
+
+    ObjCMessageExpressionAST *ObjCMessageExpression(ExpressionAST *receiver_expression = 0, ObjCSelectorAST *selector = 0, ObjCMessageArgumentListAST *argument_list = 0)
+    {
+        ObjCMessageExpressionAST *ast = new (&pool) ObjCMessageExpressionAST;
+        ast->receiver_expression = receiver_expression;
+        ast->selector = selector;
+        ast->argument_list = argument_list;
+        return ast;
+    }
+
+    ObjCProtocolExpressionAST *ObjCProtocolExpression()
+    {
+        ObjCProtocolExpressionAST *ast = new (&pool) ObjCProtocolExpressionAST;
+        return ast;
+    }
+
+    ObjCTypeNameAST *ObjCTypeName(ExpressionAST *type_id = 0)
+    {
+        ObjCTypeNameAST *ast = new (&pool) ObjCTypeNameAST;
+        ast->type_id = type_id;
+        return ast;
+    }
+
+    ObjCEncodeExpressionAST *ObjCEncodeExpression(ObjCTypeNameAST *type_name = 0)
+    {
+        ObjCEncodeExpressionAST *ast = new (&pool) ObjCEncodeExpressionAST;
+        ast->type_name = type_name;
+        return ast;
+    }
+
+    ObjCSelectorExpressionAST *ObjCSelectorExpression(ObjCSelectorAST *selector = 0)
+    {
+        ObjCSelectorExpressionAST *ast = new (&pool) ObjCSelectorExpressionAST;
+        ast->selector = selector;
+        return ast;
+    }
+
+    ObjCInstanceVariablesDeclarationAST *ObjCInstanceVariablesDeclaration(DeclarationListAST *instance_variable_list = 0)
+    {
+        ObjCInstanceVariablesDeclarationAST *ast = new (&pool) ObjCInstanceVariablesDeclarationAST;
+        ast->instance_variable_list = instance_variable_list;
+        return ast;
+    }
+
+    ObjCVisibilityDeclarationAST *ObjCVisibilityDeclaration()
+    {
+        ObjCVisibilityDeclarationAST *ast = new (&pool) ObjCVisibilityDeclarationAST;
+        return ast;
+    }
+
+    ObjCPropertyAttributeAST *ObjCPropertyAttribute(ObjCSelectorAST *method_selector = 0)
+    {
+        ObjCPropertyAttributeAST *ast = new (&pool) ObjCPropertyAttributeAST;
+        ast->method_selector = method_selector;
+        return ast;
+    }
+
+    ObjCPropertyDeclarationAST *ObjCPropertyDeclaration(SpecifierListAST *attribute_list = 0, ObjCPropertyAttributeListAST *property_attribute_list = 0, DeclarationAST *simple_declaration = 0)
+    {
+        ObjCPropertyDeclarationAST *ast = new (&pool) ObjCPropertyDeclarationAST;
+        ast->attribute_list = attribute_list;
+        ast->property_attribute_list = property_attribute_list;
+        ast->simple_declaration = simple_declaration;
+        return ast;
+    }
+
+    ObjCMessageArgumentDeclarationAST *ObjCMessageArgumentDeclaration(ObjCTypeNameAST *type_name = 0, SpecifierListAST *attribute_list = 0, NameAST *param_name = 0)
+    {
+        ObjCMessageArgumentDeclarationAST *ast = new (&pool) ObjCMessageArgumentDeclarationAST;
+        ast->type_name = type_name;
+        ast->attribute_list = attribute_list;
+        ast->param_name = param_name;
+        return ast;
+    }
+
+    ObjCMethodPrototypeAST *ObjCMethodPrototype(ObjCTypeNameAST *type_name = 0, ObjCSelectorAST *selector = 0, ObjCMessageArgumentDeclarationListAST *argument_list = 0, SpecifierListAST *attribute_list = 0)
+    {
+        ObjCMethodPrototypeAST *ast = new (&pool) ObjCMethodPrototypeAST;
+        ast->type_name = type_name;
+        ast->selector = selector;
+        ast->argument_list = argument_list;
+        ast->attribute_list = attribute_list;
+        return ast;
+    }
+
+    ObjCMethodDeclarationAST *ObjCMethodDeclaration(ObjCMethodPrototypeAST *method_prototype = 0, StatementAST *function_body = 0)
+    {
+        ObjCMethodDeclarationAST *ast = new (&pool) ObjCMethodDeclarationAST;
+        ast->method_prototype = method_prototype;
+        ast->function_body = function_body;
+        return ast;
+    }
+
+    ObjCSynthesizedPropertyAST *ObjCSynthesizedProperty()
+    {
+        ObjCSynthesizedPropertyAST *ast = new (&pool) ObjCSynthesizedPropertyAST;
+        return ast;
+    }
+
+    ObjCSynthesizedPropertiesDeclarationAST *ObjCSynthesizedPropertiesDeclaration(ObjCSynthesizedPropertyListAST *property_identifier_list = 0)
+    {
+        ObjCSynthesizedPropertiesDeclarationAST *ast = new (&pool) ObjCSynthesizedPropertiesDeclarationAST;
+        ast->property_identifier_list = property_identifier_list;
+        return ast;
+    }
+
+    ObjCDynamicPropertiesDeclarationAST *ObjCDynamicPropertiesDeclaration(NameListAST *property_identifier_list = 0)
+    {
+        ObjCDynamicPropertiesDeclarationAST *ast = new (&pool) ObjCDynamicPropertiesDeclarationAST;
+        ast->property_identifier_list = property_identifier_list;
+        return ast;
+    }
+
+    ObjCFastEnumerationAST *ObjCFastEnumeration(SpecifierListAST *type_specifier_list = 0, DeclaratorAST *declarator = 0, ExpressionAST *initializer = 0, ExpressionAST *fast_enumeratable_expression = 0, StatementAST *statement = 0)
+    {
+        ObjCFastEnumerationAST *ast = new (&pool) ObjCFastEnumerationAST;
+        ast->type_specifier_list = type_specifier_list;
+        ast->declarator = declarator;
+        ast->initializer = initializer;
+        ast->fast_enumeratable_expression = fast_enumeratable_expression;
+        ast->statement = statement;
+        return ast;
+    }
+
+    ObjCSynchronizedStatementAST *ObjCSynchronizedStatement(ExpressionAST *synchronized_object = 0, StatementAST *statement = 0)
+    {
+        ObjCSynchronizedStatementAST *ast = new (&pool) ObjCSynchronizedStatementAST;
+        ast->synchronized_object = synchronized_object;
+        ast->statement = statement;
+        return ast;
+    }
+
+    LambdaExpressionAST *LambdaExpression(LambdaIntroducerAST *lambda_introducer = 0, LambdaDeclaratorAST *lambda_declarator = 0, StatementAST *statement = 0)
+    {
+        LambdaExpressionAST *ast = new (&pool) LambdaExpressionAST;
+        ast->lambda_introducer = lambda_introducer;
+        ast->lambda_declarator = lambda_declarator;
+        ast->statement = statement;
+        return ast;
+    }
+
+    LambdaIntroducerAST *LambdaIntroducer(LambdaCaptureAST *lambda_capture = 0)
+    {
+        LambdaIntroducerAST *ast = new (&pool) LambdaIntroducerAST;
+        ast->lambda_capture = lambda_capture;
+        return ast;
+    }
+
+    LambdaCaptureAST *LambdaCapture(CaptureListAST *capture_list = 0)
+    {
+        LambdaCaptureAST *ast = new (&pool) LambdaCaptureAST;
+        ast->capture_list = capture_list;
+        return ast;
+    }
+
+    CaptureAST *Capture(NameAST *identifier = 0)
+    {
+        CaptureAST *ast = new (&pool) CaptureAST;
+        ast->identifier = identifier;
+        return ast;
+    }
+
+    LambdaDeclaratorAST *LambdaDeclarator(ParameterDeclarationClauseAST *parameter_declaration_clause = 0, SpecifierListAST *attributes = 0, ExceptionSpecificationAST *exception_specification = 0, TrailingReturnTypeAST *trailing_return_type = 0)
+    {
+        LambdaDeclaratorAST *ast = new (&pool) LambdaDeclaratorAST;
+        ast->parameter_declaration_clause = parameter_declaration_clause;
+        ast->attributes = attributes;
+        ast->exception_specification = exception_specification;
+        ast->trailing_return_type = trailing_return_type;
+        return ast;
+    }
+
+    TrailingReturnTypeAST *TrailingReturnType(SpecifierListAST *attributes = 0, SpecifierListAST *type_specifier_list = 0, DeclaratorAST *declarator = 0)
+    {
+        TrailingReturnTypeAST *ast = new (&pool) TrailingReturnTypeAST;
+        ast->attributes = attributes;
+        ast->type_specifier_list = type_specifier_list;
+        ast->declarator = declarator;
+        return ast;
+    }
+
+    BracedInitializerAST *BracedInitializer(ExpressionListAST *expression_list = 0)
+    {
+        BracedInitializerAST *ast = new (&pool) BracedInitializerAST;
+        ast->expression_list = expression_list;
+        return ast;
+    }
+
+    DotDesignatorAST *DotDesignator()
+    {
+        DotDesignatorAST *ast = new (&pool) DotDesignatorAST;
+        return ast;
+    }
+
+    BracketDesignatorAST *BracketDesignator(ExpressionAST *expression = 0)
+    {
+        BracketDesignatorAST *ast = new (&pool) BracketDesignatorAST;
+        ast->expression = expression;
+        return ast;
+    }
+
+    DesignatedInitializerAST *DesignatedInitializer(DesignatorListAST *designator_list = 0, ExpressionAST *initializer = 0)
+    {
+        DesignatedInitializerAST *ast = new (&pool) DesignatedInitializerAST;
+        ast->designator_list = designator_list;
+        ast->initializer = initializer;
+        return ast;
+    }
+
+    BaseSpecifierListAST *BaseSpecifierList(BaseSpecifierAST *value, BaseSpecifierListAST *next = 0)
+    {
+        BaseSpecifierListAST *list = new (&pool) BaseSpecifierListAST;
+        list->next = next;
+        list->value = value;
+        return list;
+    }
+
+    CaptureListAST *CaptureList(CaptureAST *value, CaptureListAST *next = 0)
+    {
+        CaptureListAST *list = new (&pool) CaptureListAST;
+        list->next = next;
+        list->value = value;
+        return list;
+    }
+
+    CatchClauseListAST *CatchClauseList(CatchClauseAST *value, CatchClauseListAST *next = 0)
+    {
+        CatchClauseListAST *list = new (&pool) CatchClauseListAST;
+        list->next = next;
+        list->value = value;
+        return list;
+    }
+
+    DeclarationListAST *DeclarationList(DeclarationAST *value, DeclarationListAST *next = 0)
+    {
+        DeclarationListAST *list = new (&pool) DeclarationListAST;
+        list->next = next;
+        list->value = value;
+        return list;
+    }
+
+    DeclaratorListAST *DeclaratorList(DeclaratorAST *value, DeclaratorListAST *next = 0)
+    {
+        DeclaratorListAST *list = new (&pool) DeclaratorListAST;
+        list->next = next;
+        list->value = value;
+        return list;
+    }
+
+    DesignatorListAST *DesignatorList(DesignatorAST *value, DesignatorListAST *next = 0)
+    {
+        DesignatorListAST *list = new (&pool) DesignatorListAST;
+        list->next = next;
+        list->value = value;
+        return list;
+    }
+
+    EnumeratorListAST *EnumeratorList(EnumeratorAST *value, EnumeratorListAST *next = 0)
+    {
+        EnumeratorListAST *list = new (&pool) EnumeratorListAST;
+        list->next = next;
+        list->value = value;
+        return list;
+    }
+
+    ExpressionListAST *ExpressionList(ExpressionAST *value, ExpressionListAST *next = 0)
+    {
+        ExpressionListAST *list = new (&pool) ExpressionListAST;
+        list->next = next;
+        list->value = value;
+        return list;
+    }
+
+    GnuAttributeListAST *GnuAttributeList(GnuAttributeAST *value, GnuAttributeListAST *next = 0)
+    {
+        GnuAttributeListAST *list = new (&pool) GnuAttributeListAST;
+        list->next = next;
+        list->value = value;
+        return list;
+    }
+
+    MemInitializerListAST *MemInitializerList(MemInitializerAST *value, MemInitializerListAST *next = 0)
+    {
+        MemInitializerListAST *list = new (&pool) MemInitializerListAST;
+        list->next = next;
+        list->value = value;
+        return list;
+    }
+
+    NameListAST *NameList(NameAST *value, NameListAST *next = 0)
+    {
+        NameListAST *list = new (&pool) NameListAST;
+        list->next = next;
+        list->value = value;
+        return list;
+    }
+
+    NestedNameSpecifierListAST *NestedNameSpecifierList(NestedNameSpecifierAST *value, NestedNameSpecifierListAST *next = 0)
+    {
+        NestedNameSpecifierListAST *list = new (&pool) NestedNameSpecifierListAST;
+        list->next = next;
+        list->value = value;
+        return list;
+    }
+
+    NewArrayDeclaratorListAST *NewArrayDeclaratorList(NewArrayDeclaratorAST *value, NewArrayDeclaratorListAST *next = 0)
+    {
+        NewArrayDeclaratorListAST *list = new (&pool) NewArrayDeclaratorListAST;
+        list->next = next;
+        list->value = value;
+        return list;
+    }
+
+    ObjCMessageArgumentDeclarationListAST *ObjCMessageArgumentDeclarationList(ObjCMessageArgumentDeclarationAST *value, ObjCMessageArgumentDeclarationListAST *next = 0)
+    {
+        ObjCMessageArgumentDeclarationListAST *list = new (&pool) ObjCMessageArgumentDeclarationListAST;
+        list->next = next;
+        list->value = value;
+        return list;
+    }
+
+    ObjCMessageArgumentListAST *ObjCMessageArgumentList(ObjCMessageArgumentAST *value, ObjCMessageArgumentListAST *next = 0)
+    {
+        ObjCMessageArgumentListAST *list = new (&pool) ObjCMessageArgumentListAST;
+        list->next = next;
+        list->value = value;
+        return list;
+    }
+
+    ObjCPropertyAttributeListAST *ObjCPropertyAttributeList(ObjCPropertyAttributeAST *value, ObjCPropertyAttributeListAST *next = 0)
+    {
+        ObjCPropertyAttributeListAST *list = new (&pool) ObjCPropertyAttributeListAST;
+        list->next = next;
+        list->value = value;
+        return list;
+    }
+
+    ObjCSelectorArgumentListAST *ObjCSelectorArgumentList(ObjCSelectorArgumentAST *value, ObjCSelectorArgumentListAST *next = 0)
+    {
+        ObjCSelectorArgumentListAST *list = new (&pool) ObjCSelectorArgumentListAST;
+        list->next = next;
+        list->value = value;
+        return list;
+    }
+
+    ObjCSynthesizedPropertyListAST *ObjCSynthesizedPropertyList(ObjCSynthesizedPropertyAST *value, ObjCSynthesizedPropertyListAST *next = 0)
+    {
+        ObjCSynthesizedPropertyListAST *list = new (&pool) ObjCSynthesizedPropertyListAST;
+        list->next = next;
+        list->value = value;
+        return list;
+    }
+
+    ParameterDeclarationListAST *ParameterDeclarationList(ParameterDeclarationAST *value, ParameterDeclarationListAST *next = 0)
+    {
+        ParameterDeclarationListAST *list = new (&pool) ParameterDeclarationListAST;
+        list->next = next;
+        list->value = value;
+        return list;
+    }
+
+    PostfixDeclaratorListAST *PostfixDeclaratorList(PostfixDeclaratorAST *value, PostfixDeclaratorListAST *next = 0)
+    {
+        PostfixDeclaratorListAST *list = new (&pool) PostfixDeclaratorListAST;
+        list->next = next;
+        list->value = value;
+        return list;
+    }
+
+    PtrOperatorListAST *PtrOperatorList(PtrOperatorAST *value, PtrOperatorListAST *next = 0)
+    {
+        PtrOperatorListAST *list = new (&pool) PtrOperatorListAST;
+        list->next = next;
+        list->value = value;
+        return list;
+    }
+
+    QtInterfaceNameListAST *QtInterfaceNameList(QtInterfaceNameAST *value, QtInterfaceNameListAST *next = 0)
+    {
+        QtInterfaceNameListAST *list = new (&pool) QtInterfaceNameListAST;
+        list->next = next;
+        list->value = value;
+        return list;
+    }
+
+    QtPropertyDeclarationItemListAST *QtPropertyDeclarationItemList(QtPropertyDeclarationItemAST *value, QtPropertyDeclarationItemListAST *next = 0)
+    {
+        QtPropertyDeclarationItemListAST *list = new (&pool) QtPropertyDeclarationItemListAST;
+        list->next = next;
+        list->value = value;
+        return list;
+    }
+
+    SpecifierListAST *SpecifierList(SpecifierAST *value, SpecifierListAST *next = 0)
+    {
+        SpecifierListAST *list = new (&pool) SpecifierListAST;
+        list->next = next;
+        list->value = value;
+        return list;
+    }
+
+    StatementListAST *StatementList(StatementAST *value, StatementListAST *next = 0)
+    {
+        StatementListAST *list = new (&pool) StatementListAST;
+        list->next = next;
+        list->value = value;
+        return list;
+    }
+
+};
+
+} // end of namespace CPlusPlus
+
+#endif // CPLUSPLUS_AST_PATTERN_BUILDER_H

+ 1313 - 0
Source/ToolCore/JSBind/cplusplus/ASTVisit.cpp

@@ -0,0 +1,1313 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is automatically generated by "cplusplus-update-frontend".
+// Changes will be lost.
+//
+
+
+#include "AST.h"
+#include "ASTVisitor.h"
+
+using namespace CPlusPlus;
+
+void ObjCSelectorArgumentAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCSelectorAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(selector_argument_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void SimpleSpecifierAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+    }
+    visitor->endVisit(this);
+}
+
+void AlignmentSpecifierAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(typeIdExprOrAlignmentExpr, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void GnuAttributeSpecifierAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(attribute_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void GnuAttributeAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(expression_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void TypeofSpecifierAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(expression, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void DecltypeSpecifierAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(expression, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void DeclaratorAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(attribute_list, visitor);
+        accept(ptr_operator_list, visitor);
+        accept(core_declarator, visitor);
+        accept(postfix_declarator_list, visitor);
+        accept(post_attribute_list, visitor);
+        accept(initializer, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void SimpleDeclarationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(decl_specifier_list, visitor);
+        accept(declarator_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void EmptyDeclarationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+    }
+    visitor->endVisit(this);
+}
+
+void AccessDeclarationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+    }
+    visitor->endVisit(this);
+}
+
+void QtObjectTagAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+    }
+    visitor->endVisit(this);
+}
+
+void QtPrivateSlotAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(type_specifier_list, visitor);
+        accept(declarator, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void QtPropertyDeclarationItemAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(expression, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void QtPropertyDeclarationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(expression, visitor);
+        accept(type_id, visitor);
+        accept(property_name, visitor);
+        accept(property_declaration_item_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void QtEnumDeclarationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(enumerator_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void QtFlagsDeclarationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(flag_enums_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void QtInterfaceNameAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(interface_name, visitor);
+        accept(constraint_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void QtInterfacesDeclarationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(interface_name_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void AsmDefinitionAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+    }
+    visitor->endVisit(this);
+}
+
+void BaseSpecifierAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(name, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void IdExpressionAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(name, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void CompoundExpressionAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(statement, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void CompoundLiteralAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(type_id, visitor);
+        accept(initializer, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void QtMethodAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(declarator, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void QtMemberDeclarationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(type_id, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void BinaryExpressionAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(left_expression, visitor);
+        accept(right_expression, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void CastExpressionAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(type_id, visitor);
+        accept(expression, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ClassSpecifierAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(attribute_list, visitor);
+        accept(name, visitor);
+        accept(base_clause_list, visitor);
+        accept(member_specifier_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void CaseStatementAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(expression, visitor);
+        accept(statement, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void CompoundStatementAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(statement_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ConditionAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(type_specifier_list, visitor);
+        accept(declarator, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ConditionalExpressionAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(condition, visitor);
+        accept(left_expression, visitor);
+        accept(right_expression, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void CppCastExpressionAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(type_id, visitor);
+        accept(expression, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void CtorInitializerAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(member_initializer_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void DeclarationStatementAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(declaration, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void DeclaratorIdAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(name, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void NestedDeclaratorAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(declarator, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void FunctionDeclaratorAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(parameter_declaration_clause, visitor);
+        accept(cv_qualifier_list, visitor);
+        accept(exception_specification, visitor);
+        accept(trailing_return_type, visitor);
+        accept(as_cpp_initializer, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ArrayDeclaratorAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(expression, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void DeleteExpressionAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(expression, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void DoStatementAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(statement, visitor);
+        accept(expression, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void NamedTypeSpecifierAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(name, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ElaboratedTypeSpecifierAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(attribute_list, visitor);
+        accept(name, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void EnumSpecifierAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(name, visitor);
+        accept(type_specifier_list, visitor);
+        accept(enumerator_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void EnumeratorAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(expression, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ExceptionDeclarationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(type_specifier_list, visitor);
+        accept(declarator, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void DynamicExceptionSpecificationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(type_id_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void NoExceptSpecificationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(expression, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ExpressionOrDeclarationStatementAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(expression, visitor);
+        accept(declaration, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ExpressionStatementAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(expression, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void FunctionDefinitionAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(decl_specifier_list, visitor);
+        accept(declarator, visitor);
+        accept(ctor_initializer, visitor);
+        accept(function_body, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ForeachStatementAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(type_specifier_list, visitor);
+        accept(declarator, visitor);
+        accept(initializer, visitor);
+        accept(expression, visitor);
+        accept(statement, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void RangeBasedForStatementAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(type_specifier_list, visitor);
+        accept(declarator, visitor);
+        accept(expression, visitor);
+        accept(statement, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ForStatementAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(initializer, visitor);
+        accept(condition, visitor);
+        accept(expression, visitor);
+        accept(statement, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void IfStatementAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(condition, visitor);
+        accept(statement, visitor);
+        accept(else_statement, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ArrayInitializerAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(expression_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void LabeledStatementAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(statement, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void LinkageBodyAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(declaration_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void LinkageSpecificationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(declaration, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void MemInitializerAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(name, visitor);
+        accept(expression, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void NestedNameSpecifierAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(class_or_namespace_name, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void QualifiedNameAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(nested_name_specifier_list, visitor);
+        accept(unqualified_name, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void OperatorFunctionIdAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(op, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ConversionFunctionIdAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(type_specifier_list, visitor);
+        accept(ptr_operator_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void AnonymousNameAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+    }
+    visitor->endVisit(this);
+}
+
+void SimpleNameAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+    }
+    visitor->endVisit(this);
+}
+
+void DestructorNameAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(unqualified_name, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void TemplateIdAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(template_argument_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void NamespaceAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(attribute_list, visitor);
+        accept(linkage_body, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void NamespaceAliasDefinitionAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(name, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void AliasDeclarationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(name, visitor);
+        accept(typeId, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ExpressionListParenAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(expression_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void NewArrayDeclaratorAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(expression, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void NewExpressionAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(new_placement, visitor);
+        accept(type_id, visitor);
+        accept(new_type_id, visitor);
+        accept(new_initializer, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void NewTypeIdAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(type_specifier_list, visitor);
+        accept(ptr_operator_list, visitor);
+        accept(new_array_declarator_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void OperatorAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+    }
+    visitor->endVisit(this);
+}
+
+void ParameterDeclarationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(type_specifier_list, visitor);
+        accept(declarator, visitor);
+        accept(expression, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ParameterDeclarationClauseAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(parameter_declaration_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void CallAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(base_expression, visitor);
+        accept(expression_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ArrayAccessAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(base_expression, visitor);
+        accept(expression, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void PostIncrDecrAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(base_expression, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void MemberAccessAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(base_expression, visitor);
+        accept(member_name, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void TypeidExpressionAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(expression, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void TypenameCallExpressionAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(name, visitor);
+        accept(expression, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void TypeConstructorCallAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(type_specifier_list, visitor);
+        accept(expression, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void PointerToMemberAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(nested_name_specifier_list, visitor);
+        accept(cv_qualifier_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void PointerAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(cv_qualifier_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ReferenceAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+    }
+    visitor->endVisit(this);
+}
+
+void BreakStatementAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+    }
+    visitor->endVisit(this);
+}
+
+void ContinueStatementAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+    }
+    visitor->endVisit(this);
+}
+
+void GotoStatementAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+    }
+    visitor->endVisit(this);
+}
+
+void ReturnStatementAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(expression, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void SizeofExpressionAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(expression, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void AlignofExpressionAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(typeId, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void PointerLiteralAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+    }
+    visitor->endVisit(this);
+}
+
+void NumericLiteralAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+    }
+    visitor->endVisit(this);
+}
+
+void BoolLiteralAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+    }
+    visitor->endVisit(this);
+}
+
+void ThisExpressionAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+    }
+    visitor->endVisit(this);
+}
+
+void NestedExpressionAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(expression, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void StaticAssertDeclarationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(expression, visitor);
+        accept(string_literal, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void StringLiteralAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+    }
+    visitor->endVisit(this);
+}
+
+void SwitchStatementAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(condition, visitor);
+        accept(statement, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void TemplateDeclarationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(template_parameter_list, visitor);
+        accept(declaration, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ThrowExpressionAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(expression, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void TranslationUnitAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(declaration_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void TryBlockStatementAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(statement, visitor);
+        accept(catch_clause_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void CatchClauseAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(exception_declaration, visitor);
+        accept(statement, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void TypeIdAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(type_specifier_list, visitor);
+        accept(declarator, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void TypenameTypeParameterAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(name, visitor);
+        accept(type_id, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void TemplateTypeParameterAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(template_parameter_list, visitor);
+        accept(name, visitor);
+        accept(type_id, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void UnaryExpressionAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(expression, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void UsingAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(name, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void UsingDirectiveAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(name, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void WhileStatementAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(condition, visitor);
+        accept(statement, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCClassForwardDeclarationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(attribute_list, visitor);
+        accept(identifier_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCClassDeclarationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(attribute_list, visitor);
+        accept(class_name, visitor);
+        accept(category_name, visitor);
+        accept(superclass, visitor);
+        accept(protocol_refs, visitor);
+        accept(inst_vars_decl, visitor);
+        accept(member_declaration_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCProtocolForwardDeclarationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(attribute_list, visitor);
+        accept(identifier_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCProtocolDeclarationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(attribute_list, visitor);
+        accept(name, visitor);
+        accept(protocol_refs, visitor);
+        accept(member_declaration_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCProtocolRefsAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(identifier_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCMessageArgumentAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(parameter_value_expression, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCMessageExpressionAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(receiver_expression, visitor);
+        accept(selector, visitor);
+        accept(argument_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCProtocolExpressionAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCTypeNameAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(type_id, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCEncodeExpressionAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(type_name, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCSelectorExpressionAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(selector, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCInstanceVariablesDeclarationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(instance_variable_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCVisibilityDeclarationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCPropertyAttributeAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(method_selector, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCPropertyDeclarationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(attribute_list, visitor);
+        accept(property_attribute_list, visitor);
+        accept(simple_declaration, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCMessageArgumentDeclarationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(type_name, visitor);
+        accept(attribute_list, visitor);
+        accept(param_name, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCMethodPrototypeAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(type_name, visitor);
+        accept(selector, visitor);
+        accept(argument_list, visitor);
+        accept(attribute_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCMethodDeclarationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(method_prototype, visitor);
+        accept(function_body, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCSynthesizedPropertyAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCSynthesizedPropertiesDeclarationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(property_identifier_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCDynamicPropertiesDeclarationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(property_identifier_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCFastEnumerationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(type_specifier_list, visitor);
+        accept(declarator, visitor);
+        accept(initializer, visitor);
+        accept(fast_enumeratable_expression, visitor);
+        accept(statement, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCSynchronizedStatementAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(synchronized_object, visitor);
+        accept(statement, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void LambdaExpressionAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(lambda_introducer, visitor);
+        accept(lambda_declarator, visitor);
+        accept(statement, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void LambdaIntroducerAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(lambda_capture, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void LambdaCaptureAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(capture_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void CaptureAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(identifier, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void LambdaDeclaratorAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(parameter_declaration_clause, visitor);
+        accept(attributes, visitor);
+        accept(exception_specification, visitor);
+        accept(trailing_return_type, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void TrailingReturnTypeAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(attributes, visitor);
+        accept(type_specifier_list, visitor);
+        accept(declarator, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void BracedInitializerAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(expression_list, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void DotDesignatorAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+    }
+    visitor->endVisit(this);
+}
+
+void BracketDesignatorAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(expression, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void DesignatedInitializerAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(designator_list, visitor);
+        accept(initializer, visitor);
+    }
+    visitor->endVisit(this);
+}
+

+ 92 - 0
Source/ToolCore/JSBind/cplusplus/ASTVisitor.cpp

@@ -0,0 +1,92 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "ASTVisitor.h"
+#include "AST.h"
+#include "TranslationUnit.h"
+#include "Control.h"
+
+using namespace CPlusPlus;
+
+ASTVisitor::ASTVisitor(TranslationUnit *translationUnit)
+    : _translationUnit(translationUnit)
+{ }
+
+ASTVisitor::~ASTVisitor()
+{ }
+
+void ASTVisitor::accept(AST *ast)
+{ AST::accept(ast, this); }
+
+Control *ASTVisitor::control() const
+{
+    if (_translationUnit)
+        return _translationUnit->control();
+
+    return 0;
+}
+
+TranslationUnit *ASTVisitor::translationUnit() const
+{ return _translationUnit; }
+
+void ASTVisitor::setTranslationUnit(TranslationUnit *translationUnit)
+{ _translationUnit = translationUnit; }
+
+unsigned ASTVisitor::tokenCount() const
+{ return translationUnit()->tokenCount(); }
+
+const Token &ASTVisitor::tokenAt(unsigned index) const
+{ return translationUnit()->tokenAt(index); }
+
+int ASTVisitor::tokenKind(unsigned index) const
+{ return translationUnit()->tokenKind(index); }
+
+const char *ASTVisitor::spell(unsigned index) const
+{ return translationUnit()->spell(index); }
+
+const Identifier *ASTVisitor::identifier(unsigned index) const
+{ return translationUnit()->identifier(index); }
+
+const Literal *ASTVisitor::literal(unsigned index) const
+{ return translationUnit()->literal(index); }
+
+const NumericLiteral *ASTVisitor::numericLiteral(unsigned index) const
+{ return translationUnit()->numericLiteral(index); }
+
+const StringLiteral *ASTVisitor::stringLiteral(unsigned index) const
+{ return translationUnit()->stringLiteral(index); }
+
+void ASTVisitor::getPosition(unsigned offset,
+                             unsigned *line,
+                             unsigned *column,
+                             const StringLiteral **fileName) const
+{ translationUnit()->getPosition(offset, line, column, fileName); }
+
+void ASTVisitor::getTokenPosition(unsigned index,
+                                  unsigned *line,
+                                  unsigned *column,
+                                  const StringLiteral **fileName) const
+{ translationUnit()->getTokenPosition(index, line, column, fileName); }
+
+void ASTVisitor::getTokenStartPosition(unsigned index, unsigned *line, unsigned *column) const
+{ getPosition(tokenAt(index).utf16charsBegin(), line, column); }
+
+void ASTVisitor::getTokenEndPosition(unsigned index, unsigned *line, unsigned *column) const
+{ getPosition(tokenAt(index).utf16charsEnd(), line, column); }

+ 382 - 0
Source/ToolCore/JSBind/cplusplus/ASTVisitor.h

@@ -0,0 +1,382 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_ASTVISITOR_H
+#define CPLUSPLUS_ASTVISITOR_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include "ASTfwd.h"
+
+namespace CPlusPlus {
+
+class CPLUSPLUS_EXPORT ASTVisitor
+{
+    ASTVisitor(const ASTVisitor &other);
+    void operator =(const ASTVisitor &other);
+
+public:
+    ASTVisitor(TranslationUnit *unit);
+    virtual ~ASTVisitor();
+
+    TranslationUnit *translationUnit() const;
+    void setTranslationUnit(TranslationUnit *translationUnit);
+
+    Control *control() const;
+    unsigned tokenCount() const;
+    const Token &tokenAt(unsigned index) const;
+    int tokenKind(unsigned index) const;
+    const char *spell(unsigned index) const;
+    const Identifier *identifier(unsigned index) const;
+    const Literal *literal(unsigned index) const;
+    const NumericLiteral *numericLiteral(unsigned index) const;
+    const StringLiteral *stringLiteral(unsigned index) const;
+
+    void getPosition(unsigned offset,
+                     unsigned *line,
+                     unsigned *column = 0,
+                     const StringLiteral **fileName = 0) const;
+
+    void getTokenPosition(unsigned index,
+                          unsigned *line,
+                          unsigned *column = 0,
+                          const StringLiteral **fileName = 0) const;
+
+    void getTokenStartPosition(unsigned index, unsigned *line, unsigned *column) const;
+    void getTokenEndPosition(unsigned index, unsigned *line, unsigned *column) const;
+
+    void accept(AST *ast);
+
+    template <typename Tptr>
+    void accept(List<Tptr> *it)
+    {
+        for (; it; it = it->next)
+            accept(it->value);
+    }
+
+    virtual bool preVisit(AST *) { return true; }
+    virtual void postVisit(AST *) {}
+
+    virtual bool visit(AccessDeclarationAST *) { return true; }
+    virtual bool visit(AliasDeclarationAST *) { return true; }
+    virtual bool visit(AlignmentSpecifierAST *) { return true; }
+    virtual bool visit(AlignofExpressionAST *) { return true; }
+    virtual bool visit(AnonymousNameAST *) { return true; }
+    virtual bool visit(ArrayAccessAST *) { return true; }
+    virtual bool visit(ArrayDeclaratorAST *) { return true; }
+    virtual bool visit(ArrayInitializerAST *) { return true; }
+    virtual bool visit(AsmDefinitionAST *) { return true; }
+    virtual bool visit(BaseSpecifierAST *) { return true; }
+    virtual bool visit(BinaryExpressionAST *) { return true; }
+    virtual bool visit(BoolLiteralAST *) { return true; }
+    virtual bool visit(BracedInitializerAST *) { return true; }
+    virtual bool visit(BracketDesignatorAST *) { return true; }
+    virtual bool visit(BreakStatementAST *) { return true; }
+    virtual bool visit(CallAST *) { return true; }
+    virtual bool visit(CaptureAST *) { return true; }
+    virtual bool visit(CaseStatementAST *) { return true; }
+    virtual bool visit(CastExpressionAST *) { return true; }
+    virtual bool visit(CatchClauseAST *) { return true; }
+    virtual bool visit(ClassSpecifierAST *) { return true; }
+    virtual bool visit(CompoundExpressionAST *) { return true; }
+    virtual bool visit(CompoundLiteralAST *) { return true; }
+    virtual bool visit(CompoundStatementAST *) { return true; }
+    virtual bool visit(ConditionAST *) { return true; }
+    virtual bool visit(ConditionalExpressionAST *) { return true; }
+    virtual bool visit(ContinueStatementAST *) { return true; }
+    virtual bool visit(ConversionFunctionIdAST *) { return true; }
+    virtual bool visit(CppCastExpressionAST *) { return true; }
+    virtual bool visit(CtorInitializerAST *) { return true; }
+    virtual bool visit(DeclarationStatementAST *) { return true; }
+    virtual bool visit(DeclaratorAST *) { return true; }
+    virtual bool visit(DeclaratorIdAST *) { return true; }
+    virtual bool visit(DecltypeSpecifierAST *) { return true; }
+    virtual bool visit(DeleteExpressionAST *) { return true; }
+    virtual bool visit(DesignatedInitializerAST *) { return true; }
+    virtual bool visit(DestructorNameAST *) { return true; }
+    virtual bool visit(DoStatementAST *) { return true; }
+    virtual bool visit(DotDesignatorAST *) { return true; }
+    virtual bool visit(DynamicExceptionSpecificationAST *) { return true; }
+    virtual bool visit(ElaboratedTypeSpecifierAST *) { return true; }
+    virtual bool visit(EmptyDeclarationAST *) { return true; }
+    virtual bool visit(EnumSpecifierAST *) { return true; }
+    virtual bool visit(EnumeratorAST *) { return true; }
+    virtual bool visit(ExceptionDeclarationAST *) { return true; }
+    virtual bool visit(ExpressionListParenAST *) { return true; }
+    virtual bool visit(ExpressionOrDeclarationStatementAST *) { return true; }
+    virtual bool visit(ExpressionStatementAST *) { return true; }
+    virtual bool visit(ForStatementAST *) { return true; }
+    virtual bool visit(ForeachStatementAST *) { return true; }
+    virtual bool visit(FunctionDeclaratorAST *) { return true; }
+    virtual bool visit(FunctionDefinitionAST *) { return true; }
+    virtual bool visit(GnuAttributeAST *) { return true; }
+    virtual bool visit(GnuAttributeSpecifierAST *) { return true; }
+    virtual bool visit(GotoStatementAST *) { return true; }
+    virtual bool visit(IdExpressionAST *) { return true; }
+    virtual bool visit(IfStatementAST *) { return true; }
+    virtual bool visit(LabeledStatementAST *) { return true; }
+    virtual bool visit(LambdaCaptureAST *) { return true; }
+    virtual bool visit(LambdaDeclaratorAST *) { return true; }
+    virtual bool visit(LambdaExpressionAST *) { return true; }
+    virtual bool visit(LambdaIntroducerAST *) { return true; }
+    virtual bool visit(LinkageBodyAST *) { return true; }
+    virtual bool visit(LinkageSpecificationAST *) { return true; }
+    virtual bool visit(MemInitializerAST *) { return true; }
+    virtual bool visit(MemberAccessAST *) { return true; }
+    virtual bool visit(NamedTypeSpecifierAST *) { return true; }
+    virtual bool visit(NamespaceAST *) { return true; }
+    virtual bool visit(NamespaceAliasDefinitionAST *) { return true; }
+    virtual bool visit(NestedDeclaratorAST *) { return true; }
+    virtual bool visit(NestedExpressionAST *) { return true; }
+    virtual bool visit(NestedNameSpecifierAST *) { return true; }
+    virtual bool visit(NewArrayDeclaratorAST *) { return true; }
+    virtual bool visit(NewExpressionAST *) { return true; }
+    virtual bool visit(NewTypeIdAST *) { return true; }
+    virtual bool visit(NoExceptSpecificationAST *) { return true; }
+    virtual bool visit(NumericLiteralAST *) { return true; }
+    virtual bool visit(ObjCClassDeclarationAST *) { return true; }
+    virtual bool visit(ObjCClassForwardDeclarationAST *) { return true; }
+    virtual bool visit(ObjCDynamicPropertiesDeclarationAST *) { return true; }
+    virtual bool visit(ObjCEncodeExpressionAST *) { return true; }
+    virtual bool visit(ObjCFastEnumerationAST *) { return true; }
+    virtual bool visit(ObjCInstanceVariablesDeclarationAST *) { return true; }
+    virtual bool visit(ObjCMessageArgumentAST *) { return true; }
+    virtual bool visit(ObjCMessageArgumentDeclarationAST *) { return true; }
+    virtual bool visit(ObjCMessageExpressionAST *) { return true; }
+    virtual bool visit(ObjCMethodDeclarationAST *) { return true; }
+    virtual bool visit(ObjCMethodPrototypeAST *) { return true; }
+    virtual bool visit(ObjCPropertyAttributeAST *) { return true; }
+    virtual bool visit(ObjCPropertyDeclarationAST *) { return true; }
+    virtual bool visit(ObjCProtocolDeclarationAST *) { return true; }
+    virtual bool visit(ObjCProtocolExpressionAST *) { return true; }
+    virtual bool visit(ObjCProtocolForwardDeclarationAST *) { return true; }
+    virtual bool visit(ObjCProtocolRefsAST *) { return true; }
+    virtual bool visit(ObjCSelectorAST *) { return true; }
+    virtual bool visit(ObjCSelectorArgumentAST *) { return true; }
+    virtual bool visit(ObjCSelectorExpressionAST *) { return true; }
+    virtual bool visit(ObjCSynchronizedStatementAST *) { return true; }
+    virtual bool visit(ObjCSynthesizedPropertiesDeclarationAST *) { return true; }
+    virtual bool visit(ObjCSynthesizedPropertyAST *) { return true; }
+    virtual bool visit(ObjCTypeNameAST *) { return true; }
+    virtual bool visit(ObjCVisibilityDeclarationAST *) { return true; }
+    virtual bool visit(OperatorAST *) { return true; }
+    virtual bool visit(OperatorFunctionIdAST *) { return true; }
+    virtual bool visit(ParameterDeclarationAST *) { return true; }
+    virtual bool visit(ParameterDeclarationClauseAST *) { return true; }
+    virtual bool visit(PointerAST *) { return true; }
+    virtual bool visit(PointerLiteralAST *) { return true; }
+    virtual bool visit(PointerToMemberAST *) { return true; }
+    virtual bool visit(PostIncrDecrAST *) { return true; }
+    virtual bool visit(QtEnumDeclarationAST *) { return true; }
+    virtual bool visit(QtFlagsDeclarationAST *) { return true; }
+    virtual bool visit(QtInterfaceNameAST *) { return true; }
+    virtual bool visit(QtInterfacesDeclarationAST *) { return true; }
+    virtual bool visit(QtMemberDeclarationAST *) { return true; }
+    virtual bool visit(QtMethodAST *) { return true; }
+    virtual bool visit(QtObjectTagAST *) { return true; }
+    virtual bool visit(QtPrivateSlotAST *) { return true; }
+    virtual bool visit(QtPropertyDeclarationAST *) { return true; }
+    virtual bool visit(QtPropertyDeclarationItemAST *) { return true; }
+    virtual bool visit(QualifiedNameAST *) { return true; }
+    virtual bool visit(RangeBasedForStatementAST *) { return true; }
+    virtual bool visit(ReferenceAST *) { return true; }
+    virtual bool visit(ReturnStatementAST *) { return true; }
+    virtual bool visit(SimpleDeclarationAST *) { return true; }
+    virtual bool visit(SimpleNameAST *) { return true; }
+    virtual bool visit(SimpleSpecifierAST *) { return true; }
+    virtual bool visit(SizeofExpressionAST *) { return true; }
+    virtual bool visit(StaticAssertDeclarationAST *) { return true; }
+    virtual bool visit(StringLiteralAST *) { return true; }
+    virtual bool visit(SwitchStatementAST *) { return true; }
+    virtual bool visit(TemplateDeclarationAST *) { return true; }
+    virtual bool visit(TemplateIdAST *) { return true; }
+    virtual bool visit(TemplateTypeParameterAST *) { return true; }
+    virtual bool visit(ThisExpressionAST *) { return true; }
+    virtual bool visit(ThrowExpressionAST *) { return true; }
+    virtual bool visit(TrailingReturnTypeAST *) { return true; }
+    virtual bool visit(TranslationUnitAST *) { return true; }
+    virtual bool visit(TryBlockStatementAST *) { return true; }
+    virtual bool visit(TypeConstructorCallAST *) { return true; }
+    virtual bool visit(TypeIdAST *) { return true; }
+    virtual bool visit(TypeidExpressionAST *) { return true; }
+    virtual bool visit(TypenameCallExpressionAST *) { return true; }
+    virtual bool visit(TypenameTypeParameterAST *) { return true; }
+    virtual bool visit(TypeofSpecifierAST *) { return true; }
+    virtual bool visit(UnaryExpressionAST *) { return true; }
+    virtual bool visit(UsingAST *) { return true; }
+    virtual bool visit(UsingDirectiveAST *) { return true; }
+    virtual bool visit(WhileStatementAST *) { return true; }
+
+    virtual void endVisit(AccessDeclarationAST *) {}
+    virtual void endVisit(AliasDeclarationAST *) {}
+    virtual void endVisit(AlignmentSpecifierAST *) {}
+    virtual void endVisit(AlignofExpressionAST *) {}
+    virtual void endVisit(AnonymousNameAST *) {}
+    virtual void endVisit(ArrayAccessAST *) {}
+    virtual void endVisit(ArrayDeclaratorAST *) {}
+    virtual void endVisit(ArrayInitializerAST *) {}
+    virtual void endVisit(AsmDefinitionAST *) {}
+    virtual void endVisit(BaseSpecifierAST *) {}
+    virtual void endVisit(BinaryExpressionAST *) {}
+    virtual void endVisit(BoolLiteralAST *) {}
+    virtual void endVisit(BracedInitializerAST *) {}
+    virtual void endVisit(BracketDesignatorAST *) {}
+    virtual void endVisit(BreakStatementAST *) {}
+    virtual void endVisit(CallAST *) {}
+    virtual void endVisit(CaptureAST *) {}
+    virtual void endVisit(CaseStatementAST *) {}
+    virtual void endVisit(CastExpressionAST *) {}
+    virtual void endVisit(CatchClauseAST *) {}
+    virtual void endVisit(ClassSpecifierAST *) {}
+    virtual void endVisit(CompoundExpressionAST *) {}
+    virtual void endVisit(CompoundLiteralAST *) {}
+    virtual void endVisit(CompoundStatementAST *) {}
+    virtual void endVisit(ConditionAST *) {}
+    virtual void endVisit(ConditionalExpressionAST *) {}
+    virtual void endVisit(ContinueStatementAST *) {}
+    virtual void endVisit(ConversionFunctionIdAST *) {}
+    virtual void endVisit(CppCastExpressionAST *) {}
+    virtual void endVisit(CtorInitializerAST *) {}
+    virtual void endVisit(DeclarationStatementAST *) {}
+    virtual void endVisit(DeclaratorAST *) {}
+    virtual void endVisit(DeclaratorIdAST *) {}
+    virtual void endVisit(DecltypeSpecifierAST *) {}
+    virtual void endVisit(DeleteExpressionAST *) {}
+    virtual void endVisit(DesignatedInitializerAST *) {}
+    virtual void endVisit(DestructorNameAST *) {}
+    virtual void endVisit(DoStatementAST *) {}
+    virtual void endVisit(DotDesignatorAST *) {}
+    virtual void endVisit(DynamicExceptionSpecificationAST *) {}
+    virtual void endVisit(ElaboratedTypeSpecifierAST *) {}
+    virtual void endVisit(EmptyDeclarationAST *) {}
+    virtual void endVisit(EnumSpecifierAST *) {}
+    virtual void endVisit(EnumeratorAST *) {}
+    virtual void endVisit(ExceptionDeclarationAST *) {}
+    virtual void endVisit(ExpressionListParenAST *) {}
+    virtual void endVisit(ExpressionOrDeclarationStatementAST *) {}
+    virtual void endVisit(ExpressionStatementAST *) {}
+    virtual void endVisit(ForStatementAST *) {}
+    virtual void endVisit(ForeachStatementAST *) {}
+    virtual void endVisit(FunctionDeclaratorAST *) {}
+    virtual void endVisit(FunctionDefinitionAST *) {}
+    virtual void endVisit(GnuAttributeAST *) {}
+    virtual void endVisit(GnuAttributeSpecifierAST *) {}
+    virtual void endVisit(GotoStatementAST *) {}
+    virtual void endVisit(IdExpressionAST *) {}
+    virtual void endVisit(IfStatementAST *) {}
+    virtual void endVisit(LabeledStatementAST *) {}
+    virtual void endVisit(LambdaCaptureAST *) {}
+    virtual void endVisit(LambdaDeclaratorAST *) {}
+    virtual void endVisit(LambdaExpressionAST *) {}
+    virtual void endVisit(LambdaIntroducerAST *) {}
+    virtual void endVisit(LinkageBodyAST *) {}
+    virtual void endVisit(LinkageSpecificationAST *) {}
+    virtual void endVisit(MemInitializerAST *) {}
+    virtual void endVisit(MemberAccessAST *) {}
+    virtual void endVisit(NamedTypeSpecifierAST *) {}
+    virtual void endVisit(NamespaceAST *) {}
+    virtual void endVisit(NamespaceAliasDefinitionAST *) {}
+    virtual void endVisit(NestedDeclaratorAST *) {}
+    virtual void endVisit(NestedExpressionAST *) {}
+    virtual void endVisit(NestedNameSpecifierAST *) {}
+    virtual void endVisit(NewArrayDeclaratorAST *) {}
+    virtual void endVisit(NewExpressionAST *) {}
+    virtual void endVisit(NewTypeIdAST *) {}
+    virtual void endVisit(NoExceptSpecificationAST *) {}
+    virtual void endVisit(NumericLiteralAST *) {}
+    virtual void endVisit(ObjCClassDeclarationAST *) {}
+    virtual void endVisit(ObjCClassForwardDeclarationAST *) {}
+    virtual void endVisit(ObjCDynamicPropertiesDeclarationAST *) {}
+    virtual void endVisit(ObjCEncodeExpressionAST *) {}
+    virtual void endVisit(ObjCFastEnumerationAST *) {}
+    virtual void endVisit(ObjCInstanceVariablesDeclarationAST *) {}
+    virtual void endVisit(ObjCMessageArgumentAST *) {}
+    virtual void endVisit(ObjCMessageArgumentDeclarationAST *) {}
+    virtual void endVisit(ObjCMessageExpressionAST *) {}
+    virtual void endVisit(ObjCMethodDeclarationAST *) {}
+    virtual void endVisit(ObjCMethodPrototypeAST *) {}
+    virtual void endVisit(ObjCPropertyAttributeAST *) {}
+    virtual void endVisit(ObjCPropertyDeclarationAST *) {}
+    virtual void endVisit(ObjCProtocolDeclarationAST *) {}
+    virtual void endVisit(ObjCProtocolExpressionAST *) {}
+    virtual void endVisit(ObjCProtocolForwardDeclarationAST *) {}
+    virtual void endVisit(ObjCProtocolRefsAST *) {}
+    virtual void endVisit(ObjCSelectorAST *) {}
+    virtual void endVisit(ObjCSelectorArgumentAST *) {}
+    virtual void endVisit(ObjCSelectorExpressionAST *) {}
+    virtual void endVisit(ObjCSynchronizedStatementAST *) {}
+    virtual void endVisit(ObjCSynthesizedPropertiesDeclarationAST *) {}
+    virtual void endVisit(ObjCSynthesizedPropertyAST *) {}
+    virtual void endVisit(ObjCTypeNameAST *) {}
+    virtual void endVisit(ObjCVisibilityDeclarationAST *) {}
+    virtual void endVisit(OperatorAST *) {}
+    virtual void endVisit(OperatorFunctionIdAST *) {}
+    virtual void endVisit(ParameterDeclarationAST *) {}
+    virtual void endVisit(ParameterDeclarationClauseAST *) {}
+    virtual void endVisit(PointerAST *) {}
+    virtual void endVisit(PointerLiteralAST *) {}
+    virtual void endVisit(PointerToMemberAST *) {}
+    virtual void endVisit(PostIncrDecrAST *) {}
+    virtual void endVisit(QtEnumDeclarationAST *) {}
+    virtual void endVisit(QtFlagsDeclarationAST *) {}
+    virtual void endVisit(QtInterfaceNameAST *) {}
+    virtual void endVisit(QtInterfacesDeclarationAST *) {}
+    virtual void endVisit(QtMemberDeclarationAST *) {}
+    virtual void endVisit(QtMethodAST *) {}
+    virtual void endVisit(QtObjectTagAST *) {}
+    virtual void endVisit(QtPrivateSlotAST *) {}
+    virtual void endVisit(QtPropertyDeclarationAST *) {}
+    virtual void endVisit(QtPropertyDeclarationItemAST *) {}
+    virtual void endVisit(QualifiedNameAST *) {}
+    virtual void endVisit(RangeBasedForStatementAST *) {}
+    virtual void endVisit(ReferenceAST *) {}
+    virtual void endVisit(ReturnStatementAST *) {}
+    virtual void endVisit(SimpleDeclarationAST *) {}
+    virtual void endVisit(SimpleNameAST *) {}
+    virtual void endVisit(SimpleSpecifierAST *) {}
+    virtual void endVisit(SizeofExpressionAST *) {}
+    virtual void endVisit(StaticAssertDeclarationAST *) {}
+    virtual void endVisit(StringLiteralAST *) {}
+    virtual void endVisit(SwitchStatementAST *) {}
+    virtual void endVisit(TemplateDeclarationAST *) {}
+    virtual void endVisit(TemplateIdAST *) {}
+    virtual void endVisit(TemplateTypeParameterAST *) {}
+    virtual void endVisit(ThisExpressionAST *) {}
+    virtual void endVisit(ThrowExpressionAST *) {}
+    virtual void endVisit(TrailingReturnTypeAST *) {}
+    virtual void endVisit(TranslationUnitAST *) {}
+    virtual void endVisit(TryBlockStatementAST *) {}
+    virtual void endVisit(TypeConstructorCallAST *) {}
+    virtual void endVisit(TypeIdAST *) {}
+    virtual void endVisit(TypeidExpressionAST *) {}
+    virtual void endVisit(TypenameCallExpressionAST *) {}
+    virtual void endVisit(TypenameTypeParameterAST *) {}
+    virtual void endVisit(TypeofSpecifierAST *) {}
+    virtual void endVisit(UnaryExpressionAST *) {}
+    virtual void endVisit(UsingAST *) {}
+    virtual void endVisit(UsingDirectiveAST *) {}
+    virtual void endVisit(WhileStatementAST *) {}
+
+private:
+   TranslationUnit *_translationUnit;
+};
+
+} // namespace CPlusPlus
+
+#endif // CPLUSPLUS_ASTVISITOR_H

+ 229 - 0
Source/ToolCore/JSBind/cplusplus/ASTfwd.h

@@ -0,0 +1,229 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_ASTFWD_H
+#define CPLUSPLUS_ASTFWD_H
+
+#include "CPlusPlusForwardDeclarations.h"
+
+namespace CPlusPlus {
+
+template <typename Tptr> class List;
+
+class AST;
+class ASTVisitor;
+class ASTMatcher;
+
+class AccessDeclarationAST;
+class AliasDeclarationAST;
+class AlignmentSpecifierAST;
+class AlignofExpressionAST;
+class AnonymousNameAST;
+class ArrayAccessAST;
+class ArrayDeclaratorAST;
+class ArrayInitializerAST;
+class AsmDefinitionAST;
+class AttributeSpecifierAST;
+class BaseSpecifierAST;
+class BinaryExpressionAST;
+class BoolLiteralAST;
+class BracedInitializerAST;
+class BracketDesignatorAST;
+class BreakStatementAST;
+class CallAST;
+class CaptureAST;
+class CaseStatementAST;
+class CastExpressionAST;
+class CatchClauseAST;
+class ClassSpecifierAST;
+class CompoundExpressionAST;
+class CompoundLiteralAST;
+class CompoundStatementAST;
+class ConditionAST;
+class ConditionalExpressionAST;
+class ContinueStatementAST;
+class ConversionFunctionIdAST;
+class CoreDeclaratorAST;
+class CppCastExpressionAST;
+class CtorInitializerAST;
+class DeclarationAST;
+class DeclarationStatementAST;
+class DeclaratorAST;
+class DeclaratorIdAST;
+class DecltypeSpecifierAST;
+class DeleteExpressionAST;
+class DesignatedInitializerAST;
+class DesignatorAST;
+class DestructorNameAST;
+class DoStatementAST;
+class DotDesignatorAST;
+class DynamicExceptionSpecificationAST;
+class ElaboratedTypeSpecifierAST;
+class EmptyDeclarationAST;
+class EnumSpecifierAST;
+class EnumeratorAST;
+class ExceptionDeclarationAST;
+class ExceptionSpecificationAST;
+class ExpressionAST;
+class ExpressionListParenAST;
+class ExpressionOrDeclarationStatementAST;
+class ExpressionStatementAST;
+class ForStatementAST;
+class ForeachStatementAST;
+class FunctionDeclaratorAST;
+class FunctionDefinitionAST;
+class GnuAttributeAST;
+class GnuAttributeSpecifierAST;
+class GotoStatementAST;
+class IdExpressionAST;
+class IfStatementAST;
+class LabeledStatementAST;
+class LambdaCaptureAST;
+class LambdaDeclaratorAST;
+class LambdaExpressionAST;
+class LambdaIntroducerAST;
+class LinkageBodyAST;
+class LinkageSpecificationAST;
+class MemInitializerAST;
+class MemberAccessAST;
+class NameAST;
+class NamedTypeSpecifierAST;
+class NamespaceAST;
+class NamespaceAliasDefinitionAST;
+class NestedDeclaratorAST;
+class NestedExpressionAST;
+class NestedNameSpecifierAST;
+class NewArrayDeclaratorAST;
+class NewExpressionAST;
+class NewTypeIdAST;
+class NoExceptSpecificationAST;
+class NumericLiteralAST;
+class ObjCClassDeclarationAST;
+class ObjCClassForwardDeclarationAST;
+class ObjCDynamicPropertiesDeclarationAST;
+class ObjCEncodeExpressionAST;
+class ObjCFastEnumerationAST;
+class ObjCInstanceVariablesDeclarationAST;
+class ObjCMessageArgumentAST;
+class ObjCMessageArgumentDeclarationAST;
+class ObjCMessageExpressionAST;
+class ObjCMethodDeclarationAST;
+class ObjCMethodPrototypeAST;
+class ObjCPropertyAttributeAST;
+class ObjCPropertyDeclarationAST;
+class ObjCProtocolDeclarationAST;
+class ObjCProtocolExpressionAST;
+class ObjCProtocolForwardDeclarationAST;
+class ObjCProtocolRefsAST;
+class ObjCSelectorAST;
+class ObjCSelectorArgumentAST;
+class ObjCSelectorExpressionAST;
+class ObjCSynchronizedStatementAST;
+class ObjCSynthesizedPropertiesDeclarationAST;
+class ObjCSynthesizedPropertyAST;
+class ObjCTypeNameAST;
+class ObjCVisibilityDeclarationAST;
+class OperatorAST;
+class OperatorFunctionIdAST;
+class ParameterDeclarationAST;
+class ParameterDeclarationClauseAST;
+class PointerAST;
+class PointerLiteralAST;
+class PointerToMemberAST;
+class PostIncrDecrAST;
+class PostfixAST;
+class PostfixDeclaratorAST;
+class PtrOperatorAST;
+class QtEnumDeclarationAST;
+class QtFlagsDeclarationAST;
+class QtInterfaceNameAST;
+class QtInterfacesDeclarationAST;
+class QtMemberDeclarationAST;
+class QtMethodAST;
+class QtObjectTagAST;
+class QtPrivateSlotAST;
+class QtPropertyDeclarationAST;
+class QtPropertyDeclarationItemAST;
+class QualifiedNameAST;
+class RangeBasedForStatementAST;
+class ReferenceAST;
+class ReturnStatementAST;
+class SimpleDeclarationAST;
+class SimpleNameAST;
+class SimpleSpecifierAST;
+class SizeofExpressionAST;
+class SpecifierAST;
+class StatementAST;
+class StaticAssertDeclarationAST;
+class StringLiteralAST;
+class SwitchStatementAST;
+class TemplateDeclarationAST;
+class TemplateIdAST;
+class TemplateTypeParameterAST;
+class ThisExpressionAST;
+class ThrowExpressionAST;
+class TrailingReturnTypeAST;
+class TranslationUnitAST;
+class TryBlockStatementAST;
+class TypeConstructorCallAST;
+class TypeIdAST;
+class TypeidExpressionAST;
+class TypenameCallExpressionAST;
+class TypenameTypeParameterAST;
+class TypeofSpecifierAST;
+class UnaryExpressionAST;
+class UsingAST;
+class UsingDirectiveAST;
+class WhileStatementAST;
+
+typedef List<ExpressionAST *> ExpressionListAST;
+typedef List<DeclarationAST *> DeclarationListAST;
+typedef List<StatementAST *> StatementListAST;
+typedef List<DeclaratorAST *> DeclaratorListAST;
+typedef List<BaseSpecifierAST *> BaseSpecifierListAST;
+typedef List<EnumeratorAST *> EnumeratorListAST;
+typedef List<MemInitializerAST *> MemInitializerListAST;
+typedef List<NewArrayDeclaratorAST *> NewArrayDeclaratorListAST;
+typedef List<PostfixAST *> PostfixListAST;
+typedef List<PostfixDeclaratorAST *> PostfixDeclaratorListAST;
+typedef List<GnuAttributeAST *> GnuAttributeListAST;
+typedef List<NestedNameSpecifierAST *> NestedNameSpecifierListAST;
+typedef List<CatchClauseAST *> CatchClauseListAST;
+typedef List<PtrOperatorAST *> PtrOperatorListAST;
+typedef List<SpecifierAST *> SpecifierListAST;
+typedef List<QtPropertyDeclarationItemAST *> QtPropertyDeclarationItemListAST;
+typedef List<NameAST *> NameListAST;
+typedef List<QtInterfaceNameAST *> QtInterfaceNameListAST;
+
+typedef List<ParameterDeclarationAST *> ParameterDeclarationListAST;
+typedef List<CaptureAST *> CaptureListAST;
+
+typedef List<ObjCMessageArgumentAST *> ObjCMessageArgumentListAST;
+typedef List<ObjCSelectorArgumentAST *> ObjCSelectorArgumentListAST;
+typedef List<ObjCPropertyAttributeAST *> ObjCPropertyAttributeListAST;
+typedef List<ObjCMessageArgumentDeclarationAST *> ObjCMessageArgumentDeclarationListAST;
+typedef List<ObjCSynthesizedPropertyAST *> ObjCSynthesizedPropertyListAST;
+
+typedef List<DesignatorAST *> DesignatorListAST;
+
+} // namespace CPlusPlus
+
+
+#endif // CPLUSPLUS_ASTFWD_H

+ 3261 - 0
Source/ToolCore/JSBind/cplusplus/Bind.cpp

@@ -0,0 +1,3261 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "Bind.h"
+#include "AST.h"
+#include "TranslationUnit.h"
+#include "Control.h"
+#include "Names.h"
+#include "Symbols.h"
+#include "CoreTypes.h"
+#include "Literals.h"
+#include "Scope.h"
+
+#include "cppassert.h"
+
+#include <vector>
+#include <string>
+#include <memory>
+#include <algorithm>
+
+
+using namespace CPlusPlus;
+
+const int Bind::kMaxDepth(100);
+
+Bind::Bind(TranslationUnit *unit)
+    : ASTVisitor(unit),
+      _scope(0),
+      _expression(0),
+      _name(0),
+      _declaratorId(0),
+      _visibility(Symbol::Public),
+      _objcVisibility(Symbol::Public),
+      _methodKey(Function::NormalMethod),
+      _skipFunctionBodies(false),
+      _depth(0)
+{
+}
+
+bool Bind::skipFunctionBodies() const
+{
+    return _skipFunctionBodies;
+}
+
+void Bind::setSkipFunctionBodies(bool skipFunctionBodies)
+{
+    _skipFunctionBodies = skipFunctionBodies;
+}
+
+unsigned Bind::location(DeclaratorAST *ast, unsigned defaultLocation) const
+{
+    if (! ast)
+        return defaultLocation;
+
+    else if (ast->core_declarator)
+        return location(ast->core_declarator, defaultLocation);
+
+    return ast->firstToken();
+}
+
+unsigned Bind::location(CoreDeclaratorAST *ast, unsigned defaultLocation) const
+{
+    if (! ast)
+        return defaultLocation;
+
+    else if (NestedDeclaratorAST *nested = ast->asNestedDeclarator())
+        return location(nested->declarator, defaultLocation);
+
+    else if (DeclaratorIdAST *id = ast->asDeclaratorId())
+        return location(id->name, defaultLocation);
+
+    return ast->firstToken();
+}
+
+unsigned Bind::location(NameAST *name, unsigned defaultLocation) const
+{
+    if (! name)
+        return defaultLocation;
+
+    else if (DestructorNameAST *dtor = name->asDestructorName())
+        return location(dtor->unqualified_name, defaultLocation);
+
+    else if (TemplateIdAST *templId = name->asTemplateId())
+        return templId->identifier_token;
+
+    else if (QualifiedNameAST *q = name->asQualifiedName()) {
+        if (q->unqualified_name)
+            return location(q->unqualified_name, defaultLocation);
+    }
+
+    return name->firstToken();
+}
+
+void Bind::setDeclSpecifiers(Symbol *symbol, const FullySpecifiedType &declSpecifiers)
+{
+    if (! symbol)
+        return;
+
+    int storage = Symbol::NoStorage;
+
+    if (declSpecifiers.isFriend())
+        storage = Symbol::Friend;
+    else if (declSpecifiers.isAuto())
+        storage = Symbol::Auto;
+    else if (declSpecifiers.isRegister())
+        storage = Symbol::Register;
+    else if (declSpecifiers.isStatic())
+        storage = Symbol::Static;
+    else if (declSpecifiers.isExtern())
+        storage = Symbol::Extern;
+    else if (declSpecifiers.isMutable())
+        storage = Symbol::Mutable;
+    else if (declSpecifiers.isTypedef())
+        storage = Symbol::Typedef;
+
+    symbol->setStorage(storage);
+
+    if (Function *funTy = symbol->asFunction()) {
+        if (declSpecifiers.isVirtual())
+            funTy->setVirtual(true);
+    }
+
+    if (declSpecifiers.isDeprecated())
+        symbol->setDeprecated(true);
+
+    if (declSpecifiers.isUnavailable())
+        symbol->setUnavailable(true);
+}
+
+Scope *Bind::switchScope(Scope *scope)
+{
+    if (! scope)
+        return _scope;
+
+    std::swap(_scope, scope);
+    return scope;
+}
+
+int Bind::switchVisibility(int visibility)
+{
+    std::swap(_visibility, visibility);
+    return visibility;
+}
+
+int Bind::switchObjCVisibility(int visibility)
+{
+    std::swap(_objcVisibility, visibility);
+    return visibility;
+}
+
+int Bind::switchMethodKey(int methodKey)
+{
+    std::swap(_methodKey, methodKey);
+    return methodKey;
+}
+
+void Bind::operator()(TranslationUnitAST *ast, Namespace *globalNamespace)
+{
+    Scope *previousScope = switchScope(globalNamespace);
+    translationUnit(ast);
+    (void) switchScope(previousScope);
+}
+
+void Bind::operator()(DeclarationAST *ast, Scope *scope)
+{
+    Scope *previousScope = switchScope(scope);
+    declaration(ast);
+    (void) switchScope(previousScope);
+}
+
+void Bind::operator()(StatementAST *ast, Scope *scope)
+{
+    Scope *previousScope = switchScope(scope);
+    statement(ast);
+    (void) switchScope(previousScope);
+}
+
+FullySpecifiedType Bind::operator()(ExpressionAST *ast, Scope *scope)
+{
+    Scope *previousScope = switchScope(scope);
+    FullySpecifiedType ty = expression(ast);
+    (void) switchScope(previousScope);
+    return ty;
+}
+
+FullySpecifiedType Bind::operator()(NewTypeIdAST *ast, Scope *scope)
+{
+    Scope *previousScope = switchScope(scope);
+    FullySpecifiedType ty = newTypeId(ast);
+    (void) switchScope(previousScope);
+    return ty;
+}
+
+void Bind::statement(StatementAST *ast)
+{
+    accept(ast);
+}
+
+Bind::ExpressionTy Bind::expression(ExpressionAST *ast)
+{
+    ExpressionTy value = ExpressionTy();
+    std::swap(_expression, value);
+    accept(ast);
+    std::swap(_expression, value);
+    return value;
+}
+
+void Bind::declaration(DeclarationAST *ast)
+{
+    accept(ast);
+}
+
+const Name *Bind::name(NameAST *ast)
+{
+    const Name *value = 0;
+    std::swap(_name, value);
+    accept(ast);
+    std::swap(_name, value);
+    return value;
+}
+
+FullySpecifiedType Bind::specifier(SpecifierAST *ast, const FullySpecifiedType &init)
+{
+    FullySpecifiedType value = init;
+    std::swap(_type, value);
+    accept(ast);
+    std::swap(_type, value);
+    return value;
+}
+
+FullySpecifiedType Bind::ptrOperator(PtrOperatorAST *ast, const FullySpecifiedType &init)
+{
+    FullySpecifiedType value = init;
+    std::swap(_type, value);
+    accept(ast);
+    std::swap(_type, value);
+    return value;
+}
+
+FullySpecifiedType Bind::coreDeclarator(CoreDeclaratorAST *ast, const FullySpecifiedType &init)
+{
+    FullySpecifiedType value = init;
+    std::swap(_type, value);
+    accept(ast);
+    std::swap(_type, value);
+    return value;
+}
+
+FullySpecifiedType Bind::postfixDeclarator(PostfixDeclaratorAST *ast, const FullySpecifiedType &init)
+{
+    FullySpecifiedType value = init;
+    std::swap(_type, value);
+    accept(ast);
+    std::swap(_type, value);
+    return value;
+}
+
+bool Bind::preVisit(AST *)
+{
+    ++_depth;
+    if (_depth > kMaxDepth)
+        return false;
+    return true;
+}
+
+void Bind::postVisit(AST *)
+{
+    --_depth;
+}
+
+// AST
+bool Bind::visit(ObjCSelectorArgumentAST *ast)
+{
+    (void) ast;
+    CPP_CHECK(!"unreachable");
+    return false;
+}
+
+const Name *Bind::objCSelectorArgument(ObjCSelectorArgumentAST *ast, bool *hasArg)
+{
+    if (! (ast && ast->name_token))
+        return 0;
+
+    if (ast->colon_token)
+        *hasArg = true;
+
+    return identifier(ast->name_token);
+}
+
+bool Bind::visit(GnuAttributeAST *ast)
+{
+    (void) ast;
+    CPP_CHECK(!"unreachable");
+    return false;
+}
+
+void Bind::attribute(GnuAttributeAST *ast)
+{
+    if (! ast)
+        return;
+
+    // unsigned identifier_token = ast->identifier_token;
+    if (const Identifier *id = identifier(ast->identifier_token)) {
+        if (id == control()->deprecatedId())
+            _type.setDeprecated(true);
+        else if (id == control()->unavailableId())
+            _type.setUnavailable(true);
+    }
+
+    // unsigned lparen_token = ast->lparen_token;
+    // unsigned tag_token = ast->tag_token;
+    for (ExpressionListAST *it = ast->expression_list; it; it = it->next) {
+        ExpressionTy value = this->expression(it->value);
+    }
+    // unsigned rparen_token = ast->rparen_token;
+}
+
+bool Bind::visit(DeclaratorAST *ast)
+{
+    (void) ast;
+    CPP_CHECK(!"unreachable");
+    return false;
+}
+
+FullySpecifiedType Bind::declarator(DeclaratorAST *ast, const FullySpecifiedType &init, DeclaratorIdAST **declaratorId)
+{
+    FullySpecifiedType type = init;
+
+    if (! ast)
+        return type;
+
+    std::swap(_declaratorId, declaratorId);
+    bool isAuto = false;
+    const bool cxx11Enabled = translationUnit()->languageFeatures().cxx11Enabled;
+    if (cxx11Enabled)
+        isAuto = type.isAuto();
+
+    for (SpecifierListAST *it = ast->attribute_list; it; it = it->next) {
+        type = this->specifier(it->value, type);
+        if (type.isAuto())
+            isAuto = true;
+    }
+    for (PtrOperatorListAST *it = ast->ptr_operator_list; it; it = it->next) {
+        type = this->ptrOperator(it->value, type);
+    }
+    for (PostfixDeclaratorListAST *it = ast->postfix_declarator_list; it; it = it->next) {
+        type = this->postfixDeclarator(it->value, type);
+    }
+    type = this->coreDeclarator(ast->core_declarator, type);
+    for (SpecifierListAST *it = ast->post_attribute_list; it; it = it->next) {
+        type = this->specifier(it->value, type);
+        if (type.isAuto())
+            isAuto = true;
+    }
+    if (!type->isFunctionType()) {
+        ExpressionTy initializer = this->expression(ast->initializer);
+        if (cxx11Enabled && isAuto) {
+            type = initializer;
+            type.setAuto(true);
+        }
+    }
+
+    std::swap(_declaratorId, declaratorId);
+    return type;
+}
+
+bool Bind::visit(QtPropertyDeclarationItemAST *ast)
+{
+    (void) ast;
+    CPP_CHECK(!"unreachable");
+    return false;
+}
+
+bool Bind::visit(QtInterfaceNameAST *ast)
+{
+    (void) ast;
+    CPP_CHECK(!"unreachable");
+    return false;
+}
+
+void Bind::qtInterfaceName(QtInterfaceNameAST *ast)
+{
+    if (! ast)
+        return;
+
+    /*const Name *interface_name =*/ this->name(ast->interface_name);
+    for (NameListAST *it = ast->constraint_list; it; it = it->next) {
+        /*const Name *value =*/ this->name(it->value);
+    }
+}
+
+bool Bind::visit(BaseSpecifierAST *ast)
+{
+    (void) ast;
+    CPP_CHECK(!"unreachable");
+    return false;
+}
+
+void Bind::baseSpecifier(BaseSpecifierAST *ast, unsigned colon_token, Class *klass)
+{
+    if (! ast)
+        return;
+
+    unsigned sourceLocation = location(ast->name, ast->firstToken());
+    if (! sourceLocation)
+        sourceLocation = std::max(colon_token, klass->sourceLocation());
+
+    const Name *baseClassName = this->name(ast->name);
+    BaseClass *baseClass = control()->newBaseClass(sourceLocation, baseClassName);
+    if (ast->virtual_token)
+        baseClass->setVirtual(true);
+    if (ast->access_specifier_token) {
+        const int visibility = visibilityForAccessSpecifier(tokenKind(ast->access_specifier_token));
+        baseClass->setVisibility(visibility); // ### well, not exactly.
+    }
+    klass->addBaseClass(baseClass);
+    ast->symbol = baseClass;
+}
+
+bool Bind::visit(CtorInitializerAST *ast)
+{
+    (void) ast;
+    CPP_CHECK(!"unreachable");
+    return false;
+}
+
+void Bind::ctorInitializer(CtorInitializerAST *ast, Function *fun)
+{
+    if (! ast)
+        return;
+
+    // unsigned colon_token = ast->colon_token;
+    for (MemInitializerListAST *it = ast->member_initializer_list; it; it = it->next) {
+        this->memInitializer(it->value, fun);
+    }
+    // unsigned dot_dot_dot_token = ast->dot_dot_dot_token;
+}
+
+bool Bind::visit(EnumeratorAST *ast)
+{
+    (void) ast;
+    CPP_CHECK(!"unreachable");
+    return false;
+}
+
+void Bind::enumerator(EnumeratorAST *ast, Enum *symbol)
+{
+    (void) symbol;
+
+    if (! ast)
+        return;
+
+    // unsigned identifier_token = ast->identifier_token;
+    // unsigned equal_token = ast->equal_token;
+    /*ExpressionTy expression =*/ this->expression(ast->expression);
+
+    if (ast->identifier_token) {
+        const Name *name = identifier(ast->identifier_token);
+        EnumeratorDeclaration *e = control()->newEnumeratorDeclaration(ast->identifier_token, name);
+        e->setType(control()->integerType(IntegerType::Int)); // ### introduce IntegerType::Enumerator
+
+        if (ExpressionAST *expr = ast->expression)
+            e->setConstantValue(asStringLiteral(expr->firstToken(), expr->lastToken()));
+
+        symbol->addMember(e);
+    }
+}
+
+bool Bind::visit(DynamicExceptionSpecificationAST *ast)
+{
+    (void) ast;
+    CPP_CHECK(!"unreachable");
+    return false;
+}
+
+FullySpecifiedType Bind::exceptionSpecification(ExceptionSpecificationAST *ast, const FullySpecifiedType &init)
+{
+    FullySpecifiedType type = init;
+
+    if (! ast)
+        return type;
+
+    if (DynamicExceptionSpecificationAST *dyn = ast->asDynamicExceptionSpecification()) {
+        // unsigned throw_token = ast->throw_token;
+        // unsigned lparen_token = ast->lparen_token;
+        // unsigned dot_dot_dot_token = ast->dot_dot_dot_token;
+        for (ExpressionListAST *it = dyn->type_id_list; it; it = it->next) {
+            /*ExpressionTy value =*/ this->expression(it->value);
+        }
+    } else if (NoExceptSpecificationAST *no = ast->asNoExceptSpecification()) {
+        /*ExpressionTy value =*/ this->expression(no->expression);
+    }
+    // unsigned rparen_token = ast->rparen_token;
+    return type;
+}
+
+bool Bind::visit(MemInitializerAST *ast)
+{
+    (void) ast;
+    CPP_CHECK(!"unreachable");
+    return false;
+}
+
+void Bind::memInitializer(MemInitializerAST *ast, Function *fun)
+{
+    if (! ast)
+        return;
+
+    /*const Name *name =*/ this->name(ast->name);
+
+    Scope *previousScope = switchScope(fun);
+    this->expression(ast->expression);
+    (void) switchScope(previousScope);
+}
+
+bool Bind::visit(NestedNameSpecifierAST *ast)
+{
+    (void) ast;
+    CPP_CHECK(!"unreachable");
+    return false;
+}
+
+const Name *Bind::nestedNameSpecifier(NestedNameSpecifierAST *ast)
+{
+    if (! ast)
+        return 0;
+
+    const Name *class_or_namespace_name = this->name(ast->class_or_namespace_name);
+    return class_or_namespace_name;
+}
+
+bool Bind::visit(ExpressionListParenAST *ast)
+{
+    // unsigned lparen_token = ast->lparen_token;
+    for (ExpressionListAST *it = ast->expression_list; it; it = it->next) {
+        /*ExpressionTy value =*/ this->expression(it->value);
+    }
+    // unsigned rparen_token = ast->rparen_token;
+
+    return false;
+}
+
+void Bind::newPlacement(ExpressionListParenAST *ast)
+{
+    if (! ast)
+        return;
+
+    // unsigned lparen_token = ast->lparen_token;
+    for (ExpressionListAST *it = ast->expression_list; it; it = it->next) {
+        ExpressionTy value = this->expression(it->value);
+    }
+    // unsigned rparen_token = ast->rparen_token;
+}
+
+bool Bind::visit(NewArrayDeclaratorAST *ast)
+{
+    (void) ast;
+    CPP_CHECK(!"unreachable");
+    return false;
+}
+
+FullySpecifiedType Bind::newArrayDeclarator(NewArrayDeclaratorAST *ast, const FullySpecifiedType &init)
+{
+    FullySpecifiedType type = init;
+
+    if (! ast)
+        return type;
+
+    // unsigned lbracket_token = ast->lbracket_token;
+    ExpressionTy expression = this->expression(ast->expression);
+    // unsigned rbracket_token = ast->rbracket_token;
+    return type;
+}
+
+bool Bind::visit(NewTypeIdAST *ast)
+{
+    (void) ast;
+    CPP_CHECK(!"unreachable");
+    return false;
+}
+
+FullySpecifiedType Bind::newTypeId(NewTypeIdAST *ast)
+{
+    FullySpecifiedType type;
+
+    if (! ast)
+        return type;
+
+
+    for (SpecifierListAST *it = ast->type_specifier_list; it; it = it->next) {
+        type = this->specifier(it->value, type);
+    }
+    for (PtrOperatorListAST *it = ast->ptr_operator_list; it; it = it->next) {
+        type = this->ptrOperator(it->value, type);
+    }
+    for (NewArrayDeclaratorListAST *it = ast->new_array_declarator_list; it; it = it->next) {
+        type = this->newArrayDeclarator(it->value, type);
+    }
+    return type;
+}
+
+bool Bind::visit(OperatorAST *ast)
+{
+    (void) ast;
+    CPP_CHECK(!"unreachable");
+    return false;
+}
+
+OperatorNameId::Kind Bind::cppOperator(OperatorAST *ast)
+{
+    OperatorNameId::Kind kind = OperatorNameId::InvalidOp;
+
+    if (! ast)
+        return kind;
+
+    // unsigned op_token = ast->op_token;
+    // unsigned open_token = ast->open_token;
+    // unsigned close_token = ast->close_token;
+
+    switch (tokenKind(ast->op_token)) {
+    case T_NEW:
+        if (ast->open_token)
+            kind = OperatorNameId::NewArrayOp;
+        else
+            kind = OperatorNameId::NewOp;
+        break;
+
+    case T_DELETE:
+        if (ast->open_token)
+            kind = OperatorNameId::DeleteArrayOp;
+        else
+            kind = OperatorNameId::DeleteOp;
+        break;
+
+    case T_PLUS:
+        kind = OperatorNameId::PlusOp;
+        break;
+
+    case T_MINUS:
+        kind = OperatorNameId::MinusOp;
+        break;
+
+    case T_STAR:
+        kind = OperatorNameId::StarOp;
+        break;
+
+    case T_SLASH:
+        kind = OperatorNameId::SlashOp;
+        break;
+
+    case T_PERCENT:
+        kind = OperatorNameId::PercentOp;
+        break;
+
+    case T_CARET:
+        kind = OperatorNameId::CaretOp;
+        break;
+
+    case T_AMPER:
+        kind = OperatorNameId::AmpOp;
+        break;
+
+    case T_PIPE:
+        kind = OperatorNameId::PipeOp;
+        break;
+
+    case T_TILDE:
+        kind = OperatorNameId::TildeOp;
+        break;
+
+    case T_EXCLAIM:
+        kind = OperatorNameId::ExclaimOp;
+        break;
+
+    case T_EQUAL:
+        kind = OperatorNameId::EqualOp;
+        break;
+
+    case T_LESS:
+        kind = OperatorNameId::LessOp;
+        break;
+
+    case T_GREATER:
+        kind = OperatorNameId::GreaterOp;
+        break;
+
+    case T_PLUS_EQUAL:
+        kind = OperatorNameId::PlusEqualOp;
+        break;
+
+    case T_MINUS_EQUAL:
+        kind = OperatorNameId::MinusEqualOp;
+        break;
+
+    case T_STAR_EQUAL:
+        kind = OperatorNameId::StarEqualOp;
+        break;
+
+    case T_SLASH_EQUAL:
+        kind = OperatorNameId::SlashEqualOp;
+        break;
+
+    case T_PERCENT_EQUAL:
+        kind = OperatorNameId::PercentEqualOp;
+        break;
+
+    case T_CARET_EQUAL:
+        kind = OperatorNameId::CaretEqualOp;
+        break;
+
+    case T_AMPER_EQUAL:
+        kind = OperatorNameId::AmpEqualOp;
+        break;
+
+    case T_PIPE_EQUAL:
+        kind = OperatorNameId::PipeEqualOp;
+        break;
+
+    case T_LESS_LESS:
+        kind = OperatorNameId::LessLessOp;
+        break;
+
+    case T_GREATER_GREATER:
+        kind = OperatorNameId::GreaterGreaterOp;
+        break;
+
+    case T_LESS_LESS_EQUAL:
+        kind = OperatorNameId::LessLessEqualOp;
+        break;
+
+    case T_GREATER_GREATER_EQUAL:
+        kind = OperatorNameId::GreaterGreaterEqualOp;
+        break;
+
+    case T_EQUAL_EQUAL:
+        kind = OperatorNameId::EqualEqualOp;
+        break;
+
+    case T_EXCLAIM_EQUAL:
+        kind = OperatorNameId::ExclaimEqualOp;
+        break;
+
+    case T_LESS_EQUAL:
+        kind = OperatorNameId::LessEqualOp;
+        break;
+
+    case T_GREATER_EQUAL:
+        kind = OperatorNameId::GreaterEqualOp;
+        break;
+
+    case T_AMPER_AMPER:
+        kind = OperatorNameId::AmpAmpOp;
+        break;
+
+    case T_PIPE_PIPE:
+        kind = OperatorNameId::PipePipeOp;
+        break;
+
+    case T_PLUS_PLUS:
+        kind = OperatorNameId::PlusPlusOp;
+        break;
+
+    case T_MINUS_MINUS:
+        kind = OperatorNameId::MinusMinusOp;
+        break;
+
+    case T_COMMA:
+        kind = OperatorNameId::CommaOp;
+        break;
+
+    case T_ARROW_STAR:
+        kind = OperatorNameId::ArrowStarOp;
+        break;
+
+    case T_ARROW:
+        kind = OperatorNameId::ArrowOp;
+        break;
+
+    case T_LPAREN:
+        kind = OperatorNameId::FunctionCallOp;
+        break;
+
+    case T_LBRACKET:
+        kind = OperatorNameId::ArrayAccessOp;
+        break;
+
+    default:
+        kind = OperatorNameId::InvalidOp;
+    } // switch
+
+    return kind;
+}
+
+bool Bind::visit(ParameterDeclarationClauseAST *ast)
+{
+    (void) ast;
+    CPP_CHECK(!"unreachable");
+    return false;
+}
+
+void Bind::parameterDeclarationClause(ParameterDeclarationClauseAST *ast, unsigned lparen_token, Function *fun)
+{
+    if (! ast)
+        return;
+
+    if (! fun) {
+        translationUnit()->warning(lparen_token, "undefined function");
+        return;
+    }
+
+    Scope *previousScope = switchScope(fun);
+
+    for (ParameterDeclarationListAST *it = ast->parameter_declaration_list; it; it = it->next) {
+        this->declaration(it->value);
+    }
+
+    if (ast->dot_dot_dot_token)
+        fun->setVariadic(true);
+
+    (void) switchScope(previousScope);
+}
+
+bool Bind::visit(TranslationUnitAST *ast)
+{
+    (void) ast;
+    CPP_CHECK(!"unreachable");
+    return false;
+}
+
+void Bind::translationUnit(TranslationUnitAST *ast)
+{
+    if (! ast)
+        return;
+
+    for (DeclarationListAST *it = ast->declaration_list; it; it = it->next) {
+        this->declaration(it->value);
+    }
+}
+
+bool Bind::visit(ObjCProtocolRefsAST *ast)
+{
+    (void) ast;
+    CPP_CHECK(!"unreachable");
+    return false;
+}
+
+void Bind::objCProtocolRefs(ObjCProtocolRefsAST *ast, Symbol *objcClassOrProtocol)
+{
+    if (! ast)
+        return;
+
+    for (NameListAST *it = ast->identifier_list; it; it = it->next) {
+        const Name *protocolName = this->name(it->value);
+        ObjCBaseProtocol *baseProtocol = control()->newObjCBaseProtocol(it->value->firstToken(), protocolName);
+        if (ObjCClass *klass = objcClassOrProtocol->asObjCClass())
+            klass->addProtocol(baseProtocol);
+        else if (ObjCProtocol *proto = objcClassOrProtocol->asObjCProtocol())
+            proto->addProtocol(baseProtocol);
+    }
+}
+
+bool Bind::visit(ObjCMessageArgumentAST *ast)
+{
+    (void) ast;
+    CPP_CHECK(!"unreachable");
+    return false;
+}
+
+void Bind::objCMessageArgument(ObjCMessageArgumentAST *ast)
+{
+    if (! ast)
+        return;
+
+    ExpressionTy parameter_value_expression = this->expression(ast->parameter_value_expression);
+}
+
+bool Bind::visit(ObjCTypeNameAST *ast)
+{
+    (void) ast;
+    CPP_CHECK(!"unreachable");
+    return false;
+}
+
+FullySpecifiedType Bind::objCTypeName(ObjCTypeNameAST *ast)
+{
+    if (! ast)
+        return FullySpecifiedType();
+
+    // unsigned type_qualifier_token = ast->type_qualifier_token;
+    ExpressionTy type_id = this->expression(ast->type_id);
+    return type_id;
+}
+
+bool Bind::visit(ObjCInstanceVariablesDeclarationAST *ast)
+{
+    (void) ast;
+    CPP_CHECK(!"unreachable");
+    return false;
+}
+
+void Bind::objCInstanceVariablesDeclaration(ObjCInstanceVariablesDeclarationAST *ast, ObjCClass *klass)
+{
+    (void) klass;
+
+    if (! ast)
+        return;
+
+    // unsigned lbrace_token = ast->lbrace_token;
+    for (DeclarationListAST *it = ast->instance_variable_list; it; it = it->next) {
+        this->declaration(it->value);
+    }
+    // unsigned rbrace_token = ast->rbrace_token;
+}
+
+bool Bind::visit(ObjCPropertyAttributeAST *ast)
+{
+    (void) ast;
+    CPP_CHECK(!"unreachable");
+    return false;
+}
+
+void Bind::objCPropertyAttribute(ObjCPropertyAttributeAST *ast)
+{
+    if (! ast)
+        return;
+
+    // unsigned attribute_identifier_token = ast->attribute_identifier_token;
+    // unsigned equals_token = ast->equals_token;
+    /*const Name *method_selector =*/ this->name(ast->method_selector);
+}
+
+bool Bind::visit(ObjCMessageArgumentDeclarationAST *ast)
+{
+    (void) ast;
+    CPP_CHECK(!"unreachable");
+    return false;
+}
+
+void Bind::objCMessageArgumentDeclaration(ObjCMessageArgumentDeclarationAST *ast, ObjCMethod *method)
+{
+    if (! ast)
+        return;
+
+    FullySpecifiedType type = this->objCTypeName(ast->type_name);
+
+    for (SpecifierListAST *it = ast->attribute_list; it; it = it->next) {
+        type = this->specifier(it->value, type);
+    }
+
+    const Name *param_name = this->name(ast->param_name);
+    Argument *arg = control()->newArgument(location(ast->param_name, ast->firstToken()), param_name);
+    arg->setType(type);
+    ast->argument = arg;
+    method->addMember(arg);
+}
+
+bool Bind::visit(ObjCMethodPrototypeAST *ast)
+{
+    (void) ast;
+    CPP_CHECK(!"unreachable");
+    return false;
+}
+
+ObjCMethod *Bind::objCMethodPrototype(ObjCMethodPrototypeAST *ast)
+{
+    if (! ast)
+        return 0;
+
+    // unsigned method_type_token = ast->method_type_token;
+    FullySpecifiedType returnType = this->objCTypeName(ast->type_name);
+    const Name *selector = this->name(ast->selector);
+
+    const unsigned sourceLocation = location(ast->selector, ast->firstToken());
+    ObjCMethod *method = control()->newObjCMethod(sourceLocation, selector);
+    // ### set the offsets
+    method->setReturnType(returnType);
+    if (isObjCClassMethod(tokenKind(ast->method_type_token)))
+        method->setStorage(Symbol::Static);
+    method->setVisibility(_objcVisibility);
+    ast->symbol = method;
+
+    Scope *previousScope = switchScope(method);
+    for (ObjCMessageArgumentDeclarationListAST *it = ast->argument_list; it; it = it->next) {
+        this->objCMessageArgumentDeclaration(it->value, method);
+    }
+    (void) switchScope(previousScope);
+
+    if (ast->dot_dot_dot_token)
+        method->setVariadic(true);
+
+    FullySpecifiedType specifiers;
+    for (SpecifierListAST *it = ast->attribute_list; it; it = it->next) {
+        specifiers = this->specifier(it->value, specifiers);
+    }
+    //setDeclSpecifiers(method, specifiers);
+
+    return method;
+}
+
+bool Bind::visit(ObjCSynthesizedPropertyAST *ast)
+{
+    (void) ast;
+    CPP_CHECK(!"unreachable");
+    return false;
+}
+
+void Bind::objCSynthesizedProperty(ObjCSynthesizedPropertyAST *ast)
+{
+    if (! ast)
+        return;
+
+    // unsigned property_identifier_token = ast->property_identifier_token;
+    // unsigned equals_token = ast->equals_token;
+    // unsigned alias_identifier_token = ast->alias_identifier_token;
+}
+
+bool Bind::visit(LambdaIntroducerAST *ast)
+{
+    (void) ast;
+    CPP_CHECK(!"unreachable");
+    return false;
+}
+
+void Bind::lambdaIntroducer(LambdaIntroducerAST *ast)
+{
+    if (! ast)
+        return;
+
+    // unsigned lbracket_token = ast->lbracket_token;
+    this->lambdaCapture(ast->lambda_capture);
+    // unsigned rbracket_token = ast->rbracket_token;
+}
+
+bool Bind::visit(LambdaCaptureAST *ast)
+{
+    (void) ast;
+    CPP_CHECK(!"unreachable");
+    return false;
+}
+
+void Bind::lambdaCapture(LambdaCaptureAST *ast)
+{
+    if (! ast)
+        return;
+
+    // unsigned default_capture_token = ast->default_capture_token;
+    for (CaptureListAST *it = ast->capture_list; it; it = it->next) {
+        this->capture(it->value);
+    }
+}
+
+bool Bind::visit(CaptureAST *ast)
+{
+    (void) ast;
+    CPP_CHECK(!"unreachable");
+    return false;
+}
+
+void Bind::capture(CaptureAST *ast)
+{
+    if (! ast)
+        return;
+
+    name(ast->identifier);
+}
+
+bool Bind::visit(LambdaDeclaratorAST *ast)
+{
+    (void) ast;
+    CPP_CHECK(!"unreachable");
+    return false;
+}
+
+Function *Bind::lambdaDeclarator(LambdaDeclaratorAST *ast)
+{
+    if (! ast)
+        return 0;
+
+    Function *fun = control()->newFunction(0, 0);
+    fun->setStartOffset(tokenAt(ast->firstToken()).utf16charsBegin());
+    fun->setEndOffset(tokenAt(ast->lastToken() - 1).utf16charsEnd());
+
+    FullySpecifiedType type;
+    if (ast->trailing_return_type)
+        type = this->trailingReturnType(ast->trailing_return_type, type);
+    ast->symbol = fun;
+
+    // unsigned lparen_token = ast->lparen_token;
+    this->parameterDeclarationClause(ast->parameter_declaration_clause, ast->lparen_token, fun);
+    // unsigned rparen_token = ast->rparen_token;
+    for (SpecifierListAST *it = ast->attributes; it; it = it->next) {
+        type = this->specifier(it->value, type);
+    }
+    // unsigned mutable_token = ast->mutable_token;
+    type = this->exceptionSpecification(ast->exception_specification, type);
+
+    if (!type.isValid())
+        type.setType(control()->voidType());
+    fun->setReturnType(type);
+    return fun;
+}
+
+bool Bind::visit(TrailingReturnTypeAST *ast)
+{
+    (void) ast;
+    CPP_CHECK(!"unreachable");
+    return false;
+}
+
+FullySpecifiedType Bind::trailingReturnType(TrailingReturnTypeAST *ast, const FullySpecifiedType &init)
+{
+    FullySpecifiedType type = init;
+
+    if (! ast)
+        return type;
+
+    // unsigned arrow_token = ast->arrow_token;
+    for (SpecifierListAST *it = ast->attributes; it; it = it->next) {
+        type = this->specifier(it->value, type);
+    }
+    for (SpecifierListAST *it = ast->type_specifier_list; it; it = it->next) {
+        type = this->specifier(it->value, type);
+    }
+    DeclaratorIdAST *declaratorId = 0;
+    type = this->declarator(ast->declarator, type, &declaratorId);
+    return type;
+}
+
+const StringLiteral *Bind::asStringLiteral(unsigned firstToken, unsigned lastToken)
+{
+    std::string buffer;
+    for (unsigned index = firstToken; index != lastToken; ++index) {
+        const Token &tk = tokenAt(index);
+        if (index != firstToken && (tk.whitespace() || tk.newline()))
+            buffer += ' ';
+        buffer += tk.spell();
+    }
+    return control()->stringLiteral(buffer.c_str(), unsigned(buffer.size()));
+}
+
+// StatementAST
+bool Bind::visit(QtMemberDeclarationAST *ast)
+{
+    const Name *name = 0;
+
+    if (tokenKind(ast->q_token) == T_Q_D)
+        name = control()->identifier("d");
+    else
+        name = control()->identifier("q");
+
+    FullySpecifiedType declTy = this->expression(ast->type_id);
+
+    if (tokenKind(ast->q_token) == T_Q_D) {
+        if (NamedType *namedTy = declTy->asNamedType()) {
+            if (const Identifier *nameId = namedTy->name()->asNameId()) {
+                std::string privateClass;
+                privateClass += nameId->identifier()->chars();
+                privateClass += "Private";
+
+                const Name *privName = control()->identifier(privateClass.c_str(), unsigned(privateClass.size()));
+                declTy.setType(control()->namedType(privName));
+            }
+        }
+    }
+
+    Declaration *symbol = control()->newDeclaration(/*generated*/ 0, name);
+    symbol->setType(control()->pointerType(declTy));
+
+    _scope->addMember(symbol);
+    return false;
+}
+
+bool Bind::visit(CaseStatementAST *ast)
+{
+    ExpressionTy expression = this->expression(ast->expression);
+    this->statement(ast->statement);
+    return false;
+}
+
+bool Bind::visit(CompoundStatementAST *ast)
+{
+    Block *block = control()->newBlock(ast->firstToken());
+    unsigned startScopeToken = ast->lbrace_token ? ast->lbrace_token : ast->firstToken();
+    block->setStartOffset(tokenAt(startScopeToken).utf16charsEnd());
+    block->setEndOffset(tokenAt(ast->lastToken() - 1).utf16charsEnd());
+    ast->symbol = block;
+    _scope->addMember(block);
+    Scope *previousScope = switchScope(block);
+    for (StatementListAST *it = ast->statement_list; it; it = it->next) {
+        this->statement(it->value);
+    }
+    (void) switchScope(previousScope);
+    return false;
+}
+
+bool Bind::visit(DeclarationStatementAST *ast)
+{
+    this->declaration(ast->declaration);
+    return false;
+}
+
+bool Bind::visit(DoStatementAST *ast)
+{
+    this->statement(ast->statement);
+    ExpressionTy expression = this->expression(ast->expression);
+    return false;
+}
+
+bool Bind::visit(ExpressionOrDeclarationStatementAST *ast)
+{
+    this->statement(ast->expression);
+    this->statement(ast->declaration);
+    return false;
+}
+
+bool Bind::visit(ExpressionStatementAST *ast)
+{
+    ExpressionTy expression = this->expression(ast->expression);
+    // unsigned semicolon_token = ast->semicolon_token;
+    return false;
+}
+
+bool Bind::visit(ForeachStatementAST *ast)
+{
+    Block *block = control()->newBlock(ast->firstToken());
+    const unsigned startScopeToken = ast->lparen_token ? ast->lparen_token : ast->firstToken();
+    block->setStartOffset(tokenAt(startScopeToken).utf16charsEnd());
+    block->setEndOffset(tokenAt(ast->lastToken()).utf16charsBegin());
+    _scope->addMember(block);
+    ast->symbol = block;
+
+    Scope *previousScope = switchScope(block);
+
+    FullySpecifiedType type;
+    for (SpecifierListAST *it = ast->type_specifier_list; it; it = it->next) {
+        type = this->specifier(it->value, type);
+    }
+    DeclaratorIdAST *declaratorId = 0;
+    type = this->declarator(ast->declarator, type, &declaratorId);
+    const StringLiteral *initializer = 0;
+    if (type.isAuto() && translationUnit()->languageFeatures().cxx11Enabled) {
+        ExpressionTy exprType = this->expression(ast->expression);
+
+        ArrayType* arrayType = 0;
+        arrayType = exprType->asArrayType();
+
+        if (arrayType != 0)
+            type = arrayType->elementType();
+        else if (ast->expression != 0) {
+            unsigned startOfExpression = ast->expression->firstToken();
+            unsigned endOfExpression = ast->expression->lastToken();
+            const StringLiteral *sl = asStringLiteral(startOfExpression, endOfExpression);
+            const std::string buff = std::string("*") + sl->chars() + ".begin()";
+            initializer = control()->stringLiteral(buff.c_str(), unsigned(buff.size()));
+        }
+    }
+
+    if (declaratorId && declaratorId->name) {
+        unsigned sourceLocation = location(declaratorId->name, ast->firstToken());
+        Declaration *decl = control()->newDeclaration(sourceLocation, declaratorId->name->name);
+        decl->setType(type);
+        decl->setInitializer(initializer);
+        block->addMember(decl);
+    }
+
+    /*ExpressionTy initializer =*/ this->expression(ast->initializer);
+    /*ExpressionTy expression =*/ this->expression(ast->expression);
+    this->statement(ast->statement);
+    (void) switchScope(previousScope);
+    return false;
+}
+
+bool Bind::visit(RangeBasedForStatementAST *ast)
+{
+    Block *block = control()->newBlock(ast->firstToken());
+    const unsigned startScopeToken = ast->lparen_token ? ast->lparen_token : ast->firstToken();
+    block->setStartOffset(tokenAt(startScopeToken).utf16charsEnd());
+    block->setEndOffset(tokenAt(ast->lastToken()).utf16charsBegin());
+    _scope->addMember(block);
+    ast->symbol = block;
+
+    Scope *previousScope = switchScope(block);
+
+    FullySpecifiedType type;
+    for (SpecifierListAST *it = ast->type_specifier_list; it; it = it->next) {
+        type = this->specifier(it->value, type);
+    }
+    DeclaratorIdAST *declaratorId = 0;
+    type = this->declarator(ast->declarator, type, &declaratorId);
+    const StringLiteral *initializer = 0;
+    if (type.isAuto() && translationUnit()->languageFeatures().cxx11Enabled) {
+        ExpressionTy exprType = this->expression(ast->expression);
+
+        ArrayType* arrayType = 0;
+        arrayType = exprType->asArrayType();
+
+        if (arrayType != 0)
+            type = arrayType->elementType();
+        else if (ast->expression != 0) {
+            unsigned startOfExpression = ast->expression->firstToken();
+            unsigned endOfExpression = ast->expression->lastToken();
+            const StringLiteral *sl = asStringLiteral(startOfExpression, endOfExpression);
+            const std::string buff = std::string("*") + sl->chars() + ".begin()";
+            initializer = control()->stringLiteral(buff.c_str(), unsigned(buff.size()));
+        }
+    }
+
+    if (declaratorId && declaratorId->name) {
+        unsigned sourceLocation = location(declaratorId->name, ast->firstToken());
+        Declaration *decl = control()->newDeclaration(sourceLocation, declaratorId->name->name);
+        decl->setType(type);
+        decl->setInitializer(initializer);
+        block->addMember(decl);
+    }
+
+    /*ExpressionTy expression =*/ this->expression(ast->expression);
+    this->statement(ast->statement);
+    (void) switchScope(previousScope);
+    return false;
+}
+
+bool Bind::visit(ForStatementAST *ast)
+{
+    Block *block = control()->newBlock(ast->firstToken());
+    const unsigned startScopeToken = ast->lparen_token ? ast->lparen_token : ast->firstToken();
+    block->setStartOffset(tokenAt(startScopeToken).utf16charsEnd());
+    block->setEndOffset(tokenAt(ast->lastToken()).utf16charsBegin());
+    _scope->addMember(block);
+    ast->symbol = block;
+
+    Scope *previousScope = switchScope(block);
+    this->statement(ast->initializer);
+    /*ExpressionTy condition =*/ this->expression(ast->condition);
+    // unsigned semicolon_token = ast->semicolon_token;
+    /*ExpressionTy expression =*/ this->expression(ast->expression);
+    // unsigned rparen_token = ast->rparen_token;
+    this->statement(ast->statement);
+    (void) switchScope(previousScope);
+    return false;
+}
+
+bool Bind::visit(IfStatementAST *ast)
+{
+    Block *block = control()->newBlock(ast->firstToken());
+    const unsigned startScopeToken = ast->lparen_token ? ast->lparen_token : ast->firstToken();
+    block->setStartOffset(tokenAt(startScopeToken).utf16charsEnd());
+    block->setEndOffset(tokenAt(ast->lastToken()).utf16charsBegin());
+    _scope->addMember(block);
+    ast->symbol = block;
+
+    Scope *previousScope = switchScope(block);
+    /*ExpressionTy condition =*/ this->expression(ast->condition);
+    this->statement(ast->statement);
+    this->statement(ast->else_statement);
+    (void) switchScope(previousScope);
+    return false;
+}
+
+bool Bind::visit(LabeledStatementAST *ast)
+{
+    // unsigned label_token = ast->label_token;
+    // unsigned colon_token = ast->colon_token;
+    this->statement(ast->statement);
+    return false;
+}
+
+bool Bind::visit(BreakStatementAST *ast)
+{
+    (void) ast;
+    // unsigned break_token = ast->break_token;
+    // unsigned semicolon_token = ast->semicolon_token;
+    return false;
+}
+
+bool Bind::visit(ContinueStatementAST *ast)
+{
+    (void) ast;
+    // unsigned continue_token = ast->continue_token;
+    // unsigned semicolon_token = ast->semicolon_token;
+    return false;
+}
+
+bool Bind::visit(GotoStatementAST *ast)
+{
+    (void) ast;
+    // unsigned goto_token = ast->goto_token;
+    // unsigned identifier_token = ast->identifier_token;
+    // unsigned semicolon_token = ast->semicolon_token;
+    return false;
+}
+
+bool Bind::visit(ReturnStatementAST *ast)
+{
+    ExpressionTy expression = this->expression(ast->expression);
+    return false;
+}
+
+bool Bind::visit(SwitchStatementAST *ast)
+{
+    Block *block = control()->newBlock(ast->firstToken());
+    const unsigned startScopeToken = ast->lparen_token ? ast->lparen_token : ast->firstToken();
+    block->setStartOffset(tokenAt(startScopeToken).utf16charsEnd());
+    block->setEndOffset(tokenAt(ast->lastToken()).utf16charsBegin());
+    _scope->addMember(block);
+    ast->symbol = block;
+
+    Scope *previousScope = switchScope(block);
+    /*ExpressionTy condition =*/ this->expression(ast->condition);
+    this->statement(ast->statement);
+    (void) switchScope(previousScope);
+    return false;
+}
+
+bool Bind::visit(TryBlockStatementAST *ast)
+{
+    // unsigned try_token = ast->try_token;
+    this->statement(ast->statement);
+    for (CatchClauseListAST *it = ast->catch_clause_list; it; it = it->next) {
+        this->statement(it->value);
+    }
+    return false;
+}
+
+bool Bind::visit(CatchClauseAST *ast)
+{
+    Block *block = control()->newBlock(ast->firstToken());
+    const unsigned startScopeToken = ast->lparen_token ? ast->lparen_token : ast->firstToken();
+    block->setStartOffset(tokenAt(startScopeToken).utf16charsEnd());
+    block->setEndOffset(tokenAt(ast->lastToken()).utf16charsBegin());
+    _scope->addMember(block);
+    ast->symbol = block;
+
+    Scope *previousScope = switchScope(block);
+    this->declaration(ast->exception_declaration);
+    // unsigned rparen_token = ast->rparen_token;
+    this->statement(ast->statement);
+    (void) switchScope(previousScope);
+    return false;
+}
+
+bool Bind::visit(WhileStatementAST *ast)
+{
+    Block *block = control()->newBlock(ast->firstToken());
+    const unsigned startScopeToken = ast->lparen_token ? ast->lparen_token : ast->firstToken();
+    block->setStartOffset(tokenAt(startScopeToken).utf16charsEnd());
+    block->setEndOffset(tokenAt(ast->lastToken()).utf16charsBegin());
+    _scope->addMember(block);
+    ast->symbol = block;
+
+    Scope *previousScope = switchScope(block);
+    /*ExpressionTy condition =*/ this->expression(ast->condition);
+    this->statement(ast->statement);
+    (void) switchScope(previousScope);
+    return false;
+}
+
+bool Bind::visit(ObjCFastEnumerationAST *ast)
+{
+    Block *block = control()->newBlock(ast->firstToken());
+    const unsigned startScopeToken = ast->lparen_token ? ast->lparen_token : ast->firstToken();
+    block->setStartOffset(tokenAt(startScopeToken).utf16charsEnd());
+    block->setEndOffset(tokenAt(ast->lastToken()).utf16charsBegin());
+    _scope->addMember(block);
+    ast->symbol = block;
+
+    Scope *previousScope = switchScope(block);
+    FullySpecifiedType type;
+    for (SpecifierListAST *it = ast->type_specifier_list; it; it = it->next) {
+        type = this->specifier(it->value, type);
+    }
+    DeclaratorIdAST *declaratorId = 0;
+    type = this->declarator(ast->declarator, type, &declaratorId);
+
+    if (declaratorId && declaratorId->name) {
+        unsigned sourceLocation = location(declaratorId->name, ast->firstToken());
+        Declaration *decl = control()->newDeclaration(sourceLocation, declaratorId->name->name);
+        decl->setType(type);
+        block->addMember(decl);
+    }
+
+    /*ExpressionTy initializer =*/ this->expression(ast->initializer);
+    /*ExpressionTy fast_enumeratable_expression =*/ this->expression(ast->fast_enumeratable_expression);
+    this->statement(ast->statement);
+    (void) switchScope(previousScope);
+    return false;
+}
+
+bool Bind::visit(ObjCSynchronizedStatementAST *ast)
+{
+    // unsigned synchronized_token = ast->synchronized_token;
+    // unsigned lparen_token = ast->lparen_token;
+    ExpressionTy synchronized_object = this->expression(ast->synchronized_object);
+    // unsigned rparen_token = ast->rparen_token;
+    this->statement(ast->statement);
+    return false;
+}
+
+
+// ExpressionAST
+bool Bind::visit(IdExpressionAST *ast)
+{
+    /*const Name *name =*/ this->name(ast->name);
+    return false;
+}
+
+bool Bind::visit(CompoundExpressionAST *ast)
+{
+    // unsigned lparen_token = ast->lparen_token;
+    this->statement(ast->statement);
+    // unsigned rparen_token = ast->rparen_token;
+    return false;
+}
+
+bool Bind::visit(CompoundLiteralAST *ast)
+{
+    // unsigned lparen_token = ast->lparen_token;
+    ExpressionTy type_id = this->expression(ast->type_id);
+    // unsigned rparen_token = ast->rparen_token;
+    ExpressionTy initializer = this->expression(ast->initializer);
+    return false;
+}
+
+bool Bind::visit(QtMethodAST *ast)
+{
+    // unsigned method_token = ast->method_token;
+    // unsigned lparen_token = ast->lparen_token;
+    FullySpecifiedType type;
+    DeclaratorIdAST *declaratorId = 0;
+    type = this->declarator(ast->declarator, type, &declaratorId);
+    // unsigned rparen_token = ast->rparen_token;
+    return false;
+}
+
+bool Bind::visit(BinaryExpressionAST *ast)
+{
+    ExpressionTy left_expression = this->expression(ast->left_expression);
+    // unsigned binary_op_token = ast->binary_op_token;
+    ExpressionTy right_expression = this->expression(ast->right_expression);
+    return false;
+}
+
+bool Bind::visit(CastExpressionAST *ast)
+{
+    // unsigned lparen_token = ast->lparen_token;
+    ExpressionTy type_id = this->expression(ast->type_id);
+    // unsigned rparen_token = ast->rparen_token;
+    ExpressionTy expression = this->expression(ast->expression);
+    return false;
+}
+
+bool Bind::visit(ConditionAST *ast)
+{
+    FullySpecifiedType type;
+    for (SpecifierListAST *it = ast->type_specifier_list; it; it = it->next) {
+        type = this->specifier(it->value, type);
+    }
+    DeclaratorIdAST *declaratorId = 0;
+    type = this->declarator(ast->declarator, type, &declaratorId);
+
+    if (declaratorId && declaratorId->name) {
+        unsigned sourceLocation = location(declaratorId->name, ast->firstToken());
+        Declaration *decl = control()->newDeclaration(sourceLocation, declaratorId->name->name);
+        decl->setType(type);
+        _scope->addMember(decl);
+    }
+
+    return false;
+}
+
+bool Bind::visit(ConditionalExpressionAST *ast)
+{
+    ExpressionTy condition = this->expression(ast->condition);
+    // unsigned question_token = ast->question_token;
+    ExpressionTy left_expression = this->expression(ast->left_expression);
+    // unsigned colon_token = ast->colon_token;
+    ExpressionTy right_expression = this->expression(ast->right_expression);
+    return false;
+}
+
+bool Bind::visit(CppCastExpressionAST *ast)
+{
+    // unsigned cast_token = ast->cast_token;
+    // unsigned less_token = ast->less_token;
+    ExpressionTy type_id = this->expression(ast->type_id);
+    // unsigned greater_token = ast->greater_token;
+    // unsigned lparen_token = ast->lparen_token;
+    ExpressionTy expression = this->expression(ast->expression);
+    // unsigned rparen_token = ast->rparen_token;
+    return false;
+}
+
+bool Bind::visit(DeleteExpressionAST *ast)
+{
+    // unsigned scope_token = ast->scope_token;
+    // unsigned delete_token = ast->delete_token;
+    // unsigned lbracket_token = ast->lbracket_token;
+    // unsigned rbracket_token = ast->rbracket_token;
+    ExpressionTy expression = this->expression(ast->expression);
+    return false;
+}
+
+bool Bind::visit(ArrayInitializerAST *ast)
+{
+    // unsigned lbrace_token = ast->lbrace_token;
+    for (ExpressionListAST *it = ast->expression_list; it; it = it->next) {
+        ExpressionTy value = this->expression(it->value);
+    }
+    // unsigned rbrace_token = ast->rbrace_token;
+    return false;
+}
+
+bool Bind::visit(NewExpressionAST *ast)
+{
+    // unsigned scope_token = ast->scope_token;
+    // unsigned new_token = ast->new_token;
+    this->newPlacement(ast->new_placement);
+    // unsigned lparen_token = ast->lparen_token;
+    ExpressionTy type_id = this->expression(ast->type_id);
+    // unsigned rparen_token = ast->rparen_token;
+    this->newTypeId(ast->new_type_id);
+    this->expression(ast->new_initializer);
+    return false;
+}
+
+bool Bind::visit(TypeidExpressionAST *ast)
+{
+    // unsigned typeid_token = ast->typeid_token;
+    // unsigned lparen_token = ast->lparen_token;
+    ExpressionTy expression = this->expression(ast->expression);
+    // unsigned rparen_token = ast->rparen_token;
+    return false;
+}
+
+bool Bind::visit(TypenameCallExpressionAST *ast)
+{
+    // unsigned typename_token = ast->typename_token;
+    /*const Name *name =*/ this->name(ast->name);
+    this->expression(ast->expression);
+    return false;
+}
+
+bool Bind::visit(TypeConstructorCallAST *ast)
+{
+    FullySpecifiedType type;
+    for (SpecifierListAST *it = ast->type_specifier_list; it; it = it->next) {
+        type = this->specifier(it->value, type);
+    }
+    this->expression(ast->expression);
+    return false;
+}
+
+bool Bind::visit(SizeofExpressionAST *ast)
+{
+    // unsigned sizeof_token = ast->sizeof_token;
+    // unsigned dot_dot_dot_token = ast->dot_dot_dot_token;
+    // unsigned lparen_token = ast->lparen_token;
+    ExpressionTy expression = this->expression(ast->expression);
+    // unsigned rparen_token = ast->rparen_token;
+    return false;
+}
+
+bool Bind::visit(PointerLiteralAST *ast)
+{
+    (void) ast;
+    // unsigned literal_token = ast->literal_token;
+    return false;
+}
+
+bool Bind::visit(NumericLiteralAST *ast)
+{
+    (void) ast;
+    // unsigned literal_token = ast->literal_token;
+    return false;
+}
+
+bool Bind::visit(BoolLiteralAST *ast)
+{
+    (void) ast;
+    // unsigned literal_token = ast->literal_token;
+    return false;
+}
+
+bool Bind::visit(ThisExpressionAST *ast)
+{
+    (void) ast;
+    // unsigned this_token = ast->this_token;
+    return false;
+}
+
+bool Bind::visit(NestedExpressionAST *ast)
+{
+    // unsigned lparen_token = ast->lparen_token;
+    ExpressionTy expression = this->expression(ast->expression);
+    // unsigned rparen_token = ast->rparen_token;
+    return false;
+}
+
+bool Bind::visit(StringLiteralAST *ast)
+{
+    // unsigned literal_token = ast->literal_token;
+    ExpressionTy next = this->expression(ast->next);
+    return false;
+}
+
+bool Bind::visit(ThrowExpressionAST *ast)
+{
+    // unsigned throw_token = ast->throw_token;
+    ExpressionTy expression = this->expression(ast->expression);
+    return false;
+}
+
+bool Bind::visit(TypeIdAST *ast)
+{
+    FullySpecifiedType type;
+    for (SpecifierListAST *it = ast->type_specifier_list; it; it = it->next) {
+        type = this->specifier(it->value, type);
+    }
+    DeclaratorIdAST *declaratorId = 0;
+    type = this->declarator(ast->declarator, type, &declaratorId);
+    _expression = type;
+    return false;
+}
+
+bool Bind::visit(UnaryExpressionAST *ast)
+{
+    // unsigned unary_op_token = ast->unary_op_token;
+    ExpressionTy expression = this->expression(ast->expression);
+    return false;
+}
+
+bool Bind::visit(ObjCMessageExpressionAST *ast)
+{
+    // unsigned lbracket_token = ast->lbracket_token;
+    /*ExpressionTy receiver_expression =*/ this->expression(ast->receiver_expression);
+    /*const Name *selector =*/ this->name(ast->selector);
+    for (ObjCMessageArgumentListAST *it = ast->argument_list; it; it = it->next) {
+        this->objCMessageArgument(it->value);
+    }
+    // unsigned rbracket_token = ast->rbracket_token;
+    return false;
+}
+
+bool Bind::visit(ObjCProtocolExpressionAST *ast)
+{
+    (void) ast;
+    // unsigned protocol_token = ast->protocol_token;
+    // unsigned lparen_token = ast->lparen_token;
+    // unsigned identifier_token = ast->identifier_token;
+    // unsigned rparen_token = ast->rparen_token;
+    return false;
+}
+
+bool Bind::visit(ObjCEncodeExpressionAST *ast)
+{
+    // unsigned encode_token = ast->encode_token;
+    FullySpecifiedType type = this->objCTypeName(ast->type_name);
+    return false;
+}
+
+bool Bind::visit(ObjCSelectorExpressionAST *ast)
+{
+    // unsigned selector_token = ast->selector_token;
+    // unsigned lparen_token = ast->lparen_token;
+    /*const Name *selector =*/ this->name(ast->selector);
+    // unsigned rparen_token = ast->rparen_token;
+    return false;
+}
+
+bool Bind::visit(LambdaExpressionAST *ast)
+{
+    this->lambdaIntroducer(ast->lambda_introducer);
+    if (Function *function = this->lambdaDeclarator(ast->lambda_declarator)) {
+        _scope->addMember(function);
+        Scope *previousScope = switchScope(function);
+        this->statement(ast->statement);
+        (void) switchScope(previousScope);
+    } else {
+        this->statement(ast->statement);
+    }
+
+    return false;
+}
+
+bool Bind::visit(BracedInitializerAST *ast)
+{
+    // unsigned lbrace_token = ast->lbrace_token;
+    for (ExpressionListAST *it = ast->expression_list; it; it = it->next) {
+        /*ExpressionTy value =*/ this->expression(it->value);
+    }
+    // unsigned comma_token = ast->comma_token;
+    // unsigned rbrace_token = ast->rbrace_token;
+    return false;
+}
+
+static int methodKeyForInvokableToken(int kind)
+{
+    if (kind == T_Q_SIGNAL)
+        return Function::SignalMethod;
+    else if (kind == T_Q_SLOT)
+        return Function::SlotMethod;
+    else if (kind == T_Q_INVOKABLE)
+        return Function::InvokableMethod;
+
+    return Function::NormalMethod;
+}
+
+// DeclarationAST
+bool Bind::visit(SimpleDeclarationAST *ast)
+{
+    int methodKey = _methodKey;
+    if (ast->qt_invokable_token)
+        methodKey = methodKeyForInvokableToken(tokenKind(ast->qt_invokable_token));
+
+    // unsigned qt_invokable_token = ast->qt_invokable_token;
+    FullySpecifiedType type;
+    for (SpecifierListAST *it = ast->decl_specifier_list; it; it = it->next) {
+        type = this->specifier(it->value, type);
+    }
+
+    List<Symbol *> **symbolTail = &ast->symbols;
+
+    if (! ast->declarator_list) {
+        ElaboratedTypeSpecifierAST *elabTypeSpec = 0;
+        for (SpecifierListAST *it = ast->decl_specifier_list; ! elabTypeSpec && it; it = it->next)
+            elabTypeSpec = it->value->asElaboratedTypeSpecifier();
+
+        if (elabTypeSpec && tokenKind(elabTypeSpec->classkey_token) != T_TYPENAME) {
+            unsigned sourceLocation = elabTypeSpec->firstToken();
+            const Name *name = 0;
+            if (elabTypeSpec->name) {
+                sourceLocation = location(elabTypeSpec->name, sourceLocation);
+                name = elabTypeSpec->name->name;
+            }
+
+            ensureValidClassName(&name, sourceLocation);
+
+            ForwardClassDeclaration *decl = control()->newForwardClassDeclaration(sourceLocation, name);
+            setDeclSpecifiers(decl, type);
+            _scope->addMember(decl);
+
+            *symbolTail = new (translationUnit()->memoryPool()) List<Symbol *>(decl);
+            symbolTail = &(*symbolTail)->next;
+        }
+    }
+
+    for (DeclaratorListAST *it = ast->declarator_list; it; it = it->next) {
+        DeclaratorIdAST *declaratorId = 0;
+        FullySpecifiedType declTy = this->declarator(it->value, type.qualifiedType(), &declaratorId);
+
+        const Name *declName = 0;
+        unsigned sourceLocation = location(it->value, ast->firstToken());
+        if (declaratorId && declaratorId->name)
+            declName = declaratorId->name->name;
+
+        Declaration *decl = control()->newDeclaration(sourceLocation, declName);
+        decl->setType(declTy);
+        setDeclSpecifiers(decl, type);
+
+        if (Function *fun = decl->type()->asFunctionType()) {
+            fun->setEnclosingScope(_scope);
+            fun->setSourceLocation(sourceLocation, translationUnit());
+
+            setDeclSpecifiers(fun, type);
+            if (declaratorId && declaratorId->name)
+                fun->setName(declaratorId->name->name); // update the function name
+        }
+        else if (declTy.isAuto()) {
+            const ExpressionAST *initializer = it->value->initializer;
+            if (!initializer && declaratorId)
+                translationUnit()->error(location(declaratorId->name, ast->firstToken()), "auto-initialized variable must have an initializer");
+            else if (initializer) {
+                unsigned startOfExpression = initializer->firstToken();
+                unsigned endOfExpression = initializer->lastToken();
+                decl->setInitializer(asStringLiteral(startOfExpression, endOfExpression));
+            }
+        }
+
+        if (_scope->isClass()) {
+            decl->setVisibility(_visibility);
+
+            if (Function *funTy = decl->type()->asFunctionType()) {
+                funTy->setMethodKey(methodKey);
+
+                bool pureVirtualInit = it->value->equal_token
+                        && it->value->initializer
+                        && it->value->initializer->asNumericLiteral();
+                if (funTy->isVirtual() && pureVirtualInit)
+                    funTy->setPureVirtual(true);
+            }
+        }
+
+        _scope->addMember(decl);
+
+        *symbolTail = new (translationUnit()->memoryPool()) List<Symbol *>(decl);
+        symbolTail = &(*symbolTail)->next;
+    }
+    return false;
+}
+
+bool Bind::visit(EmptyDeclarationAST *ast)
+{
+    (void) ast;
+    unsigned semicolon_token = ast->semicolon_token;
+    if (_scope && (_scope->isClass() || _scope->isNamespace())) {
+        const Token &tk = tokenAt(semicolon_token);
+
+        if (! tk.generated())
+            translationUnit()->warning(semicolon_token, "extra `;'");
+    }
+    return false;
+}
+
+bool Bind::visit(AccessDeclarationAST *ast)
+{
+    const int accessSpecifier = tokenKind(ast->access_specifier_token);
+    _visibility = visibilityForAccessSpecifier(accessSpecifier);
+
+    if (ast->slots_token)
+        _methodKey = Function::SlotMethod;
+    else if (accessSpecifier == T_Q_SIGNALS)
+        _methodKey = Function::SignalMethod;
+    else
+        _methodKey = Function::NormalMethod;
+
+    return false;
+}
+
+bool Bind::visit(QtObjectTagAST *ast)
+{
+    (void) ast;
+    // unsigned q_object_token = ast->q_object_token;
+    return false;
+}
+
+bool Bind::visit(QtPrivateSlotAST *ast)
+{
+    // unsigned q_private_slot_token = ast->q_private_slot_token;
+    // unsigned lparen_token = ast->lparen_token;
+    // unsigned dptr_token = ast->dptr_token;
+    // unsigned dptr_lparen_token = ast->dptr_lparen_token;
+    // unsigned dptr_rparen_token = ast->dptr_rparen_token;
+    // unsigned comma_token = ast->comma_token;
+    FullySpecifiedType type;
+    for (SpecifierListAST *it = ast->type_specifier_list; it; it = it->next) {
+        type = this->specifier(it->value, type);
+    }
+    DeclaratorIdAST *declaratorId = 0;
+    type = this->declarator(ast->declarator, type, &declaratorId);
+    // unsigned rparen_token = ast->rparen_token;
+    return false;
+}
+
+static void qtPropertyAttribute(TranslationUnit *unit, ExpressionAST *expression,
+                                int *flags,
+                                QtPropertyDeclaration::Flag flag,
+                                QtPropertyDeclaration::Flag function)
+{
+    if (!expression)
+        return;
+    *flags &= ~function & ~flag;
+    if (BoolLiteralAST *boollit = expression->asBoolLiteral()) {
+        const int kind = unit->tokenAt(boollit->literal_token).kind();
+        if (kind == T_TRUE)
+            *flags |= flag;
+    } else {
+        *flags |= function;
+    }
+}
+
+bool Bind::visit(QtPropertyDeclarationAST *ast)
+{
+    // unsigned property_specifier_token = ast->property_specifier_token;
+    // unsigned lparen_token = ast->lparen_token;
+    ExpressionTy type_id = this->expression(ast->type_id);
+    const Name *property_name = this->name(ast->property_name);
+
+    unsigned sourceLocation = ast->firstToken();
+    if (ast->property_name)
+        sourceLocation = ast->property_name->firstToken();
+    QtPropertyDeclaration *propertyDeclaration = control()->newQtPropertyDeclaration(sourceLocation, property_name);
+    propertyDeclaration->setType(type_id);
+
+    int flags = QtPropertyDeclaration::DesignableFlag
+            | QtPropertyDeclaration::ScriptableFlag
+            | QtPropertyDeclaration::StoredFlag;
+    for (QtPropertyDeclarationItemListAST *it = ast->property_declaration_item_list; it; it = it->next) {
+        if (!it->value || !it->value->item_name_token)
+            continue;
+        this->expression(it->value->expression);
+
+        std::string name = spell(it->value->item_name_token);
+
+        if (name == "CONSTANT") {
+            flags |= QtPropertyDeclaration::ConstantFlag;
+        } else if (name == "FINAL") {
+            flags |= QtPropertyDeclaration::FinalFlag;
+        } else if (name == "READ") {
+            flags |= QtPropertyDeclaration::ReadFunction;
+        } else if (name == "WRITE") {
+            flags |= QtPropertyDeclaration::WriteFunction;
+        } else if (name == "MEMBER") {
+            flags |= QtPropertyDeclaration::MemberVariable;
+        } else if (name == "RESET") {
+            flags |= QtPropertyDeclaration::ResetFunction;
+        } else if (name == "NOTIFY") {
+            flags |= QtPropertyDeclaration::NotifyFunction;
+        } else if (name == "REVISION") {
+            // ### handle REVISION property
+        } else if (name == "DESIGNABLE") {
+            qtPropertyAttribute(translationUnit(), it->value->expression, &flags,
+                                QtPropertyDeclaration::DesignableFlag, QtPropertyDeclaration::DesignableFunction);
+        } else if (name == "SCRIPTABLE") {
+            qtPropertyAttribute(translationUnit(), it->value->expression, &flags,
+                                QtPropertyDeclaration::ScriptableFlag, QtPropertyDeclaration::ScriptableFunction);
+        } else if (name == "STORED") {
+            qtPropertyAttribute(translationUnit(), it->value->expression, &flags,
+                                QtPropertyDeclaration::StoredFlag, QtPropertyDeclaration::StoredFunction);
+        } else if (name == "USER") {
+            qtPropertyAttribute(translationUnit(), it->value->expression, &flags,
+                                QtPropertyDeclaration::UserFlag, QtPropertyDeclaration::UserFunction);
+        }
+    }
+    propertyDeclaration->setFlags(flags);
+    _scope->addMember(propertyDeclaration);
+    // unsigned rparen_token = ast->rparen_token;
+    return false;
+}
+
+bool Bind::visit(QtEnumDeclarationAST *ast)
+{
+    // unsigned enum_specifier_token = ast->enum_specifier_token;
+    // unsigned lparen_token = ast->lparen_token;
+    for (NameListAST *it = ast->enumerator_list; it; it = it->next) {
+        const Name *value = this->name(it->value);
+        if (!value)
+            continue;
+        QtEnum *qtEnum = control()->newQtEnum(it->value->firstToken(), value);
+        _scope->addMember(qtEnum);
+    }
+
+    // unsigned rparen_token = ast->rparen_token;
+    return false;
+}
+
+bool Bind::visit(QtFlagsDeclarationAST *ast)
+{
+    // unsigned flags_specifier_token = ast->flags_specifier_token;
+    // unsigned lparen_token = ast->lparen_token;
+    for (NameListAST *it = ast->flag_enums_list; it; it = it->next) {
+        /*const Name *value =*/ this->name(it->value);
+    }
+    // unsigned rparen_token = ast->rparen_token;
+    return false;
+}
+
+bool Bind::visit(QtInterfacesDeclarationAST *ast)
+{
+    // unsigned interfaces_token = ast->interfaces_token;
+    // unsigned lparen_token = ast->lparen_token;
+    for (QtInterfaceNameListAST *it = ast->interface_name_list; it; it = it->next) {
+        this->qtInterfaceName(it->value);
+    }
+    // unsigned rparen_token = ast->rparen_token;
+    return false;
+}
+
+bool Bind::visit(AliasDeclarationAST *ast)
+{
+    if (!ast->name)
+        return false;
+
+    const Name *name = this->name(ast->name);
+
+    FullySpecifiedType ty = expression(ast->typeId);
+    ty.setTypedef(true);
+
+    Declaration *decl = control()->newDeclaration(ast->name->firstToken(), name);
+    decl->setType(ty);
+    decl->setStorage(Symbol::Typedef);
+    ast->symbol = decl;
+    if (_scope->isClass())
+        decl->setVisibility(_visibility);
+    _scope->addMember(decl);
+
+    return false;
+}
+
+bool Bind::visit(AsmDefinitionAST *ast)
+{
+    (void) ast;
+    // unsigned asm_token = ast->asm_token;
+    // unsigned volatile_token = ast->volatile_token;
+    // unsigned lparen_token = ast->lparen_token;
+    // unsigned rparen_token = ast->rparen_token;
+    // unsigned semicolon_token = ast->semicolon_token;
+    return false;
+}
+
+bool Bind::visit(ExceptionDeclarationAST *ast)
+{
+    FullySpecifiedType type;
+    for (SpecifierListAST *it = ast->type_specifier_list; it; it = it->next) {
+        type = this->specifier(it->value, type);
+    }
+    DeclaratorIdAST *declaratorId = 0;
+    type = this->declarator(ast->declarator, type, &declaratorId);
+
+    const Name *argName = 0;
+    if (declaratorId && declaratorId->name)
+        argName = declaratorId->name->name;
+    Argument *arg = control()->newArgument(location(declaratorId, ast->firstToken()), argName);
+    arg->setType(type);
+    _scope->addMember(arg);
+
+    // unsigned dot_dot_dot_token = ast->dot_dot_dot_token;
+
+    return false;
+}
+
+bool Bind::visit(FunctionDefinitionAST *ast)
+{
+    int methodKey = _methodKey;
+    if (ast->qt_invokable_token)
+        methodKey = methodKeyForInvokableToken(tokenKind(ast->qt_invokable_token));
+
+    FullySpecifiedType declSpecifiers;
+    for (SpecifierListAST *it = ast->decl_specifier_list; it; it = it->next) {
+        declSpecifiers = this->specifier(it->value, declSpecifiers);
+    }
+    DeclaratorIdAST *declaratorId = 0;
+    FullySpecifiedType type = this->declarator(ast->declarator, declSpecifiers.qualifiedType(), &declaratorId);
+
+    Function *fun = type->asFunctionType();
+    ast->symbol = fun;
+
+    if (fun) {
+        setDeclSpecifiers(fun, declSpecifiers);
+        fun->setEndOffset(tokenAt(ast->lastToken() - 1).utf16charsEnd());
+
+        if (_scope->isClass()) {
+            fun->setVisibility(_visibility);
+            fun->setMethodKey(methodKey);
+        }
+
+        if (declaratorId && declaratorId->name) {
+            fun->setSourceLocation(location(declaratorId, ast->firstToken()), translationUnit());
+            fun->setName(declaratorId->name->name);
+        }
+
+        _scope->addMember(fun);
+    } else
+        translationUnit()->warning(ast->firstToken(), "expected a function declarator");
+
+    this->ctorInitializer(ast->ctor_initializer, fun);
+
+    if (fun && ! _skipFunctionBodies && ast->function_body) {
+        Scope *previousScope = switchScope(fun);
+        this->statement(ast->function_body);
+        (void) switchScope(previousScope);
+    }
+
+    return false;
+}
+
+bool Bind::visit(LinkageBodyAST *ast)
+{
+    // unsigned lbrace_token = ast->lbrace_token;
+    for (DeclarationListAST *it = ast->declaration_list; it; it = it->next) {
+        this->declaration(it->value);
+    }
+    // unsigned rbrace_token = ast->rbrace_token;
+    return false;
+}
+
+bool Bind::visit(LinkageSpecificationAST *ast)
+{
+    // unsigned extern_token = ast->extern_token;
+    // unsigned extern_type_token = ast->extern_type_token;
+    this->declaration(ast->declaration);
+    return false;
+}
+
+bool Bind::visit(NamespaceAST *ast)
+{
+    // unsigned namespace_token = ast->namespace_token;
+    // unsigned identifier_token = ast->identifier_token;
+    FullySpecifiedType type;
+    for (SpecifierListAST *it = ast->attribute_list; it; it = it->next) {
+        type = this->specifier(it->value, type);
+    }
+
+    unsigned sourceLocation = ast->firstToken();
+    const Name *namespaceName = 0;
+    if (ast->identifier_token) {
+        sourceLocation = ast->identifier_token;
+        namespaceName = identifier(ast->identifier_token);
+    }
+
+    Namespace *ns = control()->newNamespace(sourceLocation, namespaceName);
+    ns->setStartOffset(tokenAt(sourceLocation).utf16charsEnd()); // the scope starts after the namespace or the identifier token.
+    ns->setEndOffset(tokenAt(ast->lastToken() - 1).utf16charsEnd());
+    ns->setInline(ast->inline_token != 0);
+    ast->symbol = ns;
+    _scope->addMember(ns);
+
+    Scope *previousScope = switchScope(ns);
+    this->declaration(ast->linkage_body);
+    (void) switchScope(previousScope);
+    return false;
+}
+
+bool Bind::visit(NamespaceAliasDefinitionAST *ast)
+{
+    unsigned sourceLocation = ast->firstToken();
+    const Name *name = 0;
+    if (ast->namespace_name_token) {
+        sourceLocation = ast->namespace_name_token;
+        name = identifier(ast->namespace_name_token);
+    }
+
+    NamespaceAlias *namespaceAlias = control()->newNamespaceAlias(sourceLocation, name);
+    namespaceAlias->setNamespaceName(this->name(ast->name));
+    _scope->addMember(namespaceAlias);
+    return false;
+}
+
+bool Bind::visit(ParameterDeclarationAST *ast)
+{
+    FullySpecifiedType type;
+    for (SpecifierListAST *it = ast->type_specifier_list; it; it = it->next) {
+        type = this->specifier(it->value, type);
+    }
+    DeclaratorIdAST *declaratorId = 0;
+    type = this->declarator(ast->declarator, type, &declaratorId);
+    // unsigned equal_token = ast->equal_token;
+    ExpressionTy expression = this->expression(ast->expression);
+
+    const Name *argName = 0;
+    if (declaratorId && declaratorId->name)
+        argName = declaratorId->name->name;
+
+    Argument *arg = control()->newArgument(location(declaratorId, ast->firstToken()), argName);
+    arg->setType(type);
+
+    if (ast->expression) {
+        unsigned startOfExpression = ast->expression->firstToken();
+        unsigned endOfExpression = ast->expression->lastToken();
+        arg->setInitializer(asStringLiteral(startOfExpression, endOfExpression));
+    }
+
+    _scope->addMember(arg);
+
+    ast->symbol = arg;
+    return false;
+}
+
+bool Bind::visit(TemplateDeclarationAST *ast)
+{
+    Template *templ = control()->newTemplate(ast->firstToken(), 0);
+    templ->setStartOffset(tokenAt(ast->firstToken()).utf16charsBegin());
+    templ->setEndOffset(tokenAt(ast->lastToken() - 1).utf16charsEnd());
+    ast->symbol = templ;
+    Scope *previousScope = switchScope(templ);
+
+    for (DeclarationListAST *it = ast->template_parameter_list; it; it = it->next) {
+        this->declaration(it->value);
+    }
+    // unsigned greater_token = ast->greater_token;
+    this->declaration(ast->declaration);
+    (void) switchScope(previousScope);
+
+    if (Symbol *decl = templ->declaration()) {
+        templ->setSourceLocation(decl->sourceLocation(), translationUnit());
+        templ->setName(decl->name());
+    }
+
+    _scope->addMember(templ);
+    return false;
+}
+
+bool Bind::visit(TypenameTypeParameterAST *ast)
+{
+    unsigned sourceLocation = location(ast->name, ast->firstToken());
+    // unsigned classkey_token = ast->classkey_token;
+    // unsigned dot_dot_dot_token = ast->dot_dot_dot_token;
+    const Name *name = this->name(ast->name);
+    ExpressionTy type_id = this->expression(ast->type_id);
+
+    TypenameArgument *arg = control()->newTypenameArgument(sourceLocation, name);
+    arg->setType(type_id);
+    ast->symbol = arg;
+    _scope->addMember(arg);
+    return false;
+}
+
+bool Bind::visit(TemplateTypeParameterAST *ast)
+{
+    unsigned sourceLocation = location(ast->name, ast->firstToken());
+
+    // unsigned template_token = ast->template_token;
+    // unsigned less_token = ast->less_token;
+    // ### process the template prototype
+#if 0
+    for (DeclarationListAST *it = ast->template_parameter_list; it; it = it->next) {
+        this->declaration(it->value);
+    }
+#endif
+    // unsigned greater_token = ast->greater_token;
+    // unsigned class_token = ast->class_token;
+    // unsigned dot_dot_dot_token = ast->dot_dot_dot_token;
+
+    const Name *name = this->name(ast->name);
+    ExpressionTy type_id = this->expression(ast->type_id);
+
+    // ### introduce TemplateTypeArgument
+    TypenameArgument *arg = control()->newTypenameArgument(sourceLocation, name);
+    arg->setType(type_id);
+    ast->symbol = arg;
+    _scope->addMember(arg);
+
+    return false;
+}
+
+bool Bind::visit(UsingAST *ast)
+{
+    unsigned sourceLocation = location(ast->name, ast->firstToken());
+    const Name *name = this->name(ast->name);
+
+    UsingDeclaration *symbol = control()->newUsingDeclaration(sourceLocation, name);
+    ast->symbol = symbol;
+    _scope->addMember(symbol);
+    return false;
+}
+
+bool Bind::visit(UsingDirectiveAST *ast)
+{
+    unsigned sourceLocation = location(ast->name, ast->firstToken());
+    const Name *name = this->name(ast->name);
+    UsingNamespaceDirective *symbol = control()->newUsingNamespaceDirective(sourceLocation, name);
+    ast->symbol = symbol;
+    _scope->addMember(symbol);
+    return false;
+}
+
+bool Bind::visit(ObjCClassForwardDeclarationAST *ast)
+{
+    FullySpecifiedType declSpecifiers;
+    for (SpecifierListAST *it = ast->attribute_list; it; it = it->next) {
+        declSpecifiers = this->specifier(it->value, declSpecifiers);
+    }
+
+    List<ObjCForwardClassDeclaration *> **symbolTail = &ast->symbols;
+
+    // unsigned class_token = ast->class_token;
+    for (NameListAST *it = ast->identifier_list; it; it = it->next) {
+        const Name *name = this->name(it->value);
+
+        const unsigned sourceLocation = location(it->value, ast->firstToken());
+        ObjCForwardClassDeclaration *fwd = control()->newObjCForwardClassDeclaration(sourceLocation, name);
+        setDeclSpecifiers(fwd, declSpecifiers);
+        _scope->addMember(fwd);
+
+        *symbolTail = new (translationUnit()->memoryPool()) List<ObjCForwardClassDeclaration *>(fwd);
+        symbolTail = &(*symbolTail)->next;
+    }
+
+    return false;
+}
+
+unsigned Bind::calculateScopeStart(ObjCClassDeclarationAST *ast) const
+{
+    if (ast->inst_vars_decl)
+        if (unsigned pos = ast->inst_vars_decl->lbrace_token)
+            return tokenAt(pos).utf16charsEnd();
+
+    if (ast->protocol_refs)
+        if (unsigned pos = ast->protocol_refs->lastToken())
+            return tokenAt(pos - 1).utf16charsEnd();
+
+    if (ast->superclass)
+        if (unsigned pos = ast->superclass->lastToken())
+            return tokenAt(pos - 1).utf16charsEnd();
+
+    if (ast->colon_token)
+        return tokenAt(ast->colon_token).utf16charsEnd();
+
+    if (ast->rparen_token)
+        return tokenAt(ast->rparen_token).utf16charsEnd();
+
+    if (ast->category_name)
+        if (unsigned pos = ast->category_name->lastToken())
+            return tokenAt(pos - 1).utf16charsEnd();
+
+    if (ast->lparen_token)
+        return tokenAt(ast->lparen_token).utf16charsEnd();
+
+    if (ast->class_name)
+        if (unsigned pos = ast->class_name->lastToken())
+            return tokenAt(pos - 1).utf16charsEnd();
+
+    return tokenAt(ast->firstToken()).utf16charsBegin();
+}
+
+bool Bind::visit(ObjCClassDeclarationAST *ast)
+{
+    FullySpecifiedType declSpecifiers;
+    for (SpecifierListAST *it = ast->attribute_list; it; it = it->next) {
+        declSpecifiers = this->specifier(it->value, declSpecifiers);
+    }
+    const Name *class_name = this->name(ast->class_name);
+    const Name *category_name = this->name(ast->category_name);
+
+    const unsigned sourceLocation = location(ast->class_name, ast->firstToken());
+    ObjCClass *klass = control()->newObjCClass(sourceLocation, class_name);
+    ast->symbol = klass;
+    _scope->addMember(klass);
+
+    klass->setStartOffset(calculateScopeStart(ast));
+    klass->setEndOffset(tokenAt(ast->lastToken() - 1).utf16charsEnd());
+
+    if (ast->interface_token)
+        klass->setInterface(true);
+
+    klass->setCategoryName(category_name);
+
+    Scope *previousScope = switchScope(klass);
+
+    if (const Name *superclass = this->name(ast->superclass)) {
+        ObjCBaseClass *superKlass = control()->newObjCBaseClass(ast->superclass->firstToken(), superclass);
+        klass->setBaseClass(superKlass);
+    }
+
+    this->objCProtocolRefs(ast->protocol_refs, klass);
+
+    const int previousObjCVisibility = switchObjCVisibility(Function::Protected);
+
+    this->objCInstanceVariablesDeclaration(ast->inst_vars_decl, klass);
+
+    (void) switchObjCVisibility(Function::Public);
+    for (DeclarationListAST *it = ast->member_declaration_list; it; it = it->next) {
+        this->declaration(it->value);
+    }
+
+    (void) switchObjCVisibility(previousObjCVisibility);
+    (void) switchScope(previousScope);
+    return false;
+}
+
+bool Bind::visit(ObjCProtocolForwardDeclarationAST *ast)
+{
+    FullySpecifiedType declSpecifiers;
+    for (SpecifierListAST *it = ast->attribute_list; it; it = it->next) {
+        declSpecifiers = this->specifier(it->value, declSpecifiers);
+    }
+
+    List<ObjCForwardProtocolDeclaration *> **symbolTail = &ast->symbols;
+
+    // unsigned class_token = ast->class_token;
+    for (NameListAST *it = ast->identifier_list; it; it = it->next) {
+        const Name *name = this->name(it->value);
+
+        const unsigned sourceLocation = location(it->value, ast->firstToken());
+        ObjCForwardProtocolDeclaration *fwd = control()->newObjCForwardProtocolDeclaration(sourceLocation, name);
+        setDeclSpecifiers(fwd, declSpecifiers);
+        _scope->addMember(fwd);
+
+        *symbolTail = new (translationUnit()->memoryPool()) List<ObjCForwardProtocolDeclaration *>(fwd);
+        symbolTail = &(*symbolTail)->next;
+    }
+
+    return false;
+}
+
+unsigned Bind::calculateScopeStart(ObjCProtocolDeclarationAST *ast) const
+{
+    if (ast->protocol_refs)
+        if (unsigned pos = ast->protocol_refs->lastToken())
+            return tokenAt(pos - 1).utf16charsEnd();
+    if (ast->name)
+        if (unsigned pos = ast->name->lastToken())
+            return tokenAt(pos - 1).utf16charsEnd();
+
+    return tokenAt(ast->firstToken()).utf16charsBegin();
+}
+
+bool Bind::visit(ObjCProtocolDeclarationAST *ast)
+{
+    FullySpecifiedType type;
+    for (SpecifierListAST *it = ast->attribute_list; it; it = it->next) {
+        type = this->specifier(it->value, type);
+    }
+    // unsigned protocol_token = ast->protocol_token;
+    const Name *name = this->name(ast->name);
+
+    const unsigned sourceLocation = location(ast->name, ast->firstToken());
+    ObjCProtocol *protocol = control()->newObjCProtocol(sourceLocation, name);
+    protocol->setStartOffset(calculateScopeStart(ast));
+    protocol->setEndOffset(tokenAt(ast->lastToken() - 1).utf16charsEnd());
+    ast->symbol = protocol;
+    _scope->addMember(protocol);
+
+    Scope *previousScope = switchScope(protocol);
+    const int previousObjCVisibility = switchObjCVisibility(Function::Public);
+
+    this->objCProtocolRefs(ast->protocol_refs, protocol);
+    for (DeclarationListAST *it = ast->member_declaration_list; it; it = it->next) {
+        this->declaration(it->value);
+    }
+
+    (void) switchObjCVisibility(previousObjCVisibility);
+    (void) switchScope(previousScope);
+    return false;
+}
+
+bool Bind::visit(ObjCVisibilityDeclarationAST *ast)
+{
+    _objcVisibility = visibilityForObjCAccessSpecifier(tokenKind(ast->visibility_token));
+    return false;
+}
+
+bool Bind::visit(ObjCPropertyDeclarationAST *ast)
+{
+    (void) ast;
+    FullySpecifiedType type;
+    for (SpecifierListAST *it = ast->attribute_list; it; it = it->next) {
+        type = this->specifier(it->value, type);
+    }
+    // unsigned property_token = ast->property_token;
+    // unsigned lparen_token = ast->lparen_token;
+    for (ObjCPropertyAttributeListAST *it = ast->property_attribute_list; it; it = it->next) {
+        this->objCPropertyAttribute(it->value);
+    }
+    // unsigned rparen_token = ast->rparen_token;
+    this->declaration(ast->simple_declaration);
+    // List<ObjCPropertyDeclaration *> *symbols = ast->symbols;
+    return false;
+}
+
+bool Bind::visit(ObjCMethodDeclarationAST *ast)
+{
+    ObjCMethod *method = this->objCMethodPrototype(ast->method_prototype);
+
+    if (! ast->function_body) {
+        const Name *name = method->name();
+        unsigned sourceLocation = ast->firstToken();
+        Declaration *decl = control()->newDeclaration(sourceLocation, name);
+        decl->setType(method);
+        _scope->addMember(decl);
+    } else if (! _skipFunctionBodies && ast->function_body) {
+        Scope *previousScope = switchScope(method);
+        this->statement(ast->function_body);
+        (void) switchScope(previousScope);
+        _scope->addMember(method);
+    } else if (method) {
+        _scope->addMember(method);
+    }
+
+    return false;
+}
+
+bool Bind::visit(ObjCSynthesizedPropertiesDeclarationAST *ast)
+{
+    // unsigned synthesized_token = ast->synthesized_token;
+    for (ObjCSynthesizedPropertyListAST *it = ast->property_identifier_list; it; it = it->next) {
+        this->objCSynthesizedProperty(it->value);
+    }
+    // unsigned semicolon_token = ast->semicolon_token;
+    return false;
+}
+
+bool Bind::visit(ObjCDynamicPropertiesDeclarationAST *ast)
+{
+    // unsigned dynamic_token = ast->dynamic_token;
+    for (NameListAST *it = ast->property_identifier_list; it; it = it->next) {
+        /*const Name *value =*/ this->name(it->value);
+    }
+    // unsigned semicolon_token = ast->semicolon_token;
+    return false;
+}
+
+
+// NameAST
+bool Bind::visit(ObjCSelectorAST *ast) // ### review
+{
+    std::vector<const Name *> arguments;
+    bool hasArgs = false;
+
+    for (ObjCSelectorArgumentListAST *it = ast->selector_argument_list; it; it = it->next) {
+        if (const Name *selector_argument = this->objCSelectorArgument(it->value, &hasArgs))
+            arguments.push_back(selector_argument);
+    }
+
+    if (! arguments.empty()) {
+        _name = control()->selectorNameId(&arguments[0], unsigned(arguments.size()), hasArgs);
+        ast->name = _name;
+    }
+
+    return false;
+}
+
+bool Bind::visit(QualifiedNameAST *ast)
+{
+    for (NestedNameSpecifierListAST *it = ast->nested_name_specifier_list; it; it = it->next) {
+        const Name *class_or_namespace_name = this->nestedNameSpecifier(it->value);
+        if (_name || ast->global_scope_token)
+            _name = control()->qualifiedNameId(_name, class_or_namespace_name);
+        else
+            _name = class_or_namespace_name;
+    }
+
+    const Name *unqualified_name = this->name(ast->unqualified_name);
+    if (_name || ast->global_scope_token)
+        _name = control()->qualifiedNameId(_name, unqualified_name);
+    else
+        _name = unqualified_name;
+
+    ast->name = _name;
+    return false;
+}
+
+bool Bind::visit(OperatorFunctionIdAST *ast)
+{
+    const OperatorNameId::Kind op = this->cppOperator(ast->op);
+    ast->name = _name = control()->operatorNameId(op);
+    return false;
+}
+
+bool Bind::visit(ConversionFunctionIdAST *ast)
+{
+    FullySpecifiedType type;
+    for (SpecifierListAST *it = ast->type_specifier_list; it; it = it->next) {
+        type = this->specifier(it->value, type);
+    }
+    for (PtrOperatorListAST *it = ast->ptr_operator_list; it; it = it->next) {
+        type = this->ptrOperator(it->value, type);
+    }
+    ast->name = _name = control()->conversionNameId(type);
+    return false;
+}
+
+bool Bind::visit(AnonymousNameAST *ast)
+{
+    ast->name = _name = control()->anonymousNameId(ast->class_token);
+    return false;
+}
+
+bool Bind::visit(SimpleNameAST *ast)
+{
+    const Identifier *id = identifier(ast->identifier_token);
+    _name = id;
+    ast->name = _name;
+    return false;
+}
+
+bool Bind::visit(DestructorNameAST *ast)
+{
+    _name = control()->destructorNameId(name(ast->unqualified_name));
+    ast->name = _name;
+    return false;
+}
+
+bool Bind::visit(TemplateIdAST *ast)
+{
+    // collect the template parameters
+    std::vector<FullySpecifiedType> templateArguments;
+    for (ExpressionListAST *it = ast->template_argument_list; it; it = it->next) {
+        ExpressionTy value = this->expression(it->value);
+        templateArguments.push_back(value);
+    }
+
+    const Identifier *id = identifier(ast->identifier_token);
+    const int tokenKindBeforeIdentifier(translationUnit()->tokenKind(ast->identifier_token - 1));
+    const bool isSpecialization = (tokenKindBeforeIdentifier == T_CLASS ||
+                                   tokenKindBeforeIdentifier == T_STRUCT);
+    if (templateArguments.empty())
+        _name = control()->templateNameId(id, isSpecialization);
+    else
+        _name = control()->templateNameId(id, isSpecialization, &templateArguments[0],
+                unsigned(templateArguments.size()));
+
+    ast->name = _name;
+    return false;
+}
+
+
+// SpecifierAST
+bool Bind::visit(SimpleSpecifierAST *ast)
+{
+    switch (tokenKind(ast->specifier_token)) {
+        case T_IDENTIFIER: {
+                const Identifier *id = tokenAt(ast->specifier_token).identifier;
+                if (id->match(control()->cpp11Override())) {
+                    if (_type.isOverride())
+                        translationUnit()->error(ast->specifier_token, "duplicate `override'");
+                    _type.setOverride(true);
+                }
+                else if (id->match(control()->cpp11Final())) {
+                    if (_type.isFinal())
+                        translationUnit()->error(ast->specifier_token, "duplicate `final'");
+                    _type.setFinal(true);
+                }
+            }
+            break;
+        case T_CONST:
+            if (_type.isConst())
+                translationUnit()->error(ast->specifier_token, "duplicate `%s'", spell(ast->specifier_token));
+            _type.setConst(true);
+            break;
+
+        case T_VOLATILE:
+            if (_type.isVolatile())
+                translationUnit()->error(ast->specifier_token, "duplicate `%s'", spell(ast->specifier_token));
+            _type.setVolatile(true);
+            break;
+
+        case T_FRIEND:
+            if (_type.isFriend())
+                translationUnit()->error(ast->specifier_token, "duplicate `%s'", spell(ast->specifier_token));
+            _type.setFriend(true);
+            break;
+
+        case T_AUTO:
+            if (!translationUnit()->languageFeatures().cxx11Enabled) {
+                if (_type.isAuto())
+                    translationUnit()->error(ast->specifier_token, "duplicate `%s'", spell(ast->specifier_token));
+            }
+            _type.setAuto(true);
+            break;
+
+        case T_REGISTER:
+            if (_type.isRegister())
+                translationUnit()->error(ast->specifier_token, "duplicate `%s'", spell(ast->specifier_token));
+            _type.setRegister(true);
+            break;
+
+        case T_STATIC:
+            if (_type.isStatic())
+                translationUnit()->error(ast->specifier_token, "duplicate `%s'", spell(ast->specifier_token));
+            _type.setStatic(true);
+            break;
+
+        case T_EXTERN:
+            if (_type.isExtern())
+                translationUnit()->error(ast->specifier_token, "duplicate `%s'", spell(ast->specifier_token));
+            _type.setExtern(true);
+            break;
+
+        case T_MUTABLE:
+            if (_type.isMutable())
+                translationUnit()->error(ast->specifier_token, "duplicate `%s'", spell(ast->specifier_token));
+            _type.setMutable(true);
+            break;
+
+        case T_TYPEDEF:
+            if (_type.isTypedef())
+                translationUnit()->error(ast->specifier_token, "duplicate `%s'", spell(ast->specifier_token));
+            _type.setTypedef(true);
+            break;
+
+        case T_INLINE:
+            if (_type.isInline())
+                translationUnit()->error(ast->specifier_token, "duplicate `%s'", spell(ast->specifier_token));
+            _type.setInline(true);
+            break;
+
+        case T_VIRTUAL:
+            if (_type.isVirtual())
+                translationUnit()->error(ast->specifier_token, "duplicate `%s'", spell(ast->specifier_token));
+            _type.setVirtual(true);
+            break;
+
+        case T_EXPLICIT:
+            if (_type.isExplicit())
+                translationUnit()->error(ast->specifier_token, "duplicate `%s'", spell(ast->specifier_token));
+            _type.setExplicit(true);
+            break;
+
+        case T_SIGNED:
+            if (_type.isSigned())
+                translationUnit()->error(ast->specifier_token, "duplicate `%s'", spell(ast->specifier_token));
+            _type.setSigned(true);
+            break;
+
+        case T_UNSIGNED:
+            if (_type.isUnsigned())
+                translationUnit()->error(ast->specifier_token, "duplicate `%s'", spell(ast->specifier_token));
+            _type.setUnsigned(true);
+            break;
+
+        case T_CHAR:
+            if (_type)
+                translationUnit()->error(ast->specifier_token, "duplicate data type in declaration");
+            _type.setType(control()->integerType(IntegerType::Char));
+            break;
+
+        case T_CHAR16_T:
+            if (_type)
+                translationUnit()->error(ast->specifier_token, "duplicate data type in declaration");
+            _type.setType(control()->integerType(IntegerType::Char16));
+            break;
+
+        case T_CHAR32_T:
+            if (_type)
+                translationUnit()->error(ast->specifier_token, "duplicate data type in declaration");
+            _type.setType(control()->integerType(IntegerType::Char32));
+            break;
+
+        case T_WCHAR_T:
+            if (_type)
+                translationUnit()->error(ast->specifier_token, "duplicate data type in declaration");
+            _type.setType(control()->integerType(IntegerType::WideChar));
+            break;
+
+        case T_BOOL:
+            if (_type)
+                translationUnit()->error(ast->specifier_token, "duplicate data type in declaration");
+            _type.setType(control()->integerType(IntegerType::Bool));
+            break;
+
+        case T_SHORT:
+            if (_type) {
+                IntegerType *intType = control()->integerType(IntegerType::Int);
+                if (_type.type() != intType)
+                    translationUnit()->error(ast->specifier_token, "duplicate data type in declaration");
+            }
+            _type.setType(control()->integerType(IntegerType::Short));
+            break;
+
+        case T_INT:
+            if (_type) {
+                Type *tp = _type.type();
+                IntegerType *shortType = control()->integerType(IntegerType::Short);
+                IntegerType *longType = control()->integerType(IntegerType::Long);
+                IntegerType *longLongType = control()->integerType(IntegerType::LongLong);
+                if (tp == shortType || tp == longType || tp == longLongType)
+                    break;
+                translationUnit()->error(ast->specifier_token, "duplicate data type in declaration");
+            }
+            _type.setType(control()->integerType(IntegerType::Int));
+            break;
+
+        case T_LONG:
+            if (_type) {
+                Type *tp = _type.type();
+                IntegerType *intType = control()->integerType(IntegerType::Int);
+                IntegerType *longType = control()->integerType(IntegerType::Long);
+                FloatType *doubleType = control()->floatType(FloatType::Double);
+                if (tp == longType) {
+                    _type.setType(control()->integerType(IntegerType::LongLong));
+                    break;
+                } else if (tp == doubleType) {
+                    _type.setType(control()->floatType(FloatType::LongDouble));
+                    break;
+                } else if (tp != intType) {
+                    translationUnit()->error(ast->specifier_token, "duplicate data type in declaration");
+                }
+            }
+            _type.setType(control()->integerType(IntegerType::Long));
+            break;
+
+        case T_FLOAT:
+            if (_type)
+                translationUnit()->error(ast->specifier_token, "duplicate data type in declaration");
+            _type.setType(control()->floatType(FloatType::Float));
+            break;
+
+        case T_DOUBLE:
+            if (_type) {
+                IntegerType *longType = control()->integerType(IntegerType::Long);
+                if (_type.type() == longType) {
+                    _type.setType(control()->floatType(FloatType::LongDouble));
+                    break;
+                }
+                translationUnit()->error(ast->specifier_token, "duplicate data type in declaration");
+            }
+            _type.setType(control()->floatType(FloatType::Double));
+            break;
+
+        case T_VOID:
+            if (_type)
+                translationUnit()->error(ast->specifier_token, "duplicate data type in declaration");
+            _type.setType(control()->voidType());
+            break;
+
+        default:
+            break;
+    } // switch
+    return false;
+}
+
+bool Bind::visit(AlignmentSpecifierAST *ast)
+{
+    // Prevent visiting the type-id or alignment expression from changing the currently
+    // calculated type:
+    expression(ast->typeIdExprOrAlignmentExpr);
+    return false;
+}
+
+bool Bind::visit(GnuAttributeSpecifierAST *ast)
+{
+    // unsigned attribute_token = ast->attribute_token;
+    // unsigned first_lparen_token = ast->first_lparen_token;
+    // unsigned second_lparen_token = ast->second_lparen_token;
+    for (GnuAttributeListAST *it = ast->attribute_list; it; it = it->next) {
+        this->attribute(it->value);
+    }
+    // unsigned first_rparen_token = ast->first_rparen_token;
+    // unsigned second_rparen_token = ast->second_rparen_token;
+    return false;
+}
+
+bool Bind::visit(TypeofSpecifierAST *ast)
+{
+    ExpressionTy expression = this->expression(ast->expression);
+    _type = expression;
+    return false;
+}
+
+bool Bind::visit(DecltypeSpecifierAST *ast)
+{
+    _type = this->expression(ast->expression);
+    return false;
+}
+
+bool Bind::visit(ClassSpecifierAST *ast)
+{
+    // unsigned classkey_token = ast->classkey_token;
+    unsigned sourceLocation = ast->firstToken();
+    unsigned startScopeOffset = tokenAt(sourceLocation).utf16charsEnd(); // at the end of the class key
+
+    for (SpecifierListAST *it = ast->attribute_list; it; it = it->next) {
+        _type = this->specifier(it->value, _type);
+    }
+
+    const Name *className = this->name(ast->name);
+
+    if (ast->name && ! ast->name->asAnonymousName()) {
+        sourceLocation = location(ast->name, sourceLocation);
+        startScopeOffset = tokenAt(sourceLocation).utf16charsEnd(); // at the end of the class name
+
+        if (QualifiedNameAST *q = ast->name->asQualifiedName()) {
+            if (q->unqualified_name) {
+                sourceLocation = q->unqualified_name->firstToken();
+                startScopeOffset = tokenAt(q->unqualified_name->lastToken() - 1).utf16charsEnd(); // at the end of the unqualified name
+            }
+        }
+
+        ensureValidClassName(&className, sourceLocation);
+    }
+
+    Class *klass = control()->newClass(sourceLocation, className);
+    klass->setStartOffset(startScopeOffset);
+    klass->setEndOffset(tokenAt(ast->lastToken() - 1).utf16charsEnd());
+    _scope->addMember(klass);
+
+    if (_scope->isClass())
+        klass->setVisibility(_visibility);
+
+    // set the class key
+    unsigned classKey = tokenKind(ast->classkey_token);
+    if (classKey == T_CLASS)
+        klass->setClassKey(Class::ClassKey);
+    else if (classKey == T_STRUCT)
+        klass->setClassKey(Class::StructKey);
+    else if (classKey == T_UNION)
+        klass->setClassKey(Class::UnionKey);
+
+    _type.setType(klass);
+
+    Scope *previousScope = switchScope(klass);
+    const int previousVisibility = switchVisibility(visibilityForClassKey(classKey));
+    const int previousMethodKey = switchMethodKey(Function::NormalMethod);
+
+    for (BaseSpecifierListAST *it = ast->base_clause_list; it; it = it->next) {
+        this->baseSpecifier(it->value, ast->colon_token, klass);
+    }
+    // unsigned dot_dot_dot_token = ast->dot_dot_dot_token;
+    for (DeclarationListAST *it = ast->member_specifier_list; it; it = it->next) {
+        this->declaration(it->value);
+    }
+
+    (void) switchMethodKey(previousMethodKey);
+    (void) switchVisibility(previousVisibility);
+    (void) switchScope(previousScope);
+
+    ast->symbol = klass;
+    return false;
+}
+
+bool Bind::visit(NamedTypeSpecifierAST *ast)
+{
+    _type.setType(control()->namedType(this->name(ast->name)));
+    return false;
+}
+
+bool Bind::visit(ElaboratedTypeSpecifierAST *ast)
+{
+    // unsigned classkey_token = ast->classkey_token;
+    for (SpecifierListAST *it = ast->attribute_list; it; it = it->next) {
+        _type = this->specifier(it->value, _type);
+    }
+    _type.setType(control()->namedType(this->name(ast->name)));
+    return false;
+}
+
+bool Bind::visit(EnumSpecifierAST *ast)
+{
+    unsigned sourceLocation = location(ast->name, ast->firstToken());
+    const Name *enumName = this->name(ast->name);
+
+    Enum *e = control()->newEnum(sourceLocation, enumName);
+    e->setStartOffset(tokenAt(sourceLocation).utf16charsEnd()); // at the end of the enum or identifier token.
+    e->setEndOffset(tokenAt(ast->lastToken() - 1).utf16charsEnd());
+    if (ast->key_token)
+        e->setScoped(true);
+    ast->symbol = e;
+    _scope->addMember(e);
+
+    if (_scope->isClass())
+        e->setVisibility(_visibility);
+
+    Scope *previousScope = switchScope(e);
+    for (EnumeratorListAST *it = ast->enumerator_list; it; it = it->next) {
+        this->enumerator(it->value, e);
+    }
+
+    (void) switchScope(previousScope);
+    return false;
+}
+
+// PtrOperatorAST
+bool Bind::visit(PointerToMemberAST *ast)
+{
+    const Name *memberName = 0;
+
+    for (NestedNameSpecifierListAST *it = ast->nested_name_specifier_list; it; it = it->next) {
+        const Name *class_or_namespace_name = this->nestedNameSpecifier(it->value);
+        if (memberName || ast->global_scope_token)
+            memberName = control()->qualifiedNameId(memberName, class_or_namespace_name);
+        else
+            memberName = class_or_namespace_name;
+    }
+
+    FullySpecifiedType type(control()->pointerToMemberType(memberName, _type));
+    for (SpecifierListAST *it = ast->cv_qualifier_list; it; it = it->next) {
+        type = this->specifier(it->value, type);
+    }
+    _type = type;
+    return false;
+}
+
+bool Bind::visit(PointerAST *ast)
+{
+    if (_type->isReferenceType())
+        translationUnit()->error(ast->firstToken(), "cannot declare pointer to a reference");
+
+    FullySpecifiedType type(control()->pointerType(_type));
+    for (SpecifierListAST *it = ast->cv_qualifier_list; it; it = it->next) {
+        type = this->specifier(it->value, type);
+    }
+    _type = type;
+    return false;
+}
+
+bool Bind::visit(ReferenceAST *ast)
+{
+    const bool rvalueRef = (tokenKind(ast->reference_token) == T_AMPER_AMPER);
+
+    if (_type->isReferenceType())
+        translationUnit()->error(ast->firstToken(), "cannot declare reference to a reference");
+
+    FullySpecifiedType type(control()->referenceType(_type, rvalueRef));
+    _type = type;
+    return false;
+}
+
+
+// PostfixAST
+bool Bind::visit(CallAST *ast)
+{
+    /*ExpressionTy base_expression =*/ this->expression(ast->base_expression);
+    // unsigned lparen_token = ast->lparen_token;
+    for (ExpressionListAST *it = ast->expression_list; it; it = it->next) {
+        /*ExpressionTy value =*/ this->expression(it->value);
+    }
+    // unsigned rparen_token = ast->rparen_token;
+    return false;
+}
+
+bool Bind::visit(ArrayAccessAST *ast)
+{
+    /*ExpressionTy base_expression =*/ this->expression(ast->base_expression);
+    // unsigned lbracket_token = ast->lbracket_token;
+    /*ExpressionTy expression =*/ this->expression(ast->expression);
+    // unsigned rbracket_token = ast->rbracket_token;
+    return false;
+}
+
+bool Bind::visit(PostIncrDecrAST *ast)
+{
+    ExpressionTy base_expression = this->expression(ast->base_expression);
+    // unsigned incr_decr_token = ast->incr_decr_token;
+    return false;
+}
+
+bool Bind::visit(MemberAccessAST *ast)
+{
+    ExpressionTy base_expression = this->expression(ast->base_expression);
+    // unsigned access_token = ast->access_token;
+    // unsigned template_token = ast->template_token;
+    /*const Name *member_name =*/ this->name(ast->member_name);
+    return false;
+}
+
+
+// CoreDeclaratorAST
+bool Bind::visit(DeclaratorIdAST *ast)
+{
+    /*const Name *name =*/ this->name(ast->name);
+    *_declaratorId = ast;
+    return false;
+}
+
+bool Bind::visit(NestedDeclaratorAST *ast)
+{
+    _type = this->declarator(ast->declarator, _type, _declaratorId);
+    return false;
+}
+
+
+// PostfixDeclaratorAST
+bool Bind::visit(FunctionDeclaratorAST *ast)
+{
+    Function *fun = control()->newFunction(0, 0);
+    fun->setStartOffset(tokenAt(ast->firstToken()).utf16charsBegin());
+    fun->setEndOffset(tokenAt(ast->lastToken() - 1).utf16charsEnd());
+    if (ast->trailing_return_type)
+        _type = this->trailingReturnType(ast->trailing_return_type, _type);
+    fun->setReturnType(_type);
+
+    // unsigned lparen_token = ast->lparen_token;
+    this->parameterDeclarationClause(ast->parameter_declaration_clause, ast->lparen_token, fun);
+    // unsigned rparen_token = ast->rparen_token;
+    FullySpecifiedType type(fun);
+    for (SpecifierListAST *it = ast->cv_qualifier_list; it; it = it->next) {
+        type = this->specifier(it->value, type);
+    }
+
+    // propagate the cv-qualifiers
+    fun->setConst(type.isConst());
+    fun->setVolatile(type.isVolatile());
+    fun->setOverride(type.isOverride());
+    fun->setFinal(type.isFinal());
+
+    this->exceptionSpecification(ast->exception_specification, type);
+    if (ast->as_cpp_initializer != 0) {
+        fun->setAmbiguous(true);
+        /*ExpressionTy as_cpp_initializer =*/ this->expression(ast->as_cpp_initializer);
+    }
+    ast->symbol = fun;
+    _type = type;
+    return false;
+}
+
+bool Bind::visit(ArrayDeclaratorAST *ast)
+{
+    ExpressionTy expression = this->expression(ast->expression);
+    FullySpecifiedType type(control()->arrayType(_type));
+    _type = type;
+    return false;
+}
+
+void Bind::ensureValidClassName(const Name **name, unsigned sourceLocation)
+{
+    if (!*name)
+        return;
+
+    const QualifiedNameId *qName = (*name)->asQualifiedNameId();
+    const Name *uqName = qName ? qName->name() : *name;
+
+    if (!uqName->isNameId() && !uqName->isTemplateNameId()) {
+        translationUnit()->error(sourceLocation, "expected a class-name");
+
+        *name = uqName->identifier();
+        if (qName)
+            *name = control()->qualifiedNameId(qName->base(), *name);
+    }
+}
+
+int Bind::visibilityForAccessSpecifier(int tokenKind)
+{
+    switch (tokenKind) {
+    case T_PUBLIC:
+        return Symbol::Public;
+    case T_PROTECTED:
+        return Symbol::Protected;
+    case T_PRIVATE:
+        return Symbol::Private;
+    case T_Q_SIGNALS:
+        return Symbol::Protected;
+    default:
+        return Symbol::Public;
+    }
+}
+
+int Bind::visibilityForClassKey(int tokenKind)
+{
+    switch (tokenKind) {
+    case T_CLASS:
+        return Symbol::Private;
+    case T_STRUCT:
+    case T_UNION:
+        return Symbol::Public;
+    default:
+        return Symbol::Public;
+    }
+}
+
+int Bind::visibilityForObjCAccessSpecifier(int tokenKind)
+{
+    switch (tokenKind) {
+    case T_AT_PUBLIC:
+        return Symbol::Public;
+    case T_AT_PROTECTED:
+        return Symbol::Protected;
+    case T_AT_PRIVATE:
+        return Symbol::Private;
+    case T_AT_PACKAGE:
+        return Symbol::Package;
+    default:
+        return Symbol::Protected;
+    }
+}
+
+bool Bind::isObjCClassMethod(int tokenKind)
+{
+    switch (tokenKind) {
+    case T_PLUS:
+        return true;
+    case T_MINUS:
+    default:
+        return false;
+    }
+}

+ 295 - 0
Source/ToolCore/JSBind/cplusplus/Bind.h

@@ -0,0 +1,295 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_BIND_H
+#define CPLUSPLUS_BIND_H
+
+#include "ASTVisitor.h"
+#include "FullySpecifiedType.h"
+#include "Names.h"
+
+namespace CPlusPlus {
+
+class CPLUSPLUS_EXPORT Bind: protected ASTVisitor
+{
+public:
+    Bind(TranslationUnit *unit);
+
+    void operator()(TranslationUnitAST *ast, Namespace *globalNamespace);
+    void operator()(DeclarationAST *ast, Scope *scope);
+    void operator()(StatementAST *ast, Scope *scope);
+    FullySpecifiedType operator()(ExpressionAST *ast, Scope *scope);
+    FullySpecifiedType operator()(NewTypeIdAST *ast, Scope *scope);
+
+    bool skipFunctionBodies() const;
+    void setSkipFunctionBodies(bool skipFunctionBodies);
+
+protected:
+    using ASTVisitor::translationUnit;
+
+    unsigned location(DeclaratorAST *ast, unsigned defaultLocation) const;
+    unsigned location(CoreDeclaratorAST *ast, unsigned defaultLocation) const;
+    unsigned location(NameAST *name, unsigned defaultLocation) const;
+
+    static int visibilityForAccessSpecifier(int tokenKind);
+    static int visibilityForClassKey(int tokenKind);
+    static int visibilityForObjCAccessSpecifier(int tokenKind);
+    static bool isObjCClassMethod(int tokenKind);
+
+    void setDeclSpecifiers(Symbol *symbol, const FullySpecifiedType &declSpecifiers);
+
+    typedef FullySpecifiedType ExpressionTy;
+    ExpressionTy expression(ExpressionAST *ast);
+
+    const Name *name(NameAST *ast);
+
+    void statement(StatementAST *ast);
+    void declaration(DeclarationAST *ast);
+
+    FullySpecifiedType specifier(SpecifierAST *ast, const FullySpecifiedType &init);
+    FullySpecifiedType ptrOperator(PtrOperatorAST *ast, const FullySpecifiedType &init);
+    FullySpecifiedType coreDeclarator(CoreDeclaratorAST *ast, const FullySpecifiedType &init);
+    FullySpecifiedType postfixDeclarator(PostfixDeclaratorAST *ast, const FullySpecifiedType &init);
+
+    Scope *switchScope(Scope *scope);
+    int switchVisibility(int visibility);
+    int switchMethodKey(int methodKey);
+    int switchObjCVisibility(int visibility);
+
+    unsigned calculateScopeStart(ObjCClassDeclarationAST *ast) const;
+    unsigned calculateScopeStart(ObjCProtocolDeclarationAST *ast) const;
+
+    const Name *objCSelectorArgument(ObjCSelectorArgumentAST *ast, bool *hasArg);
+    void attribute(GnuAttributeAST *ast);
+    FullySpecifiedType declarator(DeclaratorAST *ast, const FullySpecifiedType &init, DeclaratorIdAST **declaratorId);
+    void qtInterfaceName(QtInterfaceNameAST *ast);
+    void baseSpecifier(BaseSpecifierAST *ast, unsigned colon_token, Class *klass);
+    void ctorInitializer(CtorInitializerAST *ast, Function *fun);
+    void enumerator(EnumeratorAST *ast, Enum *symbol);
+    FullySpecifiedType exceptionSpecification(ExceptionSpecificationAST *ast, const FullySpecifiedType &init);
+    void memInitializer(MemInitializerAST *ast, Function *fun);
+    const Name *nestedNameSpecifier(NestedNameSpecifierAST *ast);
+    void newPlacement(ExpressionListParenAST *ast);
+    FullySpecifiedType newArrayDeclarator(NewArrayDeclaratorAST *ast, const FullySpecifiedType &init);
+    FullySpecifiedType newTypeId(NewTypeIdAST *ast);
+    OperatorNameId::Kind cppOperator(OperatorAST *ast);
+    void parameterDeclarationClause(ParameterDeclarationClauseAST *ast, unsigned lparen_token, Function *fun);
+    void translationUnit(TranslationUnitAST *ast);
+    void objCProtocolRefs(ObjCProtocolRefsAST *ast, Symbol *objcClassOrProtocol);
+    void objCMessageArgument(ObjCMessageArgumentAST *ast);
+    FullySpecifiedType objCTypeName(ObjCTypeNameAST *ast);
+    void objCInstanceVariablesDeclaration(ObjCInstanceVariablesDeclarationAST *ast, ObjCClass *klass);
+    void objCPropertyAttribute(ObjCPropertyAttributeAST *ast);
+    void objCMessageArgumentDeclaration(ObjCMessageArgumentDeclarationAST *ast, ObjCMethod *method);
+    ObjCMethod *objCMethodPrototype(ObjCMethodPrototypeAST *ast);
+    void objCSynthesizedProperty(ObjCSynthesizedPropertyAST *ast);
+    void lambdaIntroducer(LambdaIntroducerAST *ast);
+    void lambdaCapture(LambdaCaptureAST *ast);
+    void capture(CaptureAST *ast);
+    Function *lambdaDeclarator(LambdaDeclaratorAST *ast);
+    FullySpecifiedType trailingReturnType(TrailingReturnTypeAST *ast, const FullySpecifiedType &init);
+    const StringLiteral *asStringLiteral(unsigned firstToken, unsigned lastToken);
+
+    virtual bool preVisit(AST *);
+    virtual void postVisit(AST *);
+
+    // AST
+    virtual bool visit(ObjCSelectorArgumentAST *ast);
+    virtual bool visit(GnuAttributeAST *ast);
+    virtual bool visit(DeclaratorAST *ast);
+    virtual bool visit(QtPropertyDeclarationItemAST *ast);
+    virtual bool visit(QtInterfaceNameAST *ast);
+    virtual bool visit(BaseSpecifierAST *ast);
+    virtual bool visit(CtorInitializerAST *ast);
+    virtual bool visit(EnumeratorAST *ast);
+    virtual bool visit(DynamicExceptionSpecificationAST *ast);
+    virtual bool visit(MemInitializerAST *ast);
+    virtual bool visit(NestedNameSpecifierAST *ast);
+    virtual bool visit(NewArrayDeclaratorAST *ast);
+    virtual bool visit(NewTypeIdAST *ast);
+    virtual bool visit(OperatorAST *ast);
+    virtual bool visit(ParameterDeclarationClauseAST *ast);
+    virtual bool visit(TranslationUnitAST *ast);
+    virtual bool visit(ObjCProtocolRefsAST *ast);
+    virtual bool visit(ObjCMessageArgumentAST *ast);
+    virtual bool visit(ObjCTypeNameAST *ast);
+    virtual bool visit(ObjCInstanceVariablesDeclarationAST *ast);
+    virtual bool visit(ObjCPropertyAttributeAST *ast);
+    virtual bool visit(ObjCMessageArgumentDeclarationAST *ast);
+    virtual bool visit(ObjCMethodPrototypeAST *ast);
+    virtual bool visit(ObjCSynthesizedPropertyAST *ast);
+    virtual bool visit(LambdaIntroducerAST *ast);
+    virtual bool visit(LambdaCaptureAST *ast);
+    virtual bool visit(CaptureAST *ast);
+    virtual bool visit(LambdaDeclaratorAST *ast);
+    virtual bool visit(TrailingReturnTypeAST *ast);
+
+    // StatementAST
+    virtual bool visit(QtMemberDeclarationAST *ast);
+    virtual bool visit(CaseStatementAST *ast);
+    virtual bool visit(CompoundStatementAST *ast);
+    virtual bool visit(DeclarationStatementAST *ast);
+    virtual bool visit(DoStatementAST *ast);
+    virtual bool visit(ExpressionOrDeclarationStatementAST *ast);
+    virtual bool visit(ExpressionStatementAST *ast);
+    virtual bool visit(ForeachStatementAST *ast);
+    virtual bool visit(RangeBasedForStatementAST *ast);
+    virtual bool visit(ForStatementAST *ast);
+    virtual bool visit(IfStatementAST *ast);
+    virtual bool visit(LabeledStatementAST *ast);
+    virtual bool visit(BreakStatementAST *ast);
+    virtual bool visit(ContinueStatementAST *ast);
+    virtual bool visit(GotoStatementAST *ast);
+    virtual bool visit(ReturnStatementAST *ast);
+    virtual bool visit(SwitchStatementAST *ast);
+    virtual bool visit(TryBlockStatementAST *ast);
+    virtual bool visit(CatchClauseAST *ast);
+    virtual bool visit(WhileStatementAST *ast);
+    virtual bool visit(ObjCFastEnumerationAST *ast);
+    virtual bool visit(ObjCSynchronizedStatementAST *ast);
+
+    // ExpressionAST
+    virtual bool visit(IdExpressionAST *ast);
+    virtual bool visit(CompoundExpressionAST *ast);
+    virtual bool visit(CompoundLiteralAST *ast);
+    virtual bool visit(QtMethodAST *ast);
+    virtual bool visit(BinaryExpressionAST *ast);
+    virtual bool visit(CastExpressionAST *ast);
+    virtual bool visit(ConditionAST *ast);
+    virtual bool visit(ConditionalExpressionAST *ast);
+    virtual bool visit(CppCastExpressionAST *ast);
+    virtual bool visit(DeleteExpressionAST *ast);
+    virtual bool visit(ArrayInitializerAST *ast);
+    virtual bool visit(NewExpressionAST *ast);
+    virtual bool visit(TypeidExpressionAST *ast);
+    virtual bool visit(TypenameCallExpressionAST *ast);
+    virtual bool visit(TypeConstructorCallAST *ast);
+    virtual bool visit(SizeofExpressionAST *ast);
+    virtual bool visit(PointerLiteralAST *ast);
+    virtual bool visit(NumericLiteralAST *ast);
+    virtual bool visit(BoolLiteralAST *ast);
+    virtual bool visit(ThisExpressionAST *ast);
+    virtual bool visit(NestedExpressionAST *ast);
+    virtual bool visit(StringLiteralAST *ast);
+    virtual bool visit(ThrowExpressionAST *ast);
+    virtual bool visit(TypeIdAST *ast);
+    virtual bool visit(UnaryExpressionAST *ast);
+    virtual bool visit(ObjCMessageExpressionAST *ast);
+    virtual bool visit(ObjCProtocolExpressionAST *ast);
+    virtual bool visit(ObjCEncodeExpressionAST *ast);
+    virtual bool visit(ObjCSelectorExpressionAST *ast);
+    virtual bool visit(LambdaExpressionAST *ast);
+    virtual bool visit(BracedInitializerAST *ast);
+    virtual bool visit(ExpressionListParenAST *ast);
+
+    // DeclarationAST
+    virtual bool visit(SimpleDeclarationAST *ast);
+    virtual bool visit(EmptyDeclarationAST *ast);
+    virtual bool visit(AccessDeclarationAST *ast);
+    virtual bool visit(QtObjectTagAST *ast);
+    virtual bool visit(QtPrivateSlotAST *ast);
+    virtual bool visit(QtPropertyDeclarationAST *ast);
+    virtual bool visit(QtEnumDeclarationAST *ast);
+    virtual bool visit(QtFlagsDeclarationAST *ast);
+    virtual bool visit(QtInterfacesDeclarationAST *ast);
+    virtual bool visit(AliasDeclarationAST *ast);
+    virtual bool visit(AsmDefinitionAST *ast);
+    virtual bool visit(ExceptionDeclarationAST *ast);
+    virtual bool visit(FunctionDefinitionAST *ast);
+    virtual bool visit(LinkageBodyAST *ast);
+    virtual bool visit(LinkageSpecificationAST *ast);
+    virtual bool visit(NamespaceAST *ast);
+    virtual bool visit(NamespaceAliasDefinitionAST *ast);
+    virtual bool visit(ParameterDeclarationAST *ast);
+    virtual bool visit(TemplateDeclarationAST *ast);
+    virtual bool visit(TypenameTypeParameterAST *ast);
+    virtual bool visit(TemplateTypeParameterAST *ast);
+    virtual bool visit(UsingAST *ast);
+    virtual bool visit(UsingDirectiveAST *ast);
+    virtual bool visit(ObjCClassForwardDeclarationAST *ast);
+    virtual bool visit(ObjCClassDeclarationAST *ast);
+    virtual bool visit(ObjCProtocolForwardDeclarationAST *ast);
+    virtual bool visit(ObjCProtocolDeclarationAST *ast);
+    virtual bool visit(ObjCVisibilityDeclarationAST *ast);
+    virtual bool visit(ObjCPropertyDeclarationAST *ast);
+    virtual bool visit(ObjCMethodDeclarationAST *ast);
+    virtual bool visit(ObjCSynthesizedPropertiesDeclarationAST *ast);
+    virtual bool visit(ObjCDynamicPropertiesDeclarationAST *ast);
+
+    // NameAST
+    virtual bool visit(ObjCSelectorAST *ast);
+    virtual bool visit(QualifiedNameAST *ast);
+    virtual bool visit(OperatorFunctionIdAST *ast);
+    virtual bool visit(ConversionFunctionIdAST *ast);
+    virtual bool visit(AnonymousNameAST *ast);
+    virtual bool visit(SimpleNameAST *ast);
+    virtual bool visit(DestructorNameAST *ast);
+    virtual bool visit(TemplateIdAST *ast);
+
+    // SpecifierAST
+    virtual bool visit(SimpleSpecifierAST *ast);
+    virtual bool visit(AlignmentSpecifierAST *ast);
+    virtual bool visit(GnuAttributeSpecifierAST *ast);
+    virtual bool visit(TypeofSpecifierAST *ast);
+    virtual bool visit(DecltypeSpecifierAST *ast);
+    virtual bool visit(ClassSpecifierAST *ast);
+    virtual bool visit(NamedTypeSpecifierAST *ast);
+    virtual bool visit(ElaboratedTypeSpecifierAST *ast);
+    virtual bool visit(EnumSpecifierAST *ast);
+
+    // PtrOperatorAST
+    virtual bool visit(PointerToMemberAST *ast);
+    virtual bool visit(PointerAST *ast);
+    virtual bool visit(ReferenceAST *ast);
+
+    // PostfixAST
+    virtual bool visit(CallAST *ast);
+    virtual bool visit(ArrayAccessAST *ast);
+    virtual bool visit(PostIncrDecrAST *ast);
+    virtual bool visit(MemberAccessAST *ast);
+
+    // CoreDeclaratorAST
+    virtual bool visit(DeclaratorIdAST *ast);
+    virtual bool visit(NestedDeclaratorAST *ast);
+
+    // PostfixDeclaratorAST
+    virtual bool visit(FunctionDeclaratorAST *ast);
+    virtual bool visit(ArrayDeclaratorAST *ast);
+
+private:
+    static const int kMaxDepth;
+
+    void ensureValidClassName(const Name **name, unsigned sourceLocation);
+
+    Scope *_scope;
+    ExpressionTy _expression;
+    const Name *_name;
+    FullySpecifiedType _type;
+    DeclaratorIdAST **_declaratorId;
+    int _visibility;
+    int _objcVisibility;
+    int _methodKey;
+    bool _skipFunctionBodies;
+    int _depth;
+};
+
+} // namespace CPlusPlus
+
+#endif // CPLUSPLUS_BIND_H

+ 56 - 0
Source/ToolCore/JSBind/cplusplus/CPlusPlus.h

@@ -0,0 +1,56 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_CPLUSPLUS_H
+#define CPLUSPLUS_CPLUSPLUS_H
+
+#include "AST.h"
+#include "ASTMatcher.h"
+#include "ASTPatternBuilder.h"
+#include "ASTVisitor.h"
+#include "ASTfwd.h"
+#include "Bind.h"
+#include "CPlusPlusForwardDeclarations.h"
+#include "Control.h"
+#include "CoreTypes.h"
+#include "DiagnosticClient.h"
+#include "FullySpecifiedType.h"
+#include "Lexer.h"
+#include "LiteralTable.h"
+#include "Literals.h"
+#include "MemoryPool.h"
+#include "Name.h"
+#include "NameVisitor.h"
+#include "Names.h"
+#include "ObjectiveCTypeQualifiers.h"
+#include "Parser.h"
+#include "QtContextKeywords.h"
+#include "Scope.h"
+#include "Symbol.h"
+#include "SymbolVisitor.h"
+#include "Symbols.h"
+#include "Token.h"
+#include "TranslationUnit.h"
+#include "Type.h"
+#include "Matcher.h"
+#include "TypeVisitor.h"
+#include "Templates.h"
+
+#endif // CPLUSPLUS_CPLUSPLUS_H

+ 140 - 0
Source/ToolCore/JSBind/cplusplus/CPlusPlusForwardDeclarations.h

@@ -0,0 +1,140 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_CPLUSPLUSFORWARDDECLARATIONS_H
+#define CPLUSPLUS_CPLUSPLUSFORWARDDECLARATIONS_H
+
+#include <cstdlib>
+#include <cstddef>
+
+#ifdef CPLUSPLUS_WITHOUT_QT
+#  ifndef CPLUSPLUS_UNLIKELY
+#    ifdef __GNUC__
+#      define CPLUSPLUS_UNLIKELY(expr) __builtin_expect(!!(expr), false)
+#    else
+#      define CPLUSPLUS_UNLIKELY(expr) (expr)
+#    endif
+#  endif
+#  define CPLUSPLUS_EXPORT
+#else
+#  include <qglobal.h>
+#  ifndef CPLUSPLUS_UNLIKELY
+#    ifdef Q_UNLIKELY
+#      define CPLUSPLUS_UNLIKELY(expr) Q_UNLIKELY(expr)
+#    else // pre 4.8.something
+#      ifdef __GCC__
+#        define CPLUSPLUS_UNLIKELY(expr) __builtin_expect(!!(expr), false)
+#      else
+#        define CPLUSPLUS_UNLIKELY(expr) (expr)
+#      endif
+#    endif
+#  endif
+#  if defined(CPLUSPLUS_BUILD_LIB)
+#    define CPLUSPLUS_EXPORT Q_DECL_EXPORT
+#  elif defined(CPLUSPLUS_BUILD_STATIC_LIB)
+#    define CPLUSPLUS_EXPORT
+#  else
+#    define CPLUSPLUS_EXPORT Q_DECL_IMPORT
+#  endif
+#endif
+
+namespace CPlusPlus {
+
+class TranslationUnit;
+class Control;
+class MemoryPool;
+class DiagnosticClient;
+
+class Identifier;
+class Literal;
+class StringLiteral;
+class NumericLiteral;
+
+class SymbolTable;
+
+// names
+class NameVisitor;
+class Name;
+class Identifier;
+class AnonymousNameId;
+class TemplateNameId;
+class DestructorNameId;
+class OperatorNameId;
+class ConversionNameId;
+class QualifiedNameId;
+class SelectorNameId;
+
+// types
+class Matcher;
+class FullySpecifiedType;
+class TypeVisitor;
+class Type;
+class UndefinedType;
+class VoidType;
+class IntegerType;
+class FloatType;
+class PointerToMemberType;
+class PointerType;
+class ReferenceType;
+class ArrayType;
+class NamedType;
+
+// symbols
+class Clone;
+class Subst;
+
+class SymbolVisitor;
+class Symbol;
+class Scope;
+class UsingNamespaceDirective;
+class UsingDeclaration;
+class Declaration;
+class Argument;
+class TypenameArgument;
+class Function;
+class Namespace;
+class NamespaceAlias;
+class Template;
+class BaseClass;
+class Block;
+class Class;
+class Enum;
+class EnumeratorDeclaration;
+class ForwardClassDeclaration;
+
+class Token;
+
+// Qt symbols
+class QtPropertyDeclaration;
+class QtEnum;
+
+// Objective-C symbols
+class ObjCBaseClass;
+class ObjCBaseProtocol;
+class ObjCClass;
+class ObjCForwardClassDeclaration;
+class ObjCProtocol;
+class ObjCForwardProtocolDeclaration;
+class ObjCMethod;
+class ObjCPropertyDeclaration;
+
+} // namespace CPlusPlus
+
+#endif // CPLUSPLUS_CPLUSPLUSFORWARDDECLARATIONS_H

+ 838 - 0
Source/ToolCore/JSBind/cplusplus/Control.cpp

@@ -0,0 +1,838 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "Control.h"
+#include "Literals.h"
+#include "LiteralTable.h"
+#include "TranslationUnit.h"
+#include "CoreTypes.h"
+#include "Symbols.h"
+#include "Names.h"
+#include <map>
+#include <set>
+#include <algorithm>
+
+using namespace CPlusPlus;
+
+namespace {
+
+template <typename T>
+struct Compare;
+
+template <> struct Compare<IntegerType>
+{
+    bool operator()(const IntegerType &ty, const IntegerType &otherTy) const
+    { return ty.kind() < otherTy.kind(); }
+};
+
+template <> struct Compare<FloatType>
+{
+    bool operator()(const FloatType &ty, const FloatType &otherTy) const
+    { return ty.kind() < otherTy.kind(); }
+};
+
+template <> struct Compare<PointerToMemberType>
+{
+    bool operator()(const PointerToMemberType &ty, const PointerToMemberType &otherTy) const
+    {
+        if (ty.memberName() < otherTy.memberName())
+            return true;
+
+        else if (ty.memberName() == otherTy.memberName())
+            return ty.elementType() < otherTy.elementType();
+
+        return false;
+    }
+};
+
+template <> struct Compare<PointerType>
+{
+    bool operator()(const PointerType &ty, const PointerType &otherTy) const
+    {
+        return ty.elementType() < otherTy.elementType();
+    }
+};
+
+template <> struct Compare<ReferenceType>
+{
+    bool operator()(const ReferenceType &ty, const ReferenceType &otherTy) const
+    {
+        return ty.elementType() < otherTy.elementType();
+    }
+};
+
+template <> struct Compare<NamedType>
+{
+    bool operator()(const NamedType &ty, const NamedType &otherTy) const
+    {
+        return ty.name() < otherTy.name();
+    }
+};
+
+template <> struct Compare<ArrayType>
+{
+    bool operator()(const ArrayType &ty, const ArrayType &otherTy) const
+    {
+        if (ty.size() < otherTy.size())
+            return true;
+
+        else if (ty.size() == otherTy.size())
+            return ty.elementType() < otherTy.elementType();
+
+        return false;
+    }
+};
+
+template <> struct Compare<AnonymousNameId>
+{
+    bool operator()(const AnonymousNameId &name, const AnonymousNameId &otherName) const
+    {
+        return name.classTokenIndex() < otherName.classTokenIndex();
+    }
+};
+
+template <> struct Compare<DestructorNameId>
+{
+    bool operator()(const DestructorNameId &name, const DestructorNameId &otherName) const
+    {
+        return name.identifier() < otherName.identifier();
+    }
+};
+
+template <> struct Compare<OperatorNameId>
+{
+    bool operator()(const OperatorNameId &name, const OperatorNameId &otherName) const
+    {
+        return name.kind() < otherName.kind();
+    }
+};
+
+template <> struct Compare<ConversionNameId>
+{
+    bool operator()(const ConversionNameId &name, const ConversionNameId &otherName) const
+    {
+        return name.type() < otherName.type();
+    }
+};
+template <> struct Compare<TemplateNameId>
+{
+    bool operator()(const TemplateNameId &name, const TemplateNameId &otherName) const
+    {
+        const Identifier *id = name.identifier();
+        const Identifier *otherId = otherName.identifier();
+
+        if (id == otherId) {
+            // we have to differentiate TemplateNameId with respect to specialization or
+            // instantiation
+            if (name.isSpecialization() == otherName.isSpecialization()) {
+                return std::lexicographical_compare(name.firstTemplateArgument(),
+                                                    name.lastTemplateArgument(),
+                                                    otherName.firstTemplateArgument(),
+                                                    otherName.lastTemplateArgument());
+            } else {
+                return name.isSpecialization();
+            }
+        }
+
+        return id < otherId;
+    }
+};
+template <> struct Compare<QualifiedNameId>
+{
+    bool operator()(const QualifiedNameId &name, const QualifiedNameId &otherName) const
+    {
+        if (name.base() == otherName.base())
+            return name.name() < otherName.name();
+
+        return name.base() < otherName.base();
+    }
+};
+
+template <> struct Compare<SelectorNameId>
+{
+    bool operator()(const SelectorNameId &name, const SelectorNameId &otherName) const
+    {
+        if (name.hasArguments() == otherName.hasArguments())
+            return std::lexicographical_compare(name.firstName(), name.lastName(),
+                                                otherName.firstName(), otherName.lastName());
+
+        return name.hasArguments() < otherName.hasArguments();
+    }
+};
+
+
+template <typename T>
+class Table: public std::set<T, Compare<T> >
+{
+    typedef std::set<T, Compare<T> > _Base;
+public:
+    T *intern(const T &element)
+    { return const_cast<T *>(&*_Base::insert(element).first); }
+};
+
+} // end of anonymous namespace
+
+template <typename Iterator>
+static void delete_array_entries(Iterator first, Iterator last)
+{
+    for (; first != last; ++first)
+        delete *first;
+}
+
+template <typename Array>
+static void delete_array_entries(const Array &a)
+{ delete_array_entries(a.begin(), a.end()); }
+
+class Control::Data
+{
+public:
+    Data(Control *control)
+        : control(control)
+        , translationUnit(0)
+        , diagnosticClient(0)
+        , deprecatedId(0)
+        , unavailableId(0)
+        , objcGetterId(0)
+        , objcSetterId(0)
+        , objcReadwriteId(0)
+        , objcReadonlyId(0)
+        , objcAssignId(0)
+        , objcRetainId(0)
+        , objcCopyId(0)
+        , objcNonatomicId(0)
+        , cpp11Override(0)
+        , cpp11Final(0)
+        , processor(0)
+    {}
+
+    ~Data()
+    {
+        // symbols
+        delete_array_entries(symbols);
+    }
+
+    const AnonymousNameId *findOrInsertAnonymousNameId(unsigned classTokenIndex)
+    {
+        return anonymousNameIds.intern(AnonymousNameId(classTokenIndex));
+    }
+
+    template <typename Iterator>
+    const TemplateNameId *findOrInsertTemplateNameId(const Identifier *id, bool isSpecialization,
+                                                     Iterator first, Iterator last)
+    {
+        return templateNameIds.intern(TemplateNameId(id, isSpecialization, first, last));
+    }
+
+    const DestructorNameId *findOrInsertDestructorNameId(const Name *name)
+    {
+        return destructorNameIds.intern(DestructorNameId(name));
+    }
+
+    const OperatorNameId *findOrInsertOperatorNameId(OperatorNameId::Kind kind)
+    {
+        return operatorNameIds.intern(OperatorNameId(kind));
+    }
+
+    const ConversionNameId *findOrInsertConversionNameId(const FullySpecifiedType &type)
+    {
+        return conversionNameIds.intern(ConversionNameId(type));
+    }
+
+    const QualifiedNameId *findOrInsertQualifiedNameId(const Name *base, const Name *name)
+    {
+        return qualifiedNameIds.intern(QualifiedNameId(base, name));
+    }
+
+    template <typename Iterator>
+    const SelectorNameId *findOrInsertSelectorNameId(Iterator first, Iterator last, bool hasArguments)
+    {
+        return selectorNameIds.intern(SelectorNameId(first, last, hasArguments));
+    }
+
+    IntegerType *findOrInsertIntegerType(int kind)
+    {
+        return integerTypes.intern(IntegerType(kind));
+    }
+
+    FloatType *findOrInsertFloatType(int kind)
+    {
+        return floatTypes.intern(FloatType(kind));
+    }
+
+    PointerToMemberType *findOrInsertPointerToMemberType(const Name *memberName, const FullySpecifiedType &elementType)
+    {
+        return pointerToMemberTypes.intern(PointerToMemberType(memberName, elementType));
+    }
+
+    PointerType *findOrInsertPointerType(const FullySpecifiedType &elementType)
+    {
+        return pointerTypes.intern(PointerType(elementType));
+    }
+
+    ReferenceType *findOrInsertReferenceType(const FullySpecifiedType &elementType, bool rvalueRef)
+    {
+        return referenceTypes.intern(ReferenceType(elementType, rvalueRef));
+    }
+
+    ArrayType *findOrInsertArrayType(const FullySpecifiedType &elementType, unsigned size)
+    {
+        return arrayTypes.intern(ArrayType(elementType, size));
+    }
+
+    NamedType *findOrInsertNamedType(const Name *name)
+    {
+        return namedTypes.intern(NamedType(name));
+    }
+
+    Declaration *newDeclaration(unsigned sourceLocation, const Name *name)
+    {
+        Declaration *declaration = new Declaration(translationUnit, sourceLocation, name);
+        symbols.push_back(declaration);
+        return declaration;
+    }
+
+    EnumeratorDeclaration *newEnumeratorDeclaration(unsigned sourceLocation, const Name *name)
+    {
+        EnumeratorDeclaration *decl = new EnumeratorDeclaration(translationUnit, sourceLocation, name);
+        symbols.push_back(decl);
+        return decl;
+    }
+
+    Argument *newArgument(unsigned sourceLocation, const Name *name)
+    {
+        Argument *argument = new Argument(translationUnit, sourceLocation, name);
+        symbols.push_back(argument);
+        return argument;
+    }
+
+    TypenameArgument *newTypenameArgument(unsigned sourceLocation, const Name *name)
+    {
+        TypenameArgument *argument = new TypenameArgument(translationUnit, sourceLocation, name);
+        symbols.push_back(argument);
+        return argument;
+    }
+
+    Function *newFunction(unsigned sourceLocation, const Name *name)
+    {
+        Function *function = new Function(translationUnit, sourceLocation, name);
+        symbols.push_back(function);
+        return function;
+    }
+
+    BaseClass *newBaseClass(unsigned sourceLocation, const Name *name)
+    {
+        BaseClass *baseClass = new BaseClass(translationUnit, sourceLocation, name);
+        symbols.push_back(baseClass);
+        return baseClass;
+    }
+
+    Block *newBlock(unsigned sourceLocation)
+    {
+        Block *block = new Block(translationUnit, sourceLocation);
+        symbols.push_back(block);
+        return block;
+    }
+
+    Class *newClass(unsigned sourceLocation, const Name *name)
+    {
+        Class *klass = new Class(translationUnit, sourceLocation, name);
+        symbols.push_back(klass);
+        return klass;
+    }
+
+    Namespace *newNamespace(unsigned sourceLocation, const Name *name)
+    {
+        Namespace *ns = new Namespace(translationUnit, sourceLocation, name);
+        symbols.push_back(ns);
+        return ns;
+    }
+
+    Template *newTemplate(unsigned sourceLocation, const Name *name)
+    {
+        Template *ns = new Template(translationUnit, sourceLocation, name);
+        symbols.push_back(ns);
+        return ns;
+    }
+
+    NamespaceAlias *newNamespaceAlias(unsigned sourceLocation, const Name *name)
+    {
+        NamespaceAlias *ns = new NamespaceAlias(translationUnit, sourceLocation, name);
+        symbols.push_back(ns);
+        return ns;
+    }
+
+    UsingNamespaceDirective *newUsingNamespaceDirective(unsigned sourceLocation, const Name *name)
+    {
+        UsingNamespaceDirective *u = new UsingNamespaceDirective(translationUnit, sourceLocation, name);
+        symbols.push_back(u);
+        return u;
+    }
+
+    ForwardClassDeclaration *newForwardClassDeclaration(unsigned sourceLocation, const Name *name)
+    {
+        ForwardClassDeclaration *c = new ForwardClassDeclaration(translationUnit, sourceLocation, name);
+        symbols.push_back(c);
+        return c;
+    }
+
+    QtPropertyDeclaration *newQtPropertyDeclaration(unsigned sourceLocation, const Name *name)
+    {
+        QtPropertyDeclaration *d = new QtPropertyDeclaration(translationUnit, sourceLocation, name);
+        symbols.push_back(d);
+        return d;
+    }
+
+    QtEnum *newQtEnum(unsigned sourceLocation, const Name *name)
+    {
+        QtEnum *d = new QtEnum(translationUnit, sourceLocation, name);
+        symbols.push_back(d);
+        return d;
+    }
+
+    ObjCBaseClass *newObjCBaseClass(unsigned sourceLocation, const Name *name)
+    {
+        ObjCBaseClass *c = new ObjCBaseClass(translationUnit, sourceLocation, name);
+        symbols.push_back(c);
+        return c;
+    }
+
+    ObjCBaseProtocol *newObjCBaseProtocol(unsigned sourceLocation, const Name *name)
+    {
+        ObjCBaseProtocol *p = new ObjCBaseProtocol(translationUnit, sourceLocation, name);
+        symbols.push_back(p);
+        return p;
+    }
+
+    ObjCClass *newObjCClass(unsigned sourceLocation, const Name *name)
+    {
+        ObjCClass *c = new ObjCClass(translationUnit, sourceLocation, name);
+        symbols.push_back(c);
+        return c;
+    }
+
+    ObjCForwardClassDeclaration *newObjCForwardClassDeclaration(unsigned sourceLocation, const Name *name)
+    {
+        ObjCForwardClassDeclaration *fwd = new ObjCForwardClassDeclaration(translationUnit, sourceLocation, name);
+        symbols.push_back(fwd);
+        return fwd;
+    }
+
+    ObjCProtocol *newObjCProtocol(unsigned sourceLocation, const Name *name)
+    {
+        ObjCProtocol *p = new ObjCProtocol(translationUnit, sourceLocation, name);
+        symbols.push_back(p);
+        return p;
+    }
+
+    ObjCForwardProtocolDeclaration *newObjCForwardProtocolDeclaration(unsigned sourceLocation, const Name *name)
+    {
+        ObjCForwardProtocolDeclaration *fwd = new ObjCForwardProtocolDeclaration(translationUnit, sourceLocation, name);
+        symbols.push_back(fwd);
+        return fwd;
+    }
+
+    ObjCMethod *newObjCMethod(unsigned sourceLocation, const Name *name)
+    {
+        ObjCMethod *method = new ObjCMethod(translationUnit, sourceLocation, name);
+        symbols.push_back(method);
+        return method;
+    }
+
+    ObjCPropertyDeclaration *newObjCPropertyDeclaration(unsigned sourceLocation, const Name *name)
+    {
+        ObjCPropertyDeclaration *decl = new ObjCPropertyDeclaration(translationUnit, sourceLocation, name);
+        symbols.push_back(decl);
+        return decl;
+    }
+
+    Enum *newEnum(unsigned sourceLocation, const Name *name)
+    {
+        Enum *e = new Enum(translationUnit, sourceLocation, name);
+        symbols.push_back(e);
+        return e;
+    }
+
+    UsingDeclaration *newUsingDeclaration(unsigned sourceLocation, const Name *name)
+    {
+        UsingDeclaration *u = new UsingDeclaration(translationUnit, sourceLocation, name);
+        symbols.push_back(u);
+        return u;
+    }
+
+    Control *control;
+    TranslationUnit *translationUnit;
+    DiagnosticClient *diagnosticClient;
+
+    LiteralTable<Identifier> identifiers;
+    LiteralTable<StringLiteral> stringLiterals;
+    LiteralTable<NumericLiteral> numericLiterals;
+
+    // ### replace std::map with lookup tables. ASAP!
+
+    // names
+    Table<AnonymousNameId> anonymousNameIds;
+    Table<DestructorNameId> destructorNameIds;
+    Table<OperatorNameId> operatorNameIds;
+    Table<ConversionNameId> conversionNameIds;
+    Table<TemplateNameId> templateNameIds;
+    Table<QualifiedNameId> qualifiedNameIds;
+    Table<SelectorNameId> selectorNameIds;
+
+    // types
+    VoidType voidType;
+    Table<IntegerType> integerTypes;
+    Table<FloatType> floatTypes;
+    Table<PointerToMemberType> pointerToMemberTypes;
+    Table<PointerType> pointerTypes;
+    Table<ReferenceType> referenceTypes;
+    Table<ArrayType> arrayTypes;
+    Table<NamedType> namedTypes;
+
+    // symbols
+    std::vector<Symbol *> symbols;
+
+    const Identifier *deprecatedId;
+    const Identifier *unavailableId;
+    // ObjC context keywords:
+    const Identifier *objcGetterId;
+    const Identifier *objcSetterId;
+    const Identifier *objcReadwriteId;
+    const Identifier *objcReadonlyId;
+    const Identifier *objcAssignId;
+    const Identifier *objcRetainId;
+    const Identifier *objcCopyId;
+    const Identifier *objcNonatomicId;
+    const Identifier *cpp11Override;
+    const Identifier *cpp11Final;
+    TopLevelDeclarationProcessor *processor;
+};
+
+Control::Control()
+{
+    d = new Data(this);
+
+    d->deprecatedId = identifier("deprecated");
+    d->unavailableId = identifier("unavailable");
+
+    d->objcGetterId = identifier("getter");
+    d->objcSetterId = identifier("setter");
+    d->objcReadwriteId = identifier("readwrite");
+    d->objcReadonlyId = identifier("readonly");
+    d->objcAssignId = identifier("assign");
+    d->objcRetainId = identifier("retain");
+    d->objcCopyId = identifier("copy");
+    d->objcNonatomicId = identifier("nonatomic");
+
+    d->cpp11Override = identifier("override");
+    d->cpp11Final = identifier("final");
+}
+
+Control::~Control()
+{ delete d; }
+
+TranslationUnit *Control::translationUnit() const
+{ return d->translationUnit; }
+
+TranslationUnit *Control::switchTranslationUnit(TranslationUnit *unit)
+{
+    TranslationUnit *previousTranslationUnit = d->translationUnit;
+    d->translationUnit = unit;
+    return previousTranslationUnit;
+}
+
+DiagnosticClient *Control::diagnosticClient() const
+{ return d->diagnosticClient; }
+
+void Control::setDiagnosticClient(DiagnosticClient *diagnosticClient)
+{ d->diagnosticClient = diagnosticClient; }
+
+const AnonymousNameId *Control::anonymousNameId(unsigned classTokenIndex)
+{ return d->findOrInsertAnonymousNameId(classTokenIndex); }
+
+const OperatorNameId *Control::findOperatorNameId(OperatorNameId::Kind operatorId) const
+{
+    Table<OperatorNameId>::const_iterator i = d->operatorNameIds.find(operatorId);
+    if (i == d->operatorNameIds.end())
+        return 0;
+    else
+        return &*i;
+}
+
+const Identifier *Control::findIdentifier(const char *chars, unsigned size) const
+{ return d->identifiers.findLiteral(chars, size); }
+
+const Identifier *Control::identifier(const char *chars, unsigned size)
+{ return d->identifiers.findOrInsertLiteral(chars, size); }
+
+const Identifier *Control::identifier(const char *chars)
+{
+    const unsigned length = unsigned(std::strlen(chars));
+    return identifier(chars, length);
+}
+
+Control::IdentifierIterator Control::firstIdentifier() const
+{ return d->identifiers.begin(); }
+
+Control::IdentifierIterator Control::lastIdentifier() const
+{ return d->identifiers.end(); }
+
+Control::StringLiteralIterator Control::firstStringLiteral() const
+{ return d->stringLiterals.begin(); }
+
+Control::StringLiteralIterator Control::lastStringLiteral() const
+{ return d->stringLiterals.end(); }
+
+Control::NumericLiteralIterator Control::firstNumericLiteral() const
+{ return d->numericLiterals.begin(); }
+
+Control::NumericLiteralIterator Control::lastNumericLiteral() const
+{ return d->numericLiterals.end(); }
+
+const StringLiteral *Control::stringLiteral(const char *chars, unsigned size)
+{ return d->stringLiterals.findOrInsertLiteral(chars, size); }
+
+const StringLiteral *Control::stringLiteral(const char *chars)
+{
+    const unsigned length = unsigned(std::strlen(chars));
+    return stringLiteral(chars, length);
+}
+
+const NumericLiteral *Control::numericLiteral(const char *chars, unsigned size)
+{ return d->numericLiterals.findOrInsertLiteral(chars, size); }
+
+const NumericLiteral *Control::numericLiteral(const char *chars)
+{
+    const unsigned length = unsigned(std::strlen(chars));
+    return numericLiteral(chars, length);
+}
+
+const TemplateNameId *Control::templateNameId(const Identifier *id,
+                                              bool isSpecialization,
+                                              const FullySpecifiedType *const args,
+                                              unsigned argv)
+{
+    return d->findOrInsertTemplateNameId(id, isSpecialization, args, args + argv);
+}
+
+const DestructorNameId *Control::destructorNameId(const Name *name)
+{ return d->findOrInsertDestructorNameId(name); }
+
+const OperatorNameId *Control::operatorNameId(OperatorNameId::Kind kind)
+{ return d->findOrInsertOperatorNameId(kind); }
+
+const ConversionNameId *Control::conversionNameId(const FullySpecifiedType &type)
+{ return d->findOrInsertConversionNameId(type); }
+
+const QualifiedNameId *Control::qualifiedNameId(const Name *base, const Name *name)
+{
+    return d->findOrInsertQualifiedNameId(base, name);
+}
+
+const SelectorNameId *Control::selectorNameId(const Name *const *names,
+                                              unsigned nameCount,
+                                              bool hasArguments)
+{
+    return d->findOrInsertSelectorNameId(names, names + nameCount, hasArguments);
+}
+
+
+VoidType *Control::voidType()
+{ return &d->voidType; }
+
+IntegerType *Control::integerType(int kind)
+{ return d->findOrInsertIntegerType(kind); }
+
+FloatType *Control::floatType(int kind)
+{ return d->findOrInsertFloatType(kind); }
+
+PointerToMemberType *Control::pointerToMemberType(const Name *memberName, const FullySpecifiedType &elementType)
+{ return d->findOrInsertPointerToMemberType(memberName, elementType); }
+
+PointerType *Control::pointerType(const FullySpecifiedType &elementType)
+{ return d->findOrInsertPointerType(elementType); }
+
+ReferenceType *Control::referenceType(const FullySpecifiedType &elementType, bool rvalueRef)
+{ return d->findOrInsertReferenceType(elementType, rvalueRef); }
+
+ArrayType *Control::arrayType(const FullySpecifiedType &elementType, unsigned size)
+{ return d->findOrInsertArrayType(elementType, size); }
+
+NamedType *Control::namedType(const Name *name)
+{ return d->findOrInsertNamedType(name); }
+
+Argument *Control::newArgument(unsigned sourceLocation, const Name *name)
+{ return d->newArgument(sourceLocation, name); }
+
+TypenameArgument *Control::newTypenameArgument(unsigned sourceLocation, const Name *name)
+{ return d->newTypenameArgument(sourceLocation, name); }
+
+Function *Control::newFunction(unsigned sourceLocation, const Name *name)
+{ return d->newFunction(sourceLocation, name); }
+
+Namespace *Control::newNamespace(unsigned sourceLocation, const Name *name)
+{ return d->newNamespace(sourceLocation, name); }
+
+Template *Control::newTemplate(unsigned sourceLocation, const Name *name)
+{ return d->newTemplate(sourceLocation, name); }
+
+NamespaceAlias *Control::newNamespaceAlias(unsigned sourceLocation, const Name *name)
+{ return d->newNamespaceAlias(sourceLocation, name); }
+
+BaseClass *Control::newBaseClass(unsigned sourceLocation, const Name *name)
+{ return d->newBaseClass(sourceLocation, name); }
+
+Class *Control::newClass(unsigned sourceLocation, const Name *name)
+{ return d->newClass(sourceLocation, name); }
+
+Enum *Control::newEnum(unsigned sourceLocation, const Name *name)
+{ return d->newEnum(sourceLocation, name); }
+
+Block *Control::newBlock(unsigned sourceLocation)
+{ return d->newBlock(sourceLocation); }
+
+Declaration *Control::newDeclaration(unsigned sourceLocation, const Name *name)
+{ return d->newDeclaration(sourceLocation, name); }
+
+EnumeratorDeclaration *Control::newEnumeratorDeclaration(unsigned sourceLocation, const Name *name)
+{ return d->newEnumeratorDeclaration(sourceLocation, name); }
+
+UsingNamespaceDirective *Control::newUsingNamespaceDirective(unsigned sourceLocation,
+                                                                const Name *name)
+{ return d->newUsingNamespaceDirective(sourceLocation, name); }
+
+UsingDeclaration *Control::newUsingDeclaration(unsigned sourceLocation, const Name *name)
+{ return d->newUsingDeclaration(sourceLocation, name); }
+
+ForwardClassDeclaration *Control::newForwardClassDeclaration(unsigned sourceLocation,
+                                                             const Name *name)
+{ return d->newForwardClassDeclaration(sourceLocation, name); }
+
+QtPropertyDeclaration *Control::newQtPropertyDeclaration(unsigned sourceLocation,
+                                                         const Name *name)
+{ return d->newQtPropertyDeclaration(sourceLocation, name); }
+
+QtEnum *Control::newQtEnum(unsigned sourceLocation, const Name *name)
+{ return d->newQtEnum(sourceLocation, name); }
+
+ObjCBaseClass *Control::newObjCBaseClass(unsigned sourceLocation, const Name *name)
+{ return d->newObjCBaseClass(sourceLocation, name); }
+
+ObjCBaseProtocol *Control::newObjCBaseProtocol(unsigned sourceLocation, const Name *name)
+{ return d->newObjCBaseProtocol(sourceLocation, name); }
+
+ObjCClass *Control::newObjCClass(unsigned sourceLocation, const Name *name)
+{ return d->newObjCClass(sourceLocation, name); }
+
+ObjCForwardClassDeclaration *Control::newObjCForwardClassDeclaration(unsigned sourceLocation, const Name *name)
+{ return d->newObjCForwardClassDeclaration(sourceLocation, name); }
+
+ObjCProtocol *Control::newObjCProtocol(unsigned sourceLocation, const Name *name)
+{ return d->newObjCProtocol(sourceLocation, name); }
+
+ObjCForwardProtocolDeclaration *Control::newObjCForwardProtocolDeclaration(unsigned sourceLocation, const Name *name)
+{ return d->newObjCForwardProtocolDeclaration(sourceLocation, name); }
+
+ObjCMethod *Control::newObjCMethod(unsigned sourceLocation, const Name *name)
+{ return d->newObjCMethod(sourceLocation, name); }
+
+ObjCPropertyDeclaration *Control::newObjCPropertyDeclaration(unsigned sourceLocation, const Name *name)
+{ return d->newObjCPropertyDeclaration(sourceLocation, name); }
+
+const Identifier *Control::deprecatedId() const
+{ return d->deprecatedId; }
+
+const Identifier *Control::unavailableId() const
+{ return d->unavailableId; }
+
+const Identifier *Control::objcGetterId() const
+{ return d->objcGetterId; }
+
+const Identifier *Control::objcSetterId() const
+{ return d->objcSetterId; }
+
+const Identifier *Control::objcReadwriteId() const
+{ return d->objcReadwriteId; }
+
+const Identifier *Control::objcReadonlyId() const
+{ return d->objcReadonlyId; }
+
+const Identifier *Control::objcAssignId() const
+{ return d->objcAssignId; }
+
+const Identifier *Control::objcRetainId() const
+{ return d->objcRetainId; }
+
+const Identifier *Control::objcCopyId() const
+{ return d->objcCopyId; }
+
+const Identifier *Control::objcNonatomicId() const
+{ return d->objcNonatomicId; }
+
+const Identifier *Control::cpp11Override() const
+{ return d->cpp11Override; }
+
+const Identifier *Control::cpp11Final() const
+{ return d->cpp11Final; }
+
+Symbol **Control::firstSymbol() const
+{
+    if (d->symbols.empty())
+        return 0;
+
+    return &*d->symbols.begin();
+}
+
+Symbol **Control::lastSymbol() const
+{
+    if (d->symbols.empty())
+        return 0;
+
+    return &*d->symbols.begin() + d->symbols.size();
+}
+
+unsigned Control::symbolCount() const
+{
+    return unsigned(d->symbols.size());
+}
+
+bool Control::hasSymbol(Symbol *symbol) const
+{
+    return std::find(d->symbols.begin(), d->symbols.end(), symbol) != d->symbols.end();
+}
+
+void Control::squeeze()
+{
+    d->numericLiterals.reset();
+}
+
+TopLevelDeclarationProcessor *Control::topLevelDeclarationProcessor() const
+{
+    return d->processor;
+}
+
+void Control::setTopLevelDeclarationProcessor(CPlusPlus::TopLevelDeclarationProcessor *processor)
+{
+    d->processor = processor;
+}
+
+void Control::addSymbol(Symbol *symbol)
+{
+    d->symbols.push_back(symbol);
+}

+ 232 - 0
Source/ToolCore/JSBind/cplusplus/Control.h

@@ -0,0 +1,232 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_CONTROL_H
+#define CPLUSPLUS_CONTROL_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include "ASTfwd.h"
+#include "Names.h"
+
+namespace CPlusPlus {
+
+class CPLUSPLUS_EXPORT TopLevelDeclarationProcessor
+{
+public:
+    virtual ~TopLevelDeclarationProcessor() {}
+    virtual bool processDeclaration(DeclarationAST *ast) = 0;
+};
+
+class CPLUSPLUS_EXPORT Control
+{
+public:
+    Control();
+    ~Control();
+
+    TranslationUnit *translationUnit() const;
+    TranslationUnit *switchTranslationUnit(TranslationUnit *unit);
+
+    TopLevelDeclarationProcessor *topLevelDeclarationProcessor() const;
+    void setTopLevelDeclarationProcessor(TopLevelDeclarationProcessor *processor);
+
+    DiagnosticClient *diagnosticClient() const;
+    void setDiagnosticClient(DiagnosticClient *diagnosticClient);
+
+    /// Returns the canonical anonymous name id
+    const AnonymousNameId *anonymousNameId(unsigned classTokenIndex);
+
+    /// Returns the canonical template name id.
+    const TemplateNameId *templateNameId(const Identifier *id,
+                                         bool isSpecialization,
+                                         const FullySpecifiedType *const args = 0,
+                                         unsigned argc = 0);
+
+    /// Returns the canonical destructor name id.
+    const DestructorNameId *destructorNameId(const Name *name);
+
+    /// Returns the canonical operator name id.
+    const OperatorNameId *operatorNameId(OperatorNameId::Kind operatorId);
+
+    /// Returns the canonical conversion name id.
+    const ConversionNameId *conversionNameId(const FullySpecifiedType &type);
+
+    /// Returns the canonical qualified name id.
+    const QualifiedNameId *qualifiedNameId(const Name *base, const Name *name);
+
+    const SelectorNameId *selectorNameId(const Name *const *names,
+                                         unsigned nameCount,
+                                         bool hasArguments);
+
+    /// Returns a Type object of type VoidType.
+    VoidType *voidType();
+
+    /// Returns a Type object of type IntegerType.
+    IntegerType *integerType(int integerId);
+
+    /// Returns a Type object of type FloatType.
+    FloatType *floatType(int floatId);
+
+    /// Returns a Type object of type PointertoMemberType.
+    PointerToMemberType *pointerToMemberType(const Name *memberName,
+                                             const FullySpecifiedType &elementType);
+
+    /// Returns a Type object of type PointerType.
+    PointerType *pointerType(const FullySpecifiedType &elementType);
+
+    /// Returns a Type object of type ReferenceType.
+    ReferenceType *referenceType(const FullySpecifiedType &elementType, bool rvalueRef);
+
+    /// Retruns a Type object of type ArrayType.
+    ArrayType *arrayType(const FullySpecifiedType &elementType, unsigned size = 0);
+
+    /// Returns a Type object of type NamedType.
+    NamedType *namedType(const Name *name);
+
+    /// Creates a new Declaration symbol.
+    Declaration *newDeclaration(unsigned sourceLocation, const Name *name);
+
+    /// Creates a new EnumeratorDeclaration symbol.
+    EnumeratorDeclaration *newEnumeratorDeclaration(unsigned sourceLocation, const Name *name);
+
+    /// Creates a new Argument symbol.
+    Argument *newArgument(unsigned sourceLocation, const Name *name = 0);
+
+    /// Creates a new Argument symbol.
+    TypenameArgument *newTypenameArgument(unsigned sourceLocation, const Name *name = 0);
+
+    /// Creates a new Function symbol.
+    Function *newFunction(unsigned sourceLocation, const Name *name = 0);
+
+    /// Creates a new Namespace symbol.
+    Namespace *newNamespace(unsigned sourceLocation, const Name *name = 0);
+
+    /// Creates a new Template symbol.
+    Template *newTemplate(unsigned sourceLocation, const Name *name = 0);
+
+    /// Creates a new Namespace symbol.
+    NamespaceAlias *newNamespaceAlias(unsigned sourceLocation, const Name *name = 0);
+
+    /// Creates a new BaseClass symbol.
+    BaseClass *newBaseClass(unsigned sourceLocation, const Name *name = 0);
+
+    /// Creates a new Class symbol.
+    Class *newClass(unsigned sourceLocation, const Name *name = 0);
+
+    /// Creates a new Enum symbol.
+    Enum *newEnum(unsigned sourceLocation, const Name *name = 0);
+
+    /// Creates a new Block symbol.
+    Block *newBlock(unsigned sourceLocation);
+
+    /// Creates a new UsingNamespaceDirective symbol.
+    UsingNamespaceDirective *newUsingNamespaceDirective(unsigned sourceLocation, const Name *name = 0);
+
+    /// Creates a new UsingDeclaration symbol.
+    UsingDeclaration *newUsingDeclaration(unsigned sourceLocation, const Name *name = 0);
+
+    /// Creates a new ForwardClassDeclaration symbol.
+    ForwardClassDeclaration *newForwardClassDeclaration(unsigned sourceLocation, const Name *name = 0);
+
+    /// Creates a new QtPropertyDeclaration symbol.
+    QtPropertyDeclaration *newQtPropertyDeclaration(unsigned sourceLocation, const Name *name = 0);
+
+    /// Creates a new QtEnum symbol.
+    QtEnum *newQtEnum(unsigned sourceLocation, const Name *name = 0);
+
+    ObjCBaseClass *newObjCBaseClass(unsigned sourceLocation, const Name *name);
+    ObjCBaseProtocol *newObjCBaseProtocol(unsigned sourceLocation, const Name *name);
+
+    /// Creates a new Objective-C class symbol.
+    ObjCClass *newObjCClass(unsigned sourceLocation, const Name *name = 0);
+
+    /// Creates a new Objective-C class forward declaration symbol.
+    ObjCForwardClassDeclaration *newObjCForwardClassDeclaration(unsigned sourceLocation, const Name *name = 0);
+
+    /// Creates a new Objective-C protocol symbol.
+    ObjCProtocol *newObjCProtocol(unsigned sourceLocation, const Name *name = 0);
+
+    /// Creates a new Objective-C protocol forward declaration symbol.
+    ObjCForwardProtocolDeclaration *newObjCForwardProtocolDeclaration(unsigned sourceLocation, const Name *name = 0);
+
+    /// Creates a new Objective-C method symbol.
+    ObjCMethod *newObjCMethod(unsigned sourceLocation, const Name *name = 0);
+
+    /// Creates a new Objective-C @property declaration symbol.
+    ObjCPropertyDeclaration *newObjCPropertyDeclaration(unsigned sourceLocation, const Name *name);
+
+    const Identifier *deprecatedId() const;
+    const Identifier *unavailableId() const;
+    // Objective-C specific context keywords.
+    const Identifier *objcGetterId() const;
+    const Identifier *objcSetterId() const;
+    const Identifier *objcReadwriteId() const;
+    const Identifier *objcReadonlyId() const;
+    const Identifier *objcAssignId() const;
+    const Identifier *objcRetainId() const;
+    const Identifier *objcCopyId() const;
+    const Identifier *objcNonatomicId() const;
+    // C++11 context keywords
+    const Identifier *cpp11Override() const;
+    const Identifier *cpp11Final() const;
+
+    const OperatorNameId *findOperatorNameId(OperatorNameId::Kind operatorId) const;
+
+    const Identifier *findIdentifier(const char *chars, unsigned size) const;
+    const Identifier *identifier(const char *chars, unsigned size);
+    const Identifier *identifier(const char *chars);
+
+    typedef const Identifier *const *IdentifierIterator;
+    typedef const StringLiteral *const *StringLiteralIterator;
+    typedef const NumericLiteral *const *NumericLiteralIterator;
+
+    IdentifierIterator firstIdentifier() const;
+    IdentifierIterator lastIdentifier() const;
+
+    StringLiteralIterator firstStringLiteral() const;
+    StringLiteralIterator lastStringLiteral() const;
+
+    NumericLiteralIterator firstNumericLiteral() const;
+    NumericLiteralIterator lastNumericLiteral() const;
+
+    const StringLiteral *stringLiteral(const char *chars, unsigned size);
+    const StringLiteral *stringLiteral(const char *chars);
+
+    const NumericLiteral *numericLiteral(const char *chars, unsigned size);
+    const NumericLiteral *numericLiteral(const char *chars);
+
+    Symbol **firstSymbol() const;
+    Symbol **lastSymbol() const;
+    unsigned symbolCount() const;
+
+    bool hasSymbol(Symbol *symbol) const;
+    void addSymbol(Symbol *symbol);
+
+    void squeeze();
+
+private:
+    class Data;
+    friend class Data;
+    Data *d;
+};
+
+} // namespace CPlusPlus
+
+
+#endif // CPLUSPLUS_CONTROL_H

+ 206 - 0
Source/ToolCore/JSBind/cplusplus/CoreTypes.cpp

@@ -0,0 +1,206 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "CoreTypes.h"
+#include "TypeVisitor.h"
+#include "Matcher.h"
+#include "Names.h"
+#include <algorithm>
+
+using namespace CPlusPlus;
+
+void UndefinedType::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+bool UndefinedType::match0(const Type *otherType, Matcher *matcher) const
+{
+    if (const UndefinedType *otherUndefinedTy = otherType->asUndefinedType())
+        return matcher->match(this, otherUndefinedTy);
+
+    return false;
+}
+
+void VoidType::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+bool VoidType::match0(const Type *otherType, Matcher *matcher) const
+{
+    if (const VoidType *otherVoidTy = otherType->asVoidType())
+        return matcher->match(this, otherVoidTy);
+
+    return false;
+}
+
+PointerToMemberType::PointerToMemberType(const Name *memberName, const FullySpecifiedType &elementType)
+    : _memberName(memberName),
+      _elementType(elementType)
+{ }
+
+PointerToMemberType::~PointerToMemberType()
+{ }
+
+const Name *PointerToMemberType::memberName() const
+{ return _memberName; }
+
+FullySpecifiedType PointerToMemberType::elementType() const
+{ return _elementType; }
+
+void PointerToMemberType::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+bool PointerToMemberType::match0(const Type *otherType, Matcher *matcher) const
+{
+    if (const PointerToMemberType *otherTy = otherType->asPointerToMemberType())
+        return matcher->match(this, otherTy);
+
+    return false;
+}
+
+PointerType::PointerType(const FullySpecifiedType &elementType)
+    : _elementType(elementType)
+{ }
+
+PointerType::~PointerType()
+{ }
+
+void PointerType::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+bool PointerType::match0(const Type *otherType, Matcher *matcher) const
+{
+    if (const PointerType *otherTy = otherType->asPointerType())
+        return matcher->match(this, otherTy);
+
+    return false;
+}
+
+FullySpecifiedType PointerType::elementType() const
+{ return _elementType; }
+
+ReferenceType::ReferenceType(const FullySpecifiedType &elementType, bool rvalueRef)
+    : _elementType(elementType), _rvalueReference(rvalueRef)
+{ }
+
+ReferenceType::~ReferenceType()
+{ }
+
+void ReferenceType::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+bool ReferenceType::match0(const Type *otherType, Matcher *matcher) const
+{
+    if (const ReferenceType *otherTy = otherType->asReferenceType())
+        return matcher->match(this, otherTy);
+
+    return false;
+}
+
+FullySpecifiedType ReferenceType::elementType() const
+{ return _elementType; }
+
+bool ReferenceType::isRvalueReference() const
+{ return _rvalueReference; }
+
+IntegerType::IntegerType(int kind)
+    : _kind(kind)
+{ }
+
+IntegerType::~IntegerType()
+{ }
+
+void IntegerType::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+bool IntegerType::match0(const Type *otherType, Matcher *matcher) const
+{
+    if (const IntegerType *otherTy = otherType->asIntegerType())
+        return matcher->match(this, otherTy);
+
+    return false;
+}
+
+int IntegerType::kind() const
+{ return _kind; }
+
+FloatType::FloatType(int kind)
+    : _kind(kind)
+{ }
+
+FloatType::~FloatType()
+{ }
+
+void FloatType::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+bool FloatType::match0(const Type *otherType, Matcher *matcher) const
+{
+    if (const FloatType *otherTy = otherType->asFloatType())
+        return matcher->match(this, otherTy);
+
+    return false;
+}
+
+int FloatType::kind() const
+{ return _kind; }
+
+ArrayType::ArrayType(const FullySpecifiedType &elementType, unsigned size)
+    : _elementType(elementType), _size(size)
+{ }
+
+ArrayType::~ArrayType()
+{ }
+
+void ArrayType::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+bool ArrayType::match0(const Type *otherType, Matcher *matcher) const
+{
+    if (const ArrayType *otherTy = otherType->asArrayType())
+        return matcher->match(this, otherTy);
+
+    return false;
+}
+
+FullySpecifiedType ArrayType::elementType() const
+{ return _elementType; }
+
+unsigned ArrayType::size() const
+{ return _size; }
+
+NamedType::NamedType(const Name *name)
+    : _name(name)
+{ }
+
+NamedType::~NamedType()
+{ }
+
+const Name *NamedType::name() const
+{ return _name; }
+
+void NamedType::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+bool NamedType::match0(const Type *otherType, Matcher *matcher) const
+{
+    if (const NamedType *otherTy = otherType->asNamedType())
+        return matcher->match(this, otherTy);
+
+    return false;
+}

+ 246 - 0
Source/ToolCore/JSBind/cplusplus/CoreTypes.h

@@ -0,0 +1,246 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_CORETYPES_H
+#define CPLUSPLUS_CORETYPES_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include "Type.h"
+#include "FullySpecifiedType.h"
+
+namespace CPlusPlus {
+
+class CPLUSPLUS_EXPORT UndefinedType : public Type
+{
+public:
+    static UndefinedType *instance()
+    {
+        static UndefinedType t;
+        return &t;
+    }
+
+    virtual const UndefinedType *asUndefinedType() const
+    { return this; }
+
+    virtual UndefinedType *asUndefinedType()
+    { return this; }
+
+protected:
+    virtual void accept0(TypeVisitor *visitor);
+    virtual bool match0(const Type *otherType, Matcher *matcher) const;
+};
+
+class CPLUSPLUS_EXPORT VoidType: public Type
+{
+public:
+    virtual const VoidType *asVoidType() const
+    { return this; }
+
+    virtual VoidType *asVoidType()
+    { return this; }
+
+protected:
+    virtual void accept0(TypeVisitor *visitor);
+    virtual bool match0(const Type *otherType, Matcher *matcher) const;
+};
+
+class CPLUSPLUS_EXPORT IntegerType: public Type
+{
+public:
+    enum Kind {
+        Char,
+        Char16,
+        Char32,
+        WideChar,
+        Bool,
+        Short,
+        Int,
+        Long,
+        LongLong
+    };
+
+public:
+    IntegerType(int kind);
+    virtual ~IntegerType();
+
+    int kind() const;
+
+    virtual IntegerType *asIntegerType()
+    { return this; }
+
+    virtual const IntegerType *asIntegerType() const
+    { return this; }
+
+protected:
+    virtual void accept0(TypeVisitor *visitor);
+    virtual bool match0(const Type *otherType, Matcher *matcher) const;
+
+private:
+    int _kind;
+};
+
+class CPLUSPLUS_EXPORT FloatType: public Type
+{
+public:
+    enum Kind {
+        Float,
+        Double,
+        LongDouble
+    };
+
+public:
+    FloatType(int kind);
+    virtual ~FloatType();
+
+    int kind() const;
+
+    virtual const FloatType *asFloatType() const
+    { return this; }
+
+    virtual FloatType *asFloatType()
+    { return this; }
+
+protected:
+    virtual void accept0(TypeVisitor *visitor);
+    virtual bool match0(const Type *otherType, Matcher *matcher) const;
+
+private:
+    int _kind;
+};
+
+class CPLUSPLUS_EXPORT PointerType: public Type
+{
+public:
+    PointerType(const FullySpecifiedType &elementType);
+    virtual ~PointerType();
+
+    FullySpecifiedType elementType() const;
+
+    virtual const PointerType *asPointerType() const
+    { return this; }
+
+    virtual PointerType *asPointerType()
+    { return this; }
+
+protected:
+    virtual void accept0(TypeVisitor *visitor);
+    virtual bool match0(const Type *otherType, Matcher *matcher) const;
+
+private:
+    FullySpecifiedType _elementType;
+};
+
+class CPLUSPLUS_EXPORT PointerToMemberType: public Type
+{
+public:
+    PointerToMemberType(const Name *memberName, const FullySpecifiedType &elementType);
+    virtual ~PointerToMemberType();
+
+    const Name *memberName() const;
+    FullySpecifiedType elementType() const;
+
+    virtual const PointerToMemberType *asPointerToMemberType() const
+    { return this; }
+
+    virtual PointerToMemberType *asPointerToMemberType()
+    { return this; }
+
+protected:
+    virtual void accept0(TypeVisitor *visitor);
+    virtual bool match0(const Type *otherType, Matcher *matcher) const;
+
+private:
+    const Name *_memberName;
+    FullySpecifiedType _elementType;
+};
+
+class CPLUSPLUS_EXPORT ReferenceType: public Type
+{
+public:
+    ReferenceType(const FullySpecifiedType &elementType, bool rvalueRef);
+    virtual ~ReferenceType();
+
+    FullySpecifiedType elementType() const;
+    bool isRvalueReference() const;
+
+    virtual const ReferenceType *asReferenceType() const
+    { return this; }
+
+    virtual ReferenceType *asReferenceType()
+    { return this; }
+
+protected:
+    virtual void accept0(TypeVisitor *visitor);
+    virtual bool match0(const Type *otherType, Matcher *matcher) const;
+
+private:
+    FullySpecifiedType _elementType;
+    bool _rvalueReference;
+};
+
+class CPLUSPLUS_EXPORT ArrayType: public Type
+{
+public:
+    ArrayType(const FullySpecifiedType &elementType, unsigned size);
+    virtual ~ArrayType();
+
+    FullySpecifiedType elementType() const;
+    unsigned size() const;
+
+    virtual const ArrayType *asArrayType() const
+    { return this; }
+
+    virtual ArrayType *asArrayType()
+    { return this; }
+
+protected:
+    virtual void accept0(TypeVisitor *visitor);
+    virtual bool match0(const Type *otherType, Matcher *matcher) const;
+
+private:
+    FullySpecifiedType _elementType;
+    unsigned _size;
+};
+
+class CPLUSPLUS_EXPORT NamedType: public Type
+{
+public:
+    NamedType(const Name *name);
+    virtual ~NamedType();
+
+    const Name *name() const;
+
+    virtual const NamedType *asNamedType() const
+    { return this; }
+
+    virtual NamedType *asNamedType()
+    { return this; }
+
+protected:
+    virtual void accept0(TypeVisitor *visitor);
+    virtual bool match0(const Type *otherType, Matcher *matcher) const;
+
+private:
+    const Name *_name;
+};
+
+} // namespace CPlusPlus
+
+#endif // CPLUSPLUS_CORETYPES_H

+ 31 - 0
Source/ToolCore/JSBind/cplusplus/DiagnosticClient.cpp

@@ -0,0 +1,31 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "DiagnosticClient.h"
+
+using namespace CPlusPlus;
+
+DiagnosticClient::DiagnosticClient()
+{ }
+
+DiagnosticClient::~DiagnosticClient()
+{ }
+
+

+ 53 - 0
Source/ToolCore/JSBind/cplusplus/DiagnosticClient.h

@@ -0,0 +1,53 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_DIAGNOSTICCLIENT_H
+#define CPLUSPLUS_DIAGNOSTICCLIENT_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include <cstdarg>
+
+namespace CPlusPlus {
+
+class CPLUSPLUS_EXPORT DiagnosticClient
+{
+    DiagnosticClient(const DiagnosticClient &other);
+    void operator =(const DiagnosticClient &other);
+
+public:
+    enum Level {
+        Warning,
+        Error,
+        Fatal
+    };
+
+    DiagnosticClient();
+    virtual ~DiagnosticClient();
+
+    virtual void report(int level,
+                        const StringLiteral *fileName,
+                        unsigned line, unsigned column,
+                        const char *format, va_list ap) = 0;
+};
+
+} // namespace CPlusPlus
+
+
+#endif // CPLUSPLUS_DIAGNOSTICCLIENT_H

+ 242 - 0
Source/ToolCore/JSBind/cplusplus/FullySpecifiedType.cpp

@@ -0,0 +1,242 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "FullySpecifiedType.h"
+#include "Type.h"
+#include "CoreTypes.h"
+
+using namespace CPlusPlus;
+
+FullySpecifiedType::FullySpecifiedType(Type *type) :
+    _type(type), _flags(0)
+{
+    if (! type)
+        _type = UndefinedType::instance();
+}
+
+FullySpecifiedType::~FullySpecifiedType()
+{ }
+
+bool FullySpecifiedType::isValid() const
+{ return _type != UndefinedType::instance(); }
+
+Type *FullySpecifiedType::type() const
+{ return _type; }
+
+void FullySpecifiedType::setType(Type *type)
+{ _type = type; }
+
+FullySpecifiedType FullySpecifiedType::qualifiedType() const
+{
+    FullySpecifiedType ty = *this;
+    ty.setFriend(false);
+    ty.setRegister(false);
+    ty.setStatic(false);
+    ty.setExtern(false);
+    ty.setMutable(false);
+    ty.setTypedef(false);
+
+    ty.setInline(false);
+    ty.setVirtual(false);
+    ty.setOverride(false);
+    ty.setFinal(false);
+    ty.setExplicit(false);
+
+    ty.setDeprecated(false);
+    ty.setUnavailable(false);
+    return ty;
+}
+
+bool FullySpecifiedType::isConst() const
+{ return f._isConst; }
+
+void FullySpecifiedType::setConst(bool isConst)
+{ f._isConst = isConst; }
+
+bool FullySpecifiedType::isVolatile() const
+{ return f._isVolatile; }
+
+void FullySpecifiedType::setVolatile(bool isVolatile)
+{ f._isVolatile = isVolatile; }
+
+bool FullySpecifiedType::isSigned() const
+{ return f._isSigned; }
+
+void FullySpecifiedType::setSigned(bool isSigned)
+{ f._isSigned = isSigned; }
+
+bool FullySpecifiedType::isUnsigned() const
+{ return f._isUnsigned; }
+
+void FullySpecifiedType::setUnsigned(bool isUnsigned)
+{ f._isUnsigned = isUnsigned; }
+
+bool FullySpecifiedType::isFriend() const
+{ return f._isFriend; }
+
+void FullySpecifiedType::setFriend(bool isFriend)
+{ f._isFriend = isFriend; }
+
+bool FullySpecifiedType::isAuto() const
+{ return f._isAuto; }
+
+void FullySpecifiedType::setAuto(bool isAuto)
+{ f._isAuto = isAuto; }
+
+bool FullySpecifiedType::isRegister() const
+{ return f._isRegister; }
+
+void FullySpecifiedType::setRegister(bool isRegister)
+{ f._isRegister = isRegister; }
+
+bool FullySpecifiedType::isStatic() const
+{ return f._isStatic; }
+
+void FullySpecifiedType::setStatic(bool isStatic)
+{ f._isStatic = isStatic; }
+
+bool FullySpecifiedType::isExtern() const
+{ return f._isExtern; }
+
+void FullySpecifiedType::setExtern(bool isExtern)
+{ f._isExtern = isExtern; }
+
+bool FullySpecifiedType::isMutable() const
+{ return f._isMutable; }
+
+void FullySpecifiedType::setMutable(bool isMutable)
+{ f._isMutable = isMutable; }
+
+bool FullySpecifiedType::isTypedef() const
+{ return f._isTypedef; }
+
+void FullySpecifiedType::setTypedef(bool isTypedef)
+{ f._isTypedef = isTypedef; }
+
+bool FullySpecifiedType::isInline() const
+{ return f._isInline; }
+
+void FullySpecifiedType::setInline(bool isInline)
+{ f._isInline = isInline; }
+
+bool FullySpecifiedType::isVirtual() const
+{ return f._isVirtual; }
+
+void FullySpecifiedType::setVirtual(bool isVirtual)
+{ f._isVirtual = isVirtual; }
+
+bool FullySpecifiedType::isOverride() const
+{ return f._isOverride; }
+
+void FullySpecifiedType::setOverride(bool isOverride)
+{ f._isOverride = isOverride; }
+
+bool FullySpecifiedType::isFinal() const
+{ return f._isFinal; }
+
+void FullySpecifiedType::setFinal(bool isFinal)
+{ f._isFinal = isFinal; }
+
+bool FullySpecifiedType::isExplicit() const
+{ return f._isExplicit; }
+
+void FullySpecifiedType::setExplicit(bool isExplicit)
+{ f._isExplicit = isExplicit; }
+
+bool FullySpecifiedType::isDeprecated() const
+{ return f._isDeprecated; }
+
+void FullySpecifiedType::setDeprecated(bool isDeprecated)
+{ f._isDeprecated = isDeprecated; }
+
+bool FullySpecifiedType::isUnavailable() const
+{ return f._isUnavailable; }
+
+void FullySpecifiedType::setUnavailable(bool isUnavailable)
+{ f._isUnavailable = isUnavailable; }
+
+Type &FullySpecifiedType::operator*()
+{ return *_type; }
+
+FullySpecifiedType::operator bool() const
+{ return _type != UndefinedType::instance(); }
+
+const Type &FullySpecifiedType::operator*() const
+{ return *_type; }
+
+Type *FullySpecifiedType::operator->()
+{ return _type; }
+
+const Type *FullySpecifiedType::operator->() const
+{ return _type; }
+
+bool FullySpecifiedType::operator == (const FullySpecifiedType &other) const
+{ return _type == other._type && _flags == other._flags; }
+
+bool FullySpecifiedType::operator != (const FullySpecifiedType &other) const
+{ return ! operator ==(other); }
+
+bool FullySpecifiedType::operator < (const FullySpecifiedType &other) const
+{
+    if (_type == other._type)
+        return _flags < other._flags;
+    return _type < other._type;
+}
+
+FullySpecifiedType FullySpecifiedType::simplified() const
+{
+    if (const ReferenceType *refTy = type()->asReferenceType())
+        return refTy->elementType().simplified();
+
+    return *this;
+}
+
+unsigned FullySpecifiedType::flags() const
+{ return _flags; }
+
+void FullySpecifiedType::setFlags(unsigned flags)
+{ _flags = flags; }
+
+void FullySpecifiedType::copySpecifiers(const FullySpecifiedType &type)
+{
+    // class storage specifiers
+    f._isFriend = type.f._isFriend;
+    f._isAuto = type.f._isAuto;
+    f._isRegister = type.f._isRegister;
+    f._isStatic = type.f._isStatic;
+    f._isExtern = type.f._isExtern;
+    f._isMutable = type.f._isMutable;
+    f._isTypedef = type.f._isTypedef;
+
+    // function specifiers
+    f._isInline = type.f._isInline;
+    f._isVirtual = type.f._isVirtual;
+    f._isOverride = type.f._isOverride;
+    f._isFinal = type.f._isFinal;
+    f._isExplicit = type.f._isExplicit;
+}
+
+bool FullySpecifiedType::match(const FullySpecifiedType &otherTy, Matcher *matcher) const
+{
+    if (_flags != otherTy._flags)
+        return false;
+
+    return type()->match(otherTy.type(), matcher);
+}

+ 155 - 0
Source/ToolCore/JSBind/cplusplus/FullySpecifiedType.h

@@ -0,0 +1,155 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_FULLYSPECIFIEDTYPE_H
+#define CPLUSPLUS_FULLYSPECIFIEDTYPE_H
+
+#include "CPlusPlusForwardDeclarations.h"
+
+
+namespace CPlusPlus {
+
+class CPLUSPLUS_EXPORT FullySpecifiedType
+{
+public:
+    FullySpecifiedType(Type *type = 0);
+    ~FullySpecifiedType();
+
+    bool isValid() const;
+    operator bool() const;
+
+    Type *type() const;
+    void setType(Type *type);
+
+    FullySpecifiedType qualifiedType() const;
+
+    bool isConst() const;
+    void setConst(bool isConst);
+
+    bool isVolatile() const;
+    void setVolatile(bool isVolatile);
+
+    bool isSigned() const;
+    void setSigned(bool isSigned);
+
+    bool isUnsigned() const;
+    void setUnsigned(bool isUnsigned);
+
+    bool isFriend() const;
+    void setFriend(bool isFriend);
+
+    bool isAuto() const;
+    void setAuto(bool isAuto);
+
+    bool isRegister() const;
+    void setRegister(bool isRegister);
+
+    bool isStatic() const;
+    void setStatic(bool isStatic);
+
+    bool isExtern() const;
+    void setExtern(bool isExtern);
+
+    bool isMutable() const;
+    void setMutable(bool isMutable);
+
+    bool isTypedef() const;
+    void setTypedef(bool isTypedef);
+
+    bool isInline() const;
+    void setInline(bool isInline);
+
+    bool isVirtual() const;
+    void setVirtual(bool isVirtual);
+
+    bool isOverride() const;
+    void setOverride(bool isOverride);
+
+    bool isFinal() const;
+    void setFinal(bool isFinal);
+
+    bool isExplicit() const;
+    void setExplicit(bool isExplicit);
+
+    bool isDeprecated() const;
+    void setDeprecated(bool isDeprecated);
+
+    bool isUnavailable() const;
+    void setUnavailable(bool isUnavailable);
+
+    Type &operator*();
+    const Type &operator*() const;
+
+    Type *operator->();
+    const Type *operator->() const;
+
+    bool operator == (const FullySpecifiedType &other) const;
+    bool operator != (const FullySpecifiedType &other) const;
+    bool operator < (const FullySpecifiedType &other) const;
+
+    bool match(const FullySpecifiedType &otherTy, Matcher *matcher = 0) const;
+
+    FullySpecifiedType simplified() const;
+
+    void copySpecifiers(const FullySpecifiedType &type);
+
+    unsigned flags() const;
+    void setFlags(unsigned flags);
+
+private:
+    Type *_type;
+    struct Flags {
+        // cv qualifiers
+        unsigned _isConst: 1;
+        unsigned _isVolatile: 1;
+
+        // sign
+        unsigned _isSigned: 1;
+        unsigned _isUnsigned: 1;
+
+        // storage class specifiers
+        unsigned _isFriend: 1;
+        unsigned _isAuto: 1;
+        unsigned _isRegister: 1;
+        unsigned _isStatic: 1;
+        unsigned _isExtern: 1;
+        unsigned _isMutable: 1;
+        unsigned _isTypedef: 1;
+
+        // function specifiers
+        unsigned _isInline: 1;
+        unsigned _isVirtual: 1;
+        unsigned _isOverride: 1;
+        unsigned _isFinal: 1;
+        unsigned _isExplicit: 1;
+
+        // speficiers from attributes
+        unsigned _isDeprecated: 1;
+        unsigned _isUnavailable: 1;
+    };
+    union {
+        unsigned _flags;
+        Flags f;
+    };
+};
+
+} // namespace CPlusPlus
+
+#endif // CPLUSPLUS_FULLYSPECIFIEDTYPE_H

+ 1862 - 0
Source/ToolCore/JSBind/cplusplus/Keywords.cpp

@@ -0,0 +1,1862 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "Lexer.h"
+#include "Token.h"
+
+namespace CPlusPlus {
+
+static inline int classify2(const char *s, LanguageFeatures)
+{
+  if (s[0] == 'd') {
+    if (s[1] == 'o') {
+      return T_DO;
+    }
+  }
+  else if (s[0] == 'i') {
+    if (s[1] == 'f') {
+      return T_IF;
+    }
+  }
+  return T_IDENTIFIER;
+}
+
+static inline int classify3(const char *s, LanguageFeatures features)
+{
+  if (s[0] == 'a') {
+    if (s[1] == 's') {
+      if (s[2] == 'm') {
+        return T_ASM;
+      }
+    }
+  }
+  else if (s[0] == 'f') {
+    if (s[1] == 'o') {
+      if (s[2] == 'r') {
+        return T_FOR;
+      }
+    }
+  }
+  else if (s[0] == 'i') {
+    if (s[1] == 'n') {
+      if (s[2] == 't') {
+        return T_INT;
+      }
+    }
+  }
+  else if (s[0] == 'n') {
+    if (s[1] == 'e') {
+      if (s[2] == 'w') {
+        return T_NEW;
+      }
+    }
+  }
+  else if (s[0] == 't') {
+    if (s[1] == 'r') {
+      if (s[2] == 'y') {
+        return T_TRY;
+      }
+    }
+  }
+  else if (features.qtMocRunEnabled && s[0] == 'Q') {
+    if (s[1] == '_') {
+      if (s[2] == 'D') {
+        return T_Q_D;
+      }
+      else if (s[2] == 'Q') {
+        return T_Q_Q;
+      }
+    }
+  }
+  return T_IDENTIFIER;
+}
+
+static inline int classify4(const char *s, LanguageFeatures features)
+{
+  if (s[0] == 'a') {
+    if (s[1] == 'u') {
+      if (s[2] == 't') {
+        if (s[3] == 'o') {
+          return T_AUTO;
+        }
+      }
+    }
+  }
+  else if (s[0] == 'b') {
+    if (s[1] == 'o') {
+      if (s[2] == 'o') {
+        if (s[3] == 'l') {
+          return T_BOOL;
+        }
+      }
+    }
+  }
+  else if (s[0] == 'c') {
+    if (s[1] == 'a') {
+      if (s[2] == 's') {
+        if (s[3] == 'e') {
+          return T_CASE;
+        }
+      }
+    }
+    else if (s[1] == 'h') {
+      if (s[2] == 'a') {
+        if (s[3] == 'r') {
+          return T_CHAR;
+        }
+      }
+    }
+  }
+  else if (s[0] == 'e') {
+    if (s[1] == 'l') {
+      if (s[2] == 's') {
+        if (s[3] == 'e') {
+          return T_ELSE;
+        }
+      }
+    }
+    else if (s[1] == 'n') {
+      if (s[2] == 'u') {
+        if (s[3] == 'm') {
+          return T_ENUM;
+        }
+      }
+    }
+    else if (features.qtKeywordsEnabled && s[1] == 'm') {
+      if (s[2] == 'i') {
+        if (s[3] == 't') {
+          return T_EMIT;
+        }
+      }
+    }
+  }
+  else if (s[0] == 'g') {
+    if (s[1] == 'o') {
+      if (s[2] == 't') {
+        if (s[3] == 'o') {
+          return T_GOTO;
+        }
+      }
+    }
+  }
+  else if (s[0] == 'l') {
+    if (s[1] == 'o') {
+      if (s[2] == 'n') {
+        if (s[3] == 'g') {
+          return T_LONG;
+        }
+      }
+    }
+  }
+  else if (s[0] == 't') {
+    if (s[1] == 'h') {
+      if (s[2] == 'i') {
+        if (s[3] == 's') {
+          return T_THIS;
+        }
+      }
+    }
+    else if (s[1] == 'r') {
+      if (s[2] == 'u') {
+        if (s[3] == 'e') {
+          return T_TRUE;
+        }
+      }
+    }
+  }
+  else if (s[0] == 'v') {
+    if (s[1] == 'o') {
+      if (s[2] == 'i') {
+        if (s[3] == 'd') {
+          return T_VOID;
+        }
+      }
+    }
+  }
+  else if (features.qtEnabled && s[0] == 'S') {
+    if (s[1] == 'L') {
+      if (s[2] == 'O') {
+        if (s[3] == 'T') {
+          return T_SLOT;
+        }
+      }
+    }
+  }
+  return T_IDENTIFIER;
+}
+
+static inline int classify5(const char *s, LanguageFeatures features)
+{
+  if (s[0] == '_') {
+    if (s[1] == '_') {
+      if (s[2] == 'a') {
+        if (s[3] == 's') {
+          if (s[4] == 'm') {
+            return T___ASM;
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'b') {
+    if (s[1] == 'r') {
+      if (s[2] == 'e') {
+        if (s[3] == 'a') {
+          if (s[4] == 'k') {
+            return T_BREAK;
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'c') {
+    if (s[1] == 'a') {
+      if (s[2] == 't') {
+        if (s[3] == 'c') {
+          if (s[4] == 'h') {
+            return T_CATCH;
+          }
+        }
+      }
+    }
+    else if (s[1] == 'l') {
+      if (s[2] == 'a') {
+        if (s[3] == 's') {
+          if (s[4] == 's') {
+            return T_CLASS;
+          }
+        }
+      }
+    }
+    else if (s[1] == 'o') {
+      if (s[2] == 'n') {
+        if (s[3] == 's') {
+          if (s[4] == 't') {
+            return T_CONST;
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'f') {
+    if (s[1] == 'a') {
+      if (s[2] == 'l') {
+        if (s[3] == 's') {
+          if (s[4] == 'e') {
+            return T_FALSE;
+          }
+        }
+      }
+    }
+    else if (s[1] == 'l') {
+      if (s[2] == 'o') {
+        if (s[3] == 'a') {
+          if (s[4] == 't') {
+            return T_FLOAT;
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 's') {
+    if (s[1] == 'h') {
+      if (s[2] == 'o') {
+        if (s[3] == 'r') {
+          if (s[4] == 't') {
+            return T_SHORT;
+          }
+        }
+      }
+    }
+    else if (features.qtKeywordsEnabled) {
+      if (s[1] == 'l') {
+        if (s[2] == 'o') {
+          if (s[3] == 't') {
+            if (s[4] == 's') {
+              return T_Q_SLOTS;
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 't') {
+    if (s[1] == 'h') {
+      if (s[2] == 'r') {
+        if (s[3] == 'o') {
+          if (s[4] == 'w') {
+            return T_THROW;
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'u') {
+    if (s[1] == 'n') {
+      if (s[2] == 'i') {
+        if (s[3] == 'o') {
+          if (s[4] == 'n') {
+            return T_UNION;
+          }
+        }
+      }
+    }
+    else if (s[1] == 's') {
+      if (s[2] == 'i') {
+        if (s[3] == 'n') {
+          if (s[4] == 'g') {
+            return T_USING;
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'w') {
+    if (s[1] == 'h') {
+      if (s[2] == 'i') {
+        if (s[3] == 'l') {
+          if (s[4] == 'e') {
+            return T_WHILE;
+          }
+        }
+      }
+    }
+  }
+  return T_IDENTIFIER;
+}
+
+static inline int classify6(const char *s, LanguageFeatures features)
+{
+  if (s[0] == 'd') {
+    if (s[1] == 'e') {
+      if (s[2] == 'l') {
+        if (s[3] == 'e') {
+          if (s[4] == 't') {
+            if (s[5] == 'e') {
+              return T_DELETE;
+            }
+          }
+        }
+      }
+    }
+    else if (s[1] == 'o') {
+      if (s[2] == 'u') {
+        if (s[3] == 'b') {
+          if (s[4] == 'l') {
+            if (s[5] == 'e') {
+              return T_DOUBLE;
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'e') {
+    if (s[1] == 'x') {
+      if (s[2] == 'p') {
+        if (s[3] == 'o') {
+          if (s[4] == 'r') {
+            if (s[5] == 't') {
+              return T_EXPORT;
+            }
+          }
+        }
+      }
+      else if (s[2] == 't') {
+        if (s[3] == 'e') {
+          if (s[4] == 'r') {
+            if (s[5] == 'n') {
+              return T_EXTERN;
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'f') {
+    if (s[1] == 'r') {
+      if (s[2] == 'i') {
+        if (s[3] == 'e') {
+          if (s[4] == 'n') {
+            if (s[5] == 'd') {
+              return T_FRIEND;
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'i') {
+    if (s[1] == 'n') {
+      if (s[2] == 'l') {
+        if (s[3] == 'i') {
+          if (s[4] == 'n') {
+            if (s[5] == 'e') {
+              return T_INLINE;
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'p') {
+    if (s[1] == 'u') {
+      if (s[2] == 'b') {
+        if (s[3] == 'l') {
+          if (s[4] == 'i') {
+            if (s[5] == 'c') {
+              return T_PUBLIC;
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'r') {
+    if (s[1] == 'e') {
+      if (s[2] == 't') {
+        if (s[3] == 'u') {
+          if (s[4] == 'r') {
+            if (s[5] == 'n') {
+              return T_RETURN;
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 's') {
+    if (s[1] == 'i') {
+      if (s[2] == 'g') {
+        if (s[3] == 'n') {
+          if (s[4] == 'e') {
+            if (s[5] == 'd') {
+              return T_SIGNED;
+            }
+          }
+        }
+      }
+      else if (s[2] == 'z') {
+        if (s[3] == 'e') {
+          if (s[4] == 'o') {
+            if (s[5] == 'f') {
+              return T_SIZEOF;
+            }
+          }
+        }
+      }
+    }
+    else if (s[1] == 't') {
+      if (s[2] == 'a') {
+        if (s[3] == 't') {
+          if (s[4] == 'i') {
+            if (s[5] == 'c') {
+              return T_STATIC;
+            }
+          }
+        }
+      }
+      else if (s[2] == 'r') {
+        if (s[3] == 'u') {
+          if (s[4] == 'c') {
+            if (s[5] == 't') {
+              return T_STRUCT;
+            }
+          }
+        }
+      }
+    }
+    else if (s[1] == 'w') {
+      if (s[2] == 'i') {
+        if (s[3] == 't') {
+          if (s[4] == 'c') {
+            if (s[5] == 'h') {
+              return T_SWITCH;
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 't') {
+    if (s[1] == 'y') {
+      if (s[2] == 'p') {
+        if (s[3] == 'e') {
+          if (s[4] == 'i') {
+            if (s[5] == 'd') {
+              return T_TYPEID;
+            }
+          }
+          else if (s[4] == 'o') {
+            if (s[5] == 'f') {
+              return T_TYPEOF;
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (features.qtKeywordsEnabled && s[0] == 'S') {
+    if (s[1] == 'I') {
+      if (s[2] == 'G') {
+        if (s[3] == 'N') {
+          if (s[4] == 'A') {
+            if (s[5] == 'L') {
+              return T_SIGNAL;
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (features.qtKeywordsEnabled && s[0] == 'Q') {
+    if (s[1] == '_') {
+      if (s[2] == 'S') {
+        if (s[3] == 'L') {
+          if (s[4] == 'O') {
+            if (s[5] == 'T') {
+              return T_Q_SLOT;
+            }
+          }
+        }
+      }
+      else if (s[2] == 'E') {
+        if (s[3] == 'M') {
+          if (s[4] == 'I') {
+            if (s[5] == 'T') {
+              return T_Q_EMIT;
+            }
+          }
+        }
+      }
+    }
+  }
+  return T_IDENTIFIER;
+}
+
+static inline int classify7(const char *s, LanguageFeatures features)
+{
+  if (s[0] == '_') {
+    if (s[1] == '_') {
+      if (s[2] == 'a') {
+        if (s[3] == 's') {
+          if (s[4] == 'm') {
+            if (s[5] == '_') {
+              if (s[6] == '_') {
+                return T___ASM__;
+              }
+            }
+          }
+        }
+      }
+      else if (s[2] == 'c') {
+        if (s[3] == 'o') {
+          if (s[4] == 'n') {
+            if (s[5] == 's') {
+              if (s[6] == 't') {
+                return T___CONST;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (features.cxx11Enabled && s[0] == 'a') {
+    if (s[1] == 'l') {
+      if (s[2] == 'i') {
+        if (s[3] == 'g') {
+          if (s[4] == 'n') {
+            if (s[5] == 'a') {
+              if (s[6] == 's') {
+                return T_ALIGNAS;
+              }
+            }
+            else if (s[5] == 'o') {
+              if (s[6] == 'f') {
+                return T_ALIGNOF;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'd') {
+    if (s[1] == 'e') {
+      if (s[2] == 'f') {
+        if (s[3] == 'a') {
+          if (s[4] == 'u') {
+            if (s[5] == 'l') {
+              if (s[6] == 't') {
+                return T_DEFAULT;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'm') {
+    if (s[1] == 'u') {
+      if (s[2] == 't') {
+        if (s[3] == 'a') {
+          if (s[4] == 'b') {
+            if (s[5] == 'l') {
+              if (s[6] == 'e') {
+                return T_MUTABLE;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (features.cxx11Enabled && s[0] == 'n') {
+    if (s[1] == 'u') {
+      if (s[2] == 'l') {
+        if (s[3] == 'l') {
+          if (s[4] == 'p') {
+            if (s[5] == 't') {
+              if (s[6] == 'r') {
+                return T_NULLPTR;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'p') {
+    if (s[1] == 'r') {
+      if (s[2] == 'i') {
+        if (s[3] == 'v') {
+          if (s[4] == 'a') {
+            if (s[5] == 't') {
+              if (s[6] == 'e') {
+                return T_PRIVATE;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (features.qtKeywordsEnabled && s[0] == 'f') {
+    if (s[1] == 'o') {
+      if (s[2] == 'r') {
+        if (s[3] == 'e') {
+          if (s[4] == 'a') {
+            if (s[5] == 'c') {
+              if (s[6] == 'h') {
+                return T_Q_FOREACH;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (features.qtEnabled && s[0] == 's') {
+    if (s[1] == 'i') {
+      if (s[2] == 'g') {
+        if (s[3] == 'n') {
+          if (s[4] == 'a') {
+            if (s[5] == 'l') {
+              if (s[6] == 's') {
+                return T_Q_SIGNALS;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 't') {
+    if (s[1] == 'y') {
+      if (s[2] == 'p') {
+        if (s[3] == 'e') {
+          if (s[4] == 'd') {
+            if (s[5] == 'e') {
+              if (s[6] == 'f') {
+                return T_TYPEDEF;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'v') {
+    if (s[1] == 'i') {
+      if (s[2] == 'r') {
+        if (s[3] == 't') {
+          if (s[4] == 'u') {
+            if (s[5] == 'a') {
+              if (s[6] == 'l') {
+                return T_VIRTUAL;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'w') {
+    if (s[1] == 'c') {
+      if (s[2] == 'h') {
+        if (s[3] == 'a') {
+          if (s[4] == 'r') {
+            if (s[5] == '_') {
+              if (s[6] == 't') {
+                return T_WCHAR_T;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (features.qtEnabled && s[0] == 'Q') {
+    if (s[1] == '_') {
+      if (s[2] == 'S') {
+        if (s[3] == 'L') {
+          if (s[4] == 'O') {
+            if (s[5] == 'T') {
+              if (s[6] == 'S') {
+                return T_Q_SLOTS;
+              }
+            }
+          }
+        }
+      }
+      else if (s[2] == 'E') {
+        if (s[3] == 'N') {
+          if (s[4] == 'U') {
+            if (s[5] == 'M') {
+              if (s[6] == 'S') {
+                return T_Q_ENUMS;
+              }
+            }
+          }
+        }
+      }
+      else if (s[2] == 'F') {
+        if (s[3] == 'L') {
+          if (s[4] == 'A') {
+            if (s[5] == 'G') {
+              if (s[6] == 'S') {
+                return T_Q_FLAGS;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  return T_IDENTIFIER;
+}
+
+static inline int classify8(const char *s, LanguageFeatures features)
+{
+  if (s[0] == '_') {
+    if (s[1] == '_') {
+      if (s[2] == 'i') {
+        if (s[3] == 'n') {
+          if (s[4] == 'l') {
+            if (s[5] == 'i') {
+              if (s[6] == 'n') {
+                if (s[7] == 'e') {
+                  return T___INLINE;
+                }
+              }
+            }
+          }
+        }
+      }
+      else if (s[2] == 't') {
+        if (s[3] == 'y') {
+          if (s[4] == 'p') {
+            if (s[5] == 'e') {
+              if (s[6] == 'o') {
+                if (s[7] == 'f') {
+                  return T___TYPEOF;
+                }
+              }
+            }
+          }
+        }
+        else if (s[3] == 'h') {
+          if (s[4] == 'r') {
+            if (s[5] == 'e') {
+              if (s[6] == 'a') {
+                if (s[7] == 'd') {
+                  return T___THREAD;
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'c') {
+    if (s[1] == 'o') {
+      if (s[2] == 'n') {
+        if (s[3] == 't') {
+          if (s[4] == 'i') {
+            if (s[5] == 'n') {
+              if (s[6] == 'u') {
+                if (s[7] == 'e') {
+                  return T_CONTINUE;
+                }
+              }
+            }
+          }
+        }
+      }
+    } else if (features.cxx11Enabled && s[1] == 'h') {
+        if (s[2] == 'a') {
+            if (s[3] == 'r') {
+                if (s[4] == '1') {
+                    if (s[5] == '6') {
+                        if (s[6] == '_') {
+                            if (s[7] == 't') {
+                                return T_CHAR16_T;
+                            }
+                        }
+                    }
+                } else if (s[4] == '3') {
+                    if (s[5] == '2') {
+                        if (s[6] == '_') {
+                            if (s[7] == 't') {
+                                return T_CHAR32_T;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+  }
+  else if (features.cxx11Enabled && s[0] == 'd') {
+    if (s[1] == 'e') {
+      if (s[2] == 'c') {
+        if (s[3] == 'l') {
+          if (s[4] == 't') {
+            if (s[5] == 'y') {
+              if (s[6] == 'p') {
+                if (s[7] == 'e') {
+                  return T_DECLTYPE;
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'e') {
+    if (s[1] == 'x') {
+      if (s[2] == 'p') {
+        if (s[3] == 'l') {
+          if (s[4] == 'i') {
+            if (s[5] == 'c') {
+              if (s[6] == 'i') {
+                if (s[7] == 't') {
+                  return T_EXPLICIT;
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (features.cxx11Enabled && s[0] == 'n') {
+    if (s[1] == 'o') {
+      if (s[2] == 'e') {
+        if (s[3] == 'x') {
+          if (s[4] == 'c') {
+            if (s[5] == 'e') {
+              if (s[6] == 'p') {
+                if (s[7] == 't') {
+                  return T_NOEXCEPT;
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'o') {
+    if (s[1] == 'p') {
+      if (s[2] == 'e') {
+        if (s[3] == 'r') {
+          if (s[4] == 'a') {
+            if (s[5] == 't') {
+              if (s[6] == 'o') {
+                if (s[7] == 'r') {
+                  return T_OPERATOR;
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'r') {
+    if (s[1] == 'e') {
+      if (s[2] == 'g') {
+        if (s[3] == 'i') {
+          if (s[4] == 's') {
+            if (s[5] == 't') {
+              if (s[6] == 'e') {
+                if (s[7] == 'r') {
+                  return T_REGISTER;
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 't') {
+    if (s[1] == 'e') {
+      if (s[2] == 'm') {
+        if (s[3] == 'p') {
+          if (s[4] == 'l') {
+            if (s[5] == 'a') {
+              if (s[6] == 't') {
+                if (s[7] == 'e') {
+                  return T_TEMPLATE;
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+    else if (s[1] == 'y') {
+      if (s[2] == 'p') {
+        if (s[3] == 'e') {
+          if (s[4] == 'n') {
+            if (s[5] == 'a') {
+              if (s[6] == 'm') {
+                if (s[7] == 'e') {
+                  return T_TYPENAME;
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'u') {
+    if (s[1] == 'n') {
+      if (s[2] == 's') {
+        if (s[3] == 'i') {
+          if (s[4] == 'g') {
+            if (s[5] == 'n') {
+              if (s[6] == 'e') {
+                if (s[7] == 'd') {
+                  return T_UNSIGNED;
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'v') {
+    if (s[1] == 'o') {
+      if (s[2] == 'l') {
+        if (s[3] == 'a') {
+          if (s[4] == 't') {
+            if (s[5] == 'i') {
+              if (s[6] == 'l') {
+                if (s[7] == 'e') {
+                  return T_VOLATILE;
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (features.qtEnabled && s[0] == 'Q') {
+    if (s[1] == '_') {
+      if (s[2] == 'G') {
+        if (s[3] == 'A') {
+          if (s[4] == 'D') {
+            if (s[5] == 'G') {
+              if (s[6] == 'E') {
+                if (s[7] == 'T') {
+                  return T_Q_GADGET;
+                }
+              }
+            }
+          }
+        }
+      }
+      else if (s[2] == 'O') {
+        if (s[3] == 'B') {
+          if (s[4] == 'J') {
+            if (s[5] == 'E') {
+              if (s[6] == 'C') {
+                if (s[7] == 'T') {
+                  return T_Q_OBJECT;
+                }
+              }
+            }
+          }
+        }
+      }
+      else if (s[2] == 'S') {
+        if (s[3] == 'I') {
+          if (s[4] == 'G') {
+            if (s[5] == 'N') {
+              if (s[6] == 'A') {
+                if (s[7] == 'L') {
+                  return T_Q_SIGNAL;
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  return T_IDENTIFIER;
+}
+
+static inline int classify9(const char *s, LanguageFeatures features)
+{
+  if (s[0] == '_') {
+    if (s[1] == '_') {
+      if (s[2] == 'c') {
+        if (s[3] == 'o') {
+          if (s[4] == 'n') {
+            if (s[5] == 's') {
+              if (s[6] == 't') {
+                if (s[7] == '_') {
+                  if (s[8] == '_') {
+                    return T___CONST__;
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (features.cxx11Enabled && s[0] == 'c') {
+    if (s[1] == 'o') {
+      if (s[2] == 'n') {
+        if (s[3] == 's') {
+          if (s[4] == 't') {
+            if (s[5] == 'e') {
+              if (s[6] == 'x') {
+                if (s[7] == 'p') {
+                  if (s[8] == 'r') {
+                    return T_CONSTEXPR;
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'n') {
+    if (s[1] == 'a') {
+      if (s[2] == 'm') {
+        if (s[3] == 'e') {
+          if (s[4] == 's') {
+            if (s[5] == 'p') {
+              if (s[6] == 'a') {
+                if (s[7] == 'c') {
+                  if (s[8] == 'e') {
+                    return T_NAMESPACE;
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'p') {
+    if (s[1] == 'r') {
+      if (s[2] == 'o') {
+        if (s[3] == 't') {
+          if (s[4] == 'e') {
+            if (s[5] == 'c') {
+              if (s[6] == 't') {
+                if (s[7] == 'e') {
+                  if (s[8] == 'd') {
+                    return T_PROTECTED;
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (features.qtEnabled && s[0] == 'Q') {
+    if (s[1] == '_') {
+      if (s[2] == 'S') {
+        if (s[3] == 'I') {
+          if (s[4] == 'G') {
+            if (s[5] == 'N') {
+              if (s[6] == 'A') {
+                if (s[7] == 'L') {
+                  if (s[8] == 'S') {
+                    return T_Q_SIGNALS;
+                  }
+                }
+              }
+            }
+          }
+        }
+      } else if (s[2] == 'F') {
+        if (s[3] == 'O') {
+          if (s[4] == 'R') {
+            if (s[5] == 'E') {
+              if (s[6] == 'A') {
+                if (s[7] == 'C') {
+                  if (s[8] == 'H') {
+                    return T_Q_FOREACH;
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  return T_IDENTIFIER;
+}
+
+static inline int classify10(const char *s, LanguageFeatures features)
+{
+  if (s[0] == '_') {
+    if (s[1] == '_') {
+      if (s[2] == 'i') {
+        if (s[3] == 'n') {
+          if (s[4] == 'l') {
+            if (s[5] == 'i') {
+              if (s[6] == 'n') {
+                if (s[7] == 'e') {
+                  if (s[8] == '_') {
+                    if (s[9] == '_') {
+                      return T___INLINE__;
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      else if (s[2] == 'd') {
+        if (s[3] == 'e') {
+          if (s[4] == 'c') {
+            if (s[5] == 'l') {
+              if (s[6] == 't') {
+                if (s[7] == 'y') {
+                  if (s[8] == 'p') {
+                    if (s[9] == 'e') {
+                      return T___DECLTYPE;
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      else if (s[2] == 't') {
+        if (s[3] == 'y') {
+          if (s[4] == 'p') {
+            if (s[5] == 'e') {
+              if (s[6] == 'o') {
+                if (s[7] == 'f') {
+                  if (s[8] == '_') {
+                    if (s[9] == '_') {
+                      return T___TYPEOF__;
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      else if (s[2] == 'v') {
+        if (s[3] == 'o') {
+          if (s[4] == 'l') {
+            if (s[5] == 'a') {
+              if (s[6] == 't') {
+                if (s[7] == 'i') {
+                  if (s[8] == 'l') {
+                    if (s[9] == 'e') {
+                      return T___VOLATILE;
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'c') {
+    if (s[1] == 'o') {
+      if (s[2] == 'n') {
+        if (s[3] == 's') {
+          if (s[4] == 't') {
+            if (s[5] == '_') {
+              if (s[6] == 'c') {
+                if (s[7] == 'a') {
+                  if (s[8] == 's') {
+                    if (s[9] == 't') {
+                      return T_CONST_CAST;
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (features.qtEnabled && s[0] == 'Q') {
+    if (s[1] == '_') {
+      if (s[2] == 'O') {
+        if (s[3] == 'V') {
+          if (s[4] == 'E') {
+            if (s[5] == 'R') {
+              if (s[6] == 'R') {
+                if (s[7] == 'I') {
+                  if (s[8] == 'D') {
+                    if (s[9] == 'E') {
+                      return T_Q_PROPERTY; // Q_OVERRIDE is just an alias for Q_PROPERTY
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      else if (s[2] == 'P') {
+        if (s[3] == 'R') {
+          if (s[4] == 'O') {
+            if (s[5] == 'P') {
+              if (s[6] == 'E') {
+                if (s[7] == 'R') {
+                  if (s[8] == 'T') {
+                    if (s[9] == 'Y') {
+                      return T_Q_PROPERTY;
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  return T_IDENTIFIER;
+}
+
+static inline int classify11(const char *s, LanguageFeatures features)
+{
+  if (s[0] == '_') {
+    if (s[1] == '_') {
+      if (s[2] == 'a') {
+        if (s[3] == 't') {
+          if (s[4] == 't') {
+            if (s[5] == 'r') {
+              if (s[6] == 'i') {
+                if (s[7] == 'b') {
+                  if (s[8] == 'u') {
+                    if (s[9] == 't') {
+                      if (s[10] == 'e') {
+                        return T___ATTRIBUTE;
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 's') {
+    if (s[1] == 't') {
+      if (s[2] == 'a') {
+        if (s[3] == 't') {
+          if (s[4] == 'i') {
+            if (s[5] == 'c') {
+              if (s[6] == '_') {
+                if (s[7] == 'c') {
+                  if (s[8] == 'a') {
+                    if (s[9] == 's') {
+                      if (s[10] == 't') {
+                        return T_STATIC_CAST;
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (features.qtEnabled && s[0] == 'Q') {
+    if (s[1] == '_') {
+      if (s[2] == 'I') {
+        if (s[3] == 'N') {
+          if (s[4] == 'V') {
+            if (s[5] == 'O') {
+              if (s[6] == 'K') {
+                if (s[7] == 'A') {
+                  if (s[8] == 'B') {
+                    if (s[9] == 'L') {
+                      if (s[10] == 'E') {
+                        return T_Q_INVOKABLE;
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  return T_IDENTIFIER;
+}
+
+static inline int classify12(const char *s, LanguageFeatures features)
+{
+  if (s[0] == '_') {
+    if (s[1] == '_') {
+      if (s[2] == 'v') {
+        if (s[3] == 'o') {
+          if (s[4] == 'l') {
+            if (s[5] == 'a') {
+              if (s[6] == 't') {
+                if (s[7] == 'i') {
+                  if (s[8] == 'l') {
+                    if (s[9] == 'e') {
+                      if (s[10] == '_') {
+                        if (s[11] == '_') {
+                          return T___VOLATILE__;
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (features.qtEnabled && s[0] == 'Q') {
+    if (s[1] == '_') {
+      if (s[2] == 'I') {
+        if (s[3] == 'N') {
+          if (s[4] == 'T') {
+            if (s[5] == 'E') {
+              if (s[6] == 'R') {
+                if (s[7] == 'F') {
+                  if (s[8] == 'A') {
+                    if (s[9] == 'C') {
+                      if (s[10] == 'E') {
+                        if (s[11] == 'S') {
+                          return T_Q_INTERFACES;
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'd') {
+    if (s[1] == 'y') {
+      if (s[2] == 'n') {
+        if (s[3] == 'a') {
+          if (s[4] == 'm') {
+            if (s[5] == 'i') {
+              if (s[6] == 'c') {
+                if (s[7] == '_') {
+                  if (s[8] == 'c') {
+                    if (s[9] == 'a') {
+                      if (s[10] == 's') {
+                        if (s[11] == 't') {
+                          return T_DYNAMIC_CAST;
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (features.cxx11Enabled && s[0] == 't') {
+    if (s[1] == 'h') {
+      if (s[2] == 'r') {
+        if (s[3] == 'e') {
+          if (s[4] == 'a') {
+            if (s[5] == 'd') {
+              if (s[6] == '_') {
+                if (s[7] == 'l') {
+                  if (s[8] == 'o') {
+                    if (s[9] == 'c') {
+                      if (s[10] == 'a') {
+                        if (s[11] == 'l') {
+                          return T_THREAD_LOCAL;
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  return T_IDENTIFIER;
+}
+
+static inline int classify13(const char *s, LanguageFeatures features)
+{
+  if (s[0] == '_') {
+    if (s[1] == '_') {
+      if (s[2] == 'a') {
+        if (s[3] == 't') {
+          if (s[4] == 't') {
+            if (s[5] == 'r') {
+              if (s[6] == 'i') {
+                if (s[7] == 'b') {
+                  if (s[8] == 'u') {
+                    if (s[9] == 't') {
+                      if (s[10] == 'e') {
+                        if (s[11] == '_') {
+                          if (s[12] == '_') {
+                            return T___ATTRIBUTE__;
+                          }
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  } else if (features.cxx11Enabled && s[0] == 's') {
+    if (s[1] == 't') {
+      if (s[2] == 'a') {
+        if (s[3] == 't') {
+          if (s[4] == 'i') {
+            if (s[5] == 'c') {
+              if (s[6] == '_') {
+                if (s[7] == 'a') {
+                  if (s[8] == 's') {
+                    if (s[9] == 's') {
+                      if (s[10] == 'e') {
+                        if (s[11] == 'r') {
+                          if (s[12] == 't') {
+                            return T_STATIC_ASSERT;
+                          }
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  return T_IDENTIFIER;
+}
+
+static inline int classify16(const char *s, LanguageFeatures)
+{
+  if (s[0] == 'r') {
+    if (s[1] == 'e') {
+      if (s[2] == 'i') {
+        if (s[3] == 'n') {
+          if (s[4] == 't') {
+            if (s[5] == 'e') {
+              if (s[6] == 'r') {
+                if (s[7] == 'p') {
+                  if (s[8] == 'r') {
+                    if (s[9] == 'e') {
+                      if (s[10] == 't') {
+                        if (s[11] == '_') {
+                          if (s[12] == 'c') {
+                            if (s[13] == 'a') {
+                              if (s[14] == 's') {
+                                if (s[15] == 't') {
+                                  return T_REINTERPRET_CAST;
+                                }
+                              }
+                            }
+                          }
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  return T_IDENTIFIER;
+}
+
+static inline int classify14(const char *s, LanguageFeatures features)
+{
+  if (features.qtEnabled && s[0] == 'Q') {
+    if (s[1] == '_') {
+      if (s[2] == 'P') {
+        if (s[3] == 'R') {
+          if (s[4] == 'I') {
+            if (s[5] == 'V') {
+              if (s[6] == 'A') {
+                if (s[7] == 'T') {
+                  if (s[8] == 'E') {
+                    if (s[9] == '_') {
+                      if (s[10] == 'S') {
+                        if (s[11] == 'L') {
+                          if (s[12] == 'O') {
+                            if (s[13] == 'T') {
+                              return T_Q_PRIVATE_SLOT;
+                            }
+                          }
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  return T_IDENTIFIER;
+}
+
+static inline int classify18(const char *s, LanguageFeatures features)
+{
+  if (features.qtEnabled && s[0] == 'Q') {
+    if (s[1] == '_') {
+      if (s[2] == 'P') {
+        if (s[3] == 'R') {
+          if (s[4] == 'I') {
+            if (s[5] == 'V') {
+              if (s[6] == 'A') {
+                if (s[7] == 'T') {
+                  if (s[8] == 'E') {
+                    if (s[9] == '_') {
+                      if (s[10] == 'P') {
+                        if (s[11] == 'R') {
+                          if (s[12] == 'O') {
+                            if (s[13] == 'P') {
+                              if (s[14] == 'E') {
+                                if (s[15] == 'R') {
+                                  if (s[16] == 'T') {
+                                    if (s[17] == 'Y') {
+                                      return T_Q_PRIVATE_PROPERTY;
+                                    }
+                                  }
+                                }
+                              }
+                            }
+                          }
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  return T_IDENTIFIER;
+}
+
+static inline int classify19(const char *s, LanguageFeatures features)
+{
+  if (features.qtEnabled && s[0] == 'Q') {
+    if (s[1] == '_') {
+      if (s[2] == 'D') {
+        if (s[3] == 'E') {
+          if (s[4] == 'C') {
+            if (s[5] == 'L') {
+              if (s[6] == 'A') {
+                if (s[7] == 'R') {
+                  if (s[8] == 'E') {
+                    if (s[9] == '_') {
+                      if (s[10] == 'I') {
+                        if (s[11] == 'N') {
+                          if (s[12] == 'T') {
+                            if (s[13] == 'E') {
+                              if (s[14] == 'R') {
+                                if (s[15] == 'F') {
+                                  if (s[16] == 'A') {
+                                    if (s[17] == 'C') {
+                                      if (s[18] == 'E') {
+                                        return T_Q_DECLARE_INTERFACE;
+                                      }
+                                    }
+                                  }
+                                }
+                              }
+                            }
+                          }
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  return T_IDENTIFIER;
+}
+
+
+int Lexer::classify(const char *s, int n, LanguageFeatures features) {
+  switch (n) {
+    case 2: return classify2(s, features);
+    case 3: return classify3(s, features);
+    case 4: return classify4(s, features);
+    case 5: return classify5(s, features);
+    case 6: return classify6(s, features);
+    case 7: return classify7(s, features);
+    case 8: return classify8(s, features);
+    case 9: return classify9(s, features);
+    case 10: return classify10(s, features);
+    case 11: return classify11(s, features);
+    case 12: return classify12(s, features);
+    case 13: return classify13(s, features);
+    case 14: return classify14(s, features);
+    case 16: return classify16(s, features);
+    case 18: return classify18(s, features);
+    case 19: return classify19(s, features);
+    default: return T_IDENTIFIER;
+  } // switch
+}
+
+static inline int classifyOperator2(const char *s) {
+  if (s[0] == 'o') {
+    if (s[1] == 'r') {
+      return T_OR;
+    }
+  }
+  return T_IDENTIFIER;
+}
+
+static inline int classifyOperator3(const char *s) {
+  if (s[0] == 'a') {
+    if (s[1] == 'n') {
+      if (s[2] == 'd') {
+        return T_AND;
+      }
+    }
+  }
+  else if (s[0] == 'n') {
+    if (s[1] == 'o') {
+      if (s[2] == 't') {
+        return T_NOT;
+      }
+    }
+  }
+  else if (s[0] == 'x') {
+    if (s[1] == 'o') {
+      if (s[2] == 'r') {
+        return T_XOR;
+      }
+    }
+  }
+  return T_IDENTIFIER;
+}
+
+static inline int classifyOperator5(const char *s) {
+  if (s[0] == 'b') {
+    if (s[1] == 'i') {
+      if (s[2] == 't') {
+        if (s[3] == 'o') {
+          if (s[4] == 'r') {
+            return T_BITOR;
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'c') {
+    if (s[1] == 'o') {
+      if (s[2] == 'm') {
+        if (s[3] == 'p') {
+          if (s[4] == 'l') {
+            return T_COMPL;
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'o') {
+    if (s[1] == 'r') {
+      if (s[2] == '_') {
+        if (s[3] == 'e') {
+          if (s[4] == 'q') {
+            return T_OR_EQ;
+          }
+        }
+      }
+    }
+  }
+  return T_IDENTIFIER;
+}
+
+static inline int classifyOperator6(const char *s) {
+  if (s[0] == 'a') {
+    if (s[1] == 'n') {
+      if (s[2] == 'd') {
+        if (s[3] == '_') {
+          if (s[4] == 'e') {
+            if (s[5] == 'q') {
+              return T_AND_EQ;
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'b') {
+    if (s[1] == 'i') {
+      if (s[2] == 't') {
+        if (s[3] == 'a') {
+          if (s[4] == 'n') {
+            if (s[5] == 'd') {
+              return T_BITAND;
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'n') {
+    if (s[1] == 'o') {
+      if (s[2] == 't') {
+        if (s[3] == '_') {
+          if (s[4] == 'e') {
+            if (s[5] == 'q') {
+              return T_NOT_EQ;
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'x') {
+    if (s[1] == 'o') {
+      if (s[2] == 'r') {
+        if (s[3] == '_') {
+          if (s[4] == 'e') {
+            if (s[5] == 'q') {
+              return T_XOR_EQ;
+            }
+          }
+        }
+      }
+    }
+  }
+  return T_IDENTIFIER;
+}
+
+int Lexer::classifyOperator(const char *s, int n) {
+  switch (n) {
+    case 2: return classifyOperator2(s);
+    case 3: return classifyOperator3(s);
+    case 5: return classifyOperator5(s);
+    case 6: return classifyOperator6(s);
+    default: return T_IDENTIFIER;
+  } // switch
+}
+
+
+} // namespace CPlusPlus

+ 86 - 0
Source/ToolCore/JSBind/cplusplus/Keywords.kwgen

@@ -0,0 +1,86 @@
+
+#include "Lexer.h"
+#include "Token.h"
+
+%token-prefix=T_
+%toupper
+%no-enums
+%namespace=Lexer
+
+%%
+__asm
+__asm__
+__attribute
+__attribute__
+__const
+__const__
+__inline
+__inline__
+__typeof
+__typeof__
+__volatile
+__volatile__
+asm
+auto
+bool
+break
+case
+catch
+char
+class
+const
+const_cast
+continue
+default
+delete
+do
+double
+dynamic_cast
+else
+enum
+explicit
+export
+extern
+false
+float
+for
+friend
+goto
+if
+inline
+int
+long
+mutable
+namespace
+new
+operator
+private
+protected
+public
+register
+reinterpret_cast
+return
+short
+signed
+sizeof
+static
+static_cast
+struct
+switch
+template
+this
+throw
+true
+try
+typedef
+typeid
+typename
+typeof
+union
+unsigned
+using
+virtual
+void
+volatile
+wchar_t
+while

+ 855 - 0
Source/ToolCore/JSBind/cplusplus/Lexer.cpp

@@ -0,0 +1,855 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "Lexer.h"
+#include "Control.h"
+#include "TranslationUnit.h"
+#include "Literals.h"
+
+#include "cppassert.h"
+
+#include <cctype>
+
+using namespace CPlusPlus;
+
+/*!
+    \class Lexer
+    \brief The Lexer generates tokens from an UTF-8 encoded source text.
+
+    \sa Token
+*/
+
+/*!
+    \fn static void Lexer::yyinp_utf8(const char *&currentSourceChar, unsigned char &yychar, unsigned &utf16charCounter)
+
+    Process a single unicode code point in an UTF-8 encoded source.
+
+    \a currentSourceChar points to the UTF-8 encoded source.
+    \a yychar must be the byte pointed to by \a currentSourceChar.
+
+    Points \a currentSourceChar to the byte of the next code point
+    and modifies \a yychar to the value pointed by the updated
+    \a currentSourceChar. \a utf16charCounter will be incremented by
+    the number of UTF-16 code units that were needed for that code
+    point.
+*/
+
+Lexer::Lexer(TranslationUnit *unit)
+    : _translationUnit(unit),
+      _control(unit->control()),
+      _state(0),
+      _flags(0),
+      _currentLine(1)
+{
+    f._scanKeywords = true;
+    setSource(_translationUnit->firstSourceChar(),
+              _translationUnit->lastSourceChar());
+}
+
+Lexer::Lexer(const char *firstChar, const char *lastChar)
+    : _translationUnit(0),
+      _control(0),
+      _state(0),
+      _flags(0),
+      _currentLine(1)
+{
+    f._scanKeywords = true;
+    setSource(firstChar, lastChar);
+}
+
+Lexer::~Lexer()
+{ }
+
+TranslationUnit *Lexer::translationUnit() const
+{ return _translationUnit; }
+
+void Lexer::setSource(const char *firstChar, const char *lastChar)
+{
+    _firstChar = firstChar;
+    _lastChar = lastChar;
+    _currentChar = _firstChar - 1;
+    _currentCharUtf16 = -1;
+    _tokenStart = _currentChar;
+    _yychar = '\n';
+}
+
+void Lexer::setStartWithNewline(bool enabled)
+{
+    if (enabled)
+        _yychar = '\n';
+    else
+        _yychar = ' ';
+}
+
+int Lexer::state() const
+{ return _state; }
+
+void Lexer::setState(int state)
+{ _state = state; }
+
+bool Lexer::scanCommentTokens() const
+{ return f._scanCommentTokens; }
+
+void Lexer::setScanCommentTokens(bool onoff)
+{ f._scanCommentTokens = onoff; }
+
+bool Lexer::scanKeywords() const
+{ return f._scanKeywords; }
+
+void Lexer::setScanKeywords(bool onoff)
+{ f._scanKeywords = onoff; }
+
+void Lexer::setScanAngleStringLiteralTokens(bool onoff)
+{ f._scanAngleStringLiteralTokens = onoff; }
+
+void Lexer::pushLineStartOffset()
+{
+    ++_currentLine;
+
+    if (_translationUnit)
+        _translationUnit->pushLineOffset(_currentCharUtf16);
+}
+
+void Lexer::scan(Token *tok)
+{
+    tok->reset();
+    scan_helper(tok);
+    tok->f.bytes = _currentChar - _tokenStart;
+    tok->f.utf16chars = _currentCharUtf16 - _tokenStartUtf16;
+}
+
+void Lexer::scan_helper(Token *tok)
+{
+  again:
+    while (_yychar && std::isspace(_yychar)) {
+        if (_yychar == '\n') {
+            tok->f.joined = s._newlineExpected;
+            tok->f.newline = !s._newlineExpected;
+
+            if (s._newlineExpected) {
+                s._newlineExpected = false;
+            } else {
+                switch (s._tokenKind) {
+                case T_EOF_SYMBOL:
+                case T_COMMENT:
+                case T_DOXY_COMMENT:
+                    break; // multiline tokens, don't break on newline
+                default: // Strings and C++ comments
+                    _state = 0;
+                }
+            }
+        } else {
+            tok->f.whitespace = true;
+        }
+        yyinp();
+    }
+
+    if (! _translationUnit)
+        tok->lineno = _currentLine;
+
+    _tokenStart = _currentChar;
+    tok->byteOffset = _currentChar - _firstChar;
+
+    _tokenStartUtf16 = _currentCharUtf16;
+    tok->utf16charOffset = _currentCharUtf16;
+
+    if (_yychar) {
+        s._newlineExpected = false;
+    } else if (s._tokenKind) {
+        tok->f.kind = T_EOF_SYMBOL;
+        return;
+    }
+
+    switch (s._tokenKind) {
+    case T_EOF_SYMBOL:
+        break;
+    case T_COMMENT:
+    case T_DOXY_COMMENT: {
+        const int originalKind = s._tokenKind;
+
+        while (_yychar) {
+            if (_yychar != '*')
+                yyinp();
+            else {
+                yyinp();
+                if (_yychar == '/') {
+                    yyinp();
+                    _state = 0;
+                    break;
+                }
+            }
+        }
+
+        if (! f._scanCommentTokens)
+            goto again;
+
+        tok->f.kind = originalKind;
+        return; // done
+    }
+    case T_CPP_COMMENT:
+    case T_CPP_DOXY_COMMENT: {
+        const Kind originalKind = (Kind)s._tokenKind;
+        tok->f.joined = true;
+        if (f._scanCommentTokens)
+            tok->f.kind = originalKind;
+        _state = 0;
+        scanCppComment(originalKind);
+        return;
+    }
+    default: // Strings
+        tok->f.joined = true;
+        tok->f.kind = s._tokenKind;
+        _state = 0;
+        scanUntilQuote(tok, '"');
+        return;
+    }
+
+    if (! _yychar) {
+        tok->f.kind = T_EOF_SYMBOL;
+        return;
+    }
+
+    unsigned char ch = _yychar;
+    yyinp();
+
+    switch (ch) {
+    case '\\':
+        s._newlineExpected = true;
+        goto again;
+
+    case '"':
+        scanStringLiteral(tok);
+        break;
+
+    case '\'':
+        scanCharLiteral(tok);
+        break;
+
+    case '{':
+        tok->f.kind = T_LBRACE;
+        break;
+
+    case '}':
+        tok->f.kind = T_RBRACE;
+        break;
+
+    case '[':
+        tok->f.kind = T_LBRACKET;
+        break;
+
+    case ']':
+        tok->f.kind = T_RBRACKET;
+        break;
+
+    case '#':
+        if (_yychar == '#') {
+            tok->f.kind = T_POUND_POUND;
+            yyinp();
+        } else {
+            tok->f.kind = T_POUND;
+        }
+        break;
+
+    case '(':
+        tok->f.kind = T_LPAREN;
+        break;
+
+    case ')':
+        tok->f.kind = T_RPAREN;
+        break;
+
+    case ';':
+        tok->f.kind = T_SEMICOLON;
+        break;
+
+    case ':':
+        if (_yychar == ':') {
+            yyinp();
+            tok->f.kind = T_COLON_COLON;
+        } else if (_yychar == '>') {
+            yyinp();
+            tok->f.kind = T_RBRACKET;
+        } else {
+            tok->f.kind = T_COLON;
+        }
+        break;
+
+    case '.':
+        if (_yychar == '*') {
+            yyinp();
+            tok->f.kind = T_DOT_STAR;
+        } else if (_yychar == '.') {
+            yyinp();
+            // ### CPP_CHECK(_yychar);
+            if (_yychar == '.') {
+                yyinp();
+                tok->f.kind = T_DOT_DOT_DOT;
+            } else {
+                tok->f.kind = T_ERROR;
+            }
+        } else if (std::isdigit(_yychar)) {
+            const char *yytext = _currentChar - 2;
+            do {
+                if (_yychar == 'e' || _yychar == 'E') {
+                    yyinp();
+                    if (_yychar == '-' || _yychar == '+') {
+                        yyinp();
+                        // ### CPP_CHECK(std::isdigit(_yychar));
+                    }
+                } else if (std::isalnum(_yychar) || _yychar == '.') {
+                    yyinp();
+                } else {
+                    break;
+                }
+            } while (_yychar);
+            int yylen = _currentChar - yytext;
+            tok->f.kind = T_NUMERIC_LITERAL;
+            if (control())
+                tok->number = control()->numericLiteral(yytext, yylen);
+        } else {
+            tok->f.kind = T_DOT;
+        }
+        break;
+
+    case '?':
+        if (_yychar == '?') {
+            yyinp();
+            if (_yychar == '(') {
+                yyinp();
+                tok->f.kind = T_LBRACKET;
+            } else if (_yychar == ')') {
+                yyinp();
+                tok->f.kind = T_RBRACKET;
+            } else if (_yychar == '<') {
+                yyinp();
+                tok->f.kind = T_LBRACE;
+            } else if (_yychar == '>') {
+                yyinp();
+                tok->f.kind = T_RBRACE;
+            }
+        } else {
+            tok->f.kind = T_QUESTION;
+        }
+        break;
+
+    case '+':
+        if (_yychar == '+') {
+            yyinp();
+            tok->f.kind = T_PLUS_PLUS;
+        } else if (_yychar == '=') {
+            yyinp();
+            tok->f.kind = T_PLUS_EQUAL;
+        } else {
+            tok->f.kind = T_PLUS;
+        }
+        break;
+
+    case '-':
+        if (_yychar == '-') {
+            yyinp();
+            tok->f.kind = T_MINUS_MINUS;
+        } else if (_yychar == '=') {
+            yyinp();
+            tok->f.kind = T_MINUS_EQUAL;
+        } else if (_yychar == '>') {
+            yyinp();
+            if (_yychar == '*') {
+                yyinp();
+                tok->f.kind = T_ARROW_STAR;
+            } else {
+                tok->f.kind = T_ARROW;
+            }
+        } else {
+            tok->f.kind = T_MINUS;
+        }
+        break;
+
+    case '*':
+        if (_yychar == '=') {
+            yyinp();
+            tok->f.kind = T_STAR_EQUAL;
+        } else {
+            tok->f.kind = T_STAR;
+        }
+        break;
+
+    case '/':
+        if (_yychar == '/') {
+            yyinp();
+
+            Kind commentType = T_CPP_COMMENT;
+
+            if (_yychar == '/' || _yychar == '!') {
+                yyinp();
+                commentType = T_CPP_DOXY_COMMENT;
+            }
+
+            scanCppComment(commentType);
+
+            if (! f._scanCommentTokens)
+                goto again;
+
+            tok->f.kind = commentType;
+
+        } else if (_yychar == '*') {
+            yyinp();
+
+            Kind commentKind = T_COMMENT;
+
+            if (_yychar == '*' || _yychar == '!') {
+                const char ch = _yychar;
+
+                yyinp();
+
+                if (ch == '*' && _yychar == '/')
+                    goto done;
+
+                if (_yychar == '<')
+                    yyinp();
+
+                if (! _yychar || std::isspace(_yychar))
+                    commentKind = T_DOXY_COMMENT;
+            }
+
+            while (_yychar) {
+                if (_yychar != '*') {
+                    yyinp();
+                } else {
+                    yyinp();
+                    if (_yychar == '/')
+                        break;
+                }
+            }
+
+        done:
+            if (_yychar)
+                yyinp();
+            else
+                s._tokenKind = commentKind;
+
+            if (! f._scanCommentTokens)
+                goto again;
+
+            tok->f.kind = commentKind;
+
+        } else if (_yychar == '=') {
+            yyinp();
+            tok->f.kind = T_SLASH_EQUAL;
+        } else {
+            tok->f.kind = T_SLASH;
+        }
+        break;
+
+    case '%':
+        if (_yychar == '=') {
+            yyinp();
+            tok->f.kind = T_PERCENT_EQUAL;
+        } else if (_yychar == '>') {
+            yyinp();
+            tok->f.kind = T_RBRACE;
+        } else if (_yychar == ':') {
+            yyinp();
+            tok->f.kind = T_POUND;
+        } else {
+            tok->f.kind = T_PERCENT;
+        }
+        break;
+
+    case '^':
+        if (_yychar == '=') {
+            yyinp();
+            tok->f.kind = T_CARET_EQUAL;
+        } else {
+            tok->f.kind = T_CARET;
+        }
+        break;
+
+    case '&':
+        if (_yychar == '&') {
+            yyinp();
+            tok->f.kind = T_AMPER_AMPER;
+        } else if (_yychar == '=') {
+            yyinp();
+            tok->f.kind = T_AMPER_EQUAL;
+        } else {
+            tok->f.kind = T_AMPER;
+        }
+        break;
+
+    case '|':
+        if (_yychar == '|') {
+            yyinp();
+            tok->f.kind = T_PIPE_PIPE;
+        } else if (_yychar == '=') {
+            yyinp();
+            tok->f.kind = T_PIPE_EQUAL;
+        } else {
+            tok->f.kind = T_PIPE;
+        }
+        break;
+
+    case '~':
+        if (_yychar == '=') {
+            yyinp();
+            tok->f.kind = T_TILDE_EQUAL;
+        } else {
+            tok->f.kind = T_TILDE;
+        }
+        break;
+
+    case '!':
+        if (_yychar == '=') {
+            yyinp();
+            tok->f.kind = T_EXCLAIM_EQUAL;
+        } else {
+            tok->f.kind = T_EXCLAIM;
+        }
+        break;
+
+    case '=':
+        if (_yychar == '=') {
+            yyinp();
+            tok->f.kind = T_EQUAL_EQUAL;
+        } else {
+            tok->f.kind = T_EQUAL;
+        }
+        break;
+
+    case '<':
+        if (f._scanAngleStringLiteralTokens) {
+            const char *yytext = _currentChar;
+            while (_yychar && _yychar != '>')
+                yyinp();
+            int yylen = _currentChar - yytext;
+            // ### CPP_CHECK(_yychar == '>');
+            if (_yychar == '>')
+                yyinp();
+            if (control())
+                tok->string = control()->stringLiteral(yytext, yylen);
+            tok->f.kind = T_ANGLE_STRING_LITERAL;
+        } else if (_yychar == '<') {
+            yyinp();
+            if (_yychar == '=') {
+                yyinp();
+                tok->f.kind = T_LESS_LESS_EQUAL;
+            } else
+                tok->f.kind = T_LESS_LESS;
+        } else if (_yychar == '=') {
+            yyinp();
+            tok->f.kind = T_LESS_EQUAL;
+        } else if (_yychar == ':') {
+            yyinp();
+            tok->f.kind = T_LBRACKET;
+        } else if (_yychar == '%') {
+            yyinp();
+            tok->f.kind = T_LBRACE;
+        } else {
+            tok->f.kind = T_LESS;
+        }
+        break;
+
+    case '>':
+        if (_yychar == '>') {
+            yyinp();
+            if (_yychar == '=') {
+                yyinp();
+                tok->f.kind = T_GREATER_GREATER_EQUAL;
+            } else
+                tok->f.kind = T_LESS_LESS;
+            tok->f.kind = T_GREATER_GREATER;
+        } else if (_yychar == '=') {
+            yyinp();
+            tok->f.kind = T_GREATER_EQUAL;
+        } else {
+            tok->f.kind = T_GREATER;
+        }
+        break;
+
+    case ',':
+        tok->f.kind = T_COMMA;
+        break;
+
+    default: {
+        if (_languageFeatures.objCEnabled) {
+            if (ch == '@' && _yychar >= 'a' && _yychar <= 'z') {
+                const char *yytext = _currentChar;
+
+                do {
+                    yyinp();
+                    if (! (isalnum(_yychar) || _yychar == '_' || _yychar == '$'))
+                        break;
+                } while (_yychar);
+
+                const int yylen = _currentChar - yytext;
+                tok->f.kind = classifyObjCAtKeyword(yytext, yylen);
+                break;
+            } else if (ch == '@' && _yychar == '"') {
+                yyinp();
+                scanStringLiteral(tok, '"');
+                break;
+            }
+        }
+
+        if (ch == 'L' || ch == 'u' || ch == 'U' || ch == 'R') {
+            // Either a literal or still an identifier.
+            if (_yychar == '"') {
+                yyinp();
+                if (ch == 'R')
+                    scanRawStringLiteral(tok);
+                else
+                    scanStringLiteral(tok, ch);
+            } else if (_yychar == '\'') {
+                yyinp();
+                scanCharLiteral(tok, ch);
+            } else if (ch != 'R' && _yychar == 'R') {
+                yyinp();
+                if (_yychar == '"') {
+                    yyinp();
+                    scanRawStringLiteral(tok, ch);
+                } else {
+                    scanIdentifier(tok, 1);
+                }
+            } else if (ch == 'u' && _yychar == '8') {
+                yyinp();
+                if (_yychar == '"') {
+                    yyinp();
+                    scanStringLiteral(tok, '8');
+                } else if (_yychar == '\'') {
+                    yyinp();
+                    scanCharLiteral(tok, '8');
+                } else if (_yychar == 'R') {
+                    yyinp();
+                    if (_yychar == '"') {
+                        yyinp();
+                        scanRawStringLiteral(tok, '8');
+                    } else {
+                        scanIdentifier(tok, 2);
+                    }
+                } else {
+                    scanIdentifier(tok, 1);
+                }
+            } else {
+                scanIdentifier(tok);
+            }
+        } else if (std::isalpha(ch) || ch == '_' || ch == '$' || isByteOfMultiByteCodePoint(ch)) {
+            scanIdentifier(tok, _currentChar - _tokenStart - 1);
+        } else if (std::isdigit(ch)) {
+            scanNumericLiteral(tok);
+        } else {
+            tok->f.kind = T_ERROR;
+        }
+        break;
+    } // default
+
+    } // switch
+}
+
+void Lexer::scanStringLiteral(Token *tok, unsigned char hint)
+{
+    if (hint == 'L')
+        tok->f.kind = T_WIDE_STRING_LITERAL;
+    else if (hint == 'U')
+        tok->f.kind = T_UTF32_STRING_LITERAL;
+    else if (hint == 'u')
+        tok->f.kind = T_UTF16_STRING_LITERAL;
+    else if (hint == '8')
+        tok->f.kind = T_UTF8_STRING_LITERAL;
+    else if (hint == '@')
+        tok->f.kind = T_AT_STRING_LITERAL;
+    else
+        tok->f.kind = T_STRING_LITERAL;
+
+    scanUntilQuote(tok, '"');
+}
+
+void Lexer::scanRawStringLiteral(Token *tok, unsigned char hint)
+{
+    const char *yytext = _currentChar;
+
+    int delimLength = -1;
+    const char *closingDelimCandidate = 0;
+    while (_yychar) {
+        if (_yychar == '(' && delimLength == -1) {
+            delimLength = _currentChar - yytext;
+            yyinp();
+        } else if (_yychar == ')') {
+            yyinp();
+            if (delimLength == -1)
+                break;
+            closingDelimCandidate = _currentChar;
+        } else {
+            if (delimLength == -1) {
+                if (_yychar == '\\' || std::isspace(_yychar))
+                    break;
+                yyinp();
+            } else {
+                if (!closingDelimCandidate) {
+                    yyinp();
+                } else {
+                    if (_yychar == '"') {
+                        if (delimLength == _currentChar - closingDelimCandidate) {
+                            // Got a matching closing delimiter.
+                            break;
+                        }
+                    }
+
+                    // Make sure this continues to be a valid candidate.
+                    if (_yychar != *(yytext + (_currentChar - closingDelimCandidate)))
+                        closingDelimCandidate = 0;
+
+                    yyinp();
+                }
+            }
+        }
+    }
+
+    int yylen = _currentChar - yytext;
+
+    if (_yychar == '"')
+        yyinp();
+
+    if (control())
+        tok->string = control()->stringLiteral(yytext, yylen);
+
+    if (hint == 'L')
+        tok->f.kind = T_RAW_WIDE_STRING_LITERAL;
+    else if (hint == 'U')
+        tok->f.kind = T_RAW_UTF32_STRING_LITERAL;
+    else if (hint == 'u')
+        tok->f.kind = T_RAW_UTF16_STRING_LITERAL;
+    else if (hint == '8')
+        tok->f.kind = T_RAW_UTF8_STRING_LITERAL;
+    else
+        tok->f.kind = T_RAW_STRING_LITERAL;
+}
+
+void Lexer::scanCharLiteral(Token *tok, unsigned char hint)
+{
+    if (hint == 'L')
+        tok->f.kind = T_WIDE_CHAR_LITERAL;
+    else if (hint == 'U')
+        tok->f.kind = T_UTF32_CHAR_LITERAL;
+    else if (hint == 'u')
+        tok->f.kind = T_UTF16_CHAR_LITERAL;
+    else
+        tok->f.kind = T_CHAR_LITERAL;
+
+    scanUntilQuote(tok, '\'');
+}
+
+void Lexer::scanUntilQuote(Token *tok, unsigned char quote)
+{
+    CPP_CHECK(quote == '"' || quote == '\'');
+
+    const char *yytext = _currentChar;
+    while (_yychar
+           && _yychar != quote
+           && _yychar != '\n') {
+        if (_yychar == '\\')
+            scanBackslash((Kind)tok->f.kind);
+        else
+            yyinp();
+    }
+    int yylen = _currentChar - yytext;
+
+    if (_yychar == quote)
+        yyinp();
+
+    if (control())
+        tok->string = control()->stringLiteral(yytext, yylen);
+}
+
+void Lexer::scanNumericLiteral(Token *tok)
+{
+    const char *yytext = _currentChar - 1;
+    while (_yychar) {
+        if (_yychar == 'e' || _yychar == 'E') {
+            yyinp();
+            if (_yychar == '-' || _yychar == '+') {
+                yyinp();
+                // ### CPP_CHECK(std::isdigit(_yychar));
+            }
+        } else if (std::isalnum(_yychar) || _yychar == '.') {
+            yyinp();
+        } else {
+            break;
+        }
+    }
+    int yylen = _currentChar - yytext;
+
+    tok->f.kind = T_NUMERIC_LITERAL;
+
+    if (control())
+        tok->number = control()->numericLiteral(yytext, yylen);
+}
+
+void Lexer::scanIdentifier(Token *tok, unsigned extraProcessedChars)
+{
+    const char *yytext = _currentChar - 1 - extraProcessedChars;
+    while (std::isalnum(_yychar) || _yychar == '_' || _yychar == '$'
+            || isByteOfMultiByteCodePoint(_yychar)) {
+        yyinp();
+    }
+    int yylen = _currentChar - yytext;
+    if (f._scanKeywords)
+        tok->f.kind = classify(yytext, yylen, _languageFeatures);
+    else
+        tok->f.kind = T_IDENTIFIER;
+
+    if (tok->f.kind == T_IDENTIFIER) {
+        tok->f.kind = classifyOperator(yytext, yylen);
+
+        if (control())
+            tok->identifier = control()->identifier(yytext, yylen);
+    }
+}
+
+void Lexer::scanBackslash(Kind type)
+{
+    yyinp(); // skip '\\'
+    if (_yychar && !std::isspace(_yychar)) {
+        yyinp();
+        return;
+    }
+    while (_yychar != '\n' && std::isspace(_yychar))
+        yyinp();
+    if (!_yychar) {
+        s._tokenKind = type;
+        s._newlineExpected = true;
+        return;
+    }
+    if (_yychar == '\n') {
+        yyinp();
+        while (_yychar != '\n' && std::isspace(_yychar))
+            yyinp();
+        if (!_yychar)
+            s._tokenKind = type;
+    }
+}
+
+void Lexer::scanCppComment(Kind type)
+{
+    while (_yychar && _yychar != '\n') {
+        if (_yychar == '\\')
+            scanBackslash(type);
+        else if (_yychar)
+            yyinp();
+    }
+}

+ 151 - 0
Source/ToolCore/JSBind/cplusplus/Lexer.h

@@ -0,0 +1,151 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_LEXER_H
+#define CPLUSPLUS_LEXER_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include "Token.h"
+
+namespace CPlusPlus {
+
+class CPLUSPLUS_EXPORT Lexer
+{
+    Lexer(const Lexer &other);
+    void operator =(const Lexer &other);
+
+public:
+    Lexer(TranslationUnit *unit);
+    Lexer(const char *firstChar, const char *lastChar);
+    ~Lexer();
+
+    Control *control() const { return _control; }
+    TranslationUnit *translationUnit() const;
+
+    void scan(Token *tok);
+
+    inline void operator()(Token *tok)
+    { scan(tok); }
+
+    bool scanCommentTokens() const;
+    void setScanCommentTokens(bool onoff);
+
+    bool scanKeywords() const;
+    void setScanKeywords(bool onoff);
+
+    bool scanAngleStringLiteralTokens() const;
+    void setScanAngleStringLiteralTokens(bool onoff);
+
+    void setStartWithNewline(bool enabled);
+
+    int state() const;
+    void setState(int state);
+
+    LanguageFeatures languageFeatures() const { return _languageFeatures; }
+    void setLanguageFeatures(LanguageFeatures features) { _languageFeatures = features; }
+
+public:
+    static void yyinp_utf8(const char *&currentSourceChar, unsigned char &yychar,
+                           unsigned &utf16charCounter)
+    {
+        ++utf16charCounter;
+
+        // Process multi-byte UTF-8 code point (non-latin1)
+        if (CPLUSPLUS_UNLIKELY(isByteOfMultiByteCodePoint(yychar))) {
+            unsigned trailingBytesCurrentCodePoint = 1;
+            for (unsigned char c = yychar << 2; isByteOfMultiByteCodePoint(c); c <<= 1)
+                ++trailingBytesCurrentCodePoint;
+            // Code points >= 0x00010000 are represented by two UTF-16 code units
+            if (trailingBytesCurrentCodePoint >= 3)
+                ++utf16charCounter;
+            yychar = *(currentSourceChar += trailingBytesCurrentCodePoint + 1);
+
+            // Process single-byte UTF-8 code point (latin1)
+        } else {
+            yychar = *++currentSourceChar;
+        }
+    }
+
+private:
+    void pushLineStartOffset();
+    void scan_helper(Token *tok);
+    void setSource(const char *firstChar, const char *lastChar);
+    static int classify(const char *string, int length, LanguageFeatures features);
+    static int classifyObjCAtKeyword(const char *s, int n);
+    static int classifyOperator(const char *string, int length);
+
+    void scanStringLiteral(Token *tok, unsigned char hint = 0);
+    void scanRawStringLiteral(Token *tok, unsigned char hint = 0);
+    void scanCharLiteral(Token *tok, unsigned char hint = 0);
+    void scanUntilQuote(Token *tok, unsigned char quote);
+    void scanNumericLiteral(Token *tok);
+    void scanIdentifier(Token *tok, unsigned extraProcessedChars = 0);
+    void scanBackslash(Kind type);
+    void scanCppComment(Kind type);
+
+    static bool isByteOfMultiByteCodePoint(unsigned char byte)
+    { return byte & 0x80; } // Check if most significant bit is set
+
+    void yyinp()
+    {
+        yyinp_utf8(_currentChar, _yychar, _currentCharUtf16);
+        if (CPLUSPLUS_UNLIKELY(_yychar == '\n'))
+            pushLineStartOffset();
+    }
+
+private:
+    struct Flags {
+        unsigned _scanCommentTokens: 1;
+        unsigned _scanKeywords: 1;
+        unsigned _scanAngleStringLiteralTokens: 1;
+    };
+
+    struct State {
+        unsigned char _tokenKind : 7;
+        unsigned char _newlineExpected : 1;
+    };
+
+    TranslationUnit *_translationUnit;
+    Control *_control;
+    const char *_firstChar;
+    const char *_currentChar;
+    const char *_lastChar;
+    const char *_tokenStart;
+    unsigned char _yychar;
+
+    unsigned _currentCharUtf16;
+    unsigned _tokenStartUtf16;
+
+    union {
+        unsigned char _state;
+        State s;
+    };
+    union {
+        unsigned _flags;
+        Flags f;
+    };
+
+    unsigned _currentLine;
+    LanguageFeatures _languageFeatures;
+};
+
+} // namespace CPlusPlus
+
+#endif // CPLUSPLUS_LEXER_H

+ 169 - 0
Source/ToolCore/JSBind/cplusplus/LiteralTable.h

@@ -0,0 +1,169 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_LITERALTABLE_H
+#define CPLUSPLUS_LITERALTABLE_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include <cstring>
+
+namespace CPlusPlus {
+
+template <typename Literal>
+class LiteralTable
+{
+    LiteralTable(const LiteralTable &other);
+    void operator =(const LiteralTable &other);
+
+public:
+    typedef Literal *const *iterator;
+
+public:
+    LiteralTable()
+       : _literals(0),
+         _buckets(0),
+         _allocatedLiterals(0),
+         _literalCount(-1),
+         _allocatedBuckets(0)
+    { }
+
+    ~LiteralTable()
+    {
+        reset();
+    }
+
+    void reset()
+    {
+        if (_literals) {
+            Literal **lastLiteral = _literals + _literalCount + 1;
+            for (Literal **it = _literals; it != lastLiteral; ++it)
+                delete *it;
+            std::free(_literals);
+        }
+        if (_buckets)
+            std::free(_buckets);
+
+        _literals = 0;
+        _buckets = 0;
+        _allocatedLiterals = 0;
+        _literalCount = -1;
+        _allocatedBuckets = 0;
+    }
+
+    bool empty() const
+    { return _literalCount == -1; }
+
+    unsigned size() const
+    { return _literalCount + 1; }
+
+    const Literal *at(unsigned index) const
+    { return _literals[index]; }
+
+    iterator begin() const
+    { return _literals; }
+
+    iterator end() const
+    { return _literals + _literalCount + 1; }
+
+    const Literal *findLiteral(const char *chars, unsigned size) const
+    {
+        if (_buckets) {
+            unsigned h = Literal::hashCode(chars, size);
+            Literal *literal = _buckets[h % _allocatedBuckets];
+            for (; literal; literal = static_cast<Literal *>(literal->_next)) {
+                if (literal->size() == size && ! std::strncmp(literal->chars(), chars, size))
+                    return literal;
+            }
+        }
+
+        return 0;
+    }
+
+    const Literal *findOrInsertLiteral(const char *chars, unsigned size)
+    {
+        if (_buckets) {
+            unsigned h = Literal::hashCode(chars, size);
+            Literal *literal = _buckets[h % _allocatedBuckets];
+            for (; literal; literal = static_cast<Literal *>(literal->_next)) {
+                if (literal->size() == size && ! std::strncmp(literal->chars(), chars, size))
+                    return literal;
+            }
+        }
+
+        Literal *literal = new Literal(chars, size);
+
+        if (++_literalCount == _allocatedLiterals) {
+            if (! _allocatedLiterals)
+                _allocatedLiterals = 4;
+            else
+                _allocatedLiterals <<= 1;
+
+            _literals = (Literal **) std::realloc(_literals, sizeof(Literal *) * _allocatedLiterals);
+        }
+
+        _literals[_literalCount] = literal;
+
+        if (! _buckets || _literalCount * 5 >= _allocatedBuckets * 3)
+            rehash();
+        else {
+            unsigned h = literal->hashCode() % _allocatedBuckets;
+            literal->_next = _buckets[h];
+            _buckets[h] = literal;
+        }
+
+        return literal;
+    }
+
+protected:
+    void rehash()
+    {
+       if (_buckets)
+           std::free(_buckets);
+
+       if (! _allocatedBuckets)
+           _allocatedBuckets = 4;
+       else
+           _allocatedBuckets <<= 1;
+
+       _buckets = (Literal **) std::calloc(_allocatedBuckets, sizeof(Literal *));
+
+       Literal **lastLiteral = _literals + (_literalCount + 1);
+
+       for (Literal **it = _literals; it != lastLiteral; ++it) {
+           Literal *literal = *it;
+           unsigned h = literal->hashCode() % _allocatedBuckets;
+
+           literal->_next = _buckets[h];
+           _buckets[h] = literal;
+       }
+    }
+
+protected:
+    Literal **_literals;
+    Literal **_buckets;
+    int _allocatedLiterals;
+    int _literalCount;
+    int _allocatedBuckets;
+};
+
+} // namespace CPlusPlus
+
+
+#endif // CPLUSPLUS_LITERALTABLE_H

+ 143 - 0
Source/ToolCore/JSBind/cplusplus/Literals.cpp

@@ -0,0 +1,143 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "Literals.h"
+#include "NameVisitor.h"
+#include "Matcher.h"
+#include <cstring>
+#include <algorithm>
+#include <iostream>
+
+using namespace CPlusPlus;
+
+////////////////////////////////////////////////////////////////////////////////
+Literal::Literal(const char *chars, unsigned size)
+    : _next(0), _index(0)
+{
+    _chars = new char[size + 1];
+
+    std::strncpy(_chars, chars, size);
+    _chars[size] = '\0';
+    _size = size;
+
+    _hashCode = hashCode(_chars, _size);
+}
+
+Literal::~Literal()
+{ delete[] _chars; }
+
+bool Literal::equalTo(const Literal *other) const
+{
+    if (! other)
+        return false;
+    else if (this == other)
+        return true;
+    else if (hashCode() != other->hashCode())
+        return false;
+    else if (size() != other->size())
+        return false;
+    return ! std::strcmp(chars(), other->chars());
+}
+
+
+
+unsigned Literal::hashCode(const char *chars, unsigned size)
+{
+    /* Hash taken from QtCore's qHash for strings, which in turn has the note:
+
+    These functions are based on Peter J. Weinberger's hash function
+    (from the Dragon Book). The constant 24 in the original function
+    was replaced with 23 to produce fewer collisions on input such as
+    "a", "aa", "aaa", "aaaa", ...
+    */
+
+    unsigned h = 0;
+
+    while (size--) {
+        h = (h << 4) + *chars++;
+        h ^= (h & 0xf0000000) >> 23;
+        h &= 0x0fffffff;
+    }
+    return h;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+NumericLiteral::NumericLiteral(const char *chars, unsigned size)
+    : Literal(chars, size), _flags(0)
+{
+    f._type = NumericLiteralIsInt;
+
+    if (size > 1 && chars[0] == '0' && (chars[1] == 'x' || chars[1] == 'X')) {
+        f._isHex = true;
+    } else {
+        const char *begin = chars;
+        const char *end = begin + size;
+
+        bool done = false;
+        const char *it = end - 1;
+
+        for (; it != begin - 1 && ! done; --it) {
+            switch (*it) {
+            case 'l': case 'L': // long suffix
+            case 'u': case 'U': // unsigned suffix
+            case 'f': case 'F': // floating suffix
+                break;
+
+            default:
+                done = true;
+                break;
+            } // switch
+        }
+
+        for (const char *dot = it; it != begin - 1; --it) {
+            if (*dot == '.')
+                f._type = NumericLiteralIsDouble;
+        }
+
+        for (++it; it != end; ++it) {
+            if (*it == 'l' || *it == 'L') {
+                if (f._type == NumericLiteralIsDouble) {
+                    f._type = NumericLiteralIsLongDouble;
+                } else if (it + 1 != end && (it[1] == 'l' || it[1] == 'L')) {
+                    ++it;
+                    f._type = NumericLiteralIsLongLong;
+                } else {
+                    f._type = NumericLiteralIsLong;
+                }
+            } else if (*it == 'f' || *it == 'F') {
+                f._type = NumericLiteralIsFloat;
+            } else if (*it == 'u' || *it == 'U') {
+                f._isUnsigned = true;
+            }
+        }
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+void Identifier::accept0(NameVisitor *visitor) const
+{ visitor->visit(this); }
+
+bool Identifier::match0(const Name *otherName, Matcher *matcher) const
+{
+    if (const Identifier *id = otherName->asNameId())
+        return matcher->match(this, id);
+    return false;
+}

+ 129 - 0
Source/ToolCore/JSBind/cplusplus/Literals.h

@@ -0,0 +1,129 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_LITERALS_H
+#define CPLUSPLUS_LITERALS_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include "Token.h"
+#include "Name.h"
+
+namespace CPlusPlus {
+
+class CPLUSPLUS_EXPORT Literal
+{
+    Literal(const Literal &other);
+    void operator =(const Literal &other);
+
+public:
+    typedef const char *iterator;
+    typedef iterator const_iterator;
+
+public:
+    Literal(const char *chars, unsigned size);
+    virtual ~Literal();
+
+    iterator begin() const { return _chars; }
+    iterator end() const { return _chars + _size; }
+
+    char at(unsigned index) const { return _chars[index]; }
+    const char *chars() const { return _chars; }
+    unsigned size() const { return _size; }
+
+    unsigned hashCode() const { return _hashCode; }
+    static unsigned hashCode(const char *chars, unsigned size);
+
+    bool equalTo(const Literal *other) const;
+
+    Literal *_next; // ## private
+
+private:
+    char *_chars;
+    unsigned _size;
+    unsigned _hashCode;
+
+public:
+    unsigned _index;     // ### private
+};
+
+class CPLUSPLUS_EXPORT StringLiteral: public Literal
+{
+public:
+    StringLiteral(const char *chars, unsigned size)
+        : Literal(chars, size)
+    { }
+};
+
+class CPLUSPLUS_EXPORT NumericLiteral: public Literal
+{
+public:
+    NumericLiteral(const char *chars, unsigned size);
+
+    enum {
+        NumericLiteralIsInt,
+        NumericLiteralIsFloat,
+        NumericLiteralIsDouble,
+        NumericLiteralIsLongDouble,
+        NumericLiteralIsLong,
+        NumericLiteralIsLongLong
+    };
+
+    bool isInt() const { return f._type == NumericLiteralIsInt; }
+    bool isFloat() const { return f._type == NumericLiteralIsFloat; }
+    bool isDouble() const { return f._type == NumericLiteralIsDouble; }
+    bool isLongDouble() const { return f._type == NumericLiteralIsLongDouble; }
+    bool isLong() const { return f._type == NumericLiteralIsLong; }
+    bool isLongLong() const { return f._type == NumericLiteralIsLongLong; }
+    bool isUnsigned() const { return f._isUnsigned; }
+    bool isHex() const { return f._isHex; }
+
+private:
+    struct Flags {
+        unsigned _type      : 8;
+        unsigned _isHex     : 1;
+        unsigned _isUnsigned: 1;
+    };
+    union {
+        unsigned _flags;
+        Flags f;
+    };
+};
+
+class CPLUSPLUS_EXPORT Identifier: public Literal, public Name
+{
+public:
+    Identifier(const char *chars, unsigned size)
+        : Literal(chars, size)
+    { }
+
+    virtual const Identifier *identifier() const { return this; }
+
+    virtual const Identifier *asNameId() const
+    { return this; }
+
+protected:
+    virtual void accept0(NameVisitor *visitor) const;
+    virtual bool match0(const Name *otherName, Matcher *matcher) const;
+};
+
+} // namespace CPlusPlus
+
+
+#endif // CPLUSPLUS_LITERALS_H

+ 371 - 0
Source/ToolCore/JSBind/cplusplus/Matcher.cpp

@@ -0,0 +1,371 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://www.qt.io/licensing.  For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "Matcher.h"
+#include "CoreTypes.h"
+#include "Symbols.h"
+#include "Names.h"
+#include "Literals.h"
+
+using namespace CPlusPlus;
+
+static Matcher *defaultMatcher()
+{
+    static Matcher matcher;
+    return &matcher;
+}
+
+Matcher::Matcher()
+{
+}
+
+Matcher::~Matcher()
+{
+}
+
+bool Matcher::match(const Type *type, const Type *otherType, Matcher *matcher)
+{
+    if (type == otherType)
+        return true;
+    if (!type || !otherType)
+        return false;
+
+    return type->match0(otherType, matcher ? matcher : defaultMatcher());
+}
+
+bool Matcher::match(const Name *name, const Name *otherName, Matcher *matcher)
+{
+    if (name == otherName)
+        return true;
+    if (!name || !otherName)
+        return false;
+
+    return name->match0(otherName, matcher ? matcher : defaultMatcher());
+}
+
+bool Matcher::match(const UndefinedType *, const UndefinedType *)
+{
+    return true;
+}
+
+bool Matcher::match(const VoidType *, const VoidType *)
+{
+    return true;
+}
+
+bool Matcher::match(const IntegerType *type, const IntegerType *otherType)
+{
+    if (type == otherType)
+        return true;
+
+    else if (type->kind() != otherType->kind())
+        return false;
+
+    return true;
+}
+
+bool Matcher::match(const FloatType *type, const FloatType *otherType)
+{
+    if (type == otherType)
+        return true;
+
+    else if (type->kind() != otherType->kind())
+        return false;
+
+    return true;
+}
+
+bool Matcher::match(const PointerToMemberType *type, const PointerToMemberType *otherType)
+{
+    if (type == otherType)
+        return true;
+
+    else if (! Matcher::match(type->memberName(), otherType->memberName(), this))
+        return false;
+
+    else if (! type->elementType().match(otherType->elementType(), this))
+        return false;
+
+    return true;
+}
+
+bool Matcher::match(const PointerType *type, const PointerType *otherType)
+{
+    if (type == otherType)
+        return true;
+
+    else if (! type->elementType().match(otherType->elementType(), this))
+        return false;
+
+    return true;
+}
+
+bool Matcher::match(const ReferenceType *type, const ReferenceType *otherType)
+{
+    if (type == otherType)
+        return true;
+
+    else if (type->isRvalueReference() != otherType->isRvalueReference())
+        return false;
+
+    else if (! type->elementType().match(otherType->elementType(), this))
+        return false;
+
+    return true;
+}
+
+bool Matcher::match(const ArrayType *type, const ArrayType *otherType)
+{
+    if (type == otherType)
+        return true;
+
+    else if (type->size() != otherType->size())
+        return false;
+
+    else if (! type->elementType().match(otherType->elementType(), this))
+        return false;
+
+    return true;
+}
+
+bool Matcher::match(const NamedType *type, const NamedType *otherType)
+{
+    if (type == otherType)
+        return true;
+
+    const Name *name = type->name();
+    if (const QualifiedNameId *q = name->asQualifiedNameId())
+        name = q->name();
+
+    const Name *otherName = otherType->name();
+    if (const QualifiedNameId *q = otherName->asQualifiedNameId())
+        otherName = q->name();
+
+    if (! Matcher::match(name, otherName, this))
+        return false;
+
+    return true;
+}
+
+bool Matcher::match(const Function *type, const Function *otherType)
+{
+    if (type == otherType)
+        return true;
+
+    else if (! type->isSignatureEqualTo(otherType, this))
+        return false;
+
+    else if (! type->returnType().match(otherType->returnType(), this))
+        return false;
+
+    return true;
+}
+
+bool Matcher::match(const Enum *type, const Enum *otherType)
+{
+    if (type == otherType)
+        return true;
+
+    else if (! Matcher::match(type->unqualifiedName(), otherType->unqualifiedName(), this))
+        return false;
+
+    return true;
+}
+
+bool Matcher::match(const Namespace *type, const Namespace *otherType)
+{
+    if (type == otherType)
+        return true;
+
+    else if (! Matcher::match(type->unqualifiedName(), otherType->unqualifiedName(), this))
+        return false;
+
+    return true;
+}
+
+bool Matcher::match(const Template *type, const Template *otherType)
+{
+    if (type != otherType)
+        return false;
+
+    return true;
+}
+
+bool Matcher::match(const ForwardClassDeclaration *type, const ForwardClassDeclaration *otherType)
+{
+    if (type == otherType)
+        return true;
+
+    else if (! Matcher::match(type->name(), otherType->name(), this))
+        return false;
+
+    return true;
+}
+
+bool Matcher::match(const Class *type, const Class *otherType)
+{
+    if (type == otherType)
+        return true;
+
+    else if (! Matcher::match(type->unqualifiedName(), otherType->unqualifiedName(), this))
+        return false;
+
+    return true;
+}
+
+bool Matcher::match(const ObjCClass *type, const ObjCClass *otherType)
+{
+    if (type == otherType)
+        return true;
+
+    else if (! Matcher::match(type->unqualifiedName(), otherType->unqualifiedName(), this))
+        return false;
+
+    return true;
+}
+
+bool Matcher::match(const ObjCProtocol *type, const ObjCProtocol *otherType)
+{
+    if (type == otherType)
+        return true;
+
+    else if (! Matcher::match(type->unqualifiedName(), otherType->unqualifiedName(), this))
+        return false;
+
+    return true;
+}
+
+bool Matcher::match(const ObjCForwardClassDeclaration *type, const ObjCForwardClassDeclaration *otherType)
+{
+    if (type == otherType)
+        return true;
+
+    else if (! Matcher::match(type->name(), otherType->name(), this))
+        return false;
+
+    return true;
+}
+
+bool Matcher::match(const ObjCForwardProtocolDeclaration *type, const ObjCForwardProtocolDeclaration *otherType)
+{
+    if (type == otherType)
+        return true;
+
+    else if (! Matcher::match(type->name(), otherType->name(), this))
+        return false;
+
+    return true;
+}
+
+bool Matcher::match(const ObjCMethod *type, const ObjCMethod *otherType)
+{
+    if (type == otherType)
+        return true;
+
+    else if (! Matcher::match(type->unqualifiedName(), otherType->unqualifiedName(), this))
+        return false;
+
+    else if (type->argumentCount() != otherType->argumentCount())
+        return false;
+
+    else if (! type->returnType().match(otherType->returnType(), this))
+        return false;
+
+    for (unsigned i = 0; i < type->argumentCount(); ++i) {
+        Symbol *l = type->argumentAt(i);
+        Symbol *r = otherType->argumentAt(i);
+        if (! l->type().match(r->type(), this))
+            return false;
+    }
+
+    return true;
+}
+
+bool Matcher::match(const Identifier *name, const Identifier *otherName)
+{
+    if (name == otherName)
+        return true;
+    return name->equalTo(otherName);
+}
+
+bool Matcher::match(const AnonymousNameId *name, const AnonymousNameId *otherName)
+{
+    return otherName && name->classTokenIndex() == otherName->classTokenIndex();
+}
+
+bool Matcher::match(const TemplateNameId *name, const TemplateNameId *otherName)
+{
+    const Identifier *l = name->identifier();
+    const Identifier *r = otherName->identifier();
+    if (! match(l, r))
+        return false;
+    if (name->templateArgumentCount() != otherName->templateArgumentCount())
+        return false;
+    for (unsigned i = 0, ei = name->templateArgumentCount(); i != ei; ++i) {
+        const FullySpecifiedType &l = name->templateArgumentAt(i);
+        const FullySpecifiedType &r = otherName->templateArgumentAt(i);
+        if (! l.match(r, this))
+            return false;
+    }
+    return true;
+}
+
+bool Matcher::match(const DestructorNameId *name, const DestructorNameId *otherName)
+{
+    return Matcher::match(name->name(), otherName->name(), this);
+}
+
+bool Matcher::match(const OperatorNameId *name, const OperatorNameId *otherName)
+{
+    return name->kind() == otherName->kind();
+}
+
+bool Matcher::match(const ConversionNameId *name, const ConversionNameId *otherName)
+{
+    return name->type().match(otherName->type(), this);
+}
+
+bool Matcher::match(const QualifiedNameId *name, const QualifiedNameId *otherName)
+{
+    if (Matcher::match(name->base(), otherName->base(), this))
+        return Matcher::match(name->name(), otherName->name(), this);
+    return false;
+}
+
+bool Matcher::match(const SelectorNameId *name, const SelectorNameId *otherName)
+{
+    const unsigned nc = name->nameCount();
+    if (name->hasArguments() != otherName->hasArguments() || nc != otherName->nameCount())
+        return false;
+    for (unsigned i = 0; i < nc; ++i)
+        if (! Matcher::match(name->nameAt(i), otherName->nameAt(i), this))
+            return false;
+    return true;
+}

+ 84 - 0
Source/ToolCore/JSBind/cplusplus/Matcher.h

@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://www.qt.io/licensing.  For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef TYPEMATCHER_H
+#define TYPEMATCHER_H
+
+#include "CPlusPlusForwardDeclarations.h"
+
+namespace CPlusPlus {
+
+class CPLUSPLUS_EXPORT Matcher
+{
+    Matcher(const Matcher &other);
+    void operator = (const Matcher &other);
+
+public:
+    Matcher();
+    virtual ~Matcher();
+
+    static bool match(const Type *type, const Type *otherType, Matcher *matcher = 0);
+    static bool match(const Name *name, const Name *otherName, Matcher *matcher = 0);
+
+    virtual bool match(const UndefinedType *type, const UndefinedType *otherType);
+    virtual bool match(const VoidType *type, const VoidType *otherType);
+    virtual bool match(const IntegerType *type, const IntegerType *otherType);
+    virtual bool match(const FloatType *type, const FloatType *otherType);
+    virtual bool match(const PointerToMemberType *type, const PointerToMemberType *otherType);
+    virtual bool match(const PointerType *type, const PointerType *otherType);
+    virtual bool match(const ReferenceType *type, const ReferenceType *otherType);
+    virtual bool match(const ArrayType *type, const ArrayType *otherType);
+    virtual bool match(const NamedType *type, const NamedType *otherType);
+
+    virtual bool match(const Function *type, const Function *otherType);
+    virtual bool match(const Enum *type, const Enum *otherType);
+    virtual bool match(const Namespace *type, const Namespace *otherType);
+    virtual bool match(const Template *type, const Template *otherType);
+    virtual bool match(const ForwardClassDeclaration *type, const ForwardClassDeclaration *otherType);
+    virtual bool match(const Class *type, const Class *otherType);
+    virtual bool match(const ObjCClass *type, const ObjCClass *otherType);
+    virtual bool match(const ObjCProtocol *type, const ObjCProtocol *otherType);
+    virtual bool match(const ObjCForwardClassDeclaration *type, const ObjCForwardClassDeclaration *otherType);
+    virtual bool match(const ObjCForwardProtocolDeclaration *type, const ObjCForwardProtocolDeclaration *otherType);
+    virtual bool match(const ObjCMethod *type, const ObjCMethod *otherType);
+
+    virtual bool match(const Identifier *name, const Identifier *otherName);
+    virtual bool match(const AnonymousNameId *name, const AnonymousNameId *otherName);
+    virtual bool match(const TemplateNameId *name, const TemplateNameId *otherName);
+    virtual bool match(const DestructorNameId *name, const DestructorNameId *otherName);
+    virtual bool match(const OperatorNameId *name, const OperatorNameId *otherName);
+    virtual bool match(const ConversionNameId *name, const ConversionNameId *otherName);
+    virtual bool match(const QualifiedNameId *name, const QualifiedNameId *otherName);
+    virtual bool match(const SelectorNameId *name, const SelectorNameId *otherName);
+};
+
+} // namespace CPlusPlus
+
+#endif // TYPEMATCHER_H

+ 113 - 0
Source/ToolCore/JSBind/cplusplus/MemoryPool.cpp

@@ -0,0 +1,113 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "MemoryPool.h"
+
+#include "cppassert.h"
+
+#include <cstring>
+
+using namespace CPlusPlus;
+
+MemoryPool::MemoryPool()
+    : _blocks(0),
+      _allocatedBlocks(0),
+      _blockCount(-1),
+      _ptr(0),
+      _end(0)
+{ }
+
+MemoryPool::~MemoryPool()
+{
+    if (_blocks) {
+        for (int i = 0; i < _allocatedBlocks; ++i) {
+            if (char *b = _blocks[i])
+                std::free(b);
+        }
+
+        std::free(_blocks);
+    }
+}
+
+void MemoryPool::reset()
+{
+    _blockCount = -1;
+    _ptr = _end = 0;
+}
+
+void *MemoryPool::allocate_helper(size_t size)
+{
+    CPP_CHECK(size < BLOCK_SIZE);
+
+    if (++_blockCount == _allocatedBlocks) {
+        if (! _allocatedBlocks)
+            _allocatedBlocks = DEFAULT_BLOCK_COUNT;
+        else
+            _allocatedBlocks *= 2;
+
+        _blocks = (char **) realloc(_blocks, sizeof(char *) * _allocatedBlocks);
+
+        for (int index = _blockCount; index < _allocatedBlocks; ++index)
+            _blocks[index] = 0;
+    }
+
+    char *&block = _blocks[_blockCount];
+
+    if (! block)
+        block = (char *) std::malloc(BLOCK_SIZE);
+
+    _ptr = block;
+    _end = _ptr + BLOCK_SIZE;
+
+    void *addr = _ptr;
+    _ptr += size;
+    return addr;
+}
+
+RecursiveMemoryPool::RecursiveMemoryPool(MemoryPool *pool)
+    : _pool(pool),
+      _blockCount(pool->_blockCount),
+      _ptr(pool->_ptr),
+      _end(pool->_end)
+{
+}
+
+RecursiveMemoryPool::~RecursiveMemoryPool()
+{
+    _pool->_blockCount = _blockCount;
+    _pool->_ptr = _ptr;
+    _pool->_end = _end;
+}
+
+Managed::Managed()
+{ }
+
+Managed::~Managed()
+{ }
+
+void *Managed::operator new(size_t size, MemoryPool *pool)
+{ return pool->allocate(size); }
+
+void Managed::operator delete(void *)
+{ }
+
+void Managed::operator delete(void *, MemoryPool *)
+{ }
+

+ 102 - 0
Source/ToolCore/JSBind/cplusplus/MemoryPool.h

@@ -0,0 +1,102 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_MEMORYPOOL_H
+#define CPLUSPLUS_MEMORYPOOL_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include <new>
+
+namespace CPlusPlus {
+
+class MemoryPool;
+class RecursiveMemoryPool;
+
+class CPLUSPLUS_EXPORT MemoryPool
+{
+    MemoryPool(const MemoryPool &other);
+    void operator =(const MemoryPool &other);
+
+public:
+    MemoryPool();
+    ~MemoryPool();
+
+    void reset();
+
+    inline void *allocate(size_t size)
+    {
+        size = (size + 7) & ~7;
+        if (_ptr && (_ptr + size < _end)) {
+            void *addr = _ptr;
+            _ptr += size;
+            return addr;
+        }
+        return allocate_helper(size);
+    }
+
+private:
+    void *allocate_helper(size_t size);
+
+private:
+    char **_blocks;
+    int _allocatedBlocks;
+    int _blockCount;
+    char *_ptr;
+    char *_end;
+
+    enum
+    {
+        BLOCK_SIZE = 8 * 1024,
+        DEFAULT_BLOCK_COUNT = 8
+    };
+
+    friend class RecursiveMemoryPool;
+};
+
+class CPLUSPLUS_EXPORT RecursiveMemoryPool
+{
+    MemoryPool *_pool;
+    int _blockCount;
+    char *_ptr;
+    char *_end;
+
+public:
+    RecursiveMemoryPool(MemoryPool *pool);
+    ~RecursiveMemoryPool();
+};
+
+class CPLUSPLUS_EXPORT Managed
+{
+    Managed(const Managed &other);
+    void operator = (const Managed &other);
+
+public:
+    Managed();
+    virtual ~Managed();
+
+    void *operator new(size_t size, MemoryPool *pool);
+    void operator delete(void *);
+    void operator delete(void *, MemoryPool *);
+};
+
+} // namespace CPlusPlus
+
+
+#endif // CPLUSPLUS_MEMORYPOOL_H

+ 98 - 0
Source/ToolCore/JSBind/cplusplus/Name.cpp

@@ -0,0 +1,98 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "Literals.h"
+#include "Matcher.h"
+#include "Name.h"
+#include "Names.h"
+#include "NameVisitor.h"
+
+#include <cstring>
+
+using namespace CPlusPlus;
+
+Name::Name()
+{ }
+
+Name::~Name()
+{ }
+
+bool Name::isNameId() const
+{ return asNameId() != 0; }
+
+bool Name::isAnonymousNameId() const
+{ return asAnonymousNameId() != 0; }
+
+bool Name::isTemplateNameId() const
+{ return asTemplateNameId() != 0; }
+
+bool Name::isDestructorNameId() const
+{ return asDestructorNameId() != 0; }
+
+bool Name::isOperatorNameId() const
+{ return asOperatorNameId() != 0; }
+
+bool Name::isConversionNameId() const
+{ return asConversionNameId() != 0; }
+
+bool Name::isQualifiedNameId() const
+{ return asQualifiedNameId() != 0; }
+
+bool Name::isSelectorNameId() const
+{ return asSelectorNameId() != 0; }
+
+void Name::accept(NameVisitor *visitor) const
+{
+    if (visitor->preVisit(this))
+        accept0(visitor);
+    visitor->postVisit(this);
+}
+
+void Name::accept(const Name *name, NameVisitor *visitor)
+{
+    if (! name)
+        return;
+    name->accept(visitor);
+}
+
+bool Name::match(const Name *other, Matcher *matcher) const
+{
+    return Matcher::match(this, other, matcher);
+}
+
+bool Name::Compare::operator()(const Name *name, const Name *other) const
+{
+    if (name == 0)
+        return other != 0;
+    if (other == 0)
+        return false;
+    if (name == other)
+        return false;
+
+    const Identifier *id = name->identifier();
+    const Identifier *otherId = other->identifier();
+
+    if (id == 0)
+        return otherId != 0;
+    if (otherId == 0)
+        return false;
+
+    return std::strcmp(id->chars(), otherId->chars()) < 0;
+}

+ 78 - 0
Source/ToolCore/JSBind/cplusplus/Name.h

@@ -0,0 +1,78 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_NAME_H
+#define CPLUSPLUS_NAME_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include "Matcher.h"
+
+#include <functional>
+
+namespace CPlusPlus {
+
+class CPLUSPLUS_EXPORT Name
+{
+public:
+    Name();
+    virtual ~Name();
+
+    virtual const Identifier *identifier() const = 0;
+
+    bool isNameId() const;
+    bool isAnonymousNameId() const;
+    bool isTemplateNameId() const;
+    bool isDestructorNameId() const;
+    bool isOperatorNameId() const;
+    bool isConversionNameId() const;
+    bool isQualifiedNameId() const;
+    bool isSelectorNameId() const;
+
+    virtual const Identifier *asNameId() const { return 0; }
+    virtual const AnonymousNameId *asAnonymousNameId() const { return 0; }
+    virtual const TemplateNameId *asTemplateNameId() const { return 0; }
+    virtual const DestructorNameId *asDestructorNameId() const { return 0; }
+    virtual const OperatorNameId *asOperatorNameId() const { return 0; }
+    virtual const ConversionNameId *asConversionNameId() const { return 0; }
+    virtual const QualifiedNameId *asQualifiedNameId() const { return 0; }
+    virtual const SelectorNameId *asSelectorNameId() const { return 0; }
+
+    void accept(NameVisitor *visitor) const;
+    static void accept(const Name *name, NameVisitor *visitor);
+
+    bool match(const Name *other, Matcher *matcher = 0) const;
+
+public:
+    struct Compare: std::binary_function<const Name *, const Name *, bool> {
+        bool operator()(const Name *name, const Name *other) const;
+    };
+
+protected:
+    virtual void accept0(NameVisitor *visitor) const = 0;
+
+protected: // for Matcher
+    friend class Matcher;
+    virtual bool match0(const Name *otherName, Matcher *matcher) const = 0;
+};
+
+} // namespace CPlusPlus
+
+
+#endif // CPLUSPLUS_NAME_H

+ 33 - 0
Source/ToolCore/JSBind/cplusplus/NameVisitor.cpp

@@ -0,0 +1,33 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "NameVisitor.h"
+#include "Names.h"
+
+using namespace CPlusPlus;
+
+NameVisitor::NameVisitor()
+{ }
+
+NameVisitor::~NameVisitor()
+{ }
+
+void NameVisitor::accept(const Name *name)
+{ Name::accept(name, this); }

+ 56 - 0
Source/ToolCore/JSBind/cplusplus/NameVisitor.h

@@ -0,0 +1,56 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_NAMEVISITOR_H
+#define CPLUSPLUS_NAMEVISITOR_H
+
+#include "CPlusPlusForwardDeclarations.h"
+
+
+namespace CPlusPlus {
+
+class CPLUSPLUS_EXPORT NameVisitor
+{
+    NameVisitor(const NameVisitor &other);
+    void operator =(const NameVisitor &other);
+
+public:
+    NameVisitor();
+    virtual ~NameVisitor();
+
+    void accept(const Name *name);
+
+    virtual bool preVisit(const Name *) { return true; }
+    virtual void postVisit(const Name *) {}
+
+    virtual void visit(const AnonymousNameId *) {}
+    virtual void visit(const Identifier *) {}
+    virtual void visit(const TemplateNameId *) {}
+    virtual void visit(const DestructorNameId *) {}
+    virtual void visit(const OperatorNameId *) {}
+    virtual void visit(const ConversionNameId *) {}
+    virtual void visit(const QualifiedNameId *) {}
+    virtual void visit(const SelectorNameId *) {}
+};
+
+} // namespace CPlusPlus
+
+
+#endif // CPLUSPLUS_NAMEVISITOR_H

+ 235 - 0
Source/ToolCore/JSBind/cplusplus/Names.cpp

@@ -0,0 +1,235 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "Names.h"
+#include "Matcher.h"
+#include "NameVisitor.h"
+#include "Literals.h"
+#include <algorithm>
+#include <cstring>
+
+using namespace CPlusPlus;
+
+QualifiedNameId::~QualifiedNameId()
+{ }
+
+void QualifiedNameId::accept0(NameVisitor *visitor) const
+{ visitor->visit(this); }
+
+bool QualifiedNameId::match0(const Name *otherName, Matcher *matcher) const
+{
+    if (const QualifiedNameId *name = otherName->asQualifiedNameId())
+        return matcher->match(this, name);
+    return false;
+}
+
+const Identifier *QualifiedNameId::identifier() const
+{
+    if (const Name *u = name())
+        return u->identifier();
+
+    return 0;
+}
+
+const Name *QualifiedNameId::base() const
+{ return _base; }
+
+const Name *QualifiedNameId::name() const
+{ return _name; }
+
+DestructorNameId::DestructorNameId(const Name *name)
+    : _name(name)
+{ }
+
+DestructorNameId::~DestructorNameId()
+{ }
+
+void DestructorNameId::accept0(NameVisitor *visitor) const
+{ visitor->visit(this); }
+
+bool DestructorNameId::match0(const Name *otherName, Matcher *matcher) const
+{
+    if (const DestructorNameId *name = otherName->asDestructorNameId())
+        return matcher->match(this, name);
+    return false;
+}
+
+const Name *DestructorNameId::name() const
+{ return _name; }
+
+const Identifier *DestructorNameId::identifier() const
+{ return _name->identifier(); }
+
+TemplateNameId::~TemplateNameId()
+{ }
+
+void TemplateNameId::accept0(NameVisitor *visitor) const
+{ visitor->visit(this); }
+
+bool TemplateNameId::match0(const Name *otherName, Matcher *matcher) const
+{
+    if (const TemplateNameId *other = otherName->asTemplateNameId())
+        return matcher->match(this, other);
+    return false;
+}
+
+const Identifier *TemplateNameId::identifier() const
+{ return _identifier; }
+
+unsigned TemplateNameId::templateArgumentCount() const
+{ return unsigned(_templateArguments.size()); }
+
+const FullySpecifiedType &TemplateNameId::templateArgumentAt(unsigned index) const
+{ return _templateArguments[index]; }
+
+bool TemplateNameId::Compare::operator()(const TemplateNameId *name,
+                                         const TemplateNameId *other) const
+{
+    if (name == 0)
+        return other != 0;
+    if (other == 0)
+        return false;
+    if (name == other)
+        return false;
+
+    const Identifier *id = name->identifier();
+    const Identifier *otherId = other->identifier();
+
+    if (id == 0)
+        return otherId != 0;
+    if (otherId == 0)
+        return false;
+
+    const int c = std::strcmp(id->chars(), otherId->chars());
+    if (c == 0) {
+        // we have to differentiate TemplateNameId with respect to specialization or instantiation
+        if (name->isSpecialization() == other->isSpecialization()) {
+            return std::lexicographical_compare(name->firstTemplateArgument(),
+                                                name->lastTemplateArgument(),
+                                                other->firstTemplateArgument(),
+                                                other->lastTemplateArgument());
+        } else {
+            return name->isSpecialization();
+        }
+    }
+
+    return c < 0;
+}
+
+OperatorNameId::OperatorNameId(Kind kind)
+    : _kind(kind)
+{ }
+
+OperatorNameId::~OperatorNameId()
+{ }
+
+void OperatorNameId::accept0(NameVisitor *visitor) const
+{ visitor->visit(this); }
+
+bool OperatorNameId::match0(const Name *otherName, Matcher *matcher) const
+{
+    if (const OperatorNameId *name = otherName->asOperatorNameId())
+        return matcher->match(this, name);
+    return false;
+}
+
+OperatorNameId::Kind OperatorNameId::kind() const
+{ return _kind; }
+
+const Identifier *OperatorNameId::identifier() const
+{ return 0; }
+
+ConversionNameId::ConversionNameId(const FullySpecifiedType &type)
+    : _type(type)
+{ }
+
+ConversionNameId::~ConversionNameId()
+{ }
+
+void ConversionNameId::accept0(NameVisitor *visitor) const
+{ visitor->visit(this); }
+
+bool ConversionNameId::match0(const Name *otherName, Matcher *matcher) const
+{
+    if (const ConversionNameId *name = otherName->asConversionNameId())
+        return matcher->match(this, name);
+    return false;
+}
+
+FullySpecifiedType ConversionNameId::type() const
+{ return _type; }
+
+const Identifier *ConversionNameId::identifier() const
+{ return 0; }
+
+SelectorNameId::~SelectorNameId()
+{ }
+
+void SelectorNameId::accept0(NameVisitor *visitor) const
+{ visitor->visit(this); }
+
+bool SelectorNameId::match0(const Name *otherName, Matcher *matcher) const
+{
+    if (const SelectorNameId *name = otherName->asSelectorNameId())
+        return matcher->match(this, name);
+    return false;
+}
+
+const Identifier *SelectorNameId::identifier() const
+{
+    if (_names.empty())
+        return 0;
+
+    return nameAt(0)->identifier();
+}
+
+unsigned SelectorNameId::nameCount() const
+{ return unsigned(_names.size()); }
+
+const Name *SelectorNameId::nameAt(unsigned index) const
+{ return _names[index]; }
+
+bool SelectorNameId::hasArguments() const
+{ return _hasArguments; }
+
+AnonymousNameId::AnonymousNameId(unsigned classTokenIndex)
+    : _classTokenIndex(classTokenIndex)
+{ }
+
+AnonymousNameId::~AnonymousNameId()
+{ }
+
+unsigned AnonymousNameId::classTokenIndex() const
+{
+    return _classTokenIndex;
+}
+
+void AnonymousNameId::accept0(NameVisitor *visitor) const
+{ visitor->visit(this); }
+
+bool AnonymousNameId::match0(const Name *otherName, Matcher *matcher) const
+{
+    if (const AnonymousNameId *id = otherName->asAnonymousNameId())
+        return matcher->match(this, id);
+    return false;
+}
+
+const Identifier *AnonymousNameId::identifier() const
+{ return 0; }

+ 277 - 0
Source/ToolCore/JSBind/cplusplus/Names.h

@@ -0,0 +1,277 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_NAMES_H
+#define CPLUSPLUS_NAMES_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include "Name.h"
+#include "FullySpecifiedType.h"
+#include <vector>
+
+namespace CPlusPlus {
+
+class CPLUSPLUS_EXPORT QualifiedNameId: public Name
+{
+public:
+    QualifiedNameId(const Name *base, const Name *name)
+        : _base(base), _name(name) {}
+
+    virtual ~QualifiedNameId();
+
+    virtual const Identifier *identifier() const;
+
+    const Name *base() const;
+    const Name *name() const;
+
+    virtual const QualifiedNameId *asQualifiedNameId() const
+    { return this; }
+
+protected:
+    virtual void accept0(NameVisitor *visitor) const;
+    virtual bool match0(const Name *otherName, Matcher *matcher) const;
+
+private:
+    const Name *_base;
+    const Name *_name;
+};
+
+class CPLUSPLUS_EXPORT DestructorNameId: public Name
+{
+public:
+    DestructorNameId(const Name *name);
+    virtual ~DestructorNameId();
+
+    virtual const Name *name() const;
+
+    virtual const Identifier *identifier() const;
+
+    virtual const DestructorNameId *asDestructorNameId() const
+    { return this; }
+
+protected:
+    virtual void accept0(NameVisitor *visitor) const;
+    virtual bool match0(const Name *otherName, Matcher *matcher) const;
+
+private:
+    const Name *_name;
+};
+
+class CPLUSPLUS_EXPORT TemplateNameId: public Name
+{
+public:
+    template <typename Iterator>
+    TemplateNameId(const Identifier *identifier, bool isSpecialization, Iterator first,
+                   Iterator last)
+        : _identifier(identifier)
+        , _templateArguments(first, last)
+        , _isSpecialization(isSpecialization) {}
+
+    virtual ~TemplateNameId();
+
+    virtual const Identifier *identifier() const;
+
+    // ### find a better name
+    unsigned templateArgumentCount() const;
+    const FullySpecifiedType &templateArgumentAt(unsigned index) const;
+
+    virtual const TemplateNameId *asTemplateNameId() const
+    { return this; }
+
+    typedef std::vector<FullySpecifiedType>::const_iterator TemplateArgumentIterator;
+
+    TemplateArgumentIterator firstTemplateArgument() const { return _templateArguments.begin(); }
+    TemplateArgumentIterator lastTemplateArgument() const { return _templateArguments.end(); }
+    bool isSpecialization() const { return _isSpecialization; }
+    // this is temporary solution needed in ClassOrNamespace::nestedType
+    // when we try to find correct specialization for instantiation
+    void setIsSpecialization(bool isSpecialization) { _isSpecialization = isSpecialization; }
+
+    // Comparator needed to distinguish between two different TemplateNameId(e.g.:used in std::map)
+    struct Compare: std::binary_function<const TemplateNameId *, const TemplateNameId *, bool> {
+        bool operator()(const TemplateNameId *name, const TemplateNameId *other) const;
+    };
+
+protected:
+    virtual void accept0(NameVisitor *visitor) const;
+    virtual bool match0(const Name *otherName, Matcher *matcher) const;
+
+private:
+    const Identifier *_identifier;
+    std::vector<FullySpecifiedType> _templateArguments;
+    // now TemplateNameId can be a specialization or an instantiation
+    bool _isSpecialization;
+};
+
+class CPLUSPLUS_EXPORT OperatorNameId: public Name
+{
+public:
+    /*
+        new  delete    new[]     delete[]
+        +    -    *    /    %    ^    &    |    ~
+        !    =    <    >    +=   -=   *=   /=   %=
+        ^=   &=   |=   <<   >>   >>=  <<=  ==   !=
+        <=   >=   &&   ||   ++   --   ,    ->*  ->
+        ()   []
+     */
+    enum Kind {
+        InvalidOp,
+        NewOp,
+        DeleteOp,
+        NewArrayOp,
+        DeleteArrayOp,
+        PlusOp,
+        MinusOp,
+        StarOp,
+        SlashOp,
+        PercentOp,
+        CaretOp,
+        AmpOp,
+        PipeOp,
+        TildeOp,
+        ExclaimOp,
+        EqualOp,
+        LessOp,
+        GreaterOp,
+        PlusEqualOp,
+        MinusEqualOp,
+        StarEqualOp,
+        SlashEqualOp,
+        PercentEqualOp,
+        CaretEqualOp,
+        AmpEqualOp,
+        PipeEqualOp,
+        LessLessOp,
+        GreaterGreaterOp,
+        LessLessEqualOp,
+        GreaterGreaterEqualOp,
+        EqualEqualOp,
+        ExclaimEqualOp,
+        LessEqualOp,
+        GreaterEqualOp,
+        AmpAmpOp,
+        PipePipeOp,
+        PlusPlusOp,
+        MinusMinusOp,
+        CommaOp,
+        ArrowStarOp,
+        ArrowOp,
+        FunctionCallOp,
+        ArrayAccessOp
+    };
+
+public:
+    OperatorNameId(Kind kind);
+    virtual ~OperatorNameId();
+
+    Kind kind() const;
+
+    virtual const Identifier *identifier() const;
+
+    virtual const OperatorNameId *asOperatorNameId() const
+    { return this; }
+
+protected:
+    virtual void accept0(NameVisitor *visitor) const;
+    virtual bool match0(const Name *otherName, Matcher *matcher) const;
+
+private:
+    Kind _kind;
+};
+
+class CPLUSPLUS_EXPORT ConversionNameId: public Name
+{
+public:
+    ConversionNameId(const FullySpecifiedType &type);
+    virtual ~ConversionNameId();
+
+    FullySpecifiedType type() const;
+
+    virtual const Identifier *identifier() const;
+
+    virtual const ConversionNameId *asConversionNameId() const
+    { return this; }
+
+protected:
+    virtual void accept0(NameVisitor *visitor) const;
+    virtual bool match0(const Name *otherName, Matcher *matcher) const;
+
+private:
+    FullySpecifiedType _type;
+};
+
+class CPLUSPLUS_EXPORT SelectorNameId: public Name
+{
+public:
+    template <typename Iterator>
+    SelectorNameId(Iterator first, Iterator last, bool hasArguments)
+        : _names(first, last), _hasArguments(hasArguments) {}
+
+    virtual ~SelectorNameId();
+
+    virtual const Identifier *identifier() const;
+
+    unsigned nameCount() const;
+    const Name *nameAt(unsigned index) const;
+    bool hasArguments() const;
+
+    virtual const SelectorNameId *asSelectorNameId() const
+    { return this; }
+
+    typedef std::vector<const Name *>::const_iterator NameIterator;
+
+    NameIterator firstName() const { return _names.begin(); }
+    NameIterator lastName() const { return _names.end(); }
+
+protected:
+    virtual void accept0(NameVisitor *visitor) const;
+    virtual bool match0(const Name *otherName, Matcher *matcher) const;
+
+private:
+    std::vector<const Name *> _names;
+    bool _hasArguments;
+};
+
+class CPLUSPLUS_EXPORT AnonymousNameId: public Name
+{
+public:
+    AnonymousNameId(unsigned classTokenIndex);
+    virtual ~AnonymousNameId();
+
+    unsigned classTokenIndex() const;
+
+    virtual const Identifier *identifier() const;
+
+    virtual const AnonymousNameId *asAnonymousNameId() const
+    { return this; }
+
+protected:
+    virtual void accept0(NameVisitor *visitor) const;
+    virtual bool match0(const Name *otherName, Matcher *matcher) const;
+
+private:
+    unsigned _classTokenIndex;
+};
+
+
+
+} // namespace CPlusPlus
+
+#endif // CPLUSPLUS_NAMES_H

+ 463 - 0
Source/ToolCore/JSBind/cplusplus/ObjectiveCAtKeywords.cpp

@@ -0,0 +1,463 @@
+
+#include "Lexer.h"
+#include "Token.h"
+
+using namespace CPlusPlus;
+
+static inline int classify3(const char *s) {
+  if (s[0] == 'e') {
+    if (s[1] == 'n') {
+      if (s[2] == 'd') {
+        return T_AT_END;
+      }
+    }
+  }
+  else if (s[0] == 't') {
+    if (s[1] == 'r') {
+      if (s[2] == 'y') {
+        return T_AT_TRY;
+      }
+    }
+  }
+  return T_ERROR;
+}
+
+static inline int classify4(const char *s) {
+  if (s[0] == 'd') {
+    if (s[1] == 'e') {
+      if (s[2] == 'f') {
+        if (s[3] == 's') {
+          return T_AT_DEFS;
+        }
+      }
+    }
+  }
+  return T_ERROR;
+}
+
+static inline int classify5(const char *s) {
+  if (s[0] == 'c') {
+    if (s[1] == 'a') {
+      if (s[2] == 't') {
+        if (s[3] == 'c') {
+          if (s[4] == 'h') {
+            return T_AT_CATCH;
+          }
+        }
+      }
+    }
+    else if (s[1] == 'l') {
+      if (s[2] == 'a') {
+        if (s[3] == 's') {
+          if (s[4] == 's') {
+            return T_AT_CLASS;
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 't') {
+    if (s[1] == 'h') {
+      if (s[2] == 'r') {
+        if (s[3] == 'o') {
+          if (s[4] == 'w') {
+            return T_AT_THROW;
+          }
+        }
+      }
+    }
+  }
+  return T_ERROR;
+}
+
+static inline int classify6(const char *s) {
+  if (s[0] == 'e') {
+    if (s[1] == 'n') {
+      if (s[2] == 'c') {
+        if (s[3] == 'o') {
+          if (s[4] == 'd') {
+            if (s[5] == 'e') {
+              return T_AT_ENCODE;
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'p') {
+    if (s[1] == 'u') {
+      if (s[2] == 'b') {
+        if (s[3] == 'l') {
+          if (s[4] == 'i') {
+            if (s[5] == 'c') {
+              return T_AT_PUBLIC;
+            }
+          }
+        }
+      }
+    }
+  }
+  return T_ERROR;
+}
+
+static inline int classify7(const char *s) {
+  if (s[0] == 'd') {
+    if (s[1] == 'y') {
+      if (s[2] == 'n') {
+        if (s[3] == 'a') {
+          if (s[4] == 'm') {
+            if (s[5] == 'i') {
+              if (s[6] == 'c') {
+                return T_AT_DYNAMIC;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'f') {
+    if (s[1] == 'i') {
+      if (s[2] == 'n') {
+        if (s[3] == 'a') {
+          if (s[4] == 'l') {
+            if (s[5] == 'l') {
+              if (s[6] == 'y') {
+                return T_AT_FINALLY;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'p') {
+    if (s[1] == 'a') {
+      if (s[2] == 'c') {
+        if (s[3] == 'k') {
+          if (s[4] == 'a') {
+            if (s[5] == 'g') {
+              if (s[6] == 'e') {
+                return T_AT_PACKAGE;
+              }
+            }
+          }
+        }
+      }
+    }
+    else if (s[1] == 'r') {
+      if (s[2] == 'i') {
+        if (s[3] == 'v') {
+          if (s[4] == 'a') {
+            if (s[5] == 't') {
+              if (s[6] == 'e') {
+                return T_AT_PRIVATE;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  return T_ERROR;
+}
+
+static inline int classify8(const char *s) {
+  if (s[0] == 'o') {
+    if (s[1] == 'p') {
+      if (s[2] == 't') {
+        if (s[3] == 'i') {
+          if (s[4] == 'o') {
+            if (s[5] == 'n') {
+              if (s[6] == 'a') {
+                if (s[7] == 'l') {
+                  return T_AT_OPTIONAL;
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'p') {
+    if (s[1] == 'r') {
+      if (s[2] == 'o') {
+        if (s[3] == 'p') {
+          if (s[4] == 'e') {
+            if (s[5] == 'r') {
+              if (s[6] == 't') {
+                if (s[7] == 'y') {
+                  return T_AT_PROPERTY;
+                }
+              }
+            }
+          }
+        }
+        else if (s[3] == 't') {
+          if (s[4] == 'o') {
+            if (s[5] == 'c') {
+              if (s[6] == 'o') {
+                if (s[7] == 'l') {
+                  return T_AT_PROTOCOL;
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'r') {
+    if (s[1] == 'e') {
+      if (s[2] == 'q') {
+        if (s[3] == 'u') {
+          if (s[4] == 'i') {
+            if (s[5] == 'r') {
+              if (s[6] == 'e') {
+                if (s[7] == 'd') {
+                  return T_AT_REQUIRED;
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 's') {
+    if (s[1] == 'e') {
+      if (s[2] == 'l') {
+        if (s[3] == 'e') {
+          if (s[4] == 'c') {
+            if (s[5] == 't') {
+              if (s[6] == 'o') {
+                if (s[7] == 'r') {
+                  return T_AT_SELECTOR;
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  return T_ERROR;
+}
+
+static inline int classify9(const char *s) {
+  if (s[0] == 'i') {
+    if (s[1] == 'n') {
+      if (s[2] == 't') {
+        if (s[3] == 'e') {
+          if (s[4] == 'r') {
+            if (s[5] == 'f') {
+              if (s[6] == 'a') {
+                if (s[7] == 'c') {
+                  if (s[8] == 'e') {
+                    return T_AT_INTERFACE;
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'p') {
+    if (s[1] == 'r') {
+      if (s[2] == 'o') {
+        if (s[3] == 't') {
+          if (s[4] == 'e') {
+            if (s[5] == 'c') {
+              if (s[6] == 't') {
+                if (s[7] == 'e') {
+                  if (s[8] == 'd') {
+                    return T_AT_PROTECTED;
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  return T_ERROR;
+}
+
+static inline int classify10(const char *s) {
+  if (s[0] == 's') {
+    if (s[1] == 'y') {
+      if (s[2] == 'n') {
+        if (s[3] == 't') {
+          if (s[4] == 'h') {
+            if (s[5] == 'e') {
+              if (s[6] == 's') {
+                if (s[7] == 'i') {
+                  if (s[8] == 'z') {
+                    if (s[9] == 'e') {
+                      return T_AT_SYNTHESIZE;
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  return T_ERROR;
+}
+
+static inline int classify11(const char *s) {
+  if (s[0] == 'n') {
+    if (s[1] == 'o') {
+      if (s[2] == 't') {
+        if (s[3] == '_') {
+          if (s[4] == 'k') {
+            if (s[5] == 'e') {
+              if (s[6] == 'y') {
+                if (s[7] == 'w') {
+                  if (s[8] == 'o') {
+                    if (s[9] == 'r') {
+                      if (s[10] == 'd') {
+                        return T_AT_NOT_KEYWORD;
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  return T_ERROR;
+}
+
+static inline int classify12(const char *s) {
+  if (s[0] == 's') {
+    if (s[1] == 'y') {
+      if (s[2] == 'n') {
+        if (s[3] == 'c') {
+          if (s[4] == 'h') {
+            if (s[5] == 'r') {
+              if (s[6] == 'o') {
+                if (s[7] == 'n') {
+                  if (s[8] == 'i') {
+                    if (s[9] == 'z') {
+                      if (s[10] == 'e') {
+                        if (s[11] == 'd') {
+                          return T_AT_SYNCHRONIZED;
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  return T_ERROR;
+}
+
+static inline int classify14(const char *s) {
+  if (s[0] == 'i') {
+    if (s[1] == 'm') {
+      if (s[2] == 'p') {
+        if (s[3] == 'l') {
+          if (s[4] == 'e') {
+            if (s[5] == 'm') {
+              if (s[6] == 'e') {
+                if (s[7] == 'n') {
+                  if (s[8] == 't') {
+                    if (s[9] == 'a') {
+                      if (s[10] == 't') {
+                        if (s[11] == 'i') {
+                          if (s[12] == 'o') {
+                            if (s[13] == 'n') {
+                              return T_AT_IMPLEMENTATION;
+                            }
+                          }
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  return T_ERROR;
+}
+
+static inline int classify19(const char *s) {
+  if (s[0] == 'c') {
+    if (s[1] == 'o') {
+      if (s[2] == 'm') {
+        if (s[3] == 'p') {
+          if (s[4] == 'a') {
+            if (s[5] == 't') {
+              if (s[6] == 'i') {
+                if (s[7] == 'b') {
+                  if (s[8] == 'i') {
+                    if (s[9] == 'l') {
+                      if (s[10] == 'i') {
+                        if (s[11] == 't') {
+                          if (s[12] == 'y') {
+                            if (s[13] == '_') {
+                              if (s[14] == 'a') {
+                                if (s[15] == 'l') {
+                                  if (s[16] == 'i') {
+                                    if (s[17] == 'a') {
+                                      if (s[18] == 's') {
+                                        return T_AT_COMPATIBILITY_ALIAS;
+                                      }
+                                    }
+                                  }
+                                }
+                              }
+                            }
+                          }
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  return T_ERROR;
+}
+
+int Lexer::classifyObjCAtKeyword(const char *s, int n) {
+  switch (n) {
+    case 3: return classify3(s);
+    case 4: return classify4(s);
+    case 5: return classify5(s);
+    case 6: return classify6(s);
+    case 7: return classify7(s);
+    case 8: return classify8(s);
+    case 9: return classify9(s);
+    case 10: return classify10(s);
+    case 11: return classify11(s);
+    case 12: return classify12(s);
+    case 14: return classify14(s);
+    case 19: return classify19(s);
+    default: return T_ERROR;
+  } // switch
+}

+ 222 - 0
Source/ToolCore/JSBind/cplusplus/ObjectiveCTypeQualifiers.cpp

@@ -0,0 +1,222 @@
+
+#include "ObjectiveCTypeQualifiers.h"
+
+using namespace CPlusPlus;
+
+static inline int classify2(const char *s) {
+  if (s[0] == 'i') {
+    if (s[1] == 'n') {
+      return Token_in;
+    }
+  }
+  return Token_identifier;
+}
+
+static inline int classify3(const char *s) {
+  if (s[0] == 'o') {
+    if (s[1] == 'u') {
+      if (s[2] == 't') {
+        return Token_out;
+      }
+    }
+  }
+  return Token_identifier;
+}
+
+static inline int classify4(const char *s) {
+    if (s[0] == 'c') {
+        if (s[1] == 'o') {
+            if (s[2] == 'p') {
+                if (s[3] == 'y') {
+                    return Token_copy;
+                }
+            }
+        }
+    }
+    return Token_identifier;
+}
+
+static inline int classify5(const char *s) {
+  if (s[0] == 'b') {
+    if (s[1] == 'y') {
+      if (s[2] == 'r') {
+        if (s[3] == 'e') {
+          if (s[4] == 'f') {
+            return Token_byref;
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'i') {
+    if (s[1] == 'n') {
+      if (s[2] == 'o') {
+        if (s[3] == 'u') {
+          if (s[4] == 't') {
+            return Token_inout;
+          }
+        }
+      }
+    }
+  }
+  return Token_identifier;
+}
+
+static inline int classify6(const char *s) {
+  if (s[0] == 'a') {
+      if (s[1] == 's') {
+          if (s[2] == 's') {
+              if (s[3] == 'i') {
+                  if (s[4] == 'g') {
+                      if (s[5] == 'n') {
+                          return Token_assign;
+                      }
+                  }
+              }
+          }
+      }
+  }
+  else if (s[0] == 'b') {
+    if (s[1] == 'y') {
+      if (s[2] == 'c') {
+        if (s[3] == 'o') {
+          if (s[4] == 'p') {
+            if (s[5] == 'y') {
+              return Token_bycopy;
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'g') {
+      if (s[1] == 'e') {
+          if (s[2] == 't') {
+              if (s[3] == 't') {
+                  if (s[4] == 'e') {
+                      if (s[5] == 'r') {
+                          return Token_getter;
+                      }
+                  }
+              }
+          }
+      }
+  }
+  else if (s[0] == 's') {
+      if (s[1] == 'e') {
+          if (s[2] == 't') {
+              if (s[3] == 't') {
+                  if (s[4] == 'e') {
+                      if (s[5] == 'r') {
+                          return Token_setter;
+                      }
+                  }
+              }
+          }
+      }
+  }
+  else if (s[0] == 'o') {
+    if (s[1] == 'n') {
+      if (s[2] == 'e') {
+        if (s[3] == 'w') {
+          if (s[4] == 'a') {
+            if (s[5] == 'y') {
+              return Token_oneway;
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'r') {
+      if (s[1] == 'e') {
+          if (s[2] == 't') {
+              if (s[3] == 'a') {
+                  if (s[4] == 'i') {
+                      if (s[5] == 'n') {
+                          return Token_retain;
+                      }
+                  }
+              }
+          }
+      }
+  }
+  return Token_identifier;
+}
+
+static inline int classify8(const char *s) {
+    if (s[0] == 'r') {
+        if (s[1] == 'e') {
+            if (s[2] == 'a') {
+                if (s[3] == 'd') {
+                    if (s[4] == 'o') {
+                        if (s[5] == 'n') {
+                            if (s[6] == 'l') {
+                                if (s[7] == 'y') {
+                                    return Token_readonly;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return Token_identifier;
+}
+
+static inline int classify9(const char *s) {
+    if (s[0] == 'n') {
+        if (s[1] == 'o') {
+            if (s[2] == 'n') {
+                if (s[3] == 'a') {
+                    if (s[4] == 't') {
+                        if (s[5] == 'o') {
+                            if (s[6] == 'm') {
+                                if (s[7] == 'i') {
+                                    if (s[8] == 'c') {
+                                        return Token_nonatomic;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    } else if (s[0] == 'r') {
+        if (s[1] == 'e') {
+            if (s[2] == 'a') {
+                if (s[3] == 'd') {
+                    if (s[4] == 'w') {
+                        if (s[5] == 'r') {
+                            if (s[6] == 'i') {
+                                if (s[7] == 't') {
+                                    if (s[8] == 'e') {
+                                        return Token_readwrite;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return Token_identifier;
+}
+
+int CPlusPlus::classifyObjectiveCContextKeyword(const char *s, int n) {
+  switch (n) {
+    case 2: return classify2(s);
+    case 3: return classify3(s);
+    case 4: return classify4(s);
+    case 5: return classify5(s);
+    case 6: return classify6(s);
+    case 8: return classify8(s);
+    case 9: return classify9(s);
+    default: return Token_identifier;
+  } // switch
+}
+
+

+ 32 - 0
Source/ToolCore/JSBind/cplusplus/ObjectiveCTypeQualifiers.h

@@ -0,0 +1,32 @@
+#ifndef CPLUSPLUS_OBJC_TYPEQUALIFIERS_H
+#define CPLUSPLUS_OBJC_TYPEQUALIFIERS_H
+
+#include "CPlusPlusForwardDeclarations.h"
+
+
+namespace CPlusPlus {
+
+enum {
+  Token_in,
+  Token_out,
+  Token_copy,
+  Token_byref,
+  Token_inout,
+  Token_assign,
+  Token_bycopy,
+  Token_getter,
+  Token_retain,
+  Token_setter,
+  Token_oneway,
+  Token_readonly,
+  Token_nonatomic,
+  Token_readwrite,
+  Token_identifier
+};
+
+CPLUSPLUS_EXPORT int classifyObjectiveCContextKeyword(const char *s, int n);
+
+} // namespace CPlusPlus
+
+
+#endif // CPLUSPLUS_OBJC_TYPEQUALIFIERS_H

+ 6755 - 0
Source/ToolCore/JSBind/cplusplus/Parser.cpp

@@ -0,0 +1,6755 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "Parser.h"
+#include "Token.h"
+#include "Lexer.h"
+#include "Control.h"
+#include "AST.h"
+#include "Literals.h"
+#include "ObjectiveCTypeQualifiers.h"
+#include "QtContextKeywords.h"
+
+#include <unordered_map>
+#include <utility>
+
+#include <string>
+#include <cstdio> // for putchar
+
+#if defined(_MSC_VER) && (_MSC_VER < 1800)
+#    define va_copy(dst, src) ((dst) = (src))
+#elif defined(__INTEL_COMPILER) && !defined(va_copy)
+#    define va_copy __va_copy
+#endif
+
+#define CPLUSPLUS_NO_DEBUG_RULE
+#define MAX_EXPRESSION_DEPTH 100
+#define MAX_STATEMENT_DEPTH 100
+
+using namespace CPlusPlus;
+
+namespace {
+
+class DebugRule {
+public:
+    static int depth;
+
+    DebugRule(const char *name, const char *spell, unsigned idx, bool blocked)
+    {
+        for (int i = 0; i <= depth; ++i)
+          fputc('-', stderr);
+
+        ++depth;
+        fprintf(stderr, " %s, ahead: '%s' (%u) - block-errors: %d\n", name, spell, idx, blocked);
+    }
+
+    ~DebugRule()
+    { --depth; }
+};
+
+int DebugRule::depth = 0;
+
+inline bool lookAtAssignmentOperator(int tokenKind)
+{
+    switch (tokenKind) {
+    case T_EQUAL:
+    case T_AMPER_EQUAL:
+    case T_CARET_EQUAL:
+    case T_SLASH_EQUAL:
+    case T_GREATER_GREATER_EQUAL:
+    case T_LESS_LESS_EQUAL:
+    case T_MINUS_EQUAL:
+    case T_PERCENT_EQUAL:
+    case T_PIPE_EQUAL:
+    case T_PLUS_EQUAL:
+    case T_STAR_EQUAL:
+    case T_TILDE_EQUAL:
+        return true;
+    default:
+        return false;
+    } // switch
+}
+
+namespace Prec {
+enum {
+    Unknown         = 0,
+    Comma           = 1,
+    Assignment      = 2,
+    Conditional     = 3,
+    LogicalOr       = 4,
+    LogicalAnd      = 5,
+    InclusiveOr     = 6,
+    ExclusiveOr     = 7,
+    And             = 8,
+    Equality        = 9,
+    Relational      = 10,
+    Shift           = 11,
+    Additive        = 12,
+    Multiplicative  = 13,
+    PointerToMember = 14
+};
+} // namespace Precedece
+
+inline int precedence(int tokenKind, bool templateArguments)
+{
+    // ### this will/might need some tuning for C++0x
+    // (see: [temp.names]p3)
+    if (templateArguments && (tokenKind == T_GREATER || tokenKind == T_GREATER_GREATER))
+        return -1;
+
+    if (lookAtAssignmentOperator(tokenKind))
+        return Prec::Assignment;
+
+    switch (tokenKind) {
+    case T_COMMA:           return Prec::Comma;
+    case T_QUESTION:        return Prec::Conditional;
+    case T_PIPE_PIPE:       return Prec::LogicalOr;
+    case T_AMPER_AMPER:     return Prec::LogicalAnd;
+    case T_PIPE:            return Prec::InclusiveOr;
+    case T_CARET:           return Prec::ExclusiveOr;
+    case T_AMPER:           return Prec::And;
+    case T_EQUAL_EQUAL:
+    case T_EXCLAIM_EQUAL:   return Prec::Equality;
+    case T_GREATER:
+    case T_LESS:
+    case T_LESS_EQUAL:
+    case T_GREATER_EQUAL:   return Prec::Relational;
+    case T_LESS_LESS:
+    case T_GREATER_GREATER: return Prec::ExclusiveOr;
+    case T_PLUS:
+    case T_MINUS:           return Prec::Additive;
+    case T_STAR:
+    case T_SLASH:
+    case T_PERCENT:         return Prec::Multiplicative;
+    case T_ARROW_STAR:
+    case T_DOT_STAR:        return Prec::PointerToMember;
+    default:                return Prec::Unknown;
+    }
+}
+
+inline bool isBinaryOperator(int tokenKind)
+{ return precedence(tokenKind, false) != Prec::Unknown; }
+
+inline bool isRightAssociative(int tokenKind)
+{
+    const int prec = precedence(tokenKind, false);
+    return prec == Prec::Conditional || prec == Prec::Assignment;
+}
+
+} // end of anonymous namespace
+
+class Parser::ASTCache
+{
+    ASTCache(const ASTCache &other);
+    void operator =(const ASTCache &other);
+
+public:
+    enum ASTKind {
+        Expression,
+        ExpressionList,
+        ParameterDeclarationClause,
+        TypeId
+    };
+
+public:
+    ASTCache() {}
+
+    void insert(ASTKind astKind, unsigned tokenIndexBeforeParsing,
+                AST *resultingAST, unsigned resultingTokenIndex, bool resultingReturnValue)
+    {
+        const auto key = std::make_pair(astKind, tokenIndexBeforeParsing);
+
+        ParseFunctionResult result;
+        result.resultingAST = resultingAST;
+        result.resultingTokenIndex = resultingTokenIndex;
+        result.returnValue = resultingReturnValue;
+        const auto keyValue = std::make_pair(key, result);
+        _cache.insert(keyValue);
+    }
+
+    AST *find(ASTKind astKind, unsigned tokenIndex,
+              unsigned *resultingTokenIndex, bool *foundInCache, bool *returnValue) const
+    {
+        const auto key = std::make_pair(astKind, tokenIndex);
+        const auto it = _cache.find(key);
+        if (it == _cache.end()) {
+            *foundInCache = false;
+            return 0;
+        } else {
+            *foundInCache = true;
+            *resultingTokenIndex = it->second.resultingTokenIndex;
+            *returnValue = it->second.returnValue;
+            return it->second.resultingAST;
+        }
+    }
+
+    void clear()
+    {
+        _cache.clear();
+    }
+
+private:
+    struct KeyHasher {
+        size_t operator()(const std::pair<int, unsigned> &key) const
+        { return std::hash<int>()(key.first) ^ std::hash<unsigned>()(key.second); }
+    };
+
+    struct ParseFunctionResult {
+        AST *resultingAST;
+        unsigned resultingTokenIndex;
+        bool returnValue;
+    };
+
+    typedef std::pair<int, unsigned> ASTKindAndTokenIndex;
+    std::unordered_map<ASTKindAndTokenIndex, ParseFunctionResult, KeyHasher> _cache;
+};
+
+#ifndef CPLUSPLUS_NO_DEBUG_RULE
+#  define DEBUG_THIS_RULE() DebugRule __debug_rule__(__func__, tok().spell(), cursor(), _translationUnit->blockErrors())
+inline void debugPrintCheckCache(bool goodCase)
+{
+    for (int i = 0; i <= DebugRule::depth - 1; ++i)
+        fputc('-', stderr);
+    if (goodCase)
+        fprintf(stderr, " CACHE: Re-using AST from Cache.\n");
+    else
+        fprintf(stderr, " CACHE: Already tried to parse this, skipping.\n");
+}
+#else
+#  define DEBUG_THIS_RULE() do {} while (0)
+inline void debugPrintCheckCache(bool) {}
+#endif
+
+#define CHECK_CACHE(ASTKind, ASTType) \
+    do { \
+        bool foundInCache; \
+        unsigned newTokenIndex; \
+        bool returnValue; \
+        if (AST *ast = _astCache->find(ASTKind, cursor(), \
+                                       &newTokenIndex, &foundInCache, &returnValue)) { \
+            debugPrintCheckCache(true); \
+            node = (ASTType *) ast; \
+            _tokenIndex = newTokenIndex; \
+            return returnValue; \
+        } else if (foundInCache) { \
+            debugPrintCheckCache(false); \
+            return returnValue; \
+        } \
+    } while (0)
+
+#define PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, minPrecedence) { \
+    if (LA() == T_THROW) { \
+        if (!parseThrowExpression(node)) \
+            return false; \
+    } else if (!parseCastExpression(node)) \
+        return false; \
+    \
+    parseExpressionWithOperatorPrecedence(node, minPrecedence); \
+    return true; \
+}
+
+Parser::Parser(TranslationUnit *unit)
+    : _translationUnit(unit),
+      _control(unit->control()),
+      _pool(unit->memoryPool()),
+      _languageFeatures(unit->languageFeatures()),
+      _tokenIndex(1),
+      _templateArguments(0),
+      _inFunctionBody(false),
+      _inExpressionStatement(false),
+      _expressionDepth(0),
+      _statementDepth(0),
+      _astCache(new ASTCache),
+      _expressionStatementAstCache(new ASTCache)
+{ }
+
+Parser::~Parser()
+{
+    delete _expressionStatementAstCache;
+    delete _astCache;
+}
+
+bool Parser::switchTemplateArguments(bool templateArguments)
+{
+    bool previousTemplateArguments = _templateArguments;
+    _templateArguments = templateArguments;
+    return previousTemplateArguments;
+}
+
+bool Parser::maybeSplitGreaterGreaterToken(int n)
+{
+    return _translationUnit->maybeSplitGreaterGreaterToken(_tokenIndex + n - 1);
+}
+
+bool Parser::skipUntil(int token)
+{
+    while (int tk = LA()) {
+        if (tk == token)
+            return true;
+
+        consumeToken();
+    }
+
+    return false;
+}
+
+void Parser::skipUntilDeclaration()
+{
+    for (; ; consumeToken()) {
+        switch (LA()) {
+        case T_EOF_SYMBOL:
+
+        // end of a block
+        case T_RBRACE:
+
+        // names
+        case T_IDENTIFIER:
+        case T_COLON_COLON:
+        case T_TILDE:
+        case T_OPERATOR:
+
+        // empty declaration
+        case T_SEMICOLON:
+
+        // member specification
+        case T_USING:
+        case T_TEMPLATE:
+        case T_PUBLIC:
+        case T_PROTECTED:
+        case T_PRIVATE:
+        case T_Q_SIGNALS:
+        case T_Q_SLOTS:
+        case T_Q_PROPERTY:
+        case T_Q_PRIVATE_PROPERTY:
+        case T_Q_ENUMS:
+        case T_Q_FLAGS:
+        case T_Q_INTERFACES:
+
+        // Qt function specifiers
+        case T_Q_SIGNAL:
+        case T_Q_SLOT:
+        case T_Q_INVOKABLE:
+
+        // declarations
+        case T_ENUM:
+        case T_NAMESPACE:
+        case T_INLINE:
+        case T_STATIC_ASSERT:
+        case T_ASM:
+        case T_EXPORT:
+        case T_AT_CLASS:
+        case T_AT_INTERFACE:
+        case T_AT_PROTOCOL:
+        case T_AT_IMPLEMENTATION:
+        case T_AT_END:
+            return;
+
+        default:
+            if (lookAtBuiltinTypeSpecifier() || lookAtClassKey() ||
+                lookAtFunctionSpecifier() || lookAtStorageClassSpecifier())
+                return;
+        } // switch
+    }
+}
+
+bool Parser::skipUntilStatement()
+{
+    while (int tk = LA()) {
+        switch (tk) {
+            case T_SEMICOLON:
+            case T_LBRACE:
+            case T_RBRACE:
+            case T_CONST:
+            case T_VOLATILE:
+            case T_IDENTIFIER:
+            case T_CASE:
+            case T_DEFAULT:
+            case T_IF:
+            case T_SWITCH:
+            case T_WHILE:
+            case T_DO:
+            case T_FOR:
+            case T_BREAK:
+            case T_CONTINUE:
+            case T_RETURN:
+            case T_GOTO:
+            case T_TRY:
+            case T_CATCH:
+            case T_THROW:
+            case T_CHAR:
+            case T_CHAR16_T:
+            case T_CHAR32_T:
+            case T_WCHAR_T:
+            case T_BOOL:
+            case T_SHORT:
+            case T_INT:
+            case T_LONG:
+            case T_SIGNED:
+            case T_UNSIGNED:
+            case T_FLOAT:
+            case T_DOUBLE:
+            case T_VOID:
+            case T_CLASS:
+            case T_STRUCT:
+            case T_UNION:
+            case T_ENUM:
+            case T_COLON_COLON:
+            case T_TEMPLATE:
+            case T_USING:
+                return true;
+
+            case T_AT_TRY:
+            case T_AT_SYNCHRONIZED:
+            case T_AT_THROW:
+                if (_languageFeatures.objCEnabled)
+                    return true;
+
+            default:
+                consumeToken();
+        }
+    }
+
+    return false;
+}
+
+bool Parser::skip(int l, int r)
+{
+    int count = 0;
+
+    while (int tk = LA()) {
+        if (tk == l)
+            ++count;
+        else if (tk == r)
+            --count;
+        else if (l != T_LBRACE && (tk == T_LBRACE ||
+                                   tk == T_RBRACE ||
+                                   tk == T_SEMICOLON))
+            return false;
+
+        if (count == 0)
+            return true;
+
+        consumeToken();
+    }
+
+    return false;
+}
+
+int Parser::find(int token, int stopAt)
+{
+    for (int i = 1; ; ++i) {
+        const int tk = LA(i);
+        if (!tk || tk == stopAt)
+            return 0;
+        if (tk == token)
+            return i;
+    }
+    return 0;
+}
+
+void Parser::match(int kind, unsigned *token)
+{
+    if (LA() == kind)
+        *token = consumeToken();
+    else {
+        *token = 0;
+        error(_tokenIndex, "expected token `%s' got `%s'",
+              Token::name(kind), tok().spell());
+    }
+}
+
+bool Parser::parseClassOrNamespaceName(NameAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_IDENTIFIER && (LA(2) == T_COLON_COLON || LA(2) == T_LESS)) {
+        unsigned identifier_token = cursor();
+
+        if (LA(2) == T_LESS) {
+            bool blocked = blockErrors(true);
+            if (parseTemplateId(node) && LA() == T_COLON_COLON) {
+                blockErrors(blocked);
+                return true;
+            }
+            blockErrors(blocked);
+        }
+
+        rewind(identifier_token);
+
+        if (LA(2) == T_COLON_COLON) {
+            SimpleNameAST *ast = new (_pool) SimpleNameAST;
+            ast->identifier_token = consumeToken();
+            node = ast;
+            return true;
+        }
+    } else if (LA() == T_TEMPLATE) {
+        unsigned template_token = consumeToken();
+        if (parseTemplateId(node, template_token) && LA() == T_COLON_COLON)
+            return true;
+        rewind(template_token);
+    }
+    return false;
+}
+
+bool Parser::parseTemplateId(NameAST *&node, unsigned template_token)
+{
+    DEBUG_THIS_RULE();
+
+    const unsigned start = cursor();
+
+    if (LA() == T_IDENTIFIER && LA(2) == T_LESS) {
+        TemplateIdAST *ast = new (_pool) TemplateIdAST;
+        ast->template_token = template_token;
+        ast->identifier_token = consumeToken();
+        ast->less_token = consumeToken();
+        if (maybeSplitGreaterGreaterToken() || LA() == T_GREATER || parseTemplateArgumentList(
+                ast->template_argument_list)) {
+            if (maybeSplitGreaterGreaterToken() || LA() == T_GREATER) {
+                ast->greater_token = consumeToken();
+                node = ast;
+                return true;
+            }
+        }
+    }
+
+    rewind(start);
+
+    return false;
+}
+
+bool Parser::parseNestedNameSpecifier(NestedNameSpecifierListAST *&node,
+                                      bool /*acceptTemplateId*/)
+{
+    DEBUG_THIS_RULE();
+    NestedNameSpecifierListAST **nested_name_specifier = &node;
+    NameAST *class_or_namespace_name = 0;
+    if (parseClassOrNamespaceName(class_or_namespace_name) && LA() == T_COLON_COLON) {
+        unsigned scope_token = consumeToken();
+
+        NestedNameSpecifierAST *name = new (_pool) NestedNameSpecifierAST;
+        name->class_or_namespace_name = class_or_namespace_name;
+        name->scope_token = scope_token;
+
+        *nested_name_specifier = new (_pool) NestedNameSpecifierListAST(name);
+        nested_name_specifier = &(*nested_name_specifier)->next;
+
+        while (parseClassOrNamespaceName(class_or_namespace_name) && LA() == T_COLON_COLON) {
+            scope_token = consumeToken();
+
+            name = new (_pool) NestedNameSpecifierAST;
+            name->class_or_namespace_name = class_or_namespace_name;
+            name->scope_token = scope_token;
+
+            *nested_name_specifier = new (_pool) NestedNameSpecifierListAST(name);
+            nested_name_specifier = &(*nested_name_specifier)->next;
+        }
+
+        // ### ugly hack
+        rewind(scope_token);
+        consumeToken();
+        return true;
+    }
+
+    return false;
+}
+
+bool Parser::parseNestedNameSpecifierOpt(NestedNameSpecifierListAST *&name, bool acceptTemplateId)
+{
+    DEBUG_THIS_RULE();
+    unsigned start = cursor();
+    if (! parseNestedNameSpecifier(name, acceptTemplateId))
+        rewind(start);
+    return true;
+}
+
+bool Parser::parseName(NameAST *&node, bool acceptTemplateId)
+{
+    DEBUG_THIS_RULE();
+    unsigned global_scope_token = 0;
+
+    switch (LA()) {
+    case T_COLON_COLON:
+    case T_IDENTIFIER:
+    case T_TILDE: // destructor-name-id
+    case T_OPERATOR: // operator-name-id
+    case T_TEMPLATE: // template introduced template-id
+      break;
+    default:
+      return false;
+    }
+
+    if (LA() == T_COLON_COLON)
+        global_scope_token = consumeToken();
+
+    NestedNameSpecifierListAST *nested_name_specifier = 0;
+    parseNestedNameSpecifierOpt(nested_name_specifier,
+                                /*acceptTemplateId=*/ true);
+
+    NameAST *unqualified_name = 0;
+    if (parseUnqualifiedName(unqualified_name,
+                             /*acceptTemplateId=*/ acceptTemplateId || nested_name_specifier != 0)) {
+        if (! global_scope_token && ! nested_name_specifier) {
+            node = unqualified_name;
+            return true;
+        }
+
+        QualifiedNameAST *ast = new (_pool) QualifiedNameAST;
+        ast->global_scope_token = global_scope_token;
+        ast->nested_name_specifier_list = nested_name_specifier;
+        ast->unqualified_name = unqualified_name;
+        node = ast;
+        return true;
+    }
+
+    return false;
+}
+
+bool Parser::parseTranslationUnit(TranslationUnitAST *&node)
+{
+    DEBUG_THIS_RULE();
+    TranslationUnitAST *ast = new (_pool) TranslationUnitAST;
+    DeclarationListAST **decl = &ast->declaration_list;
+
+    while (LA()) {
+        unsigned start_declaration = cursor();
+
+        DeclarationAST *declaration = 0;
+
+        if (parseDeclaration(declaration)) {
+            *decl = new (_pool) DeclarationListAST;
+            (*decl)->value = declaration;
+            decl = &(*decl)->next;
+        } else {
+            error(start_declaration, "expected a declaration");
+            rewind(start_declaration + 1);
+            skipUntilDeclaration();
+        }
+
+
+        if (TopLevelDeclarationProcessor *processor = _control->topLevelDeclarationProcessor()) {
+            if (!processor->processDeclaration(declaration))
+                break;
+        }
+
+        _templateArgumentList.clear();
+    }
+
+    node = ast;
+    return true;
+}
+
+bool Parser::parseEmptyDeclaration(DeclarationAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_SEMICOLON) {
+        EmptyDeclarationAST *ast = new (_pool) EmptyDeclarationAST;
+        ast->semicolon_token = consumeToken();
+        node = ast;
+        return true;
+    }
+    return false;
+}
+
+bool Parser::parseDeclaration(DeclarationAST *&node)
+{
+    DEBUG_THIS_RULE();
+    switch (LA()) {
+    case T_SEMICOLON:
+        return parseEmptyDeclaration(node);
+
+    case T_NAMESPACE:
+        return parseNamespace(node);
+
+    case T_USING:
+        return parseUsing(node);
+
+    case T_ASM:
+        return parseAsmDefinition(node);
+
+
+    case T_TEMPLATE:
+    case T_EXPORT:
+        return parseTemplateDeclaration(node);
+
+    // ObjcC++
+    case T_AT_CLASS:
+        return parseObjCClassForwardDeclaration(node);
+
+    case T_AT_INTERFACE:
+        return parseObjCInterface(node);
+
+    case T_AT_PROTOCOL:
+        return parseObjCProtocol(node);
+
+    case T_AT_IMPLEMENTATION:
+        return parseObjCImplementation(node);
+
+    case T_Q_DECLARE_INTERFACE:
+    {
+        consumeToken();
+        unsigned lparen_token = 0;
+        match(T_LPAREN, &lparen_token);
+        NameAST *name = 0;
+        parseName(name);
+        unsigned comma_token = 0;
+        match(T_COMMA, &comma_token);
+        unsigned string_literal = 0;
+        match(T_STRING_LITERAL, &string_literal);
+        unsigned rparen_token = 0;
+        match(T_RPAREN, &rparen_token);
+    }   return true;
+
+    case T_AT_END:
+        // TODO: should this be done here, or higher-up?
+        error(cursor(), "skip stray token `%s'", tok().spell());
+        consumeToken();
+        break;
+
+    case T_INLINE:
+        if (_languageFeatures.cxx11Enabled && LA(2) == T_NAMESPACE)
+            return parseNamespace(node);
+        return parseSimpleDeclaration(node);
+
+    case T_STATIC_ASSERT:
+        if (_languageFeatures.cxx11Enabled)
+            return parseStaticAssertDeclaration(node);
+        return parseSimpleDeclaration(node);
+
+    default: {
+        if (_languageFeatures.objCEnabled && LA() == T___ATTRIBUTE__) {
+            const unsigned start = cursor();
+            SpecifierListAST *attributes = 0, **attr = &attributes;
+            while (parseGnuAttributeSpecifier(*attr))
+                attr = &(*attr)->next;
+            if (LA() == T_AT_INTERFACE)
+                return parseObjCInterface(node, attributes);
+            else if (LA() == T_AT_PROTOCOL)
+                return parseObjCProtocol(node, attributes);
+            else if (LA() == T_AT_PROPERTY)
+                return parseObjCPropertyDeclaration(node, attributes);
+            rewind(start);
+        }
+
+        if (LA() == T_EXTERN && LA(2) == T_TEMPLATE)
+            return parseTemplateDeclaration(node);
+        else if (LA() == T_EXTERN && LA(2) == T_STRING_LITERAL)
+            return parseLinkageSpecification(node);
+        else
+            return parseSimpleDeclaration(node);
+    }   break; // default
+
+    } // end switch
+
+    return false;
+}
+
+bool Parser::parseLinkageSpecification(DeclarationAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_EXTERN && LA(2) == T_STRING_LITERAL) {
+        LinkageSpecificationAST *ast = new (_pool) LinkageSpecificationAST;
+        ast->extern_token = consumeToken();
+        ast->extern_type_token = consumeToken();
+
+        if (LA() == T_LBRACE)
+            parseLinkageBody(ast->declaration);
+        else
+            parseDeclaration(ast->declaration);
+
+        node = ast;
+        return true;
+    }
+
+    return false;
+}
+
+bool Parser::parseLinkageBody(DeclarationAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_LBRACE) {
+        LinkageBodyAST *ast = new (_pool) LinkageBodyAST;
+        ast->lbrace_token = consumeToken();
+        DeclarationListAST **declaration_ptr = &ast->declaration_list;
+
+        while (int tk = LA()) {
+            if (tk == T_RBRACE)
+                break;
+
+            unsigned start_declaration = cursor();
+            DeclarationAST *declaration = 0;
+            if (parseDeclaration(declaration)) {
+                *declaration_ptr = new (_pool) DeclarationListAST;
+                (*declaration_ptr)->value = declaration;
+                declaration_ptr = &(*declaration_ptr)->next;
+            } else {
+                error(start_declaration, "expected a declaration");
+                rewind(start_declaration + 1);
+                skipUntilDeclaration();
+            }
+
+            _templateArgumentList.clear();
+        }
+        match(T_RBRACE, &ast->rbrace_token);
+        node = ast;
+        return true;
+    }
+    return false;
+}
+
+bool Parser::parseStaticAssertDeclaration(DeclarationAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_STATIC_ASSERT)
+        return false;
+
+    StaticAssertDeclarationAST *ast = new (_pool) StaticAssertDeclarationAST;
+    ast->static_assert_token = consumeToken();
+    match(T_LPAREN, &ast->lparen_token);
+    parseConstantExpression(ast->expression);
+    match(T_COMMA, &ast->comma_token);
+    parseStringLiteral(ast->string_literal);
+    match(T_RPAREN, &ast->rparen_token);
+    match(T_SEMICOLON, &ast->semicolon_token);
+
+    node = ast;
+    return true;
+}
+
+// ### rename parseNamespaceAliarOrDeclaration?
+bool Parser::parseNamespace(DeclarationAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_NAMESPACE && !(_languageFeatures.cxx11Enabled && LA() == T_INLINE && LA(2) == T_NAMESPACE))
+        return false;
+
+    unsigned inline_token = 0;
+    if (_languageFeatures.cxx11Enabled && LA() == T_INLINE)
+        inline_token = consumeToken();
+
+    unsigned namespace_token = consumeToken();
+
+    if (LA() == T_IDENTIFIER && LA(2) == T_EQUAL) {
+        if (inline_token)
+            warning(inline_token, "namespace alias cannot be inline");
+        NamespaceAliasDefinitionAST *ast =
+                new (_pool) NamespaceAliasDefinitionAST;
+        ast->namespace_token = namespace_token;
+        ast->namespace_name_token = consumeToken();
+        ast->equal_token = consumeToken();
+        parseName(ast->name);
+        match(T_SEMICOLON, &ast->semicolon_token);
+        node = ast;
+        return true;
+    }
+
+    NamespaceAST *ast = new (_pool) NamespaceAST;
+    ast->inline_token = inline_token;
+    ast->namespace_token = namespace_token;
+    if (LA() == T_IDENTIFIER)
+        ast->identifier_token = consumeToken();
+    parseOptionalAttributeSpecifierSequence(ast->attribute_list);
+    if (LA() == T_LBRACE) {
+        parseLinkageBody(ast->linkage_body);
+    } else { // attempt to do error recovery
+        unsigned pos = cursor();
+        for (;LA() != T_EOF_SYMBOL; consumeToken()) {
+            switch (LA()) {
+            case T_IDENTIFIER:
+            case T_POUND:
+            case T_POUND_POUND:
+            case T___ATTRIBUTE__:
+            case T_LPAREN:
+            case T_RPAREN:
+            case T_DEFAULT:
+            case T_PUBLIC:
+            case T_PRIVATE:
+            case T_PROTECTED:
+                continue;
+            }
+            if (tok().isLiteral())
+                continue;
+            break;
+        }
+        if (LA() == T_LBRACE && parseLinkageBody(ast->linkage_body))
+            warning(pos, "expected '{' before '%s'", _translationUnit->tokenAt(pos).spell());
+        else
+            rewind(pos);
+    }
+    node = ast;
+    return true;
+}
+
+bool Parser::parseUsing(DeclarationAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_USING)
+        return false;
+
+    if (LA(2) == T_NAMESPACE)
+        return parseUsingDirective(node);
+
+    if (_languageFeatures.cxx11Enabled && LA(2) == T_IDENTIFIER && parseAliasDeclaration(node))
+        return true;
+
+    UsingAST *ast = new (_pool) UsingAST;
+    ast->using_token = consumeToken();
+
+    if (LA() == T_TYPENAME)
+        ast->typename_token = consumeToken();
+
+    parseName(ast->name);
+    match(T_SEMICOLON, &ast->semicolon_token);
+    node = ast;
+    return true;
+}
+
+bool Parser::parseUsingDirective(DeclarationAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_USING && LA(2) == T_NAMESPACE) {
+        UsingDirectiveAST *ast = new (_pool) UsingDirectiveAST;
+        ast->using_token = consumeToken();
+        ast->namespace_token = consumeToken();
+        if (! parseName(ast->name))
+            warning(cursor(), "expected `namespace name' before `%s'",
+                    tok().spell());
+        match(T_SEMICOLON, &ast->semicolon_token);
+        node = ast;
+        return true;
+    }
+    return false;
+}
+
+// alias-declaration = 'using' identifier attribute-specifier-seq(opt) '=' type-id ';'
+bool Parser::parseAliasDeclaration(DeclarationAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_USING || LA(2) != T_IDENTIFIER)
+        return false;
+
+    if (!find(T_EQUAL, T_SEMICOLON))
+        return false;
+
+    AliasDeclarationAST *alias = new (_pool) AliasDeclarationAST;
+    alias->using_token = consumeToken();
+    SimpleNameAST *name = new (_pool) SimpleNameAST;
+    name->identifier_token = consumeToken();
+    alias->name = name;
+
+    // ### attributes!
+    while (LA() != T_EQUAL)
+        consumeToken();
+
+    alias->equal_token = consumeToken();
+
+    ExpressionAST *expr = 0;
+    parseTypeId(expr);
+    if (expr)
+        alias->typeId = expr->asTypeId();
+
+    match(T_SEMICOLON, &alias->semicolon_token);
+
+    node = alias;
+    return true;
+}
+
+bool Parser::parseConversionFunctionId(NameAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_OPERATOR)
+        return false;
+    unsigned operator_token = consumeToken();
+    SpecifierListAST *type_specifier = 0;
+    if (! parseTypeSpecifier(type_specifier))
+        return false;
+    PtrOperatorListAST *ptr_operators = 0, **ptr_operators_tail = &ptr_operators;
+    while (parsePtrOperator(*ptr_operators_tail))
+        ptr_operators_tail = &(*ptr_operators_tail)->next;
+
+    ConversionFunctionIdAST *ast = new (_pool) ConversionFunctionIdAST;
+    ast->operator_token = operator_token;
+    ast->type_specifier_list = type_specifier;
+    ast->ptr_operator_list = ptr_operators;
+    node = ast;
+    return true;
+}
+
+bool Parser::parseOperatorFunctionId(NameAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_OPERATOR)
+        return false;
+    unsigned operator_token = consumeToken();
+
+    OperatorAST *op = 0;
+    if (! parseOperator(op))
+        return false;
+
+    OperatorFunctionIdAST *ast = new (_pool) OperatorFunctionIdAST;
+    ast->operator_token = operator_token;
+    ast->op = op;
+    node = ast;
+    return true;
+}
+
+Parser::TemplateArgumentListEntry *Parser::templateArgumentListEntry(unsigned tokenIndex)
+{
+    std::map<unsigned, TemplateArgumentListEntry>::iterator it =_templateArgumentList.find(tokenIndex);
+    if (it != _templateArgumentList.end())
+        return &it->second;
+
+    return 0;
+}
+
+bool Parser::parseTemplateArgumentList(ExpressionListAST *&node)
+{
+    DEBUG_THIS_RULE();
+
+    if (TemplateArgumentListEntry *entry = templateArgumentListEntry(cursor())) {
+        rewind(entry->cursor);
+        node = entry->ast;
+        return entry->ast != 0;
+    }
+
+    unsigned start = cursor();
+
+    ExpressionListAST **template_argument_ptr = &node;
+    ExpressionAST *template_argument = 0;
+    const bool cxx11Enabled = _languageFeatures.cxx11Enabled;
+    if (parseTemplateArgument(template_argument)) {
+        *template_argument_ptr = new (_pool) ExpressionListAST;
+        (*template_argument_ptr)->value = template_argument;
+        template_argument_ptr = &(*template_argument_ptr)->next;
+
+        if (cxx11Enabled && LA() == T_DOT_DOT_DOT)
+            consumeToken(); // ### store this token in the AST
+
+        while (LA() == T_COMMA) {
+            consumeToken(); // consume T_COMMA
+
+            if (parseTemplateArgument(template_argument)) {
+                *template_argument_ptr = new (_pool) ExpressionListAST;
+                (*template_argument_ptr)->value = template_argument;
+                template_argument_ptr = &(*template_argument_ptr)->next;
+
+                if (cxx11Enabled && LA() == T_DOT_DOT_DOT)
+                    consumeToken(); // ### store this token in the AST
+            }
+        }
+
+        if (_pool != _translationUnit->memoryPool()) {
+            MemoryPool *pool = _translationUnit->memoryPool();
+            ExpressionListAST *template_argument_list = node;
+            for (ExpressionListAST *iter = template_argument_list, **ast_iter = &node;
+                 iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+                *ast_iter = new (pool) ExpressionListAST((iter->value) ? iter->value->clone(pool) : 0);
+        }
+
+        _templateArgumentList.insert(std::make_pair(start, TemplateArgumentListEntry(start, cursor(), node)));
+        return true;
+    }
+
+    _templateArgumentList.insert(std::make_pair(start, TemplateArgumentListEntry(start, cursor(), 0)));
+    return false;
+}
+
+bool Parser::parseAsmDefinition(DeclarationAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_ASM)
+        return false;
+
+    AsmDefinitionAST *ast = new (_pool) AsmDefinitionAST;
+    ast->asm_token = consumeToken();
+
+    if (LA() == T_VOLATILE)
+        ast->volatile_token = consumeToken();
+
+    match(T_LPAREN, &ast->lparen_token);
+    unsigned string_literal_token = 0;
+    match(T_STRING_LITERAL, &string_literal_token);
+    while (LA() == T_STRING_LITERAL) {
+        consumeToken();
+    }
+    if (LA() == T_COLON) {
+        consumeToken(); // skip T_COLON
+        parseAsmOperandList();
+        if (LA() == T_COLON) {
+            consumeToken();
+            parseAsmOperandList();
+            if (LA() == T_COLON) {
+                consumeToken();
+                parseAsmClobberList();
+            }
+        } else if (LA() == T_COLON_COLON) {
+            consumeToken();
+            parseAsmClobberList();
+        }
+    } else if (LA() == T_COLON_COLON) {
+        consumeToken();
+        parseAsmOperandList();
+
+        if (LA() == T_COLON) {
+          consumeToken();
+          parseAsmClobberList();
+        }
+    }
+    match(T_RPAREN, &ast->rparen_token);
+    match(T_SEMICOLON, &ast->semicolon_token);
+    node = ast;
+    return true;
+}
+
+bool Parser::parseAsmOperandList()
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_STRING_LITERAL)
+        return true;
+
+    if (parseAsmOperand()) {
+        while (LA() == T_COMMA) {
+            consumeToken();
+            parseAsmOperand();
+        }
+        return true;
+    }
+
+    return false;
+}
+
+bool Parser::parseAsmOperand()
+{
+    DEBUG_THIS_RULE();
+    unsigned string_literal_token = 0;
+    match(T_STRING_LITERAL, &string_literal_token);
+
+    if (LA() == T_LBRACKET) {
+        /*unsigned lbracket_token = */ consumeToken();
+        match(T_STRING_LITERAL, &string_literal_token);
+        unsigned rbracket_token = 0;
+        match(T_RBRACKET, &rbracket_token);
+    }
+
+    unsigned lparen_token = 0, rparen_token = 0;
+    match(T_LPAREN, &lparen_token);
+    ExpressionAST *expression = 0;
+    parseExpression(expression);
+    match(T_RPAREN, &rparen_token);
+    return true;
+}
+
+bool Parser::parseAsmClobberList()
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_STRING_LITERAL)
+        return false;
+
+    unsigned string_literal_token = consumeToken();
+
+    while (LA() == T_COMMA) {
+        consumeToken();
+        match(T_STRING_LITERAL, &string_literal_token);
+    }
+
+    return true;
+}
+
+bool Parser::parseTemplateDeclaration(DeclarationAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (! (LA(1) == T_TEMPLATE || ((LA(1) == T_EXPORT || LA(1) == T_EXTERN)
+            && LA(2) == T_TEMPLATE)))
+        return false;
+
+    TemplateDeclarationAST *ast = new (_pool) TemplateDeclarationAST;
+
+    if (LA() == T_EXPORT || LA() == T_EXTERN)
+        ast->export_token = consumeToken();
+
+    ast->template_token = consumeToken();
+
+    if (LA() == T_LESS) {
+        ast->less_token = consumeToken();
+        if (maybeSplitGreaterGreaterToken() || LA() == T_GREATER || parseTemplateParameterList(ast->template_parameter_list))
+            match(T_GREATER, &ast->greater_token);
+    }
+
+    while (LA()) {
+        unsigned start_declaration = cursor();
+
+        ast->declaration = 0;
+        if (parseDeclaration(ast->declaration))
+            break;
+
+        error(start_declaration, "expected a declaration");
+        rewind(start_declaration + 1);
+        skipUntilDeclaration();
+    }
+
+    node = ast;
+    return true;
+}
+
+bool Parser::parseOperator(OperatorAST *&node) // ### FIXME
+{
+    DEBUG_THIS_RULE();
+    OperatorAST *ast = new (_pool) OperatorAST;
+
+    switch (LA()) {
+    case T_NEW:
+    case T_DELETE: {
+        ast->op_token = consumeToken();
+        if (LA() == T_LBRACKET) {
+            ast->open_token = consumeToken();
+            match(T_RBRACKET, &ast->close_token);
+        }
+    } break;
+
+    case T_PLUS:
+    case T_MINUS:
+    case T_STAR:
+    case T_SLASH:
+    case T_PERCENT:
+    case T_CARET:
+    case T_AMPER:
+    case T_PIPE:
+    case T_TILDE:
+    case T_EXCLAIM:
+    case T_LESS:
+    case T_GREATER:
+    case T_COMMA:
+    case T_AMPER_EQUAL:
+    case T_CARET_EQUAL:
+    case T_SLASH_EQUAL:
+    case T_EQUAL:
+    case T_EQUAL_EQUAL:
+    case T_EXCLAIM_EQUAL:
+    case T_GREATER_EQUAL:
+    case T_GREATER_GREATER_EQUAL:
+    case T_LESS_EQUAL:
+    case T_LESS_LESS_EQUAL:
+    case T_MINUS_EQUAL:
+    case T_PERCENT_EQUAL:
+    case T_PIPE_EQUAL:
+    case T_PLUS_EQUAL:
+    case T_STAR_EQUAL:
+    case T_TILDE_EQUAL:
+    case T_LESS_LESS:
+    case T_GREATER_GREATER:
+    case T_AMPER_AMPER:
+    case T_PIPE_PIPE:
+    case T_PLUS_PLUS:
+    case T_MINUS_MINUS:
+    case T_ARROW_STAR:
+    case T_DOT_STAR:
+    case T_ARROW:
+        ast->op_token = consumeToken();
+        break;
+
+    default:
+        if (LA() == T_LPAREN && LA(2) == T_RPAREN) {
+            ast->op_token = ast->open_token = consumeToken();
+            ast->close_token = consumeToken();
+        } else if (LA() == T_LBRACKET && LA(2) == T_RBRACKET) {
+            ast->op_token = ast->open_token = consumeToken();
+            ast->close_token = consumeToken();
+        } else {
+            return false;
+        }
+    }
+
+    node = ast;
+    return true;
+}
+
+bool Parser::parseCvQualifiers(SpecifierListAST *&node)
+{
+    DEBUG_THIS_RULE();
+
+    unsigned start = cursor();
+
+    SpecifierListAST **ast = &node;
+    while (*ast)
+        ast = &(*ast)->next;
+
+    while (int tk = LA()) {
+        if (tk == T_CONST || tk == T_VOLATILE) {
+            SimpleSpecifierAST *spec = new (_pool) SimpleSpecifierAST;
+            spec->specifier_token = consumeToken();
+            *ast = new (_pool) SpecifierListAST(spec);
+            ast = &(*ast)->next;
+        } else if (parseOptionalAttributeSpecifierSequence(*ast)) {
+            continue;
+        } else {
+            break;
+        }
+    }
+
+    return start != cursor();
+}
+
+bool Parser::parseRefQualifier(unsigned &ref_qualifier)
+{
+    DEBUG_THIS_RULE();
+
+    if (!_languageFeatures.cxx11Enabled)
+        return false;
+
+    if (LA() == T_AMPER || LA() == T_AMPER_AMPER) {
+        ref_qualifier = consumeToken();
+        return true;
+    }
+
+    return false;
+}
+
+/**
+ * \brief Handles override and final from C++ 2011, they are pseudo keywords and has special meaning only in function declaration
+ */
+bool Parser::parseOverrideFinalQualifiers(SpecifierListAST *&node)
+{
+    DEBUG_THIS_RULE();
+
+    if (!_languageFeatures.cxx11Enabled)
+        return false;
+
+    unsigned start = cursor();
+
+    SpecifierListAST **ast = &node;
+    while (*ast)
+        ast = &(*ast)->next;
+
+    while (LA() == T_IDENTIFIER) {
+        const Identifier &id = *(_translationUnit->tokenAt(cursor()).identifier);
+
+        if (id.equalTo(_control->cpp11Override())
+                || id.equalTo(_control->cpp11Final())) {
+            SimpleSpecifierAST *spec = new (_pool) SimpleSpecifierAST;
+            spec->specifier_token = consumeToken();
+            *ast = new (_pool) SpecifierListAST(spec);
+            ast = &(*ast)->next;
+        }
+        else {
+            break;
+        }
+    }
+
+    return (start != cursor());
+}
+
+bool Parser::parsePtrOperator(PtrOperatorListAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_AMPER || (_languageFeatures.cxx11Enabled && LA() == T_AMPER_AMPER)) {
+        ReferenceAST *ast = new (_pool) ReferenceAST;
+        ast->reference_token = consumeToken();
+        node = new (_pool) PtrOperatorListAST(ast);
+        return true;
+    } else if (LA() == T_STAR) {
+        PointerAST *ast = new (_pool) PointerAST;
+        ast->star_token = consumeToken();
+        parseCvQualifiers(ast->cv_qualifier_list);
+        node = new (_pool) PtrOperatorListAST(ast);
+        return true;
+    } else if (LA() == T_COLON_COLON || LA() == T_IDENTIFIER) {
+        unsigned scope_or_identifier_token = cursor();
+
+        unsigned global_scope_token = 0;
+        if (LA() == T_COLON_COLON)
+            global_scope_token = consumeToken();
+
+        NestedNameSpecifierListAST *nested_name_specifiers = 0;
+        bool has_nested_name_specifier = parseNestedNameSpecifier(nested_name_specifiers, true);
+        if (has_nested_name_specifier && LA() == T_STAR) {
+            PointerToMemberAST *ast = new (_pool) PointerToMemberAST;
+            ast->global_scope_token = global_scope_token;
+            ast->nested_name_specifier_list = nested_name_specifiers;
+            ast->star_token = consumeToken();
+            parseCvQualifiers(ast->cv_qualifier_list);
+            node = new (_pool) PtrOperatorListAST(ast);
+            return true;
+        }
+        rewind(scope_or_identifier_token);
+    }
+    return false;
+}
+
+bool Parser::parseTemplateArgument(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    unsigned start = cursor();
+    if (parseTypeId(node)) {
+        int index = 1;
+
+        if (_languageFeatures.cxx11Enabled && LA() == T_DOT_DOT_DOT)
+            index = 2;
+
+        if (LA(index) == T_COMMA || maybeSplitGreaterGreaterToken(index) || LA(index) == T_GREATER)
+            return true;
+    }
+
+    rewind(start);
+    bool previousTemplateArguments = switchTemplateArguments(true);
+    bool parsed = parseConstantExpression(node);
+    (void) switchTemplateArguments(previousTemplateArguments);
+    return parsed;
+}
+
+/** Parses a sequence of
+ *
+ * storage-class-specifier (unless noStorageSpecifier is true)
+ * trailing-type-specifier, which contains
+ *     cv-qualifier
+ *     simple-type-specifier
+ *     typename-specifier
+ *     elaborated-type-specifier
+ *
+ * If onlySimpleTypeSpecifiers is true, it only eats simple-type-specifiers
+ * and cv-qualifiers.
+ */
+bool Parser::parseDeclSpecifierSeq(SpecifierListAST *&decl_specifier_seq,
+                                   bool noStorageSpecifiers,
+                                   bool onlySimpleTypeSpecifiers)
+{
+    DEBUG_THIS_RULE();
+    bool has_type_specifier = false;
+    NameAST *named_type_specifier = 0;
+    SpecifierListAST **decl_specifier_seq_ptr = &decl_specifier_seq;
+    for (;;) {
+        if (! noStorageSpecifiers && ! onlySimpleTypeSpecifiers && lookAtStorageClassSpecifier()) {
+            // storage-class-specifier
+            SimpleSpecifierAST *spec = new (_pool) SimpleSpecifierAST;
+            spec->specifier_token = consumeToken();
+            *decl_specifier_seq_ptr = new (_pool) SpecifierListAST(spec);
+            decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
+        } else if (lookAtCVQualifier()) {
+            // cv-qualifier
+            SimpleSpecifierAST *spec = new (_pool) SimpleSpecifierAST;
+            spec->specifier_token = consumeToken();
+            *decl_specifier_seq_ptr = new (_pool) SpecifierListAST(spec);
+            decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
+        } else if (! named_type_specifier && lookAtBuiltinTypeSpecifier()) {
+            // parts of simple-type-specifier
+            parseBuiltinTypeSpecifier(*decl_specifier_seq_ptr);
+            decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
+            has_type_specifier = true;
+        } else if (! has_type_specifier && (LA() == T_COLON_COLON ||
+                                            LA() == T_IDENTIFIER)) {
+            // parts of simple-type-specifier
+            if (! parseName(named_type_specifier))
+                return false;
+            NamedTypeSpecifierAST *spec = new (_pool) NamedTypeSpecifierAST;
+            spec->name = named_type_specifier;
+            *decl_specifier_seq_ptr = new (_pool) SpecifierListAST(spec);
+            decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
+            has_type_specifier = true;
+        } else if (! onlySimpleTypeSpecifiers && ! has_type_specifier &&
+                   (LA() == T_TYPENAME || LA() == T_ENUM || lookAtClassKey())) {
+            // typename-specifier, elaborated-type-specifier
+            unsigned startOfElaboratedTypeSpecifier = cursor();
+            if (! parseElaboratedTypeSpecifier(*decl_specifier_seq_ptr)) {
+                error(startOfElaboratedTypeSpecifier, "expected an elaborated type specifier");
+                break;
+            }
+            decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
+            has_type_specifier = true;
+        } else
+            break;
+    }
+
+    return decl_specifier_seq != 0;
+}
+
+bool Parser::parseDeclaratorOrAbstractDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list)
+{
+    DEBUG_THIS_RULE();
+    unsigned start = cursor();
+    bool blocked = blockErrors(true);
+    if (parseDeclarator(node, decl_specifier_list)) {
+        blockErrors(blocked);
+        return true;
+    }
+    blockErrors(blocked);
+    rewind(start);
+    return parseAbstractDeclarator(node, decl_specifier_list);
+}
+
+bool Parser::parseCoreDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list, ClassSpecifierAST *)
+{
+    DEBUG_THIS_RULE();
+    unsigned start = cursor();
+    SpecifierListAST *attributes = 0;
+    parseOptionalAttributeSpecifierSequence(attributes);
+
+    PtrOperatorListAST *ptr_operators = 0, **ptr_operators_tail = &ptr_operators;
+    while (parsePtrOperator(*ptr_operators_tail))
+        ptr_operators_tail = &(*ptr_operators_tail)->next;
+
+    if (LA() == T_COLON_COLON || LA() == T_IDENTIFIER || LA() == T_TILDE || LA() == T_OPERATOR
+        || (_languageFeatures.cxx11Enabled && LA() == T_DOT_DOT_DOT && (LA(2) == T_COLON_COLON || LA(2) == T_IDENTIFIER))) {
+
+        unsigned dot_dot_dot_token = 0;
+
+        if (LA() == T_DOT_DOT_DOT)
+            dot_dot_dot_token = consumeToken();
+
+        NameAST *name = 0;
+        if (parseName(name)) {
+            DeclaratorIdAST *declarator_id = new (_pool) DeclaratorIdAST;
+            declarator_id->dot_dot_dot_token = dot_dot_dot_token;
+            declarator_id->name = name;
+            DeclaratorAST *ast = new (_pool) DeclaratorAST;
+            ast->attribute_list = attributes;
+            ast->ptr_operator_list = ptr_operators;
+            ast->core_declarator = declarator_id;
+            node = ast;
+            return true;
+        }
+    } else if (decl_specifier_list && LA() == T_LPAREN) {
+        if (attributes)
+            warning(attributes->firstToken(), "unexpected attribtues");
+
+        unsigned lparen_token = consumeToken();
+        DeclaratorAST *declarator = 0;
+        if (parseDeclarator(declarator, decl_specifier_list) && LA() == T_RPAREN) {
+            NestedDeclaratorAST *nested_declarator = new (_pool) NestedDeclaratorAST;
+            nested_declarator->lparen_token = lparen_token;
+            nested_declarator->declarator = declarator;
+            nested_declarator->rparen_token = consumeToken();
+            DeclaratorAST *ast = new (_pool) DeclaratorAST;
+            ast->ptr_operator_list = ptr_operators;
+            ast->core_declarator = nested_declarator;
+            node = ast;
+            return true;
+        }
+    }
+    rewind(start);
+    return false;
+}
+
+static bool maybeCppInitializer(DeclaratorAST *declarator)
+{
+    if (declarator->ptr_operator_list)
+        return false;
+    CoreDeclaratorAST *core_declarator = declarator->core_declarator;
+    if (! core_declarator)
+        return false;
+    DeclaratorIdAST *declarator_id = core_declarator->asDeclaratorId();
+    if (! declarator_id)
+        return false;
+    else if (! declarator_id->name)
+        return false;
+    else if (! declarator_id->name->asSimpleName())
+        return false;
+
+    return true;
+}
+
+bool Parser::parseDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list, ClassSpecifierAST *declaringClass)
+{
+    DEBUG_THIS_RULE();
+    if (! parseCoreDeclarator(node, decl_specifier_list, declaringClass))
+        return false;
+
+    PostfixDeclaratorListAST **postfix_ptr = &node->postfix_declarator_list;
+
+    for (;;) {
+        unsigned startOfPostDeclarator = cursor();
+
+        if (LA() == T_LPAREN) {
+            if (! declaringClass && LA(2) != T_RPAREN && maybeCppInitializer(node)) {
+                unsigned lparen_token = cursor();
+                ExpressionAST *initializer = 0;
+
+                bool blocked = blockErrors(true);
+                if (parseInitializer(initializer, &node->equal_token)) {
+                    // maybe the initializer also parses as a FunctionDeclarator?
+                    ExpressionListParenAST *expr = 0;
+                    if (initializer)
+                        expr = initializer->asExpressionListParen();
+                    if (expr) {
+                        if (expr->expression_list && expr->rparen_token && (LA() == T_COMMA || LA() == T_SEMICOLON)) {
+                            rewind(lparen_token);
+
+                            // check for ambiguous declarators.
+
+                            consumeToken();
+                            ParameterDeclarationClauseAST *parameter_declaration_clause = 0;
+                            if (parseParameterDeclarationClause(parameter_declaration_clause) && LA() == T_RPAREN) {
+                                unsigned rparen_token = consumeToken();
+
+                                FunctionDeclaratorAST *ast = new (_pool) FunctionDeclaratorAST;
+                                ast->lparen_token = lparen_token;
+                                ast->parameter_declaration_clause = parameter_declaration_clause;
+                                ast->as_cpp_initializer = initializer;
+                                ast->rparen_token = rparen_token;
+                                *postfix_ptr = new (_pool) PostfixDeclaratorListAST(ast);
+
+                                blockErrors(blocked);
+                                return true;
+                            }
+
+
+                            blockErrors(blocked);
+                            rewind(lparen_token);
+                            return true;
+                        }
+                    }
+                }
+
+                blockErrors(blocked);
+                rewind(lparen_token);
+            }
+
+            FunctionDeclaratorAST *ast = new (_pool) FunctionDeclaratorAST;
+            ast->lparen_token = consumeToken();
+            parseParameterDeclarationClause(ast->parameter_declaration_clause);
+            if (LA() != T_RPAREN) {
+                rewind(startOfPostDeclarator);
+                break;
+            }
+
+            ast->rparen_token = consumeToken();
+            // ### parse attributes
+            parseCvQualifiers(ast->cv_qualifier_list);
+            parseRefQualifier(ast->ref_qualifier_token);
+            parseExceptionSpecification(ast->exception_specification);
+
+            if (_languageFeatures.cxx11Enabled && ! node->ptr_operator_list && LA() == T_ARROW) {
+                // only allow if there is 1 type spec, which has to be 'auto'
+                bool hasAuto = false;
+                for (SpecifierListAST *iter = decl_specifier_list; !hasAuto && iter; iter = iter->next) {
+                    SpecifierAST *spec = iter->value;
+                    if (SimpleSpecifierAST *simpleSpec = spec->asSimpleSpecifier()) {
+                        if (_translationUnit->tokenKind(simpleSpec->specifier_token) == T_AUTO)
+                            hasAuto = true;
+                    }
+                }
+
+                if (hasAuto)
+                    parseTrailingReturnType(ast->trailing_return_type);
+            }
+
+            parseOverrideFinalQualifiers(ast->cv_qualifier_list);
+
+            *postfix_ptr = new (_pool) PostfixDeclaratorListAST(ast);
+            postfix_ptr = &(*postfix_ptr)->next;
+        } else if (LA() == T_LBRACKET) {
+            ArrayDeclaratorAST *ast = new (_pool) ArrayDeclaratorAST;
+            ast->lbracket_token = consumeToken();
+            if (LA() == T_RBRACKET || parseConstantExpression(ast->expression))
+                match(T_RBRACKET, &ast->rbracket_token);
+            *postfix_ptr = new (_pool) PostfixDeclaratorListAST(ast);
+            postfix_ptr = &(*postfix_ptr)->next;
+        } else
+            break;
+    }
+
+    if (LA() == T___ASM__ && LA(2) == T_LPAREN) { // ### store the asm specifier in the AST
+        consumeToken(); // skip __asm__
+        consumeToken(); // skip T_LPAREN
+
+        if (skipUntil(T_RPAREN))
+            consumeToken(); // skip T_RPAREN
+    }
+
+    parseOptionalAttributeSpecifierSequence(node->post_attribute_list);
+    return true;
+}
+
+bool Parser::parseAbstractCoreDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list)
+{
+    DEBUG_THIS_RULE();
+
+    PtrOperatorListAST *ptr_operators = 0, **ptr_operators_tail = &ptr_operators;
+    while (parsePtrOperator(*ptr_operators_tail))
+        ptr_operators_tail = &(*ptr_operators_tail)->next;
+
+    unsigned after_ptr_operators = cursor();
+
+    if (LA() == T_LPAREN && LA(2) != T_RPAREN) {
+        unsigned lparen_token = consumeToken();
+        DeclaratorAST *declarator = 0;
+        if (parseAbstractDeclarator(declarator, decl_specifier_list) && LA() == T_RPAREN) {
+            NestedDeclaratorAST *nested_declarator = new (_pool) NestedDeclaratorAST;
+            nested_declarator->lparen_token = lparen_token;
+            nested_declarator->declarator = declarator;
+            nested_declarator->rparen_token = consumeToken();
+            DeclaratorAST *ast = new (_pool) DeclaratorAST;
+            ast->ptr_operator_list = ptr_operators;
+            ast->core_declarator = nested_declarator;
+            node = ast;
+            return true;
+        }
+    }
+
+    rewind(after_ptr_operators);
+    if (ptr_operators) {
+        DeclaratorAST *ast = new (_pool) DeclaratorAST;
+        ast->ptr_operator_list = ptr_operators;
+        node = ast;
+    }
+
+    return true;
+}
+
+bool Parser::parseAbstractDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list)
+{
+    DEBUG_THIS_RULE();
+    if (! parseAbstractCoreDeclarator(node, decl_specifier_list))
+        return false;
+
+    PostfixDeclaratorListAST *postfix_declarators = 0,
+        **postfix_ptr = &postfix_declarators;
+
+    for (;;) {
+        if (LA() == T_LPAREN) {
+            FunctionDeclaratorAST *ast = new (_pool) FunctionDeclaratorAST;
+            ast->lparen_token = consumeToken();
+            if (LA() == T_RPAREN || parseParameterDeclarationClause(ast->parameter_declaration_clause)) {
+                if (LA() == T_RPAREN)
+                    ast->rparen_token = consumeToken();
+            }
+            parseCvQualifiers(ast->cv_qualifier_list);
+            parseRefQualifier(ast->ref_qualifier_token);
+            parseExceptionSpecification(ast->exception_specification);
+            *postfix_ptr = new (_pool) PostfixDeclaratorListAST(ast);
+            postfix_ptr = &(*postfix_ptr)->next;
+        } else if (LA() == T_LBRACKET) {
+            ArrayDeclaratorAST *ast = new (_pool) ArrayDeclaratorAST;
+            ast->lbracket_token = consumeToken();
+            if (LA() == T_RBRACKET || parseConstantExpression(ast->expression)) {
+                if (LA() == T_RBRACKET)
+                    ast->rbracket_token = consumeToken();
+            }
+            *postfix_ptr = new (_pool) PostfixDeclaratorListAST(ast);
+            postfix_ptr = &(*postfix_ptr)->next;
+        } else
+            break;
+    }
+
+    if (postfix_declarators) {
+        if (! node)
+            node = new (_pool) DeclaratorAST;
+
+        node->postfix_declarator_list = postfix_declarators;
+    }
+
+    return true;
+}
+
+/**
+ * @brief Reads enumeration type declaration, examples:
+ * @code
+    enum {
+        debug = 1
+    };
+    enum class Format {
+        FormatPNG,
+        FormatJPEG
+    };
+ * @endcode
+ */
+bool Parser::parseEnumSpecifier(SpecifierListAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_ENUM) {
+        EnumSpecifierAST *ast = new (_pool) EnumSpecifierAST;
+
+        ast->enum_token = consumeToken();
+        if (_languageFeatures.cxx11Enabled && (LA() == T_CLASS || LA() == T_STRUCT))
+            ast->key_token = consumeToken();
+
+        parseName(ast->name);
+
+        if (_languageFeatures.cxx11Enabled && LA() == T_COLON) {
+            ast->colon_token = consumeToken();
+            parseTypeSpecifier(ast->type_specifier_list);
+        }
+        if (LA() == T_LBRACE) {
+            ast->lbrace_token = consumeToken();
+            unsigned comma_token = 0;
+            EnumeratorListAST **enumerator_ptr = &ast->enumerator_list;
+            while (int tk = LA()) {
+                if (tk == T_RBRACE)
+                    break;
+
+                if (LA() != T_IDENTIFIER) {
+                    error(cursor(), "expected identifier before '%s'", tok().spell());
+                    skipUntil(T_IDENTIFIER);
+                }
+
+                if (parseEnumerator(*enumerator_ptr))
+                    enumerator_ptr = &(*enumerator_ptr)->next;
+
+                if (LA() == T_COMMA && LA(2) == T_RBRACE)
+                    ast->stray_comma_token = consumeToken();
+
+                if (LA() != T_RBRACE)
+                    match(T_COMMA, &comma_token);
+            }
+            match(T_RBRACE, &ast->rbrace_token);
+        } else if (!_languageFeatures.cxx11Enabled) {
+            return false;
+        }
+
+        node = new (_pool) SpecifierListAST(ast);
+        return true;
+    }
+    return false;
+}
+
+bool Parser::parseTemplateParameterList(DeclarationListAST *&node)
+{
+    DEBUG_THIS_RULE();
+    DeclarationListAST **template_parameter_ptr = &node;
+    DeclarationAST *declaration = 0;
+    if (parseTemplateParameter(declaration)) {
+        *template_parameter_ptr = new (_pool) DeclarationListAST;
+        (*template_parameter_ptr)->value = declaration;
+        template_parameter_ptr = &(*template_parameter_ptr)->next;
+
+        while (LA() == T_COMMA) {
+            consumeToken(); // XXX Store this token somewhere
+
+            declaration = 0;
+            if (parseTemplateParameter(declaration)) {
+                *template_parameter_ptr = new (_pool) DeclarationListAST;
+                (*template_parameter_ptr)->value = declaration;
+                template_parameter_ptr = &(*template_parameter_ptr)->next;
+            }
+        }
+        return true;
+    }
+    return false;
+}
+
+bool Parser::parseTemplateParameter(DeclarationAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (parseTypeParameter(node))
+        return true;
+    bool previousTemplateArguments = switchTemplateArguments(true);
+    ParameterDeclarationAST *ast = 0;
+    bool parsed = parseParameterDeclaration(ast);
+    node = ast;
+    (void) switchTemplateArguments(previousTemplateArguments);
+    return parsed;
+}
+
+bool Parser::parseTypenameTypeParameter(DeclarationAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_CLASS || LA() == T_TYPENAME) {
+        TypenameTypeParameterAST *ast = new (_pool) TypenameTypeParameterAST;
+        ast->classkey_token = consumeToken();
+        if (_languageFeatures.cxx11Enabled && LA() == T_DOT_DOT_DOT)
+            ast->dot_dot_dot_token = consumeToken();
+        parseName(ast->name);
+        if (LA() == T_EQUAL) {
+            ast->equal_token = consumeToken();
+            parseTypeId(ast->type_id);
+        }
+        node = ast;
+        return true;
+    }
+    return false;
+}
+
+bool Parser::parseTemplateTypeParameter(DeclarationAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_TEMPLATE) {
+        TemplateTypeParameterAST *ast = new (_pool) TemplateTypeParameterAST;
+        ast->template_token = consumeToken();
+        if (LA() == T_LESS)
+            ast->less_token = consumeToken();
+        parseTemplateParameterList(ast->template_parameter_list);
+        if (maybeSplitGreaterGreaterToken() || LA() == T_GREATER)
+            ast->greater_token = consumeToken();
+        if (LA() == T_CLASS)
+            ast->class_token = consumeToken();
+        if (_languageFeatures.cxx11Enabled && LA() == T_DOT_DOT_DOT)
+            ast->dot_dot_dot_token = consumeToken();
+
+        // parse optional name
+        parseName(ast->name);
+
+        if (LA() == T_EQUAL) {
+            ast->equal_token = consumeToken();
+            parseTypeId(ast->type_id);
+        }
+        node = ast;
+        return true;
+    }
+    return false;
+}
+
+bool Parser::lookAtTypeParameter()
+{
+    if (LA() == T_CLASS || LA() == T_TYPENAME) {
+        if (LA(2) == T_IDENTIFIER) {
+            switch (LA(3)) {
+            case T_EQUAL:
+            case T_COMMA:
+            case T_GREATER:
+                return true;
+
+            default:
+                return maybeSplitGreaterGreaterToken(3);
+            }
+        } else if (LA(2) == T_COLON_COLON) {
+            // found something like template <typename ::foo::bar>...
+            return false;
+        }
+
+        // recognized an anonymous template type parameter. e.g
+        //    template <typename>
+        return true;
+    }
+
+    return false;
+}
+
+
+bool Parser::parseTypeParameter(DeclarationAST *&node)
+{
+    DEBUG_THIS_RULE();
+
+    if (lookAtTypeParameter())
+        return parseTypenameTypeParameter(node);
+    else if (LA() == T_TEMPLATE)
+        return parseTemplateTypeParameter(node);
+    else
+        return false;
+}
+
+bool Parser::parseTypeId(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    CHECK_CACHE(ASTCache::TypeId, ExpressionAST);
+
+    SpecifierListAST *type_specifier = 0;
+    if (parseTypeSpecifier(type_specifier)) {
+        TypeIdAST *ast = new (_pool) TypeIdAST;
+        ast->type_specifier_list = type_specifier;
+        parseAbstractDeclarator(ast->declarator, type_specifier);
+        node = ast;
+        return true;
+    }
+    return false;
+}
+
+bool Parser::parseParameterDeclarationClause(ParameterDeclarationClauseAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_RPAREN)
+        return true; // nothing to do
+    CHECK_CACHE(ASTCache::ParameterDeclarationClause, ParameterDeclarationClauseAST);
+    const unsigned initialCursor = cursor();
+
+    ParameterDeclarationListAST *parameter_declarations = 0;
+
+    unsigned dot_dot_dot_token = 0;
+    if (LA() == T_DOT_DOT_DOT)
+        dot_dot_dot_token = consumeToken();
+    else {
+        parseParameterDeclarationList(parameter_declarations);
+
+        if (LA() == T_DOT_DOT_DOT) {
+            dot_dot_dot_token = consumeToken();
+        } else if (LA() == T_COMMA && LA(2) == T_DOT_DOT_DOT) {
+            consumeToken(); // skip comma
+            dot_dot_dot_token = consumeToken();
+        }
+    }
+
+    if (parameter_declarations || dot_dot_dot_token) {
+        ParameterDeclarationClauseAST *ast = new (_pool) ParameterDeclarationClauseAST;
+        ast->parameter_declaration_list = parameter_declarations;
+        ast->dot_dot_dot_token = dot_dot_dot_token;
+        node = ast;
+    }
+
+    const bool result = true;
+    _astCache->insert(ASTCache::ParameterDeclarationClause, initialCursor, node, cursor(), result);
+    return result;
+}
+
+bool Parser::parseParameterDeclarationList(ParameterDeclarationListAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_DOT_DOT_DOT || (LA() == T_COMMA && LA(2) == T_DOT_DOT_DOT))
+        return false; // nothing to do.
+
+    ParameterDeclarationListAST **parameter_declaration_ptr = &node;
+    ParameterDeclarationAST *declaration = 0;
+    if (parseParameterDeclaration(declaration)) {
+        *parameter_declaration_ptr = new (_pool) ParameterDeclarationListAST;
+        (*parameter_declaration_ptr)->value = declaration;
+        parameter_declaration_ptr = &(*parameter_declaration_ptr)->next;
+        while (LA() == T_COMMA) {
+            consumeToken();
+
+            if (LA() == T_DOT_DOT_DOT)
+                break;
+
+            declaration = 0;
+            if (parseParameterDeclaration(declaration)) {
+                *parameter_declaration_ptr = new (_pool) ParameterDeclarationListAST;
+                (*parameter_declaration_ptr)->value = declaration;
+                parameter_declaration_ptr = &(*parameter_declaration_ptr)->next;
+            }
+        }
+        return true;
+    }
+    return false;
+}
+
+bool Parser::parseParameterDeclaration(ParameterDeclarationAST *&node)
+{
+    DEBUG_THIS_RULE();
+    SpecifierListAST *decl_specifier_seq = 0;
+    if (parseDeclSpecifierSeq(decl_specifier_seq)) {
+        ParameterDeclarationAST *ast = new (_pool) ParameterDeclarationAST;
+        ast->type_specifier_list = decl_specifier_seq;
+        parseDeclaratorOrAbstractDeclarator(ast->declarator, decl_specifier_seq);
+        if (LA() == T_EQUAL) {
+            ast->equal_token = consumeToken();
+            if (!_languageFeatures.cxx11Enabled)
+                parseLogicalOrExpression(ast->expression);
+            else
+                parseInitializerClause0x(ast->expression);
+        }
+
+        node = ast;
+        return true;
+    }
+    return false;
+}
+
+const Identifier *Parser::className(ClassSpecifierAST *ast) const
+{
+  if (! ast)
+    return 0;
+
+  return identifier(ast->name);
+}
+
+const Identifier *Parser::identifier(NameAST *name) const
+{
+  if (! name)
+    return 0;
+
+  if (QualifiedNameAST *q = name->asQualifiedName())
+    name = q->unqualified_name;
+
+  if (name) {
+    if (SimpleNameAST *simple = name->asSimpleName())
+      return _translationUnit->identifier(simple->identifier_token);
+    else if (TemplateIdAST *template_id = name->asTemplateId())
+      return _translationUnit->identifier(template_id->identifier_token);
+  }
+
+  return 0;
+}
+
+bool Parser::parseClassSpecifier(SpecifierListAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (! lookAtClassKey())
+        return false;
+
+    unsigned classkey_token = consumeToken();
+
+    SpecifierListAST *attributes = 0;
+    parseOptionalAttributeSpecifierSequence(attributes);
+
+    if (LA(1) == T_IDENTIFIER && LA(2) == T_IDENTIFIER) {
+        const Identifier *id = tok(2).identifier;
+        if (!id->equalTo(_control->cpp11Final())) {
+            warning(cursor(), "skip identifier `%s'",
+                                      tok().spell());
+            consumeToken();
+        }
+    }
+
+    NameAST *name = 0;
+    parseName(name);
+
+    bool parsed = false;
+
+    const bool previousInFunctionBody = _inFunctionBody;
+    _inFunctionBody = false;
+
+    unsigned colon_token = 0;
+    unsigned dot_dot_dot_token = 0;
+    unsigned final_token = 0;
+
+    if (LA() == T_IDENTIFIER) {
+        const Identifier *id = tok().identifier;
+        if (id->equalTo(_control->cpp11Final()))
+            final_token = consumeToken();
+    }
+
+    if (LA() == T_COLON || LA() == T_LBRACE) {
+        if (!name) {
+            AnonymousNameAST *ast = new (_pool) AnonymousNameAST;
+            ast->class_token = classkey_token;
+            name = ast;
+        }
+
+        BaseSpecifierListAST *base_clause_list = 0;
+
+        if (LA() == T_COLON) {
+            colon_token = cursor();
+
+            parseBaseClause(base_clause_list);
+
+            if (_languageFeatures.cxx11Enabled && LA() == T_DOT_DOT_DOT)
+                dot_dot_dot_token = consumeToken();
+
+            if (LA() != T_LBRACE) {
+                error(cursor(), "expected `{' before `%s'", tok().spell());
+
+                const unsigned saved = cursor();
+
+                for (int n = 0; n < 3 && LA() != T_EOF_SYMBOL; ++n, consumeToken()) {
+                    if (LA() == T_LBRACE)
+                        break;
+                }
+
+                if (LA() != T_LBRACE)
+                    rewind(saved);
+            }
+        }
+
+        ClassSpecifierAST *ast = new (_pool) ClassSpecifierAST;
+        ast->classkey_token = classkey_token;
+        ast->attribute_list = attributes;
+        ast->final_token = final_token;
+        ast->name = name;
+        ast->colon_token = colon_token;
+        ast->base_clause_list = base_clause_list;
+        ast->dot_dot_dot_token = dot_dot_dot_token;
+
+        if (LA() == T_LBRACE)
+            ast->lbrace_token = consumeToken();
+
+        DeclarationListAST **declaration_ptr = &ast->member_specifier_list;
+        while (int tk = LA()) {
+            if (tk == T_RBRACE) {
+                ast->rbrace_token = consumeToken();
+                break;
+            }
+
+            unsigned start_declaration = cursor();
+            DeclarationAST *declaration = 0;
+            if (parseMemberSpecification(declaration, ast)) {
+                if (declaration) {  // paranoia check
+                    *declaration_ptr = new (_pool) DeclarationListAST;
+                    (*declaration_ptr)->value = declaration;
+                    declaration_ptr = &(*declaration_ptr)->next;
+                }
+
+                if (cursor() == start_declaration) { // more paranoia
+                    rewind(start_declaration + 1);
+                    skipUntilDeclaration();
+                }
+            } else {
+                error(start_declaration, "expected a declaration");
+                rewind(start_declaration + 1);
+                skipUntilDeclaration();
+            }
+        }
+        node = new (_pool) SpecifierListAST(ast);
+        parsed = true;
+    }
+
+    _inFunctionBody = previousInFunctionBody;
+
+    return parsed;
+}
+
+bool Parser::parseAccessDeclaration(DeclarationAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_PUBLIC || LA() == T_PROTECTED || LA() == T_PRIVATE || LA() == T_Q_SIGNALS || LA() == T_Q_SLOTS) {
+        bool isSignals = LA() == T_Q_SIGNALS;
+        bool isSlots = LA() == T_Q_SLOTS;
+        AccessDeclarationAST *ast = new (_pool) AccessDeclarationAST;
+        ast->access_specifier_token = consumeToken();
+        if (! isSignals && (LA() == T_Q_SLOTS || isSlots))
+            ast->slots_token = consumeToken();
+        match(T_COLON, &ast->colon_token);
+        node = ast;
+        return true;
+    }
+    return false;
+}
+
+/*
+ Q_PROPERTY(type name
+    (READ getFunction [WRITE setFunction]
+        | MEMBER memberName [(READ getFunction | WRITE setFunction)])
+    [RESET resetFunction]
+    [NOTIFY notifySignal]
+    [REVISION int]
+    [DESIGNABLE bool]
+    [SCRIPTABLE bool]
+    [STORED bool]
+    [USER bool]
+    [CONSTANT]
+    [FINAL])
+
+    Note that "type" appears to be any valid type. So these are valid:
+      Q_PROPERTY(const char *zoo READ zoo)
+      Q_PROPERTY(const class Blah *blah READ blah)
+
+    Furthermore, the only restriction on the order of the items in between the
+    parenthesis is that the type is the first parameter and the name comes after
+    the type. Especially, there seems to be no restriction on the READ/WRITE/MEMBER
+    order.
+*/
+bool Parser::parseQtPropertyDeclaration(DeclarationAST *&node)
+{
+    DEBUG_THIS_RULE();
+    const bool privateProperty = (LA() == T_Q_PRIVATE_PROPERTY);
+    if (LA() != T_Q_PROPERTY && !privateProperty)
+        return false;
+
+    QtPropertyDeclarationAST *ast = new (_pool)QtPropertyDeclarationAST;
+    ast->property_specifier_token = consumeToken();
+    if (LA() == T_LPAREN) {
+        ast->lparen_token = consumeToken();
+
+        if (privateProperty) {
+            if (parsePostfixExpression(ast->expression)) {
+                match(T_COMMA, &ast->comma_token);
+            } else {
+                error(cursor(), "expected expression before `%s'", tok().spell());
+                return true;
+            }
+        }
+
+        parseTypeId(ast->type_id);
+
+        SimpleNameAST *property_name = new (_pool) SimpleNameAST;
+        // special case: keywords are allowed for property names!
+        if (tok().isKeyword())
+            property_name->identifier_token = consumeToken();
+        else
+            match(T_IDENTIFIER, &property_name->identifier_token);
+
+        ast->property_name = property_name;
+        QtPropertyDeclarationItemListAST **iter = &ast->property_declaration_item_list;
+        while (true) {
+            if (LA() == T_RPAREN) {
+                ast->rparen_token = consumeToken();
+                node = ast;
+                break;
+            } else if (LA() == T_IDENTIFIER) {
+                QtPropertyDeclarationItemAST *item = 0;
+                switch (peekAtQtContextKeyword()) {
+                case Token_READ:
+                case Token_WRITE:
+                case Token_MEMBER:
+                case Token_RESET:
+                case Token_NOTIFY:
+                case Token_REVISION:
+                case Token_DESIGNABLE:
+                case Token_SCRIPTABLE:
+                case Token_STORED:
+                case Token_USER: {
+                    unsigned item_name_token = consumeToken();
+                    ExpressionAST *expr = 0;
+                    if (parsePostfixExpression(expr)) {
+                        QtPropertyDeclarationItemAST *bItem =
+                                new (_pool) QtPropertyDeclarationItemAST;
+                        bItem->item_name_token = item_name_token;
+                        bItem->expression = expr;
+                        item = bItem;
+                    } else {
+                        error(cursor(), "expected expression before `%s'", tok().spell());
+                    }
+                    break;
+                }
+
+                case Token_CONSTANT:
+                case Token_FINAL: {
+                    QtPropertyDeclarationItemAST *fItem = new (_pool) QtPropertyDeclarationItemAST;
+                    fItem->item_name_token = consumeToken();
+                    item = fItem;
+                    break;
+                }
+
+                default:
+                    error(cursor(), "expected `)' before `%s'", tok().spell());
+                    // skip the token
+                    consumeToken();
+                }
+                if (item) {
+                    *iter = new (_pool) QtPropertyDeclarationItemListAST;
+                    (*iter)->value = item;
+                    iter = &(*iter)->next;
+                }
+            } else if (!LA()) {
+                break;
+            } else {
+                error(cursor(), "expected `)' before `%s'", tok().spell());
+                // skip the token
+                consumeToken();
+            }
+        }
+    }
+    return true;
+}
+
+// q-enums-decl ::= 'Q_ENUMS' '(' q-enums-list? ')'
+// q-enums-list ::= identifier
+// q-enums-list ::= q-enums-list identifier
+//
+// Note: Q_ENUMS is a CPP macro with exactly 1 parameter.
+// Examples of valid uses:
+//   Q_ENUMS()
+//   Q_ENUMS(Priority)
+//   Q_ENUMS(Priority Severity)
+// so, these are not allowed:
+//   Q_ENUMS
+//   Q_ENUMS(Priority, Severity)
+bool Parser::parseQtEnumDeclaration(DeclarationAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_Q_ENUMS)
+        return false;
+
+    QtEnumDeclarationAST *ast = new (_pool) QtEnumDeclarationAST;
+    ast->enum_specifier_token = consumeToken();
+    match(T_LPAREN, &ast->lparen_token);
+    for (NameListAST **iter = &ast->enumerator_list; LA() && LA() != T_RPAREN; iter = &(*iter)->next) {
+        NameAST *name_ast = 0;
+        if (!parseName(name_ast))
+            break;
+        *iter = new (_pool) NameListAST;
+        (*iter)->value = name_ast;
+    }
+    match(T_RPAREN, &ast->rparen_token);
+    node = ast;
+    return true;
+}
+
+// q-flags-decl ::= 'Q_FLAGS' '(' q-flags-list? ')'
+// q-flags-list ::= identifier
+// q-flags-list ::= q-flags-list identifier
+//
+// Note: Q_FLAGS is a CPP macro with exactly 1 parameter.
+// Examples of valid uses:
+//   Q_FLAGS()
+//   Q_FLAGS(Orientation)
+//   Q_FLAGS(Orientation DropActions)
+// so, these are not allowed:
+//   Q_FLAGS
+//   Q_FLAGS(Orientation, DropActions)
+bool Parser::parseQtFlags(DeclarationAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_Q_FLAGS)
+        return false;
+
+    QtFlagsDeclarationAST *ast = new (_pool) QtFlagsDeclarationAST;
+    ast->flags_specifier_token = consumeToken();
+    match(T_LPAREN, &ast->lparen_token);
+    for (NameListAST **iter = &ast->flag_enums_list; LA() && LA() != T_RPAREN; iter = &(*iter)->next) {
+        NameAST *name_ast = 0;
+        if (!parseName(name_ast))
+            break;
+        *iter = new (_pool) NameListAST;
+        (*iter)->value = name_ast;
+    }
+    match(T_RPAREN, &ast->rparen_token);
+    node = ast;
+    return true;
+}
+
+// class-specifier ::=
+//   c++-class-specifier
+//   q-tag
+//   q-enums-of-flags
+//   q-class-info
+//   q-interfaces
+//   q-private-slot
+//
+// declaration ::=
+//   c++-declaration
+//   q-declare-interface
+//   q-declare-metatype
+//
+// q-tag ::=
+//   Q_OBJECT
+//   Q_GADGET
+//
+// q-enums-or-flags ::=
+//   (Q_ENUMS | Q_FLAGS) LPAREN name+ RPAREN
+//
+// q-class-info ::=
+//   Q_CLASS_INFO LPAREN string-literal COMMA STRING_LITERAL RPAREN
+//   Q_CLASS_INFO LPAREN string-literal COMMA IDENTIFIER LPAREN STRING_LITERAL RPAREN RPAREN
+
+// q-interfaces ::=
+//   Q_INTERFACES LPAREN (name q-constraints)* RPAREN
+//
+// q-constraints ::=
+//   (COLON name)*
+bool Parser::parseQtInterfaces(DeclarationAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_Q_INTERFACES)
+        return false;
+
+    QtInterfacesDeclarationAST *ast = new (_pool) QtInterfacesDeclarationAST;
+    ast->interfaces_token = consumeToken();
+    match(T_LPAREN, &ast->lparen_token);
+    for (QtInterfaceNameListAST **iter = &ast->interface_name_list; LA() && LA() != T_RPAREN; iter = &(*iter)->next) {
+        NameAST *name_ast = 0;
+        if (!parseName(name_ast))
+            break;
+        *iter = new (_pool) QtInterfaceNameListAST;
+        (*iter)->value = new (_pool) QtInterfaceNameAST;
+        (*iter)->value->interface_name = name_ast;
+        for (NameListAST **iter2 = &(*iter)->value->constraint_list; LA() && LA() == T_COLON; iter2 = &(*iter2)->next) {
+            /*unsigned colon_token =*/ consumeToken();
+            NameAST *name_ast2 = 0;
+            if (!parseName(name_ast2))
+                break;
+            *iter2 = new (_pool) NameListAST;
+            (*iter2)->value = name_ast2;
+        }
+    }
+
+    match(T_RPAREN, &ast->rparen_token);
+    node = ast;
+    return true;
+}
+
+// q-private-slot ::=
+//   Q_PRIVATE_SLOT LPAREN IDENTIFIER (LPAREN RPAREN)? COMMA q-function-declaration RPAREN
+//
+// q-function-declaration ::=
+//   decl-specifier-list declarator   [+ check for the function-declarator]
+//
+// q-declare-interface ::=
+//   Q_DECLARE_INTERFACE LPAREN name COMMA (STRING_LITERAL | IDENTIFIER) RPAREN
+//
+// q-declare-metatype ::=
+//   Q_DECLARE_METATYPE LPAREN name RPAREN SEMICOLON? [warning]
+
+bool Parser::parseMemberSpecification(DeclarationAST *&node, ClassSpecifierAST *declaringClass)
+{
+    DEBUG_THIS_RULE();
+    switch (LA()) {
+    case T_Q_OBJECT:
+    case T_Q_GADGET:
+    {
+        QtObjectTagAST *ast = new (_pool) QtObjectTagAST;
+        ast->q_object_token = consumeToken();
+        node = ast;
+        return true;
+    }
+
+    case T_Q_PRIVATE_SLOT:
+    {
+        QtPrivateSlotAST *ast = new (_pool) QtPrivateSlotAST;
+        ast->q_private_slot_token = consumeToken();
+        match(T_LPAREN, &ast->lparen_token);
+        match(T_IDENTIFIER, &ast->dptr_token);
+        if (LA() == T_LPAREN) {
+            ast->dptr_lparen_token = consumeToken();
+            match(T_RPAREN, &ast->dptr_rparen_token);
+        }
+        match(T_COMMA, &ast->comma_token);
+        (void) parseTypeSpecifier(ast->type_specifier_list);
+        parseDeclarator(ast->declarator, ast->type_specifier_list);
+        match(T_RPAREN, &ast->rparen_token);
+        node = ast;
+    }   return true;
+
+    case T_SEMICOLON:
+        return parseEmptyDeclaration(node);
+
+    case T_USING:
+        return parseUsing(node);
+
+    case T_TEMPLATE:
+        return parseTemplateDeclaration(node);
+
+    case T_Q_SIGNALS:
+    case T_PUBLIC:
+    case T_PROTECTED:
+    case T_PRIVATE:
+    case T_Q_SLOTS:
+        return parseAccessDeclaration(node);
+
+    case T_Q_PROPERTY:
+    case T_Q_PRIVATE_PROPERTY:
+        return parseQtPropertyDeclaration(node);
+
+    case T_Q_ENUMS:
+        return parseQtEnumDeclaration(node);
+
+    case T_Q_FLAGS:
+        return parseQtFlags(node);
+
+    case T_Q_INTERFACES:
+        return parseQtInterfaces(node);
+
+    case T_STATIC_ASSERT:
+        if (_languageFeatures.cxx11Enabled)
+            return parseStaticAssertDeclaration(node);
+        // fall-through
+
+    default:
+        return parseSimpleDeclaration(node, declaringClass);
+    } // switch
+}
+
+bool Parser::parseCtorInitializer(CtorInitializerAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_COLON) {
+        unsigned colon_token = consumeToken();
+
+        CtorInitializerAST *ast = new (_pool) CtorInitializerAST;
+        ast->colon_token = colon_token;
+
+        parseMemInitializerList(ast->member_initializer_list);
+
+        if (_languageFeatures.cxx11Enabled && LA() == T_DOT_DOT_DOT)
+            ast->dot_dot_dot_token = consumeToken();
+
+        node = ast;
+        return true;
+    }
+    return false;
+}
+
+bool Parser::parseElaboratedTypeSpecifier(SpecifierListAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (lookAtClassKey() || LA() == T_ENUM || LA() == T_TYPENAME) {
+        unsigned classkey_token = consumeToken();
+
+        SpecifierListAST *attributes = 0;
+        parseOptionalAttributeSpecifierSequence(attributes);
+        NameAST *name = 0;
+        if (parseName(name)) {
+            ElaboratedTypeSpecifierAST *ast = new (_pool) ElaboratedTypeSpecifierAST;
+            ast->classkey_token = classkey_token;
+            ast->attribute_list = attributes;
+            ast->name = name;
+            node = new (_pool) SpecifierListAST(ast);
+            return true;
+        }
+    }
+    return false;
+}
+
+bool Parser::parseExceptionSpecification(ExceptionSpecificationAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_THROW) {
+        DynamicExceptionSpecificationAST *ast = new (_pool) DynamicExceptionSpecificationAST;
+        ast->throw_token = consumeToken();
+        if (LA() == T_LPAREN)
+            ast->lparen_token = consumeToken();
+        if (LA() == T_DOT_DOT_DOT)
+            ast->dot_dot_dot_token = consumeToken();
+        else
+            parseTypeIdList(ast->type_id_list);
+        if (LA() == T_RPAREN)
+            ast->rparen_token = consumeToken();
+        node = ast;
+        return true;
+    } else if (_languageFeatures.cxx11Enabled && LA() == T_NOEXCEPT) {
+        NoExceptSpecificationAST *ast = new (_pool) NoExceptSpecificationAST;
+        ast->noexcept_token = consumeToken();
+        if (LA() == T_LPAREN) {
+            ast->lparen_token = consumeToken();
+            parseConstantExpression(ast->expression);
+            match(T_RPAREN, &ast->rparen_token);
+        }
+        node = ast;
+        return true;
+    }
+    return false;
+}
+
+bool Parser::parseEnumerator(EnumeratorListAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_IDENTIFIER) {
+        EnumeratorAST *ast = new (_pool) EnumeratorAST;
+        ast->identifier_token = consumeToken();
+
+        if (LA() == T_EQUAL) {
+            ast->equal_token = consumeToken();
+            parseConstantExpression(ast->expression);
+        }
+
+        node = new (_pool) EnumeratorListAST;
+        node->value = ast;
+        return true;
+    }
+    return false;
+}
+
+bool Parser::parseInitDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list,
+                                 ClassSpecifierAST *declaringClass) // ### rewrite me
+{
+    DEBUG_THIS_RULE();
+
+    if (declaringClass && LA() == T_COLON) {
+        // anonymous bit-field declaration.
+
+    } else if (! parseDeclarator(node, decl_specifier_list, declaringClass)) {
+        return false;
+    }
+
+    if (LA() == T_ASM && LA(2) == T_LPAREN) { // ### FIXME
+        consumeToken();
+
+        if (skip(T_LPAREN, T_RPAREN))
+            consumeToken();
+    }
+
+    const bool isFunctionDeclarator = node
+            && node->postfix_declarator_list
+            && node->postfix_declarator_list->lastValue()
+            && node->postfix_declarator_list->lastValue()->asFunctionDeclarator();
+    if (declaringClass && LA() == T_COLON
+            && (! node || ! node->postfix_declarator_list)) {
+        unsigned colon_token = consumeToken();
+        ExpressionAST *expression = 0;
+        if (parseConstantExpression(expression) && (LA() == T_COMMA ||
+                                                    LA() == T_SEMICOLON)) {
+            // recognized a bitfielddeclarator.
+            if (! node)
+                node = new (_pool) DeclaratorAST;
+            node->initializer = expression;
+            return true;
+        }
+        rewind(colon_token);
+    } else if (isFunctionDeclarator && declaringClass && node->core_declarator && LA() == T_EQUAL && LA(3) == T_SEMICOLON) { // = 0, = delete, = default
+        if (!_languageFeatures.cxx11Enabled || LA(2) == T_NUMERIC_LITERAL) {
+            parseInitializer(node->initializer, &node->equal_token);
+        } else {
+            node->equal_token = consumeToken();
+
+            IdExpressionAST *id_expr = new (_pool) IdExpressionAST;
+            node->initializer = id_expr;
+
+            SimpleNameAST *simple_name = new (_pool) SimpleNameAST;
+            id_expr->name = simple_name;
+            simple_name->identifier_token = consumeToken();
+        }
+    } else if (node->core_declarator && (LA() == T_EQUAL || (_languageFeatures.cxx11Enabled && !isFunctionDeclarator && LA() == T_LBRACE) || (! declaringClass && LA() == T_LPAREN))) {
+        parseInitializer(node->initializer, &node->equal_token);
+    }
+    return true;
+}
+
+bool Parser::parseBaseClause(BaseSpecifierListAST *&node)
+{
+    DEBUG_THIS_RULE();
+
+    if (LA() == T_COLON) {
+        consumeToken(); // ### remove me
+
+        BaseSpecifierListAST **ast = &node;
+        if (parseBaseSpecifier(*ast)) {
+            ast = &(*ast)->next;
+
+            while (LA() == T_COMMA) {
+                consumeToken(); // consume T_COMMA
+
+                if (parseBaseSpecifier(*ast))
+                    ast = &(*ast)->next;
+            }
+        }
+
+        return true;
+    }
+    return false;
+}
+
+bool Parser::parseInitializer(ExpressionAST *&node, unsigned *equals_token)
+{
+    DEBUG_THIS_RULE();
+
+    return parseInitializer0x(node, equals_token);
+}
+
+bool Parser::parseInitializer0x(ExpressionAST *&node, unsigned *equals_token)
+{
+    DEBUG_THIS_RULE();
+
+    if ((_languageFeatures.cxx11Enabled && LA() == T_LBRACE) || LA() == T_EQUAL) {
+        if (LA() == T_EQUAL)
+            *equals_token = cursor();
+
+        return parseBraceOrEqualInitializer0x(node);
+    }
+
+    else if (LA() == T_LPAREN) {
+        return parseExpressionListParen(node);
+    }
+
+    return false;
+}
+
+bool Parser::parseBraceOrEqualInitializer0x(ExpressionAST *&node)
+{
+    if (LA() == T_EQUAL) {
+        consumeToken();
+        parseInitializerClause0x(node);
+        return true;
+
+    } else if (LA() == T_LBRACE) {
+        return parseBracedInitList0x(node);
+
+    }
+
+    return false;
+}
+
+/*
+    initializer-clause:
+        assignment-expression
+        braced-init-list
+        designated-initializer
+
+    If the next token is a T_LBRACKET, it could be the begin of either
+
+        * a C++11 lambda-introducer (parsed by parseAssignmentExpression)
+        * or a C99 designator (parsed by parseDesignatedInitializer).
+
+    Because currently C99 and C++11 Support is activated at the same time,
+    first try to parse the assignment-expression. If this fails, try to
+    parse a designated-initializer.
+
+    TODO:
+        As soon as there will be only "one active language", parse either
+        the assignment-expression or the designated-initializer, not both.
+ */
+bool Parser::parseInitializerClause0x(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_LBRACE)
+        return parseBracedInitList0x(node);
+
+    if (parseAssignmentExpression(node))
+        return true;
+    return parseDesignatedInitializer(node);
+}
+
+bool Parser::parseInitializerList0x(ExpressionListAST *&node)
+{
+    ExpressionListAST **expression_list_ptr = &node;
+    ExpressionAST *expression = 0;
+
+    if (parseInitializerClause0x(expression)) {
+        *expression_list_ptr = new (_pool) ExpressionListAST;
+        (*expression_list_ptr)->value = expression;
+        expression_list_ptr = &(*expression_list_ptr)->next;
+
+        if (_languageFeatures.cxx11Enabled && LA() == T_DOT_DOT_DOT && (LA(2) == T_COMMA || LA(2) == T_RBRACE || LA(2) == T_RPAREN))
+            consumeToken(); // ### create an argument pack
+
+        while (LA() == T_COMMA && LA(2) != T_RBRACE) {
+            consumeToken(); // consume T_COMMA
+
+            if (parseInitializerClause0x(expression)) {
+                *expression_list_ptr = new (_pool) ExpressionListAST;
+                (*expression_list_ptr)->value = expression;
+
+                if (_languageFeatures.cxx11Enabled && LA() == T_DOT_DOT_DOT && (LA(2) == T_COMMA || LA(2) == T_RBRACE || LA(2) == T_RPAREN))
+                    consumeToken(); // ### create an argument pack
+
+                expression_list_ptr = &(*expression_list_ptr)->next;
+            }
+        }
+    }
+
+    return true;
+}
+
+bool Parser::parseBracedInitList0x(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_LBRACE)
+        return false;
+
+    BracedInitializerAST *ast = new (_pool) BracedInitializerAST;
+    ast->lbrace_token = consumeToken();
+
+    parseInitializerList0x(ast->expression_list);
+
+    if (LA() == T_COMMA && LA(2) == T_RBRACE)
+        ast->comma_token = consumeToken();
+
+    match(T_RBRACE, &ast->rbrace_token);
+    node = ast;
+    return true;
+}
+
+bool Parser::parseMemInitializerList(MemInitializerListAST *&node)
+{
+    DEBUG_THIS_RULE();
+    MemInitializerListAST **initializer = &node;
+
+    if (parseMemInitializer(*initializer)) {
+        initializer = &(*initializer)->next;
+
+        while (true) {
+
+            if (LA() == T_LBRACE)
+                break;
+
+            else if (_languageFeatures.cxx11Enabled && LA() == T_DOT_DOT_DOT && LA(2) == T_LBRACE)
+                break;
+
+            else if (LA() == T_COMMA
+                     || (LA() == T_IDENTIFIER
+                         && (LA(2) == T_LPAREN || LA(2) == T_COLON_COLON || (_languageFeatures.cxx11Enabled && LA(2) == T_LBRACE)))) {
+                if (LA() != T_COMMA)
+                    error(cursor(), "expected `,'");
+                else
+                    consumeToken();
+
+                if (parseMemInitializer(*initializer))
+                    initializer = &(*initializer)->next;
+                else
+                    error(cursor(), "expected a member initializer");
+
+            } else break;
+        }
+
+        if (_languageFeatures.cxx11Enabled && LA() == T_DOT_DOT_DOT) {
+            if (LA(2) != T_LBRACE)
+                error(cursor(), "expected `{'");
+
+        } else if (LA() != T_LBRACE) {
+            error(cursor(), "expected `{'");
+        }
+
+        return true;
+    }
+
+    return false;
+}
+
+bool Parser::parseMemInitializer(MemInitializerListAST *&node)
+{
+    DEBUG_THIS_RULE();
+    NameAST *name = 0;
+    if (! parseName(name))
+        return false;
+
+    MemInitializerAST *ast = new (_pool) MemInitializerAST;
+    ast->name = name;
+
+    if (LA() == T_LPAREN) {
+        parseExpressionListParen(ast->expression);
+    } else if (_languageFeatures.cxx11Enabled && LA() == T_LBRACE) {
+        parseBracedInitList0x(ast->expression);
+    } else {
+        if (!_languageFeatures.cxx11Enabled)
+            error(cursor(), "expected '('");
+        else
+            error(cursor(), "expected '(' or '{'");
+        return false;
+    }
+
+    node = new (_pool) MemInitializerListAST;
+    node->value = ast;
+    return true;
+}
+
+bool Parser::parseTypeIdList(ExpressionListAST *&node)
+{
+    DEBUG_THIS_RULE();
+    ExpressionListAST **expression_list_ptr = &node;
+    ExpressionAST *typeId = 0;
+    if (parseTypeId(typeId)) {
+        *expression_list_ptr = new (_pool) ExpressionListAST;
+        (*expression_list_ptr)->value = typeId;
+        expression_list_ptr = &(*expression_list_ptr)->next;
+
+        if (_languageFeatures.cxx11Enabled && LA() == T_DOT_DOT_DOT)
+            consumeToken(); // ### store this token
+
+        while (LA() == T_COMMA) {
+            consumeToken();
+
+            if (parseTypeId(typeId)) {
+                *expression_list_ptr = new (_pool) ExpressionListAST;
+                (*expression_list_ptr)->value = typeId;
+                expression_list_ptr = &(*expression_list_ptr)->next;
+
+                if (_languageFeatures.cxx11Enabled && LA() == T_DOT_DOT_DOT)
+                    consumeToken(); // ### store this token
+            }
+        }
+        return true;
+    }
+
+    return false;
+}
+
+bool Parser::parseExpressionList(ExpressionListAST *&node)
+{
+    DEBUG_THIS_RULE();
+    CHECK_CACHE(ASTCache::ExpressionList, ExpressionListAST);
+    unsigned initialCursor = cursor();
+
+    if (_languageFeatures.cxx11Enabled) {
+        const bool result = parseInitializerList0x(node);
+        _astCache->insert(ASTCache::ExpressionList, initialCursor, (AST *) node, cursor(), result);
+        return result;
+    }
+
+    ExpressionListAST **expression_list_ptr = &node;
+    ExpressionAST *expression = 0;
+    if (parseAssignmentExpression(expression)) {
+        *expression_list_ptr = new (_pool) ExpressionListAST;
+        (*expression_list_ptr)->value = expression;
+        expression_list_ptr = &(*expression_list_ptr)->next;
+        while (LA() == T_COMMA) {
+            consumeToken(); // consume T_COMMA
+
+            if (parseAssignmentExpression(expression)) {
+                *expression_list_ptr = new (_pool) ExpressionListAST;
+                (*expression_list_ptr)->value = expression;
+                expression_list_ptr = &(*expression_list_ptr)->next;
+            }
+        }
+        const bool result = true;
+        _astCache->insert(ASTCache::ExpressionList, initialCursor, (AST *) node, cursor(), result);
+        return result;
+    }
+
+    const bool result = false;
+    _astCache->insert(ASTCache::ExpressionList, initialCursor, 0, cursor(), result);
+    return result;
+}
+
+bool Parser::parseBaseSpecifier(BaseSpecifierListAST *&node)
+{
+    DEBUG_THIS_RULE();
+    BaseSpecifierAST *ast = new (_pool) BaseSpecifierAST;
+
+    if (LA() == T_VIRTUAL) {
+        ast->virtual_token = consumeToken();
+
+        int tk = LA();
+        if (tk == T_PUBLIC || tk == T_PROTECTED || tk == T_PRIVATE)
+            ast->access_specifier_token = consumeToken();
+    } else {
+        int tk = LA();
+        if (tk == T_PUBLIC || tk == T_PROTECTED || tk == T_PRIVATE)
+            ast->access_specifier_token = consumeToken();
+
+        if (LA() == T_VIRTUAL)
+            ast->virtual_token = consumeToken();
+    }
+
+    parseName(ast->name);
+    if (! ast->name)
+        error(cursor(), "expected class-name");
+
+    node = new (_pool) BaseSpecifierListAST;
+    node->value = ast;
+    return true;
+}
+
+bool Parser::parseInitializerList(ExpressionListAST *&node)
+{
+    DEBUG_THIS_RULE();
+    ExpressionListAST **initializer_ptr = &node;
+    ExpressionAST *initializer = 0;
+    if (parseInitializerClause(initializer)) {
+        *initializer_ptr = new (_pool) ExpressionListAST;
+        (*initializer_ptr)->value = initializer;
+        initializer_ptr = &(*initializer_ptr)->next;
+        while (LA() == T_COMMA) {
+            consumeToken(); // consume T_COMMA
+            initializer = 0;
+            parseInitializerClause(initializer);
+            *initializer_ptr = new (_pool) ExpressionListAST;
+            (*initializer_ptr)->value = initializer;
+            initializer_ptr = &(*initializer_ptr)->next;
+        }
+    }
+
+    if (_languageFeatures.cxx11Enabled && LA() == T_DOT_DOT_DOT)
+        consumeToken(); // ### store this token
+
+    return true;
+}
+
+bool Parser::parseInitializerClause(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_LBRACE) {
+        ArrayInitializerAST *ast = new (_pool) ArrayInitializerAST;
+        ast->lbrace_token = consumeToken();
+        parseInitializerList(ast->expression_list);
+        match(T_RBRACE, &ast->rbrace_token);
+        node = ast;
+        return true;
+    }
+    return parseAssignmentExpression(node);
+}
+
+bool Parser::parseUnqualifiedName(NameAST *&node, bool acceptTemplateId)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_TILDE && LA(2) == T_IDENTIFIER) {
+        DestructorNameAST *ast = new (_pool) DestructorNameAST;
+        ast->tilde_token = consumeToken();
+        parseUnqualifiedName(ast->unqualified_name);
+        node = ast;
+        return true;
+    } else if (LA() == T_OPERATOR) {
+        unsigned operator_token = cursor();
+        if (parseOperatorFunctionId(node))
+            return true;
+        rewind(operator_token);
+        return parseConversionFunctionId(node);
+     } else if (LA() == T_IDENTIFIER) {
+        unsigned identifier_token = cursor();
+        if (acceptTemplateId && LA(2) == T_LESS) {
+            bool blocked = blockErrors(true);
+            if (parseTemplateId(node)
+                    && (! _templateArguments || (LA() == T_COMMA  || maybeSplitGreaterGreaterToken() || LA() == T_GREATER ||
+                                                 LA() == T_LPAREN || LA() == T_RPAREN  ||
+                                                 LA() == T_STAR || LA() == T_AMPER || // ptr-operators
+                                                 LA() == T_COLON_COLON))) {
+                blockErrors(blocked);
+                return true;
+            }
+            blockErrors(blocked);
+        }
+        rewind(identifier_token);
+        SimpleNameAST *ast = new (_pool) SimpleNameAST;
+        ast->identifier_token = consumeToken();
+        node = ast;
+        return true;
+    } else if (LA() == T_TEMPLATE) {
+        unsigned template_token = consumeToken();
+        if (parseTemplateId(node, template_token))
+            return true;
+        rewind(template_token);
+    }
+    return false;
+}
+
+bool Parser::parseStringLiteral(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (! (LA() == T_STRING_LITERAL
+           || LA() == T_WIDE_STRING_LITERAL
+           || LA() == T_UTF8_STRING_LITERAL
+           || LA() == T_UTF16_STRING_LITERAL
+           || LA() == T_UTF32_STRING_LITERAL
+           || LA() == T_RAW_STRING_LITERAL
+           || LA() == T_RAW_WIDE_STRING_LITERAL
+           || LA() == T_RAW_UTF8_STRING_LITERAL
+           || LA() == T_RAW_UTF16_STRING_LITERAL
+           || LA() == T_RAW_UTF32_STRING_LITERAL)) {
+        return false;
+    }
+
+    StringLiteralAST **ast = reinterpret_cast<StringLiteralAST **> (&node);
+
+    while (LA() == T_STRING_LITERAL
+           || LA() == T_WIDE_STRING_LITERAL
+           || LA() == T_UTF8_STRING_LITERAL
+           || LA() == T_UTF16_STRING_LITERAL
+           || LA() == T_UTF32_STRING_LITERAL
+           || LA() == T_RAW_STRING_LITERAL
+           || LA() == T_RAW_WIDE_STRING_LITERAL
+           || LA() == T_RAW_UTF8_STRING_LITERAL
+           || LA() == T_RAW_UTF16_STRING_LITERAL
+           || LA() == T_RAW_UTF32_STRING_LITERAL) {
+        *ast = new (_pool) StringLiteralAST;
+        (*ast)->literal_token = consumeToken();
+        ast = &(*ast)->next;
+    }
+    return true;
+}
+
+bool Parser::parseExpressionStatement(StatementAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_SEMICOLON) {
+        ExpressionStatementAST *ast = new (_pool) ExpressionStatementAST;
+        match(T_SEMICOLON, &ast->semicolon_token);
+        node = ast;
+        return true;
+    }
+
+    const bool wasInExpressionStatement = _inExpressionStatement;
+    _inExpressionStatement = true;
+
+    // switch to the temp pool and cache
+    MemoryPool *previousPool = _pool;
+    _pool = &_expressionStatementTempPool;
+    ASTCache *previousASTCache = _astCache;
+    _astCache = _expressionStatementAstCache;
+
+    bool parsed = false;
+
+    ExpressionAST *expression = 0;
+    if (parseExpression(expression)) {
+        ExpressionStatementAST *ast = new (previousPool) ExpressionStatementAST;
+        if (expression)
+            ast->expression = expression->clone(previousPool);
+        match(T_SEMICOLON, &ast->semicolon_token);
+        node = ast;
+        parsed = true;
+    }
+
+    _inExpressionStatement = wasInExpressionStatement;
+
+    if (! _inExpressionStatement) {
+        // rewind the memory pool and cache after parsing a toplevel expression statement.
+        _expressionStatementTempPool.reset();
+        _astCache->clear();
+    }
+
+    // restore the pool and cache
+    _pool = previousPool;
+    _astCache = previousASTCache;
+
+    return parsed;
+}
+
+bool Parser::parseStatement(StatementAST *&node, bool blockLabeledStatement)
+{
+    DEBUG_THIS_RULE();
+    switch (LA()) {
+    case T_WHILE:
+        return parseWhileStatement(node);
+
+    case T_DO:
+        return parseDoStatement(node);
+
+    case T_Q_FOREACH:
+        return parseForeachStatement(node);
+
+    case T_FOR:
+        return parseForStatement(node);
+
+    case T_IF:
+        return parseIfStatement(node);
+
+    case T_SWITCH:
+        return parseSwitchStatement(node);
+
+    case T_TRY:
+        return parseTryBlockStatement(node, 0);
+
+    case T_CASE:
+    case T_DEFAULT:
+        if (blockLabeledStatement)
+            return false;
+        return parseLabeledStatement(node);
+
+    case T_BREAK:
+        return parseBreakStatement(node);
+
+    case T_CONTINUE:
+        return parseContinueStatement(node);
+
+    case T_GOTO:
+        return parseGotoStatement(node);
+
+    case T_RETURN:
+        return parseReturnStatement(node);
+
+    case T_LBRACE:
+        return parseCompoundStatement(node);
+
+    case T_ASM:
+    case T_NAMESPACE:
+    case T_USING:
+    case T_TEMPLATE:
+    case T_CLASS: case T_STRUCT: case T_UNION:
+        return parseDeclarationStatement(node);
+
+    case T_SEMICOLON: {
+        ExpressionStatementAST *ast = new (_pool) ExpressionStatementAST;
+        ast->semicolon_token = consumeToken();
+        node = ast;
+        return true;
+    }
+
+    case T_AT_TRY:
+        return _languageFeatures.objCEnabled && parseObjCTryStatement(node);
+
+    case T_AT_SYNCHRONIZED:
+        return _languageFeatures.objCEnabled && parseObjCSynchronizedStatement(node);
+
+    case T_AT_THROW:
+        return _languageFeatures.objCEnabled && parseObjCThrowStatement(node);
+
+    case T_Q_D:
+    case T_Q_Q: {
+        QtMemberDeclarationAST *ast = new (_pool) QtMemberDeclarationAST;
+        ast->q_token = consumeToken();
+        match(T_LPAREN, &ast->lparen_token);
+        parseTypeId(ast->type_id);
+        match(T_RPAREN, &ast->rparen_token);
+        node = ast;
+    } return true;
+
+    case T_EMIT:
+    case T_Q_EMIT: {
+        // Simply skip the emit token and parse as an expression statement - no strong
+        // reason to have an specific ast type.
+        consumeToken();
+        ExpressionAST *expression = 0;
+        if (parsePostfixExpression(expression)) {
+            ExpressionStatementAST *ast = new (_pool) ExpressionStatementAST;
+            ast->expression = expression;
+            match(T_SEMICOLON, &ast->semicolon_token);
+            node = ast;
+            return true;
+        }
+        error(cursor(), "expected statement");
+        return false;
+    }
+
+    default:
+        if (LA() == T_IDENTIFIER && LA(2) == T_COLON) {
+            if (blockLabeledStatement)
+                return false;
+            return parseLabeledStatement(node);
+        }
+
+        return parseExpressionOrDeclarationStatement(node);
+    } // switch
+    return false; //Avoid compiler warning
+}
+
+bool Parser::parseBreakStatement(StatementAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_BREAK) {
+        BreakStatementAST *ast = new (_pool) BreakStatementAST;
+        ast->break_token = consumeToken();
+        match(T_SEMICOLON, &ast->semicolon_token);
+        node = ast;
+        return true;
+    }
+    return false;
+}
+
+bool Parser::parseContinueStatement(StatementAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_CONTINUE) {
+        ContinueStatementAST *ast = new (_pool) ContinueStatementAST;
+        ast->continue_token = consumeToken();
+        match(T_SEMICOLON, &ast->semicolon_token);
+        node = ast;
+        return true;
+    }
+    return false;
+}
+
+bool Parser::parseGotoStatement(StatementAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_GOTO) {
+        GotoStatementAST *ast = new (_pool) GotoStatementAST;
+        ast->goto_token = consumeToken();
+        match(T_IDENTIFIER, &ast->identifier_token);
+        match(T_SEMICOLON, &ast->semicolon_token);
+        node = ast;
+        return true;
+    }
+    return false;
+}
+
+bool Parser::parseReturnStatement(StatementAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_RETURN) {
+        ReturnStatementAST *ast = new (_pool) ReturnStatementAST;
+        ast->return_token = consumeToken();
+        if (_languageFeatures.cxx11Enabled && LA() == T_LBRACE)
+            parseBracedInitList0x(ast->expression);
+        else
+            parseExpression(ast->expression);
+        match(T_SEMICOLON, &ast->semicolon_token);
+        node = ast;
+        return true;
+    }
+    return false;
+}
+
+bool Parser::maybeAmbiguousStatement(DeclarationStatementAST *ast, StatementAST *&node)
+{
+  const unsigned start = ast->firstToken();
+  const unsigned end = ast->lastToken();
+  const bool blocked = blockErrors(true);
+
+  bool maybeAmbiguous = false;
+
+  StatementAST *stmt = 0;
+  if (parseExpressionStatement(stmt)) {
+    if (stmt->firstToken() == start && stmt->lastToken() == end) {
+      maybeAmbiguous = true;
+      node = stmt;
+    }
+  }
+
+  rewind(end);
+  (void) blockErrors(blocked);
+  return maybeAmbiguous;
+}
+
+bool Parser::parseExpressionOrDeclarationStatement(StatementAST *&node)
+{
+    DEBUG_THIS_RULE();
+
+    if (LA() == T_SEMICOLON)
+        return parseExpressionStatement(node);
+
+    const unsigned start = cursor();
+
+    if (lookAtCVQualifier()
+            || lookAtStorageClassSpecifier()
+            || lookAtBuiltinTypeSpecifier()
+            || LA() == T_TYPENAME
+            || LA() == T_ENUM
+            || lookAtClassKey()
+            || (LA() == T_STATIC_ASSERT && _languageFeatures.cxx11Enabled)) {
+        return parseDeclarationStatement(node);
+    }
+
+    if (LA() == T_IDENTIFIER || (LA() == T_COLON_COLON && LA(2) == T_IDENTIFIER)) {
+        const bool blocked = blockErrors(true);
+
+        ExpressionAST *expression = 0;
+        const bool hasExpression = parseExpression(expression);
+        const unsigned afterExpression = cursor();
+
+        if (hasExpression/* && LA() == T_SEMICOLON*/) {
+            //const unsigned semicolon_token = consumeToken();
+            unsigned semicolon_token = 0;
+            if (LA() == T_SEMICOLON)
+                semicolon_token = cursor();
+
+            ExpressionStatementAST *as_expression = new (_pool) ExpressionStatementAST;
+            as_expression->expression = expression;
+            as_expression->semicolon_token = semicolon_token;
+            node = as_expression; // well, at least for now.
+
+            bool invalidAssignment = false;
+            if (BinaryExpressionAST *binary = expression->asBinaryExpression()) {
+                const int binop = _translationUnit->tokenKind(binary->binary_op_token);
+                if (binop == T_EQUAL) {
+                    if (! binary->left_expression->asBinaryExpression()) {
+                        (void) blockErrors(blocked);
+                        node = as_expression;
+                        match(T_SEMICOLON, &as_expression->semicolon_token);
+                        return true;
+                    } else {
+                        invalidAssignment = true;
+                    }
+                }
+            } else if (CallAST *call = expression->asCall()) {
+                if (call->base_expression->asIdExpression() != 0) {
+                    (void) blockErrors(blocked);
+                    node = as_expression;
+                    match(T_SEMICOLON, &as_expression->semicolon_token);
+                    return true;
+                }
+            }
+
+            rewind(start);
+
+            DeclarationAST *declaration = 0;
+            if (parseSimpleDeclaration(declaration)) {
+                DeclarationStatementAST *as_declaration = new (_pool) DeclarationStatementAST;
+                as_declaration->declaration = declaration;
+
+                SimpleDeclarationAST *simple = declaration->asSimpleDeclaration();
+                if (! semicolon_token || invalidAssignment || semicolon_token != simple->semicolon_token ||
+                        (simple->decl_specifier_list != 0 && simple->declarator_list != 0)) {
+                    node = as_declaration;
+                    (void) blockErrors(blocked);
+                    return true;
+                }
+
+                ExpressionOrDeclarationStatementAST *ast = new (_pool) ExpressionOrDeclarationStatementAST;
+                ast->declaration = as_declaration;
+                ast->expression = as_expression;
+                node = ast;
+                (void) blockErrors(blocked);
+                return true;
+            }
+
+            (void) blockErrors(blocked);
+
+            rewind(afterExpression);
+            match(T_SEMICOLON, &as_expression->semicolon_token);
+            return true;
+        }
+
+        rewind(start);
+        (void) blockErrors(blocked);
+
+        return parseDeclarationStatement(node);
+    }
+
+    rewind(start);
+    return parseExpressionStatement(node);
+}
+
+bool Parser::parseCondition(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    unsigned start = cursor();
+
+    bool blocked = blockErrors(true);
+    SpecifierListAST *type_specifier = 0;
+    if (parseTypeSpecifier(type_specifier)) {
+        DeclaratorAST *declarator = 0;
+        if (parseInitDeclarator(declarator, type_specifier, /*declaringClass=*/ 0)) {
+            if (declarator->initializer && declarator->equal_token) {
+                ConditionAST *ast = new (_pool) ConditionAST;
+                ast->type_specifier_list = type_specifier;
+                ast->declarator = declarator;
+                node = ast;
+                blockErrors(blocked);
+                return true;
+            }
+        }
+    }
+
+    blockErrors(blocked);
+    rewind(start);
+    return parseExpression(node);
+}
+
+bool Parser::parseWhileStatement(StatementAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_WHILE) {
+        WhileStatementAST *ast = new (_pool) WhileStatementAST;
+        ast->while_token = consumeToken();
+        match(T_LPAREN, &ast->lparen_token);
+        parseCondition(ast->condition);
+        match(T_RPAREN, &ast->rparen_token);
+        parseStatement(ast->statement);
+        node = ast;
+        return true;
+    }
+    return true;
+}
+
+bool Parser::parseDoStatement(StatementAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_DO) {
+        DoStatementAST *ast = new (_pool) DoStatementAST;
+        ast->do_token = consumeToken();
+        parseStatement(ast->statement);
+        match(T_WHILE, &ast->while_token);
+        match(T_LPAREN, &ast->lparen_token);
+        parseExpression(ast->expression);
+        match(T_RPAREN, &ast->rparen_token);
+        match(T_SEMICOLON, &ast->semicolon_token);
+        node = ast;
+        return true;
+    }
+    return false;
+}
+
+bool Parser::parseForeachStatement(StatementAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_Q_FOREACH) {
+        ForeachStatementAST *ast = new (_pool) ForeachStatementAST;
+        ast->foreach_token = consumeToken();
+        match(T_LPAREN, &ast->lparen_token);
+
+        unsigned startOfTypeSpecifier = cursor();
+        bool blocked = blockErrors(true);
+
+        if (parseTypeSpecifier(ast->type_specifier_list))
+            parseDeclarator(ast->declarator, ast->type_specifier_list);
+
+        if (! ast->type_specifier_list || ! ast->declarator) {
+            ast->type_specifier_list = 0;
+            ast->declarator = 0;
+
+            blockErrors(blocked);
+            rewind(startOfTypeSpecifier);
+            parseAssignmentExpression(ast->initializer);
+        }
+
+        blockErrors(blocked);
+
+        match(T_COMMA, &ast->comma_token);
+        parseExpression(ast->expression);
+        match(T_RPAREN, &ast->rparen_token);
+        parseStatement(ast->statement);
+
+        node = ast;
+        return true;
+    }
+    return false;
+}
+
+bool Parser::parseForStatement(StatementAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_FOR)
+        return false;
+
+    unsigned for_token = consumeToken();
+    unsigned lparen_token = 0;
+    match(T_LPAREN, &lparen_token);
+
+    unsigned startOfTypeSpecifier = cursor();
+    bool blocked = blockErrors(true);
+
+    if (_languageFeatures.objCEnabled) {
+        ObjCFastEnumerationAST *ast = new (_pool) ObjCFastEnumerationAST;
+        ast->for_token = for_token;
+        ast->lparen_token = lparen_token;
+
+        if (parseTypeSpecifier(ast->type_specifier_list))
+            parseDeclarator(ast->declarator, ast->type_specifier_list);
+
+        if ((ast->type_specifier_list || ast->declarator) && !peekAtObjCContextKeyword(Token_in)) {
+            // woops, probably parsed too much: "in" got parsed as a declarator. Let's redo it:
+            ast->type_specifier_list = 0;
+            ast->declarator = 0;
+
+            rewind(startOfTypeSpecifier);
+            parseDeclarator(ast->declarator, ast->type_specifier_list);
+        }
+
+        if (! ast->type_specifier_list || ! ast->declarator) {
+            ast->type_specifier_list = 0;
+            ast->declarator = 0;
+
+            rewind(startOfTypeSpecifier);
+            parseAssignmentExpression(ast->initializer);
+        }
+
+        if (parseObjCContextKeyword(Token_in, ast->in_token)) {
+            blockErrors(blocked);
+
+            parseExpression(ast->fast_enumeratable_expression);
+            match(T_RPAREN, &ast->rparen_token);
+            parseStatement(ast->statement);
+
+            node = ast;
+            return true;
+        }
+
+        // there was no "in" token, so we continue with a normal for-statement
+        rewind(startOfTypeSpecifier);
+    }
+
+    if (_languageFeatures.cxx11Enabled) {
+        RangeBasedForStatementAST *ast = new (_pool) RangeBasedForStatementAST;
+        ast->for_token = for_token;
+        ast->lparen_token = lparen_token;
+
+        if (parseTypeSpecifier(ast->type_specifier_list))
+            parseDeclarator(ast->declarator, ast->type_specifier_list);
+
+        if ((ast->type_specifier_list || ast->declarator) && LA() == T_COLON) {
+            ast->colon_token = consumeToken();
+            blockErrors(blocked);
+
+            if (LA() == T_LBRACE)
+                parseBracedInitList0x(ast->expression);
+            else
+                parseExpression(ast->expression);
+            match(T_RPAREN, &ast->rparen_token);
+            parseStatement(ast->statement);
+
+            // We need both type specifier and declarator for C++11 range-based for
+            if (!ast->type_specifier_list || !ast->declarator)
+               error(for_token, "expected declaration with type specifier");
+
+            node = ast;
+            return true;
+        }
+        rewind(startOfTypeSpecifier);
+    }
+
+    blockErrors(blocked);
+
+    // Normal C/C++ for-statement parsing
+    ForStatementAST *ast = new (_pool) ForStatementAST;
+
+    ast->for_token = for_token;
+    ast->lparen_token = lparen_token;
+    parseForInitStatement(ast->initializer);
+    parseCondition(ast->condition);
+    match(T_SEMICOLON, &ast->semicolon_token);
+    parseExpression(ast->expression);
+    match(T_RPAREN, &ast->rparen_token);
+    parseStatement(ast->statement);
+
+    node = ast;
+    return true;
+}
+
+bool Parser::parseForInitStatement(StatementAST *&node)
+{
+    DEBUG_THIS_RULE();
+    return parseExpressionOrDeclarationStatement(node);
+}
+
+bool Parser::parseCompoundStatement(StatementAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_LBRACE) {
+        if (_statementDepth > MAX_STATEMENT_DEPTH)
+            return false;
+        ++_statementDepth;
+
+        CompoundStatementAST *ast = new (_pool) CompoundStatementAST;
+        ast->lbrace_token = consumeToken();
+
+        // ### TODO: the GNU "local label" extension: "__label__ X, Y, Z;"
+        // These are only allowed at the start of a compound stmt regardless of the language.
+
+        StatementListAST **statement_ptr = &ast->statement_list;
+        while (int tk = LA()) {
+            if (tk == T_RBRACE)
+                break;
+
+            unsigned start_statement = cursor();
+            StatementAST *statement = 0;
+            if (! parseStatement(statement)) {
+                rewind(start_statement + 1);
+                skipUntilStatement();
+            } else {
+                *statement_ptr = new (_pool) StatementListAST;
+                (*statement_ptr)->value = statement;
+                statement_ptr = &(*statement_ptr)->next;
+            }
+        }
+        match(T_RBRACE, &ast->rbrace_token);
+        node = ast;
+        --_statementDepth;
+        return true;
+    }
+    return false;
+}
+
+bool Parser::parseIfStatement(StatementAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_IF) {
+        IfStatementAST *ast = new (_pool) IfStatementAST;
+        ast->if_token = consumeToken();
+        match(T_LPAREN, &ast->lparen_token);
+        parseCondition(ast->condition);
+        match(T_RPAREN, &ast->rparen_token);
+        if (! parseStatement(ast->statement))
+            error(cursor(), "expected statement");
+        if (LA() == T_ELSE) {
+            ast->else_token = consumeToken();
+            if (! parseStatement(ast->else_statement))
+                error(cursor(), "expected statement");
+        }
+        node = ast;
+        return true;
+    }
+    return false;
+}
+
+bool Parser::parseSwitchStatement(StatementAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_SWITCH) {
+        SwitchStatementAST *ast = new (_pool) SwitchStatementAST;
+        ast->switch_token = consumeToken();
+        match(T_LPAREN, &ast->lparen_token);
+        parseCondition(ast->condition);
+        match(T_RPAREN, &ast->rparen_token);
+        parseStatement(ast->statement);
+        node = ast;
+        return true;
+    }
+    return false;
+}
+
+bool Parser::parseLabeledStatement(StatementAST *&node)
+{
+    DEBUG_THIS_RULE();
+    switch (LA()) {
+    case T_IDENTIFIER:
+        if (LA(2) == T_COLON) {
+            LabeledStatementAST *ast = new (_pool) LabeledStatementAST;
+            ast->label_token = consumeToken();
+            ast->colon_token = consumeToken();
+            parseStatement(ast->statement, /*blockLabeledStatement =*/ true);
+            node = ast;
+            return true;
+        }
+        break;
+
+    case T_DEFAULT: {
+        LabeledStatementAST *ast = new (_pool) LabeledStatementAST;
+        ast->label_token = consumeToken();
+        match(T_COLON, &ast->colon_token);
+        parseStatement(ast->statement, /*blockLabeledStatement =*/ true);
+        node = ast;
+        return true;
+    }
+
+    case T_CASE: {
+        CaseStatementAST *ast = new (_pool) CaseStatementAST;
+        ast->case_token = consumeToken();
+        parseConstantExpression(ast->expression);
+        match(T_COLON, &ast->colon_token);
+        parseStatement(ast->statement, /*blockLabeledStatement =*/ true);
+        node = ast;
+        return true;
+    }
+
+    default:
+        break;
+    } // switch
+    return false;
+}
+
+bool Parser::parseBlockDeclaration(DeclarationAST *&node)
+{
+    DEBUG_THIS_RULE();
+    switch (LA()) {
+    case T_USING:
+        return parseUsing(node);
+
+    case T_ASM:
+        return parseAsmDefinition(node);
+
+    case T_NAMESPACE:
+        return parseNamespaceAliasDefinition(node);
+
+    case T_STATIC_ASSERT:
+        if (_languageFeatures.cxx11Enabled)
+            return parseStaticAssertDeclaration(node);
+        // fall-through
+
+    default:
+        return parseSimpleDeclaration(node);
+    } // switch
+
+}
+
+bool Parser::parseNamespaceAliasDefinition(DeclarationAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_NAMESPACE && LA(2) == T_IDENTIFIER && LA(3) == T_EQUAL) {
+        NamespaceAliasDefinitionAST *ast = new (_pool) NamespaceAliasDefinitionAST;
+        ast->namespace_token = consumeToken();
+        ast->namespace_name_token = consumeToken();
+        ast->equal_token = consumeToken();
+        parseName(ast->name);
+        match(T_SEMICOLON, &ast->semicolon_token);
+        node = ast;
+        return true;
+    }
+    return false;
+}
+
+bool Parser::parseDeclarationStatement(StatementAST *&node)
+{
+    DEBUG_THIS_RULE();
+    unsigned start = cursor();
+    DeclarationAST *declaration = 0;
+    if (! parseBlockDeclaration(declaration))
+        return false;
+
+    if (SimpleDeclarationAST *simpleDeclaration = declaration->asSimpleDeclaration()) {
+        if (! simpleDeclaration->decl_specifier_list) {
+            rewind(start);
+            return false;
+        }
+    }
+
+    DeclarationStatementAST *ast = new (_pool) DeclarationStatementAST;
+    ast->declaration = declaration;
+    node = ast;
+    return true;
+}
+
+bool Parser::lookAtCVQualifier() const
+{
+    switch (LA()) {
+    case T_CONST:
+    case T_VOLATILE:
+        return true;
+    default:
+        return false;
+    }
+}
+
+bool Parser::lookAtFunctionSpecifier() const
+{
+    switch (LA()) {
+    case T_INLINE:
+    case T_VIRTUAL:
+    case T_EXPLICIT:
+        return true;
+    default:
+        return false;
+    }
+}
+
+bool Parser::lookAtStorageClassSpecifier() const
+{
+    switch (LA()) {
+    case T_FRIEND:
+    case T_REGISTER:
+    case T_STATIC:
+    case T_EXTERN:
+    case T_MUTABLE:
+    case T_TYPEDEF:
+    case T___THREAD:
+        return true;
+    case T_THREAD_LOCAL:
+        return _languageFeatures.cxx11Enabled;
+    case T_CONSTEXPR:
+        if (_languageFeatures.cxx11Enabled)
+            return true;
+        // fall-through
+    default:
+        return false;
+    }
+}
+
+bool Parser::lookAtBuiltinTypeSpecifier() const
+{
+    switch (LA()) {
+    case T_CHAR:
+    case T_CHAR16_T:
+    case T_CHAR32_T:
+    case T_WCHAR_T:
+    case T_BOOL:
+    case T_SHORT:
+    case T_INT:
+    case T_LONG:
+    case T_SIGNED:
+    case T_UNSIGNED:
+    case T_FLOAT:
+    case T_DOUBLE:
+    case T_VOID:
+    case T_AUTO:
+    case T_DECLTYPE:
+        return true;
+    // [gcc] extensions
+    case T___TYPEOF__:
+    case T___ATTRIBUTE__:
+        return true;
+    default:
+        return false;
+    }
+}
+
+bool Parser::lookAtClassKey() const
+{
+    switch (LA()) {
+    case T_CLASS:
+    case T_STRUCT:
+    case T_UNION:
+        return true;
+    default:
+        return false;
+    }
+}
+
+bool Parser::parseOptionalAttributeSpecifierSequence(SpecifierListAST *&attribute_list)
+{
+    bool didRead = false;
+    while (parseAttributeSpecifier(attribute_list))
+        didRead = true;
+    return didRead;
+}
+
+bool Parser::parseAttributeSpecifier(SpecifierListAST *&attribute_list)
+{
+    SpecifierListAST **attr_ptr = &attribute_list;
+    switch (LA()) {
+    case T_ALIGNAS: {
+        AlignmentSpecifierAST *ast = new (_pool) AlignmentSpecifierAST;
+        ast->align_token = consumeToken();
+        match(T_LPAREN, &ast->lparen_token);
+
+        const unsigned saved = cursor();
+        if (!parseTypeId(ast->typeIdExprOrAlignmentExpr) ||
+                (LA() != T_RPAREN &&
+                (LA(1) != T_DOT_DOT_DOT || LA(2) != T_RPAREN))) {
+            rewind(saved);
+            parseExpression(ast->typeIdExprOrAlignmentExpr);
+        }
+
+        if (LA() == T_DOT_DOT_DOT)
+            ast->ellipses_token = consumeToken();
+        match(T_RPAREN, &ast->rparen_token);
+        attribute_list = new (_pool) SpecifierListAST(ast);
+        return true;
+    }
+        //### TODO: C++11-style attributes
+//    case T_LBRACKET:
+    case T___ATTRIBUTE__:
+        while (LA() == T___ATTRIBUTE__) {
+            parseGnuAttributeSpecifier(*attr_ptr);
+            attr_ptr = &(*attr_ptr)->next;
+        }
+        return true;
+    default:
+        return false;
+    }
+}
+
+bool Parser::parseGnuAttributeSpecifier(SpecifierListAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T___ATTRIBUTE__)
+        return false;
+
+    GnuAttributeSpecifierAST *ast = new (_pool) GnuAttributeSpecifierAST;
+    ast->attribute_token = consumeToken();
+    match(T_LPAREN, &ast->first_lparen_token);
+    match(T_LPAREN, &ast->second_lparen_token);
+    parseGnuAttributeList(ast->attribute_list);
+    match(T_RPAREN, &ast->first_rparen_token);
+    match(T_RPAREN, &ast->second_rparen_token);
+    node = new (_pool) SpecifierListAST(ast);
+    return true;
+}
+
+bool Parser::parseGnuAttributeList(GnuAttributeListAST *&node)
+{
+    DEBUG_THIS_RULE();
+
+    GnuAttributeListAST **iter = &node;
+    while (LA() == T_CONST || LA() == T_IDENTIFIER) {
+        *iter = new (_pool) GnuAttributeListAST;
+
+        if (LA() == T_CONST) {
+            GnuAttributeAST *attr = new (_pool) GnuAttributeAST;
+            attr->identifier_token = consumeToken();
+
+            (*iter)->value = attr;
+            iter = &(*iter)->next;
+        } else if (LA() == T_IDENTIFIER) {
+            GnuAttributeAST *attr = new (_pool) GnuAttributeAST;
+            attr->identifier_token = consumeToken();
+            if (LA() == T_LPAREN) {
+                attr->lparen_token = consumeToken();
+                parseExpressionList(attr->expression_list);
+                match(T_RPAREN, &attr->rparen_token);
+            }
+
+            (*iter)->value = attr;
+            iter = &(*iter)->next;
+        }
+
+        if (LA() != T_COMMA)
+            break;
+
+        consumeToken(); // skip T_COMMA
+    }
+
+    return true;
+}
+
+bool Parser::parseBuiltinTypeSpecifier(SpecifierListAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T___ATTRIBUTE__) {
+        return parseGnuAttributeSpecifier(node);
+    } else if (LA() == T___TYPEOF__) {
+        TypeofSpecifierAST *ast = new (_pool) TypeofSpecifierAST;
+        ast->typeof_token = consumeToken();
+        if (LA() == T_LPAREN) {
+            unsigned lparen_token = consumeToken();
+            if (parseTypeId(ast->expression) && LA() == T_RPAREN) {
+                ast->lparen_token = lparen_token;
+                ast->rparen_token = consumeToken();
+                node = new (_pool) SpecifierListAST(ast);
+                return true;
+            }
+            rewind(lparen_token);
+        }
+        parseUnaryExpression(ast->expression);
+        node = new (_pool) SpecifierListAST(ast);
+        return true;
+    } else if (LA() == T_DECLTYPE) {
+        DecltypeSpecifierAST *ast = new (_pool) DecltypeSpecifierAST;
+        ast->decltype_token = consumeToken();
+        match(T_LPAREN, &ast->lparen_token);
+        if (parseExpression(ast->expression))
+            match(T_RPAREN, &ast->rparen_token);
+        node = new (_pool) SpecifierListAST(ast);
+        return true;
+    } else if (lookAtBuiltinTypeSpecifier()) {
+        SimpleSpecifierAST *ast = new (_pool) SimpleSpecifierAST;
+        ast->specifier_token = consumeToken();
+        node = new (_pool) SpecifierListAST(ast);
+        return true;
+    }
+    return false;
+}
+
+bool Parser::parseSimpleDeclaration(DeclarationAST *&node, ClassSpecifierAST *declaringClass)
+{
+    DEBUG_THIS_RULE();
+    unsigned qt_invokable_token = 0;
+    if (declaringClass && (LA() == T_Q_SIGNAL || LA() == T_Q_SLOT || LA() == T_Q_INVOKABLE))
+        qt_invokable_token = consumeToken();
+
+    // parse a simple declaration, a function definition,
+    // or a contructor declaration.
+    bool has_type_specifier = false;
+    bool has_complex_type_specifier = false;
+    unsigned startOfNamedTypeSpecifier = 0;
+    NameAST *named_type_specifier = 0;
+    SpecifierListAST *decl_specifier_seq = 0,
+         **decl_specifier_seq_ptr = &decl_specifier_seq;
+    for (;;) {
+        if (lookAtCVQualifier() || lookAtFunctionSpecifier()
+                || lookAtStorageClassSpecifier()) {
+            SimpleSpecifierAST *spec = new (_pool) SimpleSpecifierAST;
+            spec->specifier_token = consumeToken();
+            *decl_specifier_seq_ptr = new (_pool) SpecifierListAST(spec);
+            decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
+        } else if (parseAttributeSpecifier(*decl_specifier_seq_ptr)) {
+            decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
+        } else if (! named_type_specifier && ! has_complex_type_specifier && lookAtBuiltinTypeSpecifier()) {
+            parseBuiltinTypeSpecifier(*decl_specifier_seq_ptr);
+            decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
+            has_type_specifier = true;
+        } else if (! has_type_specifier && (LA() == T_COLON_COLON ||
+                                            LA() == T_IDENTIFIER)) {
+            startOfNamedTypeSpecifier = cursor();
+            if (parseName(named_type_specifier)) {
+
+                const Identifier *classIdentifier = className(declaringClass);
+                if (QualifiedNameAST *qn = named_type_specifier->asQualifiedName())
+                    if (NestedNameSpecifierListAST *namesList = qn->nested_name_specifier_list)
+                        if (NestedNameSpecifierAST *lastName = namesList->lastValue())
+                            classIdentifier = identifier(lastName->class_or_namespace_name);
+
+                if (LA() == T_LPAREN && identifier(named_type_specifier) == classIdentifier) {
+                    // looks like a constructor declaration
+                    rewind(startOfNamedTypeSpecifier);
+                    break;
+                }
+
+                NamedTypeSpecifierAST *spec = new (_pool) NamedTypeSpecifierAST;
+                spec->name = named_type_specifier;
+                *decl_specifier_seq_ptr = new (_pool) SpecifierListAST(spec);
+                decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
+                has_type_specifier = true;
+            } else {
+                rewind(startOfNamedTypeSpecifier);
+                break;
+            }
+        } else if (! has_type_specifier && LA() == T_ENUM) {
+            unsigned startOfTypeSpecifier = cursor();
+            if (! parseElaboratedTypeSpecifier(*decl_specifier_seq_ptr)
+                    || LA() == T_LBRACE
+                    || (_languageFeatures.cxx11Enabled && LA() == T_COLON)) {
+                rewind(startOfTypeSpecifier);
+                if (! parseEnumSpecifier(*decl_specifier_seq_ptr)) {
+                    error(startOfTypeSpecifier, "expected an enum specifier");
+                    break;
+                }
+                has_complex_type_specifier = true;
+            }
+            decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
+            has_type_specifier = true;
+        } else if (! has_type_specifier && LA() == T_TYPENAME) {
+            unsigned startOfElaboratedTypeSpecifier = cursor();
+            if (! parseElaboratedTypeSpecifier(*decl_specifier_seq_ptr)) {
+                error(startOfElaboratedTypeSpecifier, "expected an elaborated type specifier");
+                break;
+            }
+            decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
+            has_type_specifier = true;
+        } else if (! has_type_specifier && lookAtClassKey()) {
+            unsigned startOfTypeSpecifier = cursor();
+            if (! parseElaboratedTypeSpecifier(*decl_specifier_seq_ptr) ||
+                (LA() == T_COLON || LA() == T_LBRACE
+                 || (LA(0) == T_IDENTIFIER && LA(1) == T_IDENTIFIER // MACRO Name followed by : or {
+                     && (LA(2) == T_COLON || LA(2) == T_LBRACE))
+                 || (LA(0) == T_IDENTIFIER && LA(1) == T_IDENTIFIER && LA(2) == T_IDENTIFIER && // MACRO Name final followed by : or {
+                     (LA(3) == T_COLON || LA(3) == T_LBRACE)))) {
+                rewind(startOfTypeSpecifier);
+                if (! parseClassSpecifier(*decl_specifier_seq_ptr)) {
+                    error(startOfTypeSpecifier, "wrong type specifier");
+                    break;
+                }
+                has_complex_type_specifier = true;
+            }
+            decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
+            has_type_specifier = true;
+        } else
+            break;
+    }
+
+    DeclaratorListAST *declarator_list = 0,
+        **declarator_ptr = &declarator_list;
+
+    DeclaratorAST *declarator = 0;
+
+    if (LA() != T_SEMICOLON) {
+        const bool maybeCtor = (LA() == T_LPAREN && named_type_specifier);
+        bool didParseInitDeclarator = parseInitDeclarator(declarator, decl_specifier_seq, declaringClass);
+        if ((! didParseInitDeclarator && maybeCtor) || (didParseInitDeclarator && maybeCtor && LA() == T_COLON)){
+            rewind(startOfNamedTypeSpecifier);
+            named_type_specifier = 0;
+            // pop the named type specifier from the decl-specifier-seq
+            SpecifierListAST **spec_ptr = &decl_specifier_seq;
+            for (; *spec_ptr; spec_ptr = &(*spec_ptr)->next) {
+                if (! (*spec_ptr)->next) {
+                    *spec_ptr = 0;
+                    break;
+                }
+            }
+            if (! parseInitDeclarator(declarator, decl_specifier_seq, declaringClass))
+                return false;
+        }
+    }
+
+    // if there is no valid declarator
+    // and it doesn't look like a fwd or a class declaration
+    // then it's not a declarations
+    if (! declarator && ! maybeForwardOrClassDeclaration(decl_specifier_seq))
+        return false;
+
+    DeclaratorAST *firstDeclarator = declarator;
+
+    if (declarator) {
+        *declarator_ptr = new (_pool) DeclaratorListAST;
+        (*declarator_ptr)->value = declarator;
+        declarator_ptr = &(*declarator_ptr)->next;
+    }
+
+    if (LA() == T_COMMA || LA() == T_SEMICOLON || has_complex_type_specifier) {
+        while (LA() == T_COMMA) {
+            consumeToken(); // consume T_COMMA
+
+            declarator = 0;
+            if (parseInitDeclarator(declarator, decl_specifier_seq, declaringClass)) {
+                *declarator_ptr = new (_pool) DeclaratorListAST;
+                (*declarator_ptr)->value = declarator;
+                declarator_ptr = &(*declarator_ptr)->next;
+            }
+        }
+        SimpleDeclarationAST *ast = new (_pool) SimpleDeclarationAST;
+        ast->qt_invokable_token = qt_invokable_token;
+        ast->decl_specifier_list = decl_specifier_seq;
+        ast->declarator_list = declarator_list;
+        match(T_SEMICOLON, &ast->semicolon_token);
+        node = ast;
+        return true;
+    } else if (! _inFunctionBody && declarator && (LA() == T_COLON || LA() == T_LBRACE || LA() == T_TRY)) {
+        if (LA() == T_TRY) {
+            FunctionDefinitionAST *ast = new (_pool) FunctionDefinitionAST;
+            ast->qt_invokable_token = qt_invokable_token;
+            ast->decl_specifier_list = decl_specifier_seq;
+            ast->declarator = firstDeclarator;
+            parseTryBlockStatement(ast->function_body, &ast->ctor_initializer);
+            node = ast;
+            return true; // recognized a function definition.
+        } else {
+            CtorInitializerAST *ctor_initializer = 0;
+            bool hasCtorInitializer = false;
+
+            if (LA() == T_COLON) {
+                hasCtorInitializer = true;
+                parseCtorInitializer(ctor_initializer);
+
+                if (LA() != T_LBRACE) {
+                    const unsigned pos = cursor();
+
+                    for (int n = 0; n < 3 && LA(); consumeToken(), ++n)
+                        if (LA() == T_LBRACE)
+                            break;
+
+                    if (LA() != T_LBRACE) {
+                        error(pos, "unexpected token `%s'", _translationUnit->spell(pos));
+                        rewind(pos);
+                    }
+                }
+            }
+
+            if (LA() == T_LBRACE || hasCtorInitializer) {
+                FunctionDefinitionAST *ast = new (_pool) FunctionDefinitionAST;
+                ast->qt_invokable_token = qt_invokable_token;
+                ast->decl_specifier_list = decl_specifier_seq;
+                ast->declarator = firstDeclarator;
+                ast->ctor_initializer = ctor_initializer;
+                parseFunctionBody(ast->function_body);
+                node = ast;
+                return true; // recognized a function definition.
+            }
+        }
+    }
+
+    error(cursor(), "unexpected token `%s'", tok().spell());
+    return false;
+}
+
+bool Parser::maybeForwardOrClassDeclaration(SpecifierListAST *decl_specifier_seq) const
+{
+    // look at the decl_specifier for possible fwd or class declarations.
+    if (SpecifierListAST *it = decl_specifier_seq) {
+        while (it) {
+            SimpleSpecifierAST *spec = it->value->asSimpleSpecifier();
+            if (spec && _translationUnit->tokenKind(spec->specifier_token) == T_FRIEND)
+                it = it->next;
+            else
+                break;
+        }
+
+        if (it) {
+            SpecifierAST *spec = it->value;
+
+            if (spec->asElaboratedTypeSpecifier() ||
+                    spec->asEnumSpecifier() ||
+                    spec->asClassSpecifier()) {
+                for (it = it->next; it; it = it->next)
+                    if (it->value->asAttributeSpecifier() == 0)
+                        return false;
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+bool Parser::parseFunctionBody(StatementAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (_translationUnit->skipFunctionBody()) {
+        unsigned token_lbrace = 0;
+        match(T_LBRACE, &token_lbrace);
+        if (! token_lbrace)
+            return false;
+
+        const Token &tk = _translationUnit->tokenAt(token_lbrace);
+        if (tk.close_brace)
+            rewind(tk.close_brace);
+        unsigned token_rbrace = 0;
+        match(T_RBRACE, &token_rbrace);
+        return true;
+    }
+
+    _inFunctionBody = true;
+    const bool parsed = parseCompoundStatement(node);
+    _inFunctionBody = false;
+    return parsed;
+}
+
+/**
+ * Parses both try-block and function-try-block
+ * @param placeholder Non-null for function-try-block in around constructor
+ *
+ *  try-block:
+ *      try compound-statement handler-seq
+ *  function-try-block:
+ *      try [ctor-initializer] compound-statement handler-seq
+ */
+bool Parser::parseTryBlockStatement(StatementAST *&node, CtorInitializerAST **placeholder)
+{
+    DEBUG_THIS_RULE();
+
+    if (LA() == T_TRY) {
+        TryBlockStatementAST *ast = new (_pool) TryBlockStatementAST;
+        // try
+        ast->try_token = consumeToken();
+        // [ctor-initializer]
+        if (LA() == T_COLON) {
+            const unsigned colonPos = cursor();
+            CtorInitializerAST *ctor_initializer = 0;
+            parseCtorInitializer(ctor_initializer);
+
+            if (LA() != T_LBRACE) {
+                const unsigned pos = cursor();
+
+                for (int n = 0; n < 3 && LA(); consumeToken(), ++n)
+                    if (LA() == T_LBRACE)
+                        break;
+
+                if (LA() != T_LBRACE) {
+                    error(pos, "unexpected token `%s'", _translationUnit->spell(pos));
+                    rewind(pos);
+                }
+            }
+
+            if (placeholder)
+                *placeholder = ctor_initializer;
+            else
+                error(colonPos, "constructor initializer not allowed inside function body");
+        }
+        // compound-statement
+        parseCompoundStatement(ast->statement);
+        // handler-seq
+        CatchClauseListAST **catch_clause_ptr = &ast->catch_clause_list;
+        while (parseCatchClause(*catch_clause_ptr))
+            catch_clause_ptr = &(*catch_clause_ptr)->next;
+        node = ast;
+        return true;
+    }
+    return false;
+}
+
+bool Parser::parseCatchClause(CatchClauseListAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_CATCH) {
+        CatchClauseAST *ast = new (_pool) CatchClauseAST;
+        ast->catch_token = consumeToken();
+        match(T_LPAREN, &ast->lparen_token);
+        parseExceptionDeclaration(ast->exception_declaration);
+        match(T_RPAREN, &ast->rparen_token);
+        parseCompoundStatement(ast->statement);
+        node = new (_pool) CatchClauseListAST(ast);
+        return true;
+    }
+    return false;
+}
+
+bool Parser::parseExceptionDeclaration(ExceptionDeclarationAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_DOT_DOT_DOT) {
+        ExceptionDeclarationAST *ast = new (_pool) ExceptionDeclarationAST;
+        ast->dot_dot_dot_token = consumeToken();
+        node = ast;
+        return true;
+    }
+
+    SpecifierListAST *type_specifier = 0;
+    if (parseTypeSpecifier(type_specifier)) {
+        ExceptionDeclarationAST *ast = new (_pool) ExceptionDeclarationAST;
+        ast->type_specifier_list = type_specifier;
+        parseDeclaratorOrAbstractDeclarator(ast->declarator, type_specifier);
+        node = ast;
+        return true;
+    }
+    return false;
+}
+
+bool Parser::parseBoolLiteral(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_TRUE || LA() == T_FALSE) {
+        BoolLiteralAST *ast = new (_pool) BoolLiteralAST;
+        ast->literal_token = consumeToken();
+        node = ast;
+        return true;
+    }
+    return false;
+}
+
+bool Parser::parseNumericLiteral(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_NUMERIC_LITERAL  ||
+        LA() == T_CHAR_LITERAL     ||
+        LA() == T_WIDE_CHAR_LITERAL ||
+        LA() == T_UTF16_CHAR_LITERAL ||
+        LA() == T_UTF32_CHAR_LITERAL) {
+        NumericLiteralAST *ast = new (_pool) NumericLiteralAST;
+        ast->literal_token = consumeToken();
+        node = ast;
+        return true;
+    }
+    return false;
+}
+
+bool Parser::parsePointerLiteral(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_NULLPTR) {
+        PointerLiteralAST *ast = new (_pool) PointerLiteralAST;
+        ast->literal_token = consumeToken();
+        node = ast;
+        return true;
+    }
+    return false;
+}
+
+bool Parser::parseThisExpression(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_THIS) {
+        ThisExpressionAST *ast = new (_pool) ThisExpressionAST;
+        ast->this_token = consumeToken();
+        node = ast;
+        return true;
+    }
+    return false;
+}
+
+bool Parser::parsePrimaryExpression(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    switch (LA()) {
+    case T_STRING_LITERAL:
+    case T_WIDE_STRING_LITERAL:
+    case T_UTF8_STRING_LITERAL:
+    case T_UTF16_STRING_LITERAL:
+    case T_UTF32_STRING_LITERAL:
+    case T_RAW_STRING_LITERAL:
+    case T_RAW_WIDE_STRING_LITERAL:
+    case T_RAW_UTF8_STRING_LITERAL:
+    case T_RAW_UTF16_STRING_LITERAL:
+    case T_RAW_UTF32_STRING_LITERAL:
+        return parseStringLiteral(node);
+
+    case T_NULLPTR:
+        if (_languageFeatures.cxx11Enabled)
+            return parsePointerLiteral(node);
+        // fall-through
+
+    case T_CHAR_LITERAL: // ### FIXME don't use NumericLiteral for chars
+    case T_WIDE_CHAR_LITERAL:
+    case T_UTF16_CHAR_LITERAL:
+    case T_UTF32_CHAR_LITERAL:
+    case T_NUMERIC_LITERAL:
+        return parseNumericLiteral(node);
+
+    case T_TRUE:
+    case T_FALSE:
+        return parseBoolLiteral(node);
+
+    case T_THIS:
+        return parseThisExpression(node);
+
+    case T_LPAREN:
+        if (LA(2) == T_LBRACE) {
+            // GNU extension: '(' '{' statement-list '}' ')'
+            CompoundExpressionAST *ast = new (_pool) CompoundExpressionAST;
+            ast->lparen_token = consumeToken();
+            StatementAST *statement = 0;
+            parseCompoundStatement(statement);
+            ast->statement = statement->asCompoundStatement();
+            match(T_RPAREN, &ast->rparen_token);
+            node = ast;
+            return true;
+        } else {
+            return parseNestedExpression(node);
+        }
+
+    case T_SIGNAL:
+    case T_SLOT:
+        return parseQtMethod(node);
+
+    case T_LBRACKET: {
+        const unsigned lbracket_token = cursor();
+
+        if (_languageFeatures.cxx11Enabled) {
+            if (parseLambdaExpression(node))
+                return true;
+        }
+
+        if (_languageFeatures.objCEnabled) {
+            rewind(lbracket_token);
+            return parseObjCExpression(node);
+        }
+    } break;
+
+    case T_AT_STRING_LITERAL:
+    case T_AT_ENCODE:
+    case T_AT_PROTOCOL:
+    case T_AT_SELECTOR:
+        return parseObjCExpression(node);
+
+    default: {
+        NameAST *name = 0;
+        if (parseNameId(name)) {
+            IdExpressionAST *ast = new (_pool) IdExpressionAST;
+            ast->name = name;
+            node = ast;
+            return true;
+        }
+        break;
+    } // default
+
+    } // switch
+
+    return false;
+}
+
+bool Parser::parseObjCExpression(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    switch (LA()) {
+    case T_AT_ENCODE:
+        return parseObjCEncodeExpression(node);
+
+    case T_AT_PROTOCOL:
+        return parseObjCProtocolExpression(node);
+
+    case T_AT_SELECTOR:
+        return parseObjCSelectorExpression(node);
+
+    case T_LBRACKET:
+        return parseObjCMessageExpression(node);
+
+    case T_AT_STRING_LITERAL:
+        return parseObjCStringLiteral(node);
+
+    default:
+        break;
+    } // switch
+    return false;
+}
+
+bool Parser::parseObjCStringLiteral(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_AT_STRING_LITERAL)
+        return false;
+
+    StringLiteralAST **ast = reinterpret_cast<StringLiteralAST **> (&node);
+
+    while (LA() == T_AT_STRING_LITERAL) {
+        *ast = new (_pool) StringLiteralAST;
+        (*ast)->literal_token = consumeToken();
+        ast = &(*ast)->next;
+    }
+    return true;
+}
+
+///  objc-try-catch-statement:
+///    @try compound-statement objc-catch-list[opt]
+///    @try compound-statement objc-catch-list[opt] @finally compound-statement
+///
+///  objc-catch-list:
+///    @catch ( parameter-declaration ) compound-statement
+///    objc-catch-list @catch ( catch-parameter-declaration ) compound-statement
+///  catch-parameter-declaration:
+///     parameter-declaration
+///     '...' [OBJC2]
+///
+bool Parser::parseObjCTryStatement(StatementAST *& /*node*/)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_AT_TRY)
+        return false;
+
+    /*try_token =*/ consumeToken();
+    StatementAST *body_statment;
+    parseCompoundStatement(body_statment);
+    while (LA() == T_AT_CATCH) {
+        /*catch_token =*/ consumeToken();
+        unsigned lparen_token;
+        match(T_LPAREN, &lparen_token);
+        if (LA() == T_DOT_DOT_DOT) {
+            /*unsigned ellipsis_token =*/ consumeToken();
+        } else {
+            ParameterDeclarationAST *exception_decl;
+            parseParameterDeclaration(exception_decl);
+        }
+        unsigned rparen_token;
+        match(T_RPAREN, &rparen_token);
+        StatementAST *catch_statement;
+        parseCompoundStatement(catch_statement);
+    }
+
+    if (LA() == T_AT_FINALLY) {
+        StatementAST *finally_statement;
+        parseCompoundStatement(finally_statement);
+    }
+
+    return true;
+}
+
+/// objc-synchronized-statement:
+///   @synchronized expression ;
+bool Parser::parseObjCSynchronizedStatement(StatementAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_AT_SYNCHRONIZED)
+        return false;
+
+    ObjCSynchronizedStatementAST *ast = new (_pool) ObjCSynchronizedStatementAST;
+
+    ast->synchronized_token = consumeToken();
+    match(T_LPAREN, &ast->lparen_token);
+    parseExpression(ast->synchronized_object);
+    match(T_RPAREN, &ast->rparen_token);
+    parseStatement(ast->statement);
+
+    node = ast;
+    return true;
+}
+
+/// objc-throw-statement:
+///   @ throw expression ;
+bool Parser::parseObjCThrowStatement(StatementAST *&/*node*/)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_AT_THROW)
+        return false;
+
+    /*throw_token =*/ consumeToken();
+    ExpressionAST *thrown_expression;
+    parseExpression(thrown_expression);
+    unsigned semicolon_token;
+    match(T_SEMICOLON, &semicolon_token);
+
+    return true;
+}
+
+bool Parser::parseObjCEncodeExpression(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_AT_ENCODE)
+        return false;
+
+    ObjCEncodeExpressionAST *ast = new (_pool) ObjCEncodeExpressionAST;
+    ast->encode_token = consumeToken();
+    parseObjCTypeName(ast->type_name);
+    node = ast;
+    return true;
+}
+
+bool Parser::parseObjCProtocolExpression(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_AT_PROTOCOL)
+        return false;
+
+    ObjCProtocolExpressionAST *ast = new (_pool) ObjCProtocolExpressionAST;
+    ast->protocol_token = consumeToken();
+    match(T_LPAREN, &ast->lparen_token);
+    match(T_IDENTIFIER, &ast->identifier_token);
+    match(T_RPAREN, &ast->rparen_token);
+    node = ast;
+    return true;
+}
+
+bool Parser::parseObjCSelectorExpression(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_AT_SELECTOR)
+        return false;
+
+    ObjCSelectorExpressionAST *ast = new (_pool) ObjCSelectorExpressionAST;
+    ast->selector_token = consumeToken();
+    match(T_LPAREN, &ast->lparen_token);
+
+    unsigned identifier_token = 0;
+    match(T_IDENTIFIER, &identifier_token);
+    if (LA() == T_COLON) {
+        ObjCSelectorAST *args = new (_pool) ObjCSelectorAST;
+        ast->selector = args;
+        ObjCSelectorArgumentListAST *last = new (_pool) ObjCSelectorArgumentListAST;
+        args->selector_argument_list = last;
+        last->value = new (_pool) ObjCSelectorArgumentAST;
+        last->value->name_token = identifier_token;
+        last->value->colon_token = consumeToken();
+
+        while (LA(1) == T_IDENTIFIER && LA(2) == T_COLON) {
+            last->next = new (_pool) ObjCSelectorArgumentListAST;
+            last = last->next;
+            last->value = new (_pool) ObjCSelectorArgumentAST;
+            last->value->name_token = consumeToken();
+            last->value->colon_token = consumeToken();
+        }
+    } else {
+        ObjCSelectorAST *args = new (_pool) ObjCSelectorAST;
+        ast->selector = args;
+        args->selector_argument_list = new (_pool) ObjCSelectorArgumentListAST;
+        args->selector_argument_list->value = new (_pool) ObjCSelectorArgumentAST;
+        args->selector_argument_list->value->name_token = identifier_token;
+    }
+
+    if (LA(1) == T_IDENTIFIER && LA(2) == T_RPAREN) {
+        const char *txt = tok(1).spell();
+        consumeToken();
+        error(cursor(), "missing ':' after '%s'", txt);
+    }
+    match(T_RPAREN, &ast->rparen_token);
+
+    node = ast;
+    return true;
+}
+
+bool Parser::parseObjCMessageExpression(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_LBRACKET)
+        return false;
+
+    unsigned start = cursor();
+
+    unsigned lbracket_token = consumeToken();
+    ExpressionAST *receiver_expression = 0;
+    ObjCSelectorAST *selector = 0;
+    ObjCMessageArgumentListAST *argument_list = 0;
+
+    if (parseObjCMessageReceiver(receiver_expression) &&
+        parseObjCMessageArguments(selector, argument_list)) {
+
+        ObjCMessageExpressionAST *ast = new (_pool) ObjCMessageExpressionAST;
+        ast->lbracket_token = lbracket_token;
+        ast->receiver_expression = receiver_expression;
+        ast->selector = selector;
+        ast->argument_list = argument_list;
+
+        match(T_RBRACKET, &ast->rbracket_token);
+        node = ast;
+
+        return true;
+    }
+
+    rewind(start);
+    return false;
+}
+
+bool Parser::parseObjCMessageReceiver(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    return parseExpression(node);
+}
+
+bool Parser::parseObjCMessageArguments(ObjCSelectorAST *&selNode, ObjCMessageArgumentListAST *& argNode)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_RBRACKET)
+        return false; // nothing to do.
+
+    unsigned start = cursor();
+
+    ObjCSelectorArgumentAST *selectorArgument = 0;
+    ObjCMessageArgumentAST *messageArgument = 0;
+
+    if (parseObjCSelectorArg(selectorArgument, messageArgument)) {
+        ObjCSelectorArgumentListAST *selAst = new (_pool) ObjCSelectorArgumentListAST;
+        selAst->value = selectorArgument;
+        ObjCSelectorArgumentListAST *lastSelector = selAst;
+
+        ObjCMessageArgumentListAST *argAst = new (_pool) ObjCMessageArgumentListAST;
+        argAst->value = messageArgument;
+        ObjCMessageArgumentListAST *lastArgument = argAst;
+
+        while (parseObjCSelectorArg(selectorArgument, messageArgument)) {
+            // accept the selector args.
+            lastSelector->next = new (_pool) ObjCSelectorArgumentListAST;
+            lastSelector = lastSelector->next;
+            lastSelector->value = selectorArgument;
+
+            lastArgument->next = new (_pool) ObjCMessageArgumentListAST;
+            lastArgument = lastArgument->next;
+            lastArgument->value = messageArgument;
+        }
+
+        if (LA() == T_COMMA) {
+            ExpressionAST **lastExpression = &lastArgument->value->parameter_value_expression;
+
+            while (LA() == T_COMMA) {
+                BinaryExpressionAST *binaryExpression = new (_pool) BinaryExpressionAST;
+                binaryExpression->left_expression = *lastExpression;
+                binaryExpression->binary_op_token = consumeToken(); // T_COMMA
+                parseAssignmentExpression(binaryExpression->right_expression);
+                lastExpression = &binaryExpression->right_expression;
+            }
+        }
+
+        ObjCSelectorAST *selWithArgs = new (_pool) ObjCSelectorAST;
+        selWithArgs->selector_argument_list = selAst;
+
+        selNode = selWithArgs;
+        argNode = argAst;
+        return true;
+    } else {
+        rewind(start);
+        unsigned name_token = 0;
+        if (!parseObjCSelector(name_token))
+            return false;
+        ObjCSelectorAST *sel = new (_pool) ObjCSelectorAST;
+        sel->selector_argument_list = new (_pool) ObjCSelectorArgumentListAST;
+        sel->selector_argument_list->value = new (_pool) ObjCSelectorArgumentAST;
+        sel->selector_argument_list->value->name_token = name_token;
+        selNode = sel;
+        argNode = 0;
+        return true;
+    }
+
+    return false;
+}
+
+bool Parser::parseObjCSelectorArg(ObjCSelectorArgumentAST *&selNode, ObjCMessageArgumentAST *&argNode)
+{
+    DEBUG_THIS_RULE();
+    unsigned selector_token = 0;
+    if (!parseObjCSelector(selector_token))
+        return false;
+
+    if (LA() != T_COLON)
+        return false;
+
+    selNode = new (_pool) ObjCSelectorArgumentAST;
+    selNode->name_token = selector_token;
+    selNode->colon_token = consumeToken();
+
+    argNode = new (_pool) ObjCMessageArgumentAST;
+    ExpressionAST **expr = &argNode->parameter_value_expression;
+    unsigned expressionStart = cursor();
+    if (parseAssignmentExpression(*expr) && LA() == T_COLON && (*expr)->asCastExpression()) {
+        rewind(expressionStart);
+        parseUnaryExpression(*expr);
+        //
+    }
+    return true;
+}
+
+bool Parser::parseNameId(NameAST *&name)
+{
+    DEBUG_THIS_RULE();
+    unsigned start = cursor();
+    if (! parseName(name))
+        return false;
+
+    if (LA() == T_RPAREN || LA() == T_COMMA)
+        return true;
+
+    QualifiedNameAST *qualified_name_id = name->asQualifiedName();
+
+    TemplateIdAST *template_id = 0;
+    if (qualified_name_id) {
+        if (NameAST *unqualified_name = qualified_name_id->unqualified_name)
+            template_id = unqualified_name->asTemplateId();
+    } else {
+        template_id = name->asTemplateId();
+    }
+
+    if (! template_id)
+        return true; // it's not a template-id, there's nothing to rewind.
+
+    else if (LA() == T_LPAREN) {
+        // a template-id followed by a T_LPAREN
+        if (ExpressionListAST *template_arguments = template_id->template_argument_list) {
+            if (! template_arguments->next && template_arguments->value &&
+                    template_arguments->value->asBinaryExpression()) {
+
+                unsigned saved = cursor();
+                ExpressionAST *expr = 0;
+
+                bool blocked = blockErrors(true);
+                bool lookAtCastExpression = parseCastExpression(expr);
+                (void) blockErrors(blocked);
+
+                if (lookAtCastExpression) {
+                    if (CastExpressionAST *cast_expression = expr->asCastExpression()) {
+                        if (cast_expression->lparen_token && cast_expression->rparen_token
+                                && cast_expression->type_id && cast_expression->expression) {
+                            rewind(start);
+
+                            name = 0;
+                            return parseName(name, false);
+                        }
+                    }
+                }
+                rewind(saved);
+            }
+        }
+    }
+
+    switch (LA()) {
+    case T_COMMA:
+    case T_SEMICOLON:
+    case T_LBRACKET:
+    case T_LPAREN:
+    case T_LBRACE:
+        return true;
+
+    case T_THIS:
+    case T_IDENTIFIER:
+    case T_STATIC_CAST:
+    case T_DYNAMIC_CAST:
+    case T_REINTERPRET_CAST:
+    case T_CONST_CAST:
+        rewind(start);
+        return parseName(name, false);
+
+    default:
+        if (tok().isLiteral() || tok().isOperator()) {
+            rewind(start);
+            return parseName(name, false);
+        }
+    } // switch
+
+    return true;
+}
+
+bool Parser::parseNestedExpression(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_LPAREN) {
+        unsigned lparen_token = consumeToken();
+        bool previousTemplateArguments = switchTemplateArguments(false);
+
+        ExpressionAST *expression = 0;
+        if (parseExpression(expression) && LA() == T_RPAREN) {
+            NestedExpressionAST *ast = new (_pool) NestedExpressionAST;
+            ast->lparen_token = lparen_token;
+            ast->expression = expression;
+            ast->rparen_token = consumeToken();
+            node = ast;
+            (void) switchTemplateArguments(previousTemplateArguments);
+            return true;
+        }
+        (void) switchTemplateArguments(previousTemplateArguments);
+    }
+    return false;
+}
+
+bool Parser::parseCppCastExpression(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_DYNAMIC_CAST     || LA() == T_STATIC_CAST ||
+        LA() == T_REINTERPRET_CAST || LA() == T_CONST_CAST) {
+        CppCastExpressionAST *ast = new (_pool) CppCastExpressionAST;
+        ast->cast_token = consumeToken();
+        match(T_LESS, &ast->less_token);
+        parseTypeId(ast->type_id);
+        match(T_GREATER, &ast->greater_token);
+        match(T_LPAREN, &ast->lparen_token);
+        parseExpression(ast->expression);
+        match(T_RPAREN, &ast->rparen_token);
+        node = ast;
+        return true;
+    }
+    return false;
+}
+
+// typename ::opt  nested-name-specifier identifier ( expression-listopt )
+// typename ::opt  nested-name-specifier templateopt  template-id ( expression-listopt )
+bool Parser::parseTypenameCallExpression(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_TYPENAME) {
+        unsigned typename_token = consumeToken();
+        NameAST *name = 0;
+        if (parseName(name)
+                && (LA() == T_LPAREN || (_languageFeatures.cxx11Enabled && LA() == T_LBRACE))) {
+            TypenameCallExpressionAST *ast = new (_pool) TypenameCallExpressionAST;
+            ast->typename_token = typename_token;
+            ast->name = name;
+            if (LA() == T_LPAREN) {
+                parseExpressionListParen(ast->expression);
+            } else { // T_LBRACE
+                parseBracedInitList0x(ast->expression);
+            }
+            node = ast;
+            return true;
+        }
+    }
+    return false;
+}
+
+// typeid ( expression )
+// typeid ( type-id )
+bool Parser::parseTypeidExpression(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_TYPEID) {
+        TypeidExpressionAST *ast = new (_pool) TypeidExpressionAST;
+        ast->typeid_token = consumeToken();
+        if (LA() == T_LPAREN)
+            ast->lparen_token = consumeToken();
+        unsigned saved = cursor();
+        if (! (parseTypeId(ast->expression) && LA() == T_RPAREN)) {
+            rewind(saved);
+            parseExpression(ast->expression);
+        }
+        match(T_RPAREN, &ast->rparen_token);
+        node = ast;
+        return true;
+    }
+    return false;
+}
+
+bool Parser::parseCorePostfixExpression(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+
+    switch (LA()) {
+    case T_DYNAMIC_CAST:
+    case T_STATIC_CAST:
+    case T_REINTERPRET_CAST:
+    case T_CONST_CAST:
+        return parseCppCastExpression(node);
+
+    case T_TYPENAME:
+        return parseTypenameCallExpression(node);
+
+    case T_TYPEID:
+        return parseTypeidExpression(node);
+
+    default: {
+        unsigned start = cursor();
+        SpecifierListAST *type_specifier = 0;
+        bool blocked = blockErrors(true);
+        if (lookAtBuiltinTypeSpecifier() &&
+                parseSimpleTypeSpecifier(type_specifier) &&
+                (LA() == T_LPAREN || (_languageFeatures.cxx11Enabled && LA() == T_LBRACE))) {
+            ExpressionAST *expr = 0;
+            if (LA() == T_LPAREN) {
+                parseExpressionListParen(expr);
+            } else { // T_LBRACE
+                parseBracedInitList0x(expr);
+            }
+            TypeConstructorCallAST *ast = new (_pool) TypeConstructorCallAST;
+            ast->type_specifier_list = type_specifier;
+            ast->expression = expr;
+            node = ast;
+            blockErrors(blocked);
+            return true;
+        }
+        rewind(start);
+
+        // look for compound literals
+        if (LA() == T_LPAREN) {
+            unsigned lparen_token = consumeToken();
+            ExpressionAST *type_id = 0;
+            if (parseTypeId(type_id) && LA() == T_RPAREN) {
+                unsigned rparen_token = consumeToken();
+                if (LA() == T_LBRACE) {
+                    blockErrors(blocked);
+
+                    CompoundLiteralAST *ast = new (_pool) CompoundLiteralAST;
+                    ast->lparen_token = lparen_token;
+                    ast->type_id = type_id;
+                    ast->rparen_token = rparen_token;
+                    parseInitializerClause(ast->initializer);
+                    node = ast;
+                    return true;
+                }
+            }
+            rewind(start);
+        }
+
+        blockErrors(blocked);
+        return parsePrimaryExpression(node);
+    } // default
+    } // switch
+}
+
+bool Parser::parsePostfixExpression(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (parseCorePostfixExpression(node)) {
+        while (LA()) {
+            if (LA() == T_LPAREN) {
+                CallAST *ast = new (_pool) CallAST;
+                ast->lparen_token = consumeToken();
+                parseExpressionList(ast->expression_list);
+                match(T_RPAREN, &ast->rparen_token);
+                ast->base_expression = node;
+                node = ast;
+            } else if (LA() == T_LBRACKET) {
+                ArrayAccessAST *ast = new (_pool) ArrayAccessAST;
+                ast->lbracket_token = consumeToken();
+                parseExpression(ast->expression);
+                match(T_RBRACKET, &ast->rbracket_token);
+                ast->base_expression = node;
+                node = ast;
+            } else if (_languageFeatures.cxx11Enabled && LA() == T_LBRACE && node->asIdExpression()) {
+                // this is slightly inconsistent: simple-type-specifier '(' expression-list ')'
+                // gets parsed as a CallAST while simple-type-specifier brace-init-list
+                // is a TypenameCallExpressionAST
+                TypenameCallExpressionAST *ast = new (_pool) TypenameCallExpressionAST;
+                ast->name = node->asIdExpression()->name;
+                parseBracedInitList0x(ast->expression);
+                node = ast;
+            } else if (LA() == T_PLUS_PLUS || LA() == T_MINUS_MINUS) {
+                PostIncrDecrAST *ast = new (_pool) PostIncrDecrAST;
+                ast->incr_decr_token = consumeToken();
+                ast->base_expression = node;
+                node = ast;
+            } else if (LA() == T_DOT || LA() == T_ARROW) {
+                MemberAccessAST *ast = new (_pool) MemberAccessAST;
+                ast->access_token = consumeToken();
+                if (LA() == T_TEMPLATE)
+                    ast->template_token = consumeToken();
+                if (! parseNameId(ast->member_name))
+                    error(cursor(), "expected unqualified-id before token `%s'", tok().spell());
+                ast->base_expression = node;
+                node = ast;
+            } else break;
+        } // while
+
+        return true;
+    }
+    return false;
+}
+
+bool Parser::parseUnaryExpression(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    switch (LA()) {
+    case T_PLUS_PLUS:
+    case T_MINUS_MINUS:
+    case T_STAR:
+    case T_AMPER:
+    case T_PLUS:
+    case T_MINUS:
+    case T_EXCLAIM: {
+        unsigned op = cursor();
+        UnaryExpressionAST *ast = new (_pool) UnaryExpressionAST;
+        ast->unary_op_token = consumeToken();
+        if (! parseCastExpression(ast->expression))
+            error(op, "expected expression after token `%s'", _translationUnit->spell(op));
+        node = ast;
+        return true;
+    }
+
+    case T_TILDE: {
+        if (LA(2) == T_IDENTIFIER && LA(3) == T_LPAREN)
+            break; // prefer destructor names
+
+        UnaryExpressionAST *ast = new (_pool) UnaryExpressionAST;
+        ast->unary_op_token = consumeToken();
+        (void) parseCastExpression(ast->expression);
+        node = ast;
+        return true;
+    }
+
+    case T_SIZEOF: {
+        SizeofExpressionAST *ast = new (_pool) SizeofExpressionAST;
+        ast->sizeof_token = consumeToken();
+
+        // sizeof...(Args)
+        if (_languageFeatures.cxx11Enabled && LA() == T_DOT_DOT_DOT && (LA(2) == T_IDENTIFIER || (LA(2) == T_LPAREN && LA(3) == T_IDENTIFIER
+                                                                                 && LA(4) == T_RPAREN)))
+            ast->dot_dot_dot_token = consumeToken();
+
+        if (LA() == T_LPAREN) {
+            unsigned lparen_token = consumeToken();
+            const bool blocked = blockErrors(true);
+            const bool hasTypeId = parseTypeId(ast->expression);
+            (void) blockErrors(blocked);
+            if (hasTypeId && LA() == T_RPAREN) {
+                ast->lparen_token = lparen_token;
+                ast->rparen_token = consumeToken();
+                node = ast;
+                return true;
+            } else {
+                rewind(lparen_token);
+            }
+        }
+
+        parseUnaryExpression(ast->expression);
+
+        node = ast;
+        return true;
+    }
+
+    case T_ALIGNOF: {
+        if (!_languageFeatures.cxx11Enabled)
+            break;
+
+        AlignofExpressionAST *ast = new (_pool) AlignofExpressionAST;
+        ast->alignof_token = consumeToken();
+
+        match(T_LPAREN, &ast->lparen_token);
+        ExpressionAST *temp = 0;
+        parseTypeId(temp);
+        if (temp)
+            ast->typeId = temp->asTypeId();
+        match(T_RPAREN, &ast->rparen_token);
+
+        node = ast;
+        return true;
+    }
+
+    default:
+        break;
+    } // switch
+
+    if (LA() == T_NEW || (LA(1) == T_COLON_COLON &&
+                          LA(2) == T_NEW))
+        return parseNewExpression(node);
+    else if (LA() == T_DELETE || (LA(1) == T_COLON_COLON &&
+                                  LA(2) == T_DELETE))
+        return parseDeleteExpression(node);
+    else
+        return parsePostfixExpression(node);
+}
+
+// new-placement ::= T_LPAREN expression-list T_RPAREN
+bool Parser::parseExpressionListParen(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_LPAREN) {
+        unsigned lparen_token = consumeToken();
+        ExpressionListAST *expression_list = 0;
+        if (parseExpressionList(expression_list) && LA() == T_RPAREN) {
+            unsigned rparen_token = consumeToken();
+            ExpressionListParenAST *ast = new (_pool) ExpressionListParenAST;
+            ast->lparen_token = lparen_token;
+            ast->expression_list = expression_list;
+            ast->rparen_token = rparen_token;
+            node = ast;
+            return true;
+        }
+    }
+
+    return false;
+}
+
+
+// new-expression ::= T_COLON_COLON? T_NEW new-placement.opt
+//                    new-type-id new-initializer.opt
+// new-expression ::= T_COLON_COLON? T_NEW new-placement.opt
+//                    T_LPAREN type-id T_RPAREN new-initializer.opt
+bool Parser::parseNewExpression(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (! (LA() == T_NEW || (LA() == T_COLON_COLON && LA(2) == T_NEW)))
+        return false;
+
+    NewExpressionAST *ast = new (_pool) NewExpressionAST;
+    if (LA() == T_COLON_COLON)
+        ast->scope_token = consumeToken();
+
+    ast->new_token = consumeToken();
+
+    ExpressionAST *parenExpressionList = 0;
+
+    if (parseExpressionListParen(parenExpressionList)) {
+        unsigned after_new_placement = cursor();
+
+        NewTypeIdAST *new_type_id = 0;
+        if (parseNewTypeId(new_type_id)) {
+            ast->new_placement = parenExpressionList->asExpressionListParen();
+            ast->new_type_id = new_type_id;
+            parseNewInitializer(ast->new_initializer);
+            // recognized new-placement.opt new-type-id new-initializer.opt
+            node = ast;
+            return true;
+        }
+
+        rewind(after_new_placement);
+        if (LA() == T_LPAREN) {
+            unsigned lparen_token = consumeToken();
+            ExpressionAST *type_id = 0;
+            if (parseTypeId(type_id) && LA() == T_RPAREN) {
+                ast->new_placement = parenExpressionList->asExpressionListParen();
+                ast->lparen_token = lparen_token;
+                ast->type_id = type_id;
+                ast->rparen_token = consumeToken();
+                parseNewInitializer(ast->new_initializer);
+                node = ast;
+                return true;
+            }
+        }
+    }
+
+    rewind(ast->new_token + 1);
+
+    if (LA() == T_LPAREN) {
+        unsigned lparen_token = consumeToken();
+        ExpressionAST *type_id = 0;
+        if (parseTypeId(type_id) && LA() == T_RPAREN) {
+            ast->lparen_token = lparen_token;
+            ast->type_id = type_id;
+            ast->rparen_token = consumeToken();
+            parseNewInitializer(ast->new_initializer);
+            node = ast;
+            return true;
+        }
+    }
+
+    parseNewTypeId(ast->new_type_id);
+    parseNewInitializer(ast->new_initializer);
+    node = ast;
+    return true;
+}
+
+bool Parser::parseNewTypeId(NewTypeIdAST *&node)
+{
+    DEBUG_THIS_RULE();
+    SpecifierListAST *typeSpec = 0;
+    if (! parseTypeSpecifier(typeSpec))
+        return false;
+
+    NewTypeIdAST *ast = new (_pool) NewTypeIdAST;
+    ast->type_specifier_list = typeSpec;
+
+    PtrOperatorListAST **ptrop_it = &ast->ptr_operator_list;
+    while (parsePtrOperator(*ptrop_it))
+        ptrop_it = &(*ptrop_it)->next;
+
+    NewArrayDeclaratorListAST **it = &ast->new_array_declarator_list;
+    while (parseNewArrayDeclarator(*it))
+        it = &(*it)->next;
+
+    node = ast;
+    return true;
+}
+
+
+bool Parser::parseNewArrayDeclarator(NewArrayDeclaratorListAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_LBRACKET)
+        return false;
+
+    NewArrayDeclaratorAST *ast = new (_pool) NewArrayDeclaratorAST;
+    ast->lbracket_token = consumeToken();
+    parseExpression(ast->expression);
+    match(T_RBRACKET, &ast->rbracket_token);
+
+    node = new (_pool) NewArrayDeclaratorListAST;
+    node->value = ast;
+    return true;
+}
+
+bool Parser::parseNewInitializer(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_LPAREN)
+        return parseExpressionListParen(node);
+    else if (_languageFeatures.cxx11Enabled && LA() == T_LBRACE)
+        return parseBracedInitList0x(node);
+    return false;
+}
+
+bool Parser::parseDeleteExpression(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_DELETE || (LA() == T_COLON_COLON && LA(2) == T_DELETE)) {
+        DeleteExpressionAST *ast = new (_pool) DeleteExpressionAST;
+
+        if (LA() == T_COLON_COLON)
+            ast->scope_token = consumeToken();
+
+        ast->delete_token = consumeToken();
+
+        if (LA() == T_LBRACKET) {
+            ast->lbracket_token = consumeToken();
+            match(T_RBRACKET, &ast->rbracket_token);
+        }
+
+        (void) parseCastExpression(ast->expression);
+        node = ast;
+        return true;
+    }
+    return false;
+}
+
+bool Parser::parseCastExpression(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_LPAREN) {
+        unsigned lparen_token = consumeToken();
+        unsigned initialCursor = cursor();
+        ExpressionAST *type_id = 0;
+        if (parseTypeId(type_id) && LA() == T_RPAREN) {
+
+            if (TypeIdAST *tid = type_id->asTypeId()) {
+                if (tid->type_specifier_list && ! tid->type_specifier_list->next) {
+                    if (tid->type_specifier_list->value->asNamedTypeSpecifier()) {
+                        switch (LA(2)) {
+                        case T_LBRACKET: // ... it's definitely a unary expression followed by an array access.
+                            goto parse_as_unary_expression;
+
+                        case T_PLUS_PLUS:
+                        case T_MINUS_MINUS: {
+                            const unsigned rparen_token = consumeToken();
+
+                            const bool blocked = blockErrors(true);
+                            ExpressionAST *unary = 0;
+                            bool followedByUnaryExpression = parseUnaryExpression(unary);
+                            blockErrors(blocked);
+                            rewind(rparen_token);
+
+                            if (followedByUnaryExpression) {
+                                if (! unary)
+                                    followedByUnaryExpression = false;
+                                else if (UnaryExpressionAST *u = unary->asUnaryExpression())
+                                    followedByUnaryExpression = u->expression != 0;
+                            }
+
+                            if (! followedByUnaryExpression)
+                                goto parse_as_unary_expression;
+
+                        }   break;
+
+                        case T_LPAREN: // .. it can be parsed as a function call.
+                            // ### TODO: check if it is followed by a parenthesized expression list.
+                            break;
+                        }
+                    }
+                }
+            }
+
+            unsigned rparen_token = consumeToken();
+            ExpressionAST *expression = 0;
+            if (parseCastExpression(expression)) {
+                CastExpressionAST *ast = new (_pool) CastExpressionAST;
+                ast->lparen_token = lparen_token;
+                ast->type_id = type_id;
+                ast->rparen_token = rparen_token;
+                ast->expression = expression;
+                node = ast;
+                return true;
+            }
+        }
+
+parse_as_unary_expression:
+        _astCache->insert(ASTCache::TypeId, initialCursor, 0, cursor(), false);
+        rewind(lparen_token);
+    }
+
+    return parseUnaryExpression(node);
+}
+
+bool Parser::parsePmExpression(ExpressionAST *&node)
+{
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::PointerToMember)
+}
+
+bool Parser::parseMultiplicativeExpression(ExpressionAST *&node)
+{
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::Multiplicative)
+}
+
+bool Parser::parseAdditiveExpression(ExpressionAST *&node)
+{
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::Additive)
+}
+
+bool Parser::parseShiftExpression(ExpressionAST *&node)
+{
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::Shift)
+}
+
+bool Parser::parseRelationalExpression(ExpressionAST *&node)
+{
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::Relational)
+}
+
+bool Parser::parseEqualityExpression(ExpressionAST *&node)
+{
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::Equality)
+}
+
+bool Parser::parseAndExpression(ExpressionAST *&node)
+{
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::And)
+}
+
+bool Parser::parseExclusiveOrExpression(ExpressionAST *&node)
+{
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::ExclusiveOr)
+}
+
+bool Parser::parseInclusiveOrExpression(ExpressionAST *&node)
+{
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::InclusiveOr)
+}
+
+bool Parser::parseLogicalAndExpression(ExpressionAST *&node)
+{
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::LogicalAnd)
+}
+
+bool Parser::parseLogicalOrExpression(ExpressionAST *&node)
+{
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::LogicalOr)
+}
+
+bool Parser::parseConditionalExpression(ExpressionAST *&node)
+{
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::Conditional)
+}
+
+bool Parser::parseAssignmentExpression(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_THROW)
+        return parseThrowExpression(node);
+    else
+        PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::Assignment)
+}
+
+bool Parser::parseQtMethod(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_SIGNAL || LA() == T_SLOT) {
+        QtMethodAST *ast = new (_pool) QtMethodAST;
+        ast->method_token = consumeToken();
+        match(T_LPAREN, &ast->lparen_token);
+        if (! parseDeclarator(ast->declarator, /*decl_specifier_seq =*/ 0))
+            error(cursor(), "expected a function declarator before token `%s'", tok().spell());
+        match(T_RPAREN, &ast->rparen_token);
+        node = ast;
+        return true;
+    }
+    return false;
+}
+
+bool Parser::parseConstantExpression(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    return parseConditionalExpression(node);
+}
+
+bool Parser::parseExpression(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    CHECK_CACHE(ASTCache::Expression, ExpressionAST);
+    unsigned initialCursor = cursor();
+
+    if (_expressionDepth > MAX_EXPRESSION_DEPTH)
+        return false;
+
+    ++_expressionDepth;
+    bool success = parseCommaExpression(node);
+    --_expressionDepth;
+
+    _astCache->insert(ASTCache::Expression, initialCursor, node, cursor(), success);
+    return success;
+}
+
+void Parser::parseExpressionWithOperatorPrecedence(ExpressionAST *&lhs, int minPrecedence)
+{
+    DEBUG_THIS_RULE();
+
+    while (precedence(tok().kind(), _templateArguments) >= minPrecedence) {
+        const int operPrecedence = precedence(tok().kind(), _templateArguments);
+        const int oper = consumeToken();
+
+        ConditionalExpressionAST *condExpr = 0;
+        if (operPrecedence == Prec::Conditional) {
+            condExpr = new (_pool) ConditionalExpressionAST;
+            condExpr->question_token = oper;
+            if (tok().kind() == T_COLON) {
+                // GNU extension:
+                //   logical-or-expression '?' ':' conditional-expression
+                condExpr->left_expression = 0;
+            } else {
+                parseExpression(condExpr->left_expression);
+            }
+            match(T_COLON, &condExpr->colon_token);
+        }
+
+        ExpressionAST *rhs = 0;
+        const bool isCPlusPlus = true;
+        if (operPrecedence <= Prec::Conditional && isCPlusPlus) {
+            // in C++ you can put a throw in the right-most expression of a conditional expression,
+            // or an assignment, so some special handling:
+            if (_languageFeatures.cxx11Enabled) {
+                if (!parseInitializerClause0x(rhs))
+                    return;
+            } else {
+                if (!parseAssignmentExpression(rhs))
+                    return;
+            }
+        } else {
+            // for C & all other expressions:
+            if (!parseCastExpression(rhs))
+                return;
+        }
+
+        for (int tokenKindAhead = tok().kind(), precedenceAhead = precedence(tokenKindAhead, _templateArguments);
+                (precedenceAhead > operPrecedence && isBinaryOperator(tokenKindAhead))
+                        || (precedenceAhead == operPrecedence && isRightAssociative(tokenKindAhead));
+                tokenKindAhead = tok().kind(), precedenceAhead = precedence(tokenKindAhead, _templateArguments)) {
+            parseExpressionWithOperatorPrecedence(rhs, precedenceAhead);
+        }
+
+        if (condExpr) { // we were parsing a ternairy conditional expression
+            condExpr->condition = lhs;
+            condExpr->right_expression = rhs;
+            lhs = condExpr;
+        } else {
+            BinaryExpressionAST *expr = new (_pool) BinaryExpressionAST;
+            expr->left_expression = lhs;
+            expr->binary_op_token = oper;
+            expr->right_expression = rhs;
+            lhs = expr;
+        }
+    }
+}
+
+bool Parser::parseCommaExpression(ExpressionAST *&node)
+{
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::Comma)
+}
+
+bool Parser::parseThrowExpression(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() == T_THROW) {
+        ThrowExpressionAST *ast = new (_pool) ThrowExpressionAST;
+        ast->throw_token = consumeToken();
+        parseAssignmentExpression(ast->expression);
+        node = ast;
+        return true;
+    }
+    return false;
+}
+
+bool Parser::lookAtObjCSelector() const
+{
+    switch (LA()) {
+    case T_IDENTIFIER:
+    case T_OR:
+    case T_AND:
+    case T_NOT:
+    case T_XOR:
+    case T_BITOR:
+    case T_COMPL:
+    case T_OR_EQ:
+    case T_AND_EQ:
+    case T_BITAND:
+    case T_NOT_EQ:
+    case T_XOR_EQ:
+        return true;
+
+    default:
+        if (tok().isKeyword())
+            return true;
+    } // switch
+
+    return false;
+}
+
+// designated-initializer ::= designator* T_EQUAL initializer-clause
+//
+bool Parser::parseDesignatedInitializer(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (!_languageFeatures.c99Enabled || (LA() != T_DOT && LA() != T_LBRACKET))
+        return false;
+
+    DesignatedInitializerAST *ast = new (_pool) DesignatedInitializerAST;
+    DesignatorListAST **designator_list_ptr = &ast->designator_list;
+    DesignatorAST *designator = 0;
+    const unsigned start = cursor();
+    while (parseDesignator(designator)) {
+        *designator_list_ptr = new (_pool) DesignatorListAST;
+        (*designator_list_ptr)->value = designator;
+        designator_list_ptr = &(*designator_list_ptr)->next;
+    }
+    if (start == cursor())
+        return false;
+
+    if (LA() == T_EQUAL) {
+        ast->equal_token = consumeToken();
+        if (parseAssignmentExpression(ast->initializer)) {
+            node = ast;
+            return true;
+        }
+    }
+
+    rewind(start);
+    return false;
+}
+
+// designator ::= T_DOT T_IDENTIFIER
+//                T_LBRACKET constant-expression T_BRACKET
+//
+bool Parser::parseDesignator(DesignatorAST *&node)
+{
+    DEBUG_THIS_RULE();
+    const unsigned start = cursor();
+    if (LA() == T_DOT) {
+        DotDesignatorAST *ast = new (_pool) DotDesignatorAST;
+        ast->dot_token = consumeToken();
+        match(T_IDENTIFIER, &ast->identifier_token);
+        node = ast;
+        return true;
+    } else if (LA() == T_LBRACKET) {
+        BracketDesignatorAST *ast = new (_pool) BracketDesignatorAST;
+        ast->lbracket_token = consumeToken();
+        if (parseConditionalExpression(ast->expression)) {
+            match(T_RBRACKET, &ast->rbracket_token);
+            node = ast;
+            return true;
+        }
+    }
+
+    rewind(start);
+    return false;
+}
+
+// objc-class-declaraton ::= T_AT_CLASS (T_IDENTIFIER @ T_COMMA) T_SEMICOLON
+//
+bool Parser::parseObjCClassForwardDeclaration(DeclarationAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_AT_CLASS)
+        return false;
+
+    ObjCClassForwardDeclarationAST *ast = new (_pool) ObjCClassForwardDeclarationAST;
+
+    ast->class_token = consumeToken();
+    unsigned identifier_token = 0;
+    match(T_IDENTIFIER, &identifier_token);
+
+    ast->identifier_list = new (_pool) NameListAST;
+    SimpleNameAST *name = new (_pool) SimpleNameAST;
+    name->identifier_token = identifier_token;
+    ast->identifier_list->value = name;
+    NameListAST **nextId = &ast->identifier_list->next;
+
+    while (LA() == T_COMMA) {
+        consumeToken(); // consume T_COMMA
+        match(T_IDENTIFIER, &identifier_token);
+
+        *nextId = new (_pool) NameListAST;
+        name = new (_pool) SimpleNameAST;
+        name->identifier_token = identifier_token;
+        (*nextId)->value = name;
+        nextId = &(*nextId)->next;
+    }
+
+    match(T_SEMICOLON, &ast->semicolon_token);
+    node = ast;
+    return true;
+}
+
+// objc-interface ::= attribute-specifier-list-opt objc-class-interface
+// objc-interface ::= objc-category-interface
+//
+// objc-class-interface ::= T_AT_INTERFACE T_IDENTIFIER (T_COLON T_IDENTIFIER)?
+//                          objc-protocol-refs-opt
+//                          objc-class-instance-variables-opt
+//                          objc-interface-declaration-list
+//                          T_AT_END
+//
+// objc-category-interface ::= T_AT_INTERFACE T_IDENTIFIER
+//                             T_LPAREN T_IDENTIFIER? T_RPAREN
+//                             objc-protocol-refs-opt
+//                             objc-interface-declaration-list
+//                             T_AT_END
+//
+bool Parser::parseObjCInterface(DeclarationAST *&node,
+                                SpecifierListAST *attributes)
+{
+    DEBUG_THIS_RULE();
+    if (! attributes && LA() == T___ATTRIBUTE__) {
+        SpecifierListAST **attr = &attributes;
+        while (parseGnuAttributeSpecifier(*attr))
+            attr = &(*attr)->next;
+    }
+
+    if (LA() != T_AT_INTERFACE)
+        return false;
+
+    unsigned objc_interface_token = consumeToken();
+    unsigned identifier_token = 0;
+    match(T_IDENTIFIER, &identifier_token);
+
+    if (LA() == T_LPAREN) {
+        // a category interface
+
+        if (attributes)
+            error(attributes->firstToken(), "invalid attributes for category interface declaration");
+
+        ObjCClassDeclarationAST *ast = new (_pool) ObjCClassDeclarationAST;
+        ast->attribute_list = attributes;
+        ast->interface_token = objc_interface_token;
+        SimpleNameAST *class_name = new (_pool) SimpleNameAST;
+        class_name->identifier_token= identifier_token;
+        ast->class_name = class_name;
+
+        match(T_LPAREN, &ast->lparen_token);
+        if (LA() == T_IDENTIFIER) {
+            SimpleNameAST *category_name = new (_pool) SimpleNameAST;
+            category_name->identifier_token = consumeToken();
+            ast->category_name = category_name;
+        }
+
+        match(T_RPAREN, &ast->rparen_token);
+
+        parseObjCProtocolRefs(ast->protocol_refs);
+
+        DeclarationListAST **nextMembers = &ast->member_declaration_list;
+        DeclarationAST *declaration = 0;
+        while (parseObjCInterfaceMemberDeclaration(declaration)) {
+            *nextMembers = new (_pool) DeclarationListAST;
+            (*nextMembers)->value = declaration;
+            nextMembers = &(*nextMembers)->next;
+        }
+
+        match(T_AT_END, &ast->end_token);
+
+        node = ast;
+        return true;
+    } else {
+        // a class interface declaration
+        ObjCClassDeclarationAST *ast = new (_pool) ObjCClassDeclarationAST;
+        ast->attribute_list = attributes;
+        ast->interface_token = objc_interface_token;
+        SimpleNameAST* class_name = new (_pool) SimpleNameAST;
+        class_name->identifier_token = identifier_token;
+        ast->class_name = class_name;
+
+        if (LA() == T_COLON) {
+            ast->colon_token = consumeToken();
+            SimpleNameAST *superclass = new (_pool) SimpleNameAST;
+            match(T_IDENTIFIER, &superclass->identifier_token);
+            ast->superclass = superclass;
+        }
+
+        parseObjCProtocolRefs(ast->protocol_refs);
+        parseObjClassInstanceVariables(ast->inst_vars_decl);
+
+        DeclarationListAST **nextMembers = &ast->member_declaration_list;
+        DeclarationAST *declaration = 0;
+        while (parseObjCInterfaceMemberDeclaration(declaration)) {
+            *nextMembers = new (_pool) DeclarationListAST;
+            (*nextMembers)->value = declaration;
+            nextMembers = &(*nextMembers)->next;
+        }
+
+        match(T_AT_END, &ast->end_token);
+
+        node = ast;
+        return true;
+    }
+}
+
+// objc-protocol ::= T_AT_PROTOCOL (T_IDENTIFIER @ T_COMMA) T_SEMICOLON
+//
+bool Parser::parseObjCProtocol(DeclarationAST *&node,
+                               SpecifierListAST *attributes)
+{
+    DEBUG_THIS_RULE();
+    if (! attributes && LA() == T___ATTRIBUTE__) {
+        SpecifierListAST **attr = &attributes;
+        while (parseGnuAttributeSpecifier(*attr))
+            attr = &(*attr)->next;
+    }
+
+    if (LA() != T_AT_PROTOCOL)
+        return false;
+
+    unsigned protocol_token = consumeToken();
+    unsigned identifier_token = 0;
+    match(T_IDENTIFIER, &identifier_token);
+
+    if (LA() == T_COMMA || LA() == T_SEMICOLON) {
+        // a protocol forward declaration
+
+        ObjCProtocolForwardDeclarationAST *ast = new (_pool) ObjCProtocolForwardDeclarationAST;
+        ast->attribute_list = attributes;
+        ast->protocol_token = protocol_token;
+        ast->identifier_list = new (_pool) NameListAST;
+        SimpleNameAST *name = new (_pool) SimpleNameAST;
+        name->identifier_token = identifier_token;
+        ast->identifier_list->value = name;
+        NameListAST **nextId = &ast->identifier_list->next;
+
+        while (LA() == T_COMMA) {
+            consumeToken(); // consume T_COMMA
+            match(T_IDENTIFIER, &identifier_token);
+
+            *nextId = new (_pool) NameListAST;
+            name = new (_pool) SimpleNameAST;
+            name->identifier_token = identifier_token;
+            (*nextId)->value = name;
+            nextId = &(*nextId)->next;
+        }
+
+        match(T_SEMICOLON, &ast->semicolon_token);
+        node = ast;
+        return true;
+    } else {
+        // a protocol definition
+        ObjCProtocolDeclarationAST *ast = new (_pool) ObjCProtocolDeclarationAST;
+        ast->attribute_list = attributes;
+        ast->protocol_token = protocol_token;
+        SimpleNameAST *name = new (_pool) SimpleNameAST;
+        name->identifier_token = identifier_token;
+        ast->name = name;
+
+        parseObjCProtocolRefs(ast->protocol_refs);
+
+        DeclarationListAST **nextMembers = &ast->member_declaration_list;
+        DeclarationAST *declaration = 0;
+        while (parseObjCInterfaceMemberDeclaration(declaration)) {
+            *nextMembers = new (_pool) DeclarationListAST;
+            (*nextMembers)->value = declaration;
+            nextMembers = &(*nextMembers)->next;
+        }
+
+        match(T_AT_END, &ast->end_token);
+
+        node = ast;
+        return true;
+    }
+}
+
+// objc-implementation ::= T_AT_IMPLEMENTAION T_IDENTIFIER (T_COLON T_IDENTIFIER)?
+//                         objc-class-instance-variables-opt
+// objc-implementation ::= T_AT_IMPLEMENTAION T_IDENTIFIER T_LPAREN T_IDENTIFIER T_RPAREN
+//
+bool Parser::parseObjCImplementation(DeclarationAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_AT_IMPLEMENTATION)
+        return false;
+
+    unsigned implementation_token = consumeToken();
+    unsigned identifier_token = 0;
+    match(T_IDENTIFIER, &identifier_token);
+
+    if (LA() == T_LPAREN) {
+        // a category implementation
+        ObjCClassDeclarationAST *ast = new (_pool) ObjCClassDeclarationAST;
+        ast->implementation_token = implementation_token;
+        SimpleNameAST *class_name = new (_pool) SimpleNameAST;
+        class_name->identifier_token = identifier_token;
+        ast->class_name = class_name;
+
+        match(T_LPAREN, &ast->lparen_token);
+        SimpleNameAST *category_name = new (_pool) SimpleNameAST;
+        match(T_IDENTIFIER, &category_name->identifier_token);
+        ast->category_name = category_name;
+        match(T_RPAREN, &ast->rparen_token);
+
+        parseObjCMethodDefinitionList(ast->member_declaration_list);
+        match(T_AT_END, &ast->end_token);
+
+        node = ast;
+    } else {
+        // a class implementation
+        ObjCClassDeclarationAST *ast = new (_pool) ObjCClassDeclarationAST;
+        ast->implementation_token = implementation_token;
+        SimpleNameAST *class_name = new (_pool) SimpleNameAST;
+        class_name->identifier_token = identifier_token;
+        ast->class_name = class_name;
+
+        if (LA() == T_COLON) {
+            ast->colon_token = consumeToken();
+            SimpleNameAST *superclass = new (_pool) SimpleNameAST;
+            match(T_IDENTIFIER, &superclass->identifier_token);
+            ast->superclass = superclass;
+        }
+
+        parseObjClassInstanceVariables(ast->inst_vars_decl);
+        parseObjCMethodDefinitionList(ast->member_declaration_list);
+        match(T_AT_END, &ast->end_token);
+
+        node = ast;
+    }
+
+    return true;
+}
+
+bool Parser::parseObjCMethodDefinitionList(DeclarationListAST *&node)
+{
+    DEBUG_THIS_RULE();
+    DeclarationListAST **next = &node;
+
+    while (LA() && LA() != T_AT_END) {
+        unsigned start = cursor();
+        DeclarationAST *declaration = 0;
+
+        switch (LA()) {
+        case T_PLUS:
+        case T_MINUS:
+            parseObjCMethodDefinition(declaration);
+
+            if (start == cursor())
+                consumeToken();
+            break;
+
+        case T_SEMICOLON:
+            consumeToken();
+            break;
+
+        case T_AT_SYNTHESIZE: {
+            ObjCSynthesizedPropertiesDeclarationAST *ast = new (_pool) ObjCSynthesizedPropertiesDeclarationAST;
+            ast->synthesized_token = consumeToken();
+            ObjCSynthesizedPropertyListAST *last = new (_pool) ObjCSynthesizedPropertyListAST;
+            ast->property_identifier_list = last;
+            last->value = new (_pool) ObjCSynthesizedPropertyAST;
+            match(T_IDENTIFIER, &last->value->property_identifier_token);
+
+            if (LA() == T_EQUAL) {
+                last->value->equals_token = consumeToken();
+
+                match(T_IDENTIFIER, &last->value->alias_identifier_token);
+            }
+
+            while (LA() == T_COMMA) {
+                consumeToken(); // consume T_COMMA
+
+                last->next = new (_pool) ObjCSynthesizedPropertyListAST;
+                last = last->next;
+
+                last->value = new (_pool) ObjCSynthesizedPropertyAST;
+                match(T_IDENTIFIER, &last->value->property_identifier_token);
+
+                if (LA() == T_EQUAL) {
+                    last->value->equals_token = consumeToken();
+
+                    match(T_IDENTIFIER, &last->value->alias_identifier_token);
+                }
+            }
+
+            match(T_SEMICOLON, &ast->semicolon_token);
+
+            declaration = ast;
+            break;
+        }
+
+        case T_AT_DYNAMIC: {
+            ObjCDynamicPropertiesDeclarationAST *ast = new (_pool) ObjCDynamicPropertiesDeclarationAST;
+            ast->dynamic_token = consumeToken();
+            ast->property_identifier_list = new (_pool) NameListAST;
+            SimpleNameAST *name = new (_pool) SimpleNameAST;
+            match(T_IDENTIFIER, &name->identifier_token);
+            ast->property_identifier_list->value = name;
+
+            NameListAST *last = ast->property_identifier_list;
+            while (LA() == T_COMMA) {
+                consumeToken(); // consume T_COMMA
+
+                last->next = new (_pool) NameListAST;
+                last = last->next;
+                name = new (_pool) SimpleNameAST;
+                match(T_IDENTIFIER, &name->identifier_token);
+                last->value = name;
+            }
+
+            match(T_SEMICOLON, &ast->semicolon_token);
+
+            declaration = ast;
+            break;
+        }
+
+        default:
+            if (LA() == T_EXTERN && LA(2) == T_STRING_LITERAL) {
+                parseDeclaration(declaration);
+            } else {
+                if (! parseBlockDeclaration(declaration)) {
+                    rewind(start);
+                    error(cursor(), "skip token `%s'", tok().spell());
+                    consumeToken();
+                }
+            }
+            break;
+        } // switch
+
+        if (declaration) {
+            *next = new (_pool) DeclarationListAST;
+            (*next)->value = declaration;
+            next = &(*next)->next;
+        }
+    }
+
+    return true;
+}
+
+bool Parser::parseObjCMethodDefinition(DeclarationAST *&node)
+{
+    DEBUG_THIS_RULE();
+    ObjCMethodPrototypeAST *method_prototype = 0;
+    if (! parseObjCMethodPrototype(method_prototype))
+        return false;
+
+    ObjCMethodDeclarationAST *ast = new (_pool) ObjCMethodDeclarationAST;
+    ast->method_prototype = method_prototype;
+
+    // Objective-C allows you to write:
+    // - (void) foo; { body; }
+    // so a method is a forward declaration when it doesn't have a _body_.
+    // However, we still need to read the semicolon.
+    if (LA() == T_SEMICOLON)
+        ast->semicolon_token = consumeToken();
+
+    parseFunctionBody(ast->function_body);
+
+    node = ast;
+    return true;
+}
+
+// objc-protocol-refs ::= T_LESS (T_IDENTIFIER @ T_COMMA) T_GREATER
+//
+bool Parser::parseObjCProtocolRefs(ObjCProtocolRefsAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_LESS)
+        return false;
+
+    ObjCProtocolRefsAST *ast = new (_pool) ObjCProtocolRefsAST;
+
+    match(T_LESS, &ast->less_token);
+
+    unsigned identifier_token = 0;
+    match(T_IDENTIFIER, &identifier_token);
+    ast->identifier_list = new (_pool) NameListAST;
+    SimpleNameAST *name = new (_pool) SimpleNameAST;
+    name->identifier_token = identifier_token;
+    ast->identifier_list->value = name;
+    NameListAST **nextId = &ast->identifier_list->next;
+
+    while (LA() == T_COMMA) {
+        consumeToken(); // consume T_COMMA
+        match(T_IDENTIFIER, &identifier_token);
+
+        *nextId = new (_pool) NameListAST;
+        name = new (_pool) SimpleNameAST;
+        name->identifier_token = identifier_token;
+        (*nextId)->value = name;
+        nextId = &(*nextId)->next;
+    }
+
+    match(T_GREATER, &ast->greater_token);
+    node = ast;
+    return true;
+}
+
+// objc-class-instance-variables ::= T_LBRACE
+//                                   objc-instance-variable-decl-list-opt
+//                                   T_RBRACE
+//
+bool Parser::parseObjClassInstanceVariables(ObjCInstanceVariablesDeclarationAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_LBRACE)
+        return false;
+
+    ObjCInstanceVariablesDeclarationAST *ast = new (_pool) ObjCInstanceVariablesDeclarationAST;
+    match(T_LBRACE, &ast->lbrace_token);
+
+    for (DeclarationListAST **next = &ast->instance_variable_list; LA(); next = &(*next)->next) {
+        if (LA() == T_RBRACE)
+            break;
+
+        const unsigned start = cursor();
+
+        *next = new (_pool) DeclarationListAST;
+        parseObjCInstanceVariableDeclaration((*next)->value);
+
+        if (start == cursor()) {
+            // skip stray token.
+            error(cursor(), "skip stray token `%s'", tok().spell());
+            consumeToken();
+        }
+    }
+
+    match(T_RBRACE, &ast->rbrace_token);
+
+    node = ast;
+    return true;
+}
+
+// objc-interface-declaration ::= T_AT_REQUIRED
+// objc-interface-declaration ::= T_AT_OPTIONAL
+// objc-interface-declaration ::= T_SEMICOLON
+// objc-interface-declaration ::= objc-property-declaration
+// objc-interface-declaration ::= objc-method-prototype
+bool Parser::parseObjCInterfaceMemberDeclaration(DeclarationAST *&node)
+{
+    DEBUG_THIS_RULE();
+    switch (LA()) {
+    case T_AT_END:
+        return false;
+
+    case T_AT_REQUIRED:
+    case T_AT_OPTIONAL:
+        consumeToken();
+        return true;
+
+    case T_SEMICOLON:
+        consumeToken();
+        return true;
+
+    case T_AT_PROPERTY: {
+        return parseObjCPropertyDeclaration(node);
+    }
+
+    case T_PLUS:
+    case T_MINUS: {
+        ObjCMethodDeclarationAST *ast = new (_pool) ObjCMethodDeclarationAST;
+        if (parseObjCMethodPrototype(ast->method_prototype)) {
+            match(T_SEMICOLON, &ast->semicolon_token);
+            node = ast;
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    case T_ENUM:
+    case T_CLASS:
+    case T_STRUCT:
+    case T_UNION: {
+        return parseSimpleDeclaration(node);
+    }
+
+    default: {
+        return parseSimpleDeclaration(node);
+    } // default
+
+    } // switch
+}
+
+// objc-instance-variable-declaration ::= objc-visibility-specifier
+// objc-instance-variable-declaration ::= block-declaration
+//
+bool Parser::parseObjCInstanceVariableDeclaration(DeclarationAST *&node)
+{
+    DEBUG_THIS_RULE();
+    switch (LA()) {
+        case T_AT_PRIVATE:
+        case T_AT_PROTECTED:
+        case T_AT_PUBLIC:
+        case T_AT_PACKAGE: {
+            ObjCVisibilityDeclarationAST *ast = new (_pool) ObjCVisibilityDeclarationAST;
+            ast->visibility_token = consumeToken();
+            node = ast;
+            return true;
+        }
+
+        default:
+            return parseSimpleDeclaration(node);
+    }
+}
+
+// objc-property-declaration ::=
+//    T_AT_PROPERTY T_LPAREN (property-attribute @ T_COMMA) T_RPAREN simple-declaration
+//
+bool Parser::parseObjCPropertyDeclaration(DeclarationAST *&node, SpecifierListAST *attributes)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_AT_PROPERTY)
+        return false;
+
+    ObjCPropertyDeclarationAST *ast = new (_pool) ObjCPropertyDeclarationAST;
+    ast->attribute_list = attributes;
+    ast->property_token = consumeToken();
+
+    if (LA() == T_LPAREN) {
+        match(T_LPAREN, &ast->lparen_token);
+
+        ObjCPropertyAttributeAST *property_attribute = 0;
+        if (parseObjCPropertyAttribute(property_attribute)) {
+            ast->property_attribute_list = new (_pool) ObjCPropertyAttributeListAST;
+            ast->property_attribute_list->value = property_attribute;
+            ObjCPropertyAttributeListAST *last = ast->property_attribute_list;
+
+            while (LA() == T_COMMA) {
+                consumeToken(); // consume T_COMMA
+                last->next = new (_pool) ObjCPropertyAttributeListAST;
+                last = last->next;
+                if (!parseObjCPropertyAttribute(last->value)) {
+                    error(_tokenIndex, "expected token `%s' got `%s'",
+                          Token::name(T_IDENTIFIER), tok().spell());
+                    break;
+                }
+            }
+        }
+
+        match(T_RPAREN, &ast->rparen_token);
+    }
+
+    if (parseSimpleDeclaration(ast->simple_declaration))
+        node = ast;
+    else
+        error(_tokenIndex, "expected a simple declaration");
+
+    return true;
+}
+
+// objc-method-prototype ::= (T_PLUS | T_MINUS) objc-method-decl objc-method-attrs-opt
+//
+// objc-method-decl ::= objc-type-name? objc-selector
+// objc-method-decl ::= objc-type-name? objc-keyword-decl-list objc-parmlist-opt
+//
+bool Parser::parseObjCMethodPrototype(ObjCMethodPrototypeAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_PLUS && LA() != T_MINUS)
+        return false;
+
+    ObjCMethodPrototypeAST *ast = new (_pool) ObjCMethodPrototypeAST;
+    ast->method_type_token = consumeToken();
+
+    parseObjCTypeName(ast->type_name);
+
+    if ((lookAtObjCSelector() && LA(2) == T_COLON) || LA() == T_COLON) {
+        ObjCSelectorArgumentAST *argument = 0;
+        ObjCMessageArgumentDeclarationAST *declaration = 0;
+        parseObjCKeywordDeclaration(argument, declaration);
+
+        ObjCSelectorAST *sel = new (_pool) ObjCSelectorAST;
+        ast->selector = sel;
+        ObjCSelectorArgumentListAST *lastSel = new (_pool) ObjCSelectorArgumentListAST;
+        sel->selector_argument_list = lastSel;
+        sel->selector_argument_list->value = argument;
+
+        ast->argument_list = new (_pool) ObjCMessageArgumentDeclarationListAST;
+        ast->argument_list->value = declaration;
+        ObjCMessageArgumentDeclarationListAST *lastArg = ast->argument_list;
+
+        while (parseObjCKeywordDeclaration(argument, declaration)) {
+            lastSel->next = new (_pool) ObjCSelectorArgumentListAST;
+            lastSel = lastSel->next;
+            lastSel->value = argument;
+
+            lastArg->next = new (_pool) ObjCMessageArgumentDeclarationListAST;
+            lastArg = lastArg->next;
+            lastArg->value = declaration;
+        }
+
+        while (LA() == T_COMMA) {
+            consumeToken();
+
+            if (LA() == T_DOT_DOT_DOT) {
+                ast->dot_dot_dot_token = consumeToken();
+                break;
+            }
+
+            // TODO: Is this still valid, and if so, should it be stored in the AST? (EV)
+            ParameterDeclarationAST *parameter_declaration = 0;
+            parseParameterDeclaration(parameter_declaration);
+        }
+    } else if (lookAtObjCSelector()) {
+        ObjCSelectorAST *sel = new (_pool) ObjCSelectorAST;
+        sel->selector_argument_list = new (_pool) ObjCSelectorArgumentListAST;
+        sel->selector_argument_list->value = new (_pool) ObjCSelectorArgumentAST;
+        parseObjCSelector(sel->selector_argument_list->value->name_token);
+        ast->selector = sel;
+    } else {
+        error(cursor(), "expected a selector");
+    }
+
+    SpecifierListAST **attr = &ast->attribute_list;
+    while (parseGnuAttributeSpecifier(*attr))
+        attr = &(*attr)->next;
+
+    node = ast;
+    return true;
+}
+
+// objc-property-attribute ::= getter '=' identifier
+// objc-property-attribute ::= setter '=' identifier ':'
+// objc-property-attribute ::= readonly
+// objc-property-attribute ::= readwrite
+// objc-property-attribute ::= assign
+// objc-property-attribute ::= retain
+// objc-property-attribute ::= copy
+// objc-property-attribute ::= nonatomic
+bool Parser::parseObjCPropertyAttribute(ObjCPropertyAttributeAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_IDENTIFIER)
+        return false;
+
+    node = new (_pool) ObjCPropertyAttributeAST;
+
+    const Identifier *id = tok().identifier;
+    const int k = classifyObjectiveCContextKeyword(id->chars(), id->size());
+    switch (k) {
+    case Token_copy:
+    case Token_assign:
+    case Token_retain:
+    case Token_readonly:
+    case Token_readwrite:
+    case Token_nonatomic:
+        node->attribute_identifier_token = consumeToken();
+        return true;
+
+    case Token_getter: {
+        node->attribute_identifier_token = consumeToken();
+        match(T_EQUAL, &node->equals_token);
+        ObjCSelectorAST *sel = new (_pool) ObjCSelectorAST;
+        sel->selector_argument_list = new (_pool) ObjCSelectorArgumentListAST;
+        sel->selector_argument_list->value = new (_pool) ObjCSelectorArgumentAST;
+        match(T_IDENTIFIER, &sel->selector_argument_list->value->name_token);
+        node->method_selector = sel;
+        return true;
+    }
+
+    case Token_setter: {
+        node->attribute_identifier_token = consumeToken();
+        match(T_EQUAL, &node->equals_token);
+        ObjCSelectorAST *sel = new (_pool) ObjCSelectorAST;
+        sel->selector_argument_list = new (_pool) ObjCSelectorArgumentListAST;
+        sel->selector_argument_list->value = new (_pool) ObjCSelectorArgumentAST;
+        match(T_IDENTIFIER, &sel->selector_argument_list->value->name_token);
+        match(T_COLON, &sel->selector_argument_list->value->colon_token);
+        node->method_selector = sel;
+        return true;
+    }
+
+    default:
+        return false;
+    }
+}
+
+// objc-type-name ::= T_LPAREN objc-type-qualifiers-opt type-id T_RPAREN
+//
+bool Parser::parseObjCTypeName(ObjCTypeNameAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_LPAREN)
+        return false;
+
+    ObjCTypeNameAST *ast = new (_pool) ObjCTypeNameAST;
+    match(T_LPAREN, &ast->lparen_token);
+    parseObjCTypeQualifiers(ast->type_qualifier_token);
+    parseTypeId(ast->type_id);
+    match(T_RPAREN, &ast->rparen_token);
+    node = ast;
+    return true;
+}
+
+// objc-selector ::= T_IDENTIFIER | keyword
+//
+bool Parser::parseObjCSelector(unsigned &selector_token)
+{
+    DEBUG_THIS_RULE();
+    if (! lookAtObjCSelector())
+        return false;
+
+    selector_token = consumeToken();
+    return true;
+}
+
+// objc-keyword-decl ::= objc-selector? T_COLON objc-type-name? objc-keyword-attributes-opt T_IDENTIFIER
+//
+bool Parser::parseObjCKeywordDeclaration(ObjCSelectorArgumentAST *&argument, ObjCMessageArgumentDeclarationAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (! (LA() == T_COLON || (lookAtObjCSelector() && LA(2) == T_COLON)))
+        return false;
+
+    node = new (_pool) ObjCMessageArgumentDeclarationAST;
+    argument = new (_pool) ObjCSelectorArgumentAST;
+
+    parseObjCSelector(argument->name_token);
+    match(T_COLON, &argument->colon_token);
+
+    parseObjCTypeName(node->type_name);
+
+    SpecifierListAST **attr = &node->attribute_list;
+    while (parseGnuAttributeSpecifier(*attr))
+        attr = &(*attr)->next;
+
+    SimpleNameAST *param_name = new (_pool) SimpleNameAST;
+    match(T_IDENTIFIER, &param_name->identifier_token);
+    node->param_name = param_name;
+
+    return true;
+}
+
+bool Parser::parseObjCTypeQualifiers(unsigned &type_qualifier)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_IDENTIFIER)
+        return false;
+
+    const Identifier *id = tok().identifier;
+    switch (classifyObjectiveCContextKeyword(id->chars(), id->size())) {
+    case Token_bycopy:
+    case Token_byref:
+    case Token_in:
+    case Token_inout:
+    case Token_oneway:
+    case Token_out:
+        type_qualifier = consumeToken();
+        return true;
+    default:
+        return false;
+    }
+}
+
+bool Parser::peekAtObjCContextKeyword(int kind)
+{
+    if (LA() != T_IDENTIFIER)
+        return false;
+
+    const Identifier *id = tok().identifier;
+    const int k = classifyObjectiveCContextKeyword(id->chars(), id->size());
+    return k == kind;
+}
+
+bool Parser::parseObjCContextKeyword(int kind, unsigned &in_token)
+{
+    DEBUG_THIS_RULE();
+
+    if (!peekAtObjCContextKeyword(kind))
+        return false;
+
+    in_token = consumeToken();
+    return true;
+}
+
+int Parser::peekAtQtContextKeyword() const
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_IDENTIFIER)
+        return false;
+
+    const Identifier *id = tok().identifier;
+    return classifyQtContextKeyword(id->chars(), id->size());
+}
+
+bool Parser::parseLambdaExpression(ExpressionAST *&node)
+{
+    DEBUG_THIS_RULE();
+
+    LambdaIntroducerAST *lambda_introducer = 0;
+    if (parseLambdaIntroducer(lambda_introducer)) {
+        LambdaExpressionAST *ast = new (_pool) LambdaExpressionAST;
+        ast->lambda_introducer = lambda_introducer;
+        parseLambdaDeclarator(ast->lambda_declarator);
+        parseCompoundStatement(ast->statement);
+        node = ast;
+        return true;
+    }
+
+    return false;
+}
+
+bool Parser::parseLambdaIntroducer(LambdaIntroducerAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_LBRACKET)
+        return false;
+
+    LambdaIntroducerAST *ast = new (_pool) LambdaIntroducerAST;
+    ast->lbracket_token = consumeToken();
+
+    if (LA() != T_RBRACKET)
+        parseLambdaCapture(ast->lambda_capture);
+
+    if (LA() == T_RBRACKET) {
+        ast->rbracket_token = consumeToken();
+
+        if (LA() == T_LPAREN || LA() == T_LBRACE) {
+            node = ast;
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool Parser::parseLambdaCapture(LambdaCaptureAST *&node)
+{
+    DEBUG_THIS_RULE();
+    bool startsWithDefaultCapture = false;
+
+    unsigned default_capture = 0;
+    CaptureListAST *capture_list = 0;
+
+    if (LA() == T_AMPER || LA() == T_EQUAL) {
+        if (LA(2) == T_COMMA || LA(2) == T_RBRACKET) {
+            startsWithDefaultCapture = true;
+            default_capture = consumeToken(); // consume capture-default
+        }
+    }
+
+    if (startsWithDefaultCapture && LA() == T_COMMA) {
+        consumeToken(); // consume ','
+        parseCaptureList(capture_list); // required
+
+    } else if (LA() != T_RBRACKET) {
+        parseCaptureList(capture_list); // optional
+
+    }
+
+    LambdaCaptureAST *ast = new (_pool) LambdaCaptureAST;
+    ast->default_capture_token = default_capture;
+    ast->capture_list = capture_list;
+    node = ast;
+
+    return true;
+}
+
+bool Parser::parseCapture(CaptureAST *&node)
+{
+    DEBUG_THIS_RULE();
+
+    if (LA() == T_THIS) {
+        consumeToken();
+        return true;
+    }
+
+    if (LA() == T_AMPER)
+        consumeToken();
+
+    if (LA() == T_IDENTIFIER) {
+        SimpleNameAST *ast = new (_pool) SimpleNameAST;
+        ast->identifier_token = consumeToken();
+
+        node = new (_pool) CaptureAST;
+        node->identifier = ast;
+        return true;
+    }
+
+    return false;
+}
+
+bool Parser::parseCaptureList(CaptureListAST *&node)
+{
+    DEBUG_THIS_RULE();
+
+    CaptureAST *capture = 0;
+
+    if (parseCapture(capture)) {
+        node = new (_pool) CaptureListAST;
+        node->value = capture;
+
+        CaptureListAST **l = &node->next;
+        while (LA() == T_COMMA) {
+            consumeToken(); // consume `,'
+            CaptureAST *capture = 0;
+            parseCapture(capture);
+            if (capture) {
+                *l = new (_pool) CaptureListAST;
+                (*l)->value = capture;
+                l = &(*l)->next;
+            }
+        }
+
+        return true;
+    }
+
+    return false;
+}
+
+bool Parser::parseLambdaDeclarator(LambdaDeclaratorAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_LPAREN)
+        return false;
+
+    LambdaDeclaratorAST *ast = new (_pool) LambdaDeclaratorAST;
+
+    ast->lparen_token = consumeToken(); // consume `('
+    parseParameterDeclarationClause(ast->parameter_declaration_clause);
+    match(T_RPAREN, &ast->rparen_token);
+
+    SpecifierListAST **attr = &ast->attributes;
+    while (parseGnuAttributeSpecifier(*attr))
+        attr = &(*attr)->next;
+
+    if (LA() == T_MUTABLE)
+        ast->mutable_token = consumeToken();
+
+    parseExceptionSpecification(ast->exception_specification);
+    parseTrailingReturnType(ast->trailing_return_type);
+    node = ast;
+
+    return true;
+}
+
+bool Parser::parseTrailingReturnType(TrailingReturnTypeAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_ARROW)
+        return false;
+
+    TrailingReturnTypeAST *ast = new (_pool) TrailingReturnTypeAST;
+
+    ast->arrow_token = consumeToken();
+
+    SpecifierListAST **attr = &ast->attributes;
+    while (parseGnuAttributeSpecifier(*attr))
+        attr = &(*attr)->next;
+
+    parseTrailingTypeSpecifierSeq(ast->type_specifier_list);
+    parseAbstractDeclarator(ast->declarator, ast->type_specifier_list);
+    node = ast;
+    return true;
+}
+
+void Parser::rewind(unsigned cursor)
+{
+#ifndef CPLUSPLUS_NO_DEBUG_RULE
+    if (cursor != _tokenIndex)
+        fprintf(stderr, "! rewinding from token %d to token %d\n", _tokenIndex, cursor);
+#endif
+
+    const unsigned n = _translationUnit->tokenCount();
+    if (cursor < n)
+        _tokenIndex = cursor;
+    else
+        _tokenIndex = n - 1;
+}
+
+void Parser::warning(unsigned index, const char *format, ...)
+{
+    va_list args, ap;
+    va_start(args, format);
+    va_copy(ap, args);
+    _translationUnit->message(DiagnosticClient::Warning, index, format, ap);
+    va_end(ap);
+    va_end(args);
+}
+
+void Parser::error(unsigned index, const char *format, ...)
+{
+    va_list args, ap;
+    va_start(args, format);
+    va_copy(ap, args);
+    _translationUnit->message(DiagnosticClient::Error, index, format, ap);
+    va_end(ap);
+    va_end(args);
+}
+
+void Parser::fatal(unsigned index, const char *format, ...)
+{
+    va_list args, ap;
+    va_start(args, format);
+    va_copy(ap, args);
+    _translationUnit->message(DiagnosticClient::Fatal, index, format, ap);
+    va_end(ap);
+    va_end(args);
+}

+ 340 - 0
Source/ToolCore/JSBind/cplusplus/Parser.h

@@ -0,0 +1,340 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_PARSER_H
+#define CPLUSPLUS_PARSER_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include "ASTfwd.h"
+#include "Token.h"
+#include "TranslationUnit.h"
+#include "MemoryPool.h"
+#include <map>
+
+namespace CPlusPlus {
+
+class CPLUSPLUS_EXPORT Parser
+{
+public:
+    Parser(TranslationUnit *translationUnit);
+    ~Parser();
+
+    bool parseTranslationUnit(TranslationUnitAST *&node);
+
+public:
+    bool parseExpressionList(ExpressionListAST *&node);
+    bool parseAbstractCoreDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list);
+    bool parseAbstractDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list);
+    bool parseEmptyDeclaration(DeclarationAST *&node);
+    bool parseAccessDeclaration(DeclarationAST *&node);
+    bool parseQtPropertyDeclaration(DeclarationAST *&node);
+    bool parseQtEnumDeclaration(DeclarationAST *&node);
+    bool parseQtFlags(DeclarationAST *&node);
+    bool parseQtInterfaces(DeclarationAST *&node);
+    bool parseAdditiveExpression(ExpressionAST *&node);
+    bool parseAndExpression(ExpressionAST *&node);
+    bool parseAsmDefinition(DeclarationAST *&node);
+    bool parseAsmOperandList();
+    bool parseAsmOperand();
+    bool parseAsmClobberList();
+    bool parseAssignmentExpression(ExpressionAST *&node);
+    bool parseBaseClause(BaseSpecifierListAST *&node);
+    bool parseBaseSpecifier(BaseSpecifierListAST *&node);
+    bool parseBlockDeclaration(DeclarationAST *&node);
+    bool parseCppCastExpression(ExpressionAST *&node);
+    bool parseCastExpression(ExpressionAST *&node);
+    bool parseClassSpecifier(SpecifierListAST *&node);
+    bool parseCommaExpression(ExpressionAST *&node);
+    bool parseCompoundStatement(StatementAST *&node);
+    bool parseBreakStatement(StatementAST *&node);
+    bool parseContinueStatement(StatementAST *&node);
+    bool parseGotoStatement(StatementAST *&node);
+    bool parseReturnStatement(StatementAST *&node);
+    bool parseCondition(ExpressionAST *&node);
+    bool parseConditionalExpression(ExpressionAST *&node);
+    bool parseConstantExpression(ExpressionAST *&node);
+    bool parseCtorInitializer(CtorInitializerAST *&node);
+    bool parseCvQualifiers(SpecifierListAST *&node);
+    bool parseRefQualifier(unsigned &ref_qualifier);
+    bool parseOverrideFinalQualifiers(SpecifierListAST *&node);
+    bool parseDeclaratorOrAbstractDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list);
+    bool parseDeclaration(DeclarationAST *&node);
+    bool parseSimpleDeclaration(DeclarationAST *&node, ClassSpecifierAST *declaringClass = 0);
+    bool parseDeclarationStatement(StatementAST *&node);
+    bool parseCoreDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list, ClassSpecifierAST *declaringClass);
+    bool parseDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list, ClassSpecifierAST *declaringClass = 0);
+    bool parseDeleteExpression(ExpressionAST *&node);
+    bool parseDoStatement(StatementAST *&node);
+    bool parseElaboratedTypeSpecifier(SpecifierListAST *&node);
+    bool parseEnumSpecifier(SpecifierListAST *&node);
+    bool parseEnumerator(EnumeratorListAST *&node);
+    bool parseEqualityExpression(ExpressionAST *&node);
+    bool parseExceptionDeclaration(ExceptionDeclarationAST *&node);
+    bool parseExceptionSpecification(ExceptionSpecificationAST *&node);
+    bool parseExclusiveOrExpression(ExpressionAST *&node);
+    bool parseExpression(ExpressionAST *&node);
+    bool parseExpressionOrDeclarationStatement(StatementAST *&node);
+    bool parseExpressionStatement(StatementAST *&node);
+    bool parseForInitStatement(StatementAST *&node);
+    bool parseForeachStatement(StatementAST *&node);
+    bool parseForStatement(StatementAST *&node);
+    bool parseFunctionBody(StatementAST *&node);
+    bool parseIfStatement(StatementAST *&node);
+    bool parseInclusiveOrExpression(ExpressionAST *&node);
+    bool parseInitDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list, ClassSpecifierAST *declaringClass);
+    bool parseInitializerList(ExpressionListAST *&node);
+    bool parseInitializer(ExpressionAST *&node, unsigned *equals_token);
+    bool parseInitializerClause(ExpressionAST *&node);
+    bool parseLabeledStatement(StatementAST *&node);
+    bool parseLinkageBody(DeclarationAST *&node);
+    bool parseLinkageSpecification(DeclarationAST *&node);
+    bool parseLogicalAndExpression(ExpressionAST *&node);
+    bool parseLogicalOrExpression(ExpressionAST *&node);
+    bool parseMemInitializer(MemInitializerListAST *&node);
+    bool parseMemInitializerList(MemInitializerListAST *&node);
+    bool parseMemberSpecification(DeclarationAST *&node, ClassSpecifierAST *declaringClass);
+    bool parseMultiplicativeExpression(ExpressionAST *&node);
+    bool parseTemplateId(NameAST *&node, unsigned template_token = 0);
+    bool parseClassOrNamespaceName(NameAST *&node);
+    bool parseNameId(NameAST *&node);
+    bool parseName(NameAST *&node, bool acceptTemplateId = true);
+    bool parseNestedNameSpecifier(NestedNameSpecifierListAST *&node, bool acceptTemplateId);
+    bool parseNestedNameSpecifierOpt(NestedNameSpecifierListAST *&name, bool acceptTemplateId);
+    bool parseStaticAssertDeclaration(DeclarationAST *&node);
+    bool parseNamespace(DeclarationAST *&node);
+    bool parseNamespaceAliasDefinition(DeclarationAST *&node);
+    bool parseNewArrayDeclarator(NewArrayDeclaratorListAST *&node);
+    bool parseNewExpression(ExpressionAST *&node);
+    bool parseExpressionListParen(ExpressionAST *&node);
+    bool parseNewInitializer(ExpressionAST *&node);
+    bool parseNewTypeId(NewTypeIdAST *&node);
+    bool parseOperator(OperatorAST *&node);
+    bool parseConversionFunctionId(NameAST *&node);
+    bool parseOperatorFunctionId(NameAST *&node);
+    bool parseParameterDeclaration(ParameterDeclarationAST *&node);
+    bool parseParameterDeclarationClause(ParameterDeclarationClauseAST *&node);
+    bool parseParameterDeclarationList(ParameterDeclarationListAST *&node);
+    bool parsePmExpression(ExpressionAST *&node);
+    bool parseTypeidExpression(ExpressionAST *&node);
+    bool parseTypenameCallExpression(ExpressionAST *&node);
+    bool parseCorePostfixExpression(ExpressionAST *&node);
+    bool parsePostfixExpression(ExpressionAST *&node);
+    bool parsePostfixExpressionInternal(ExpressionAST *&node);
+    bool parsePrimaryExpression(ExpressionAST *&node);
+    bool parseNestedExpression(ExpressionAST *&node);
+    bool parsePtrOperator(PtrOperatorListAST *&node);
+    bool parseRelationalExpression(ExpressionAST *&node);
+    bool parseShiftExpression(ExpressionAST *&node);
+    bool parseStatement(StatementAST *&node, bool blockLabeledStatement = false);
+    bool parseThisExpression(ExpressionAST *&node);
+    bool parseBoolLiteral(ExpressionAST *&node);
+    bool parseNumericLiteral(ExpressionAST *&node);
+    bool parsePointerLiteral(ExpressionAST *&node);
+    bool parseStringLiteral(ExpressionAST *&node);
+    bool parseSwitchStatement(StatementAST *&node);
+    bool parseTemplateArgument(ExpressionAST *&node);
+    bool parseTemplateArgumentList(ExpressionListAST *&node);
+    bool parseTemplateDeclaration(DeclarationAST *&node);
+    bool parseTemplateParameter(DeclarationAST *&node);
+    bool parseTemplateParameterList(DeclarationListAST *&node);
+    bool parseThrowExpression(ExpressionAST *&node);
+    bool parseTryBlockStatement(StatementAST *&node, CtorInitializerAST **placeholder);
+    bool parseCatchClause(CatchClauseListAST *&node);
+    bool parseTypeId(ExpressionAST *&node);
+    bool parseTypeIdList(ExpressionListAST *&node);
+    bool parseTypenameTypeParameter(DeclarationAST *&node);
+    bool parseTemplateTypeParameter(DeclarationAST *&node);
+    bool parseTypeParameter(DeclarationAST *&node);
+
+    bool parseBuiltinTypeSpecifier(SpecifierListAST *&node);
+    bool parseOptionalAttributeSpecifierSequence(SpecifierListAST *&attribute_list);
+    bool parseAttributeSpecifier(SpecifierListAST *&attribute_list);
+    bool parseGnuAttributeSpecifier(SpecifierListAST *&node);
+    bool parseGnuAttributeList(GnuAttributeListAST *&node);
+
+    bool parseDeclSpecifierSeq(SpecifierListAST *&node,
+                               bool noStorageSpecifiers = false,
+                               bool onlySimpleTypeSpecifiers = false);
+
+    bool parseTrailingTypeSpecifierSeq(SpecifierListAST *&node)
+    { return parseDeclSpecifierSeq(node, true); }
+    /// This actually parses a trailing-type-specifier sequence
+    bool parseTypeSpecifier(SpecifierListAST *&node)
+    { return parseTrailingTypeSpecifierSeq(node); }
+    bool parseSimpleTypeSpecifier(SpecifierListAST *&node)
+    { return parseDeclSpecifierSeq(node, true, true); }
+
+    bool parseUnaryExpression(ExpressionAST *&node);
+    bool parseUnqualifiedName(NameAST *&node, bool acceptTemplateId = true);
+    bool parseUsing(DeclarationAST *&node);
+    bool parseUsingDirective(DeclarationAST *&node);
+    bool parseAliasDeclaration(DeclarationAST *&node);
+    bool parseWhileStatement(StatementAST *&node);
+
+    void parseExpressionWithOperatorPrecedence(ExpressionAST *&lhs, int minPrecedence);
+
+    // Qt MOC run
+    bool parseQtMethod(ExpressionAST *&node);
+
+    // C++0x
+    bool parseInitializer0x(ExpressionAST *&node, unsigned *equals_token);
+    bool parseBraceOrEqualInitializer0x(ExpressionAST *&node);
+    bool parseInitializerClause0x(ExpressionAST *&node);
+    bool parseInitializerList0x(ExpressionListAST *&node);
+    bool parseBracedInitList0x(ExpressionAST *&node);
+
+    bool parseLambdaExpression(ExpressionAST *&node);
+    bool parseLambdaIntroducer(LambdaIntroducerAST *&node);
+    bool parseLambdaCapture(LambdaCaptureAST *&node);
+    bool parseLambdaDeclarator(LambdaDeclaratorAST *&node);
+    bool parseCapture(CaptureAST *&node);
+    bool parseCaptureList(CaptureListAST *&node);
+    bool parseTrailingReturnType(TrailingReturnTypeAST *&node);
+
+    // ObjC++
+    bool parseObjCExpression(ExpressionAST *&node);
+    bool parseObjCClassForwardDeclaration(DeclarationAST *&node);
+    bool parseObjCInterface(DeclarationAST *&node,
+                            SpecifierListAST *attributes = 0);
+    bool parseObjCProtocol(DeclarationAST *&node,
+                           SpecifierListAST *attributes = 0);
+
+    bool parseObjCTryStatement(StatementAST *&node);
+    bool parseObjCSynchronizedStatement(StatementAST *&node);
+    bool parseObjCThrowStatement(StatementAST *&node);
+    bool parseObjCEncodeExpression(ExpressionAST *&node);
+    bool parseObjCProtocolExpression(ExpressionAST *&node);
+    bool parseObjCSelectorExpression(ExpressionAST *&node);
+    bool parseObjCStringLiteral(ExpressionAST *&node);
+    bool parseObjCMessageExpression(ExpressionAST *&node);
+    bool parseObjCMessageReceiver(ExpressionAST *&node);
+    bool parseObjCMessageArguments(ObjCSelectorAST *&selNode, ObjCMessageArgumentListAST *& argNode);
+    bool parseObjCSelectorArg(ObjCSelectorArgumentAST *&selNode, ObjCMessageArgumentAST *&argNode);
+    bool parseObjCMethodDefinitionList(DeclarationListAST *&node);
+    bool parseObjCMethodDefinition(DeclarationAST *&node);
+
+    bool parseObjCProtocolRefs(ObjCProtocolRefsAST *&node);
+    bool parseObjClassInstanceVariables(ObjCInstanceVariablesDeclarationAST *&node);
+    bool parseObjCInterfaceMemberDeclaration(DeclarationAST *&node);
+    bool parseObjCInstanceVariableDeclaration(DeclarationAST *&node);
+    bool parseObjCPropertyDeclaration(DeclarationAST *&node,
+                                      SpecifierListAST *attributes = 0);
+    bool parseObjCImplementation(DeclarationAST *&node);
+    bool parseObjCMethodPrototype(ObjCMethodPrototypeAST *&node);
+    bool parseObjCPropertyAttribute(ObjCPropertyAttributeAST *&node);
+    bool parseObjCTypeName(ObjCTypeNameAST *&node);
+    bool parseObjCSelector(unsigned &selector_token);
+    bool parseObjCKeywordDeclaration(ObjCSelectorArgumentAST *&argument, ObjCMessageArgumentDeclarationAST *&node);
+    bool parseObjCTypeQualifiers(unsigned &type_qualifier);
+    bool peekAtObjCContextKeyword(int kind);
+    bool parseObjCContextKeyword(int kind, unsigned &in_token);
+
+    bool lookAtObjCSelector() const;
+
+    // c99
+    bool parseDesignatedInitializerList(ExpressionListAST *&node);
+    bool parseDesignatedInitializer(ExpressionAST *&node);
+    bool parseDesignator(DesignatorAST *&node);
+
+    bool skipUntil(int token);
+    void skipUntilDeclaration();
+    bool skipUntilStatement();
+    bool skip(int l, int r);
+    int find(int token, int stopAt);
+
+    bool lookAtTypeParameter();
+    bool lookAtCVQualifier() const;
+    bool lookAtFunctionSpecifier() const;
+    bool lookAtStorageClassSpecifier() const;
+    bool lookAtBuiltinTypeSpecifier() const;
+    bool lookAtClassKey() const;
+
+    const Identifier *className(ClassSpecifierAST *ast) const;
+    const Identifier *identifier(NameAST *name) const;
+
+    void match(int kind, unsigned *token);
+
+    bool maybeAmbiguousStatement(DeclarationStatementAST *ast, StatementAST *&node);
+    bool maybeForwardOrClassDeclaration(SpecifierListAST *decl_specifier_seq) const;
+
+    int peekAtQtContextKeyword() const;
+
+    bool switchTemplateArguments(bool templateArguments);
+    bool maybeSplitGreaterGreaterToken(int n = 1);
+
+    bool blockErrors(bool block) { return _translationUnit->blockErrors(block); }
+    void warning(unsigned index, const char *format, ...);
+    void error(unsigned index, const char *format, ...);
+    void fatal(unsigned index, const char *format, ...);
+
+    inline const Token &tok(int i = 1) const
+    { return _translationUnit->tokenAt(_tokenIndex + i - 1); }
+
+    inline int LA(int n = 1) const
+    { return _translationUnit->tokenKind(_tokenIndex + n - 1); }
+
+    inline int consumeToken()
+    { return _tokenIndex++; }
+
+    inline unsigned cursor() const
+    { return _tokenIndex; }
+
+    void rewind(unsigned cursor);
+
+    struct TemplateArgumentListEntry {
+        unsigned index;
+        unsigned cursor;
+        ExpressionListAST *ast;
+
+        TemplateArgumentListEntry(unsigned index = 0, unsigned cursor = 0, ExpressionListAST *ast = 0)
+            : index(index), cursor(cursor), ast(ast) {}
+    };
+
+    TemplateArgumentListEntry *templateArgumentListEntry(unsigned tokenIndex);
+    void clearTemplateArgumentList() { _templateArgumentList.clear(); }
+
+private:
+    TranslationUnit *_translationUnit;
+    Control *_control;
+    MemoryPool *_pool;
+    LanguageFeatures _languageFeatures;
+    unsigned _tokenIndex;
+    bool _templateArguments: 1;
+    bool _inFunctionBody: 1;
+    bool _inExpressionStatement: 1;
+    int _expressionDepth;
+    int _statementDepth;
+
+    MemoryPool _expressionStatementTempPool;
+    std::map<unsigned, TemplateArgumentListEntry> _templateArgumentList;
+
+    class ASTCache;
+    ASTCache *_astCache;
+    ASTCache *_expressionStatementAstCache;
+
+private:
+    Parser(const Parser& source);
+    void operator =(const Parser& source);
+};
+
+} // namespace CPlusPlus
+
+
+#endif // CPLUSPLUS_PARSER_H

+ 201 - 0
Source/ToolCore/JSBind/cplusplus/QtContextKeywords.cpp

@@ -0,0 +1,201 @@
+
+#include "QtContextKeywords.h"
+
+using namespace CPlusPlus;
+
+static inline int classify4(const char *s) {
+  if (s[0] == 'R') {
+    if (s[1] == 'E') {
+      if (s[2] == 'A') {
+        if (s[3] == 'D') {
+          return Token_READ;
+        }
+      }
+    }
+  }
+  else if (s[0] == 'U') {
+    if (s[1] == 'S') {
+      if (s[2] == 'E') {
+        if (s[3] == 'R') {
+          return Token_USER;
+        }
+      }
+    }
+  }
+  return Token_not_Qt_context_keyword;
+}
+
+static inline int classify5(const char *s) {
+  if (s[0] == 'F') {
+    if (s[1] == 'I') {
+      if (s[2] == 'N') {
+        if (s[3] == 'A') {
+          if (s[4] == 'L') {
+            return Token_FINAL;
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'R') {
+    if (s[1] == 'E') {
+      if (s[2] == 'S') {
+        if (s[3] == 'E') {
+          if (s[4] == 'T') {
+            return Token_RESET;
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'W') {
+    if (s[1] == 'R') {
+      if (s[2] == 'I') {
+        if (s[3] == 'T') {
+          if (s[4] == 'E') {
+            return Token_WRITE;
+          }
+        }
+      }
+    }
+  }
+  return Token_not_Qt_context_keyword;
+}
+
+static inline int classify6(const char *s) {
+  if (s[0] == 'M') {
+    if (s[1] == 'E') {
+      if (s[2] == 'M') {
+        if (s[3] == 'B') {
+          if (s[4] == 'E') {
+            if (s[5] == 'R') {
+              return Token_MEMBER;
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'N') {
+    if (s[1] == 'O') {
+      if (s[2] == 'T') {
+        if (s[3] == 'I') {
+          if (s[4] == 'F') {
+            if (s[5] == 'Y') {
+              return Token_NOTIFY;
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'S') {
+    if (s[1] == 'T') {
+      if (s[2] == 'O') {
+        if (s[3] == 'R') {
+          if (s[4] == 'E') {
+            if (s[5] == 'D') {
+              return Token_STORED;
+            }
+          }
+        }
+      }
+    }
+  }
+  return Token_not_Qt_context_keyword;
+}
+
+static inline int classify8(const char *s) {
+  if (s[0] == 'C') {
+    if (s[1] == 'O') {
+      if (s[2] == 'N') {
+        if (s[3] == 'S') {
+          if (s[4] == 'T') {
+            if (s[5] == 'A') {
+              if (s[6] == 'N') {
+                if (s[7] == 'T') {
+                  return Token_CONSTANT;
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  if (s[0] == 'R') {
+    if (s[1] == 'E') {
+      if (s[2] == 'V') {
+        if (s[3] == 'I') {
+          if (s[4] == 'S') {
+            if (s[5] == 'I') {
+              if (s[6] == 'O') {
+                if (s[7] == 'N') {
+                  return Token_REVISION;
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  return Token_not_Qt_context_keyword;
+}
+
+static inline int classify10(const char *s) {
+  if (s[0] == 'D') {
+    if (s[1] == 'E') {
+      if (s[2] == 'S') {
+        if (s[3] == 'I') {
+          if (s[4] == 'G') {
+            if (s[5] == 'N') {
+              if (s[6] == 'A') {
+                if (s[7] == 'B') {
+                  if (s[8] == 'L') {
+                    if (s[9] == 'E') {
+                      return Token_DESIGNABLE;
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (s[0] == 'S') {
+    if (s[1] == 'C') {
+      if (s[2] == 'R') {
+        if (s[3] == 'I') {
+          if (s[4] == 'P') {
+            if (s[5] == 'T') {
+              if (s[6] == 'A') {
+                if (s[7] == 'B') {
+                  if (s[8] == 'L') {
+                    if (s[9] == 'E') {
+                      return Token_SCRIPTABLE;
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  return Token_not_Qt_context_keyword;
+}
+
+int CPlusPlus::classifyQtContextKeyword(const char *s, int n) {
+  switch (n) {
+    case 4: return classify4(s);
+    case 5: return classify5(s);
+    case 6: return classify6(s);
+    case 8: return classify8(s);
+    case 10: return classify10(s);
+    default: return Token_not_Qt_context_keyword;
+  } // switch
+}

+ 28 - 0
Source/ToolCore/JSBind/cplusplus/QtContextKeywords.h

@@ -0,0 +1,28 @@
+
+#ifndef QTCONTEXTKEYWORDS_H
+#define QTCONTEXTKEYWORDS_H
+
+#include "CPlusPlusForwardDeclarations.h"
+
+namespace CPlusPlus {
+
+enum {
+    Token_not_Qt_context_keyword = 0,
+    Token_READ,
+    Token_USER,
+    Token_FINAL,
+    Token_RESET,
+    Token_WRITE,
+    Token_NOTIFY,
+    Token_STORED,
+    Token_CONSTANT,
+    Token_DESIGNABLE,
+    Token_SCRIPTABLE,
+    Token_REVISION,
+    Token_MEMBER
+};
+
+CPLUSPLUS_EXPORT int classifyQtContextKeyword(const char *s, int n);
+} // namespace CPlusPlus;
+
+#endif // QTCONTEXTKEYWORDS_H

+ 161 - 0
Source/ToolCore/JSBind/cplusplus/SafeMatcher.cpp

@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://www.qt.io/licensing.  For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "CoreTypes.h"
+#include "Names.h"
+#include "SafeMatcher.h"
+
+using namespace std;
+using namespace CPlusPlus;
+
+namespace {
+template<typename T>
+class Blocker
+{
+    vector<const T *> &v;
+
+public:
+    Blocker(vector<const T *> &v, const T *el1, const T *el2)
+        : v(v)
+    { v.push_back(el1); v.push_back(el2); }
+    ~Blocker() { v.pop_back(); v.pop_back(); }
+};
+
+template<typename T, typename U>
+bool isBlocked(const vector<const T *> &v, const U *t1, const U *t2)
+{
+    for (size_t i = v.size(); i > 0; ) {
+        const T *t = v[--i];
+        if (t == t1 || t == t2)
+            return true;
+    }
+
+    return false;
+}
+} // anonymous namespace
+
+SafeMatcher::SafeMatcher()
+{
+    _blockedTypes.reserve(8);
+    _blockedNames.reserve(8);
+}
+
+SafeMatcher::~SafeMatcher()
+{}
+
+bool SafeMatcher::match(const PointerToMemberType *type, const PointerToMemberType *otherType)
+{
+    if (isBlocked(_blockedTypes, type, otherType))
+        return true;
+
+    Blocker<Type> b(_blockedTypes, type, otherType);
+    return Matcher::match(type, otherType);
+}
+
+bool SafeMatcher::match(const PointerType *type, const PointerType *otherType)
+{
+    if (isBlocked(_blockedTypes, type, otherType))
+        return true;
+
+    Blocker<Type> b(_blockedTypes, type, otherType);
+    return Matcher::match(type, otherType);
+}
+
+bool SafeMatcher::match(const ReferenceType *type, const ReferenceType *otherType)
+{
+    if (isBlocked(_blockedTypes, type, otherType))
+        return true;
+
+    Blocker<Type> b(_blockedTypes, type, otherType);
+    return Matcher::match(type, otherType);
+}
+
+bool SafeMatcher::match(const ArrayType *type, const ArrayType *otherType)
+{
+    if (isBlocked(_blockedTypes, type, otherType))
+        return true;
+
+    Blocker<Type> b(_blockedTypes, type, otherType);
+    return Matcher::match(type, otherType);
+}
+
+bool SafeMatcher::match(const NamedType *type, const NamedType *otherType)
+{
+    if (isBlocked(_blockedTypes, type, otherType))
+        return true;
+
+    Blocker<Type> b(_blockedTypes, type, otherType);
+    return Matcher::match(type, otherType);
+}
+
+bool SafeMatcher::match(const TemplateNameId *name, const TemplateNameId *otherName)
+{
+    if (isBlocked(_blockedNames, name, otherName))
+        return true;
+
+    Blocker<Name> b(_blockedNames, name, otherName);
+    return Matcher::match(name, otherName);
+}
+
+bool SafeMatcher::match(const DestructorNameId *name, const DestructorNameId *otherName)
+{
+    if (isBlocked(_blockedNames, name, otherName))
+        return true;
+
+    Blocker<Name> b(_blockedNames, name, otherName);
+    return Matcher::match(name, otherName);
+}
+
+bool SafeMatcher::match(const ConversionNameId *name, const ConversionNameId *otherName)
+{
+    if (isBlocked(_blockedNames, name, otherName))
+        return true;
+
+    Blocker<Name> b(_blockedNames, name, otherName);
+    return Matcher::match(name, otherName);
+}
+
+bool SafeMatcher::match(const QualifiedNameId *name, const QualifiedNameId *otherName)
+{
+    if (isBlocked(_blockedNames, name, otherName))
+        return true;
+
+    Blocker<Name> b(_blockedNames, name, otherName);
+    return Matcher::match(name, otherName);
+}
+
+bool SafeMatcher::match(const SelectorNameId *name, const SelectorNameId *otherName)
+{
+    if (isBlocked(_blockedNames, name, otherName))
+        return true;
+
+    Blocker<Name> b(_blockedNames, name, otherName);
+    return Matcher::match(name, otherName);
+}

+ 65 - 0
Source/ToolCore/JSBind/cplusplus/SafeMatcher.h

@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://www.qt.io/licensing.  For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef CPLUSPLUS_SAFETYPEMATCHER_H
+#define CPLUSPLUS_SAFETYPEMATCHER_H
+
+#include "Matcher.h"
+
+#include <vector>
+
+namespace CPlusPlus {
+
+class SafeMatcher : public Matcher
+{
+public:
+    SafeMatcher();
+    ~SafeMatcher();
+
+    bool match(const PointerToMemberType *type, const PointerToMemberType *otherType);
+    bool match(const PointerType *type, const PointerType *otherType);
+    bool match(const ReferenceType *type, const ReferenceType *otherType);
+    bool match(const ArrayType *type, const ArrayType *otherType);
+    bool match(const NamedType *type, const NamedType *otherType);
+
+    bool match(const TemplateNameId *name, const TemplateNameId *otherName);
+    bool match(const DestructorNameId *name, const DestructorNameId *otherName);
+    bool match(const ConversionNameId *name, const ConversionNameId *otherName);
+    bool match(const QualifiedNameId *name, const QualifiedNameId *otherName);
+    bool match(const SelectorNameId *name, const SelectorNameId *otherName);
+
+private:
+    std::vector<const Type *> _blockedTypes;
+    std::vector<const Name *> _blockedNames;
+};
+
+} // CPlusPlus namespace
+
+#endif // CPLUSPLUS_SAFETYPEMATCHER_H

+ 295 - 0
Source/ToolCore/JSBind/cplusplus/Scope.cpp

@@ -0,0 +1,295 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "Scope.h"
+#include "Symbols.h"
+#include "Names.h"
+#include "Literals.h"
+#include "Templates.h"
+
+#include "cppassert.h"
+
+#include <cstring>
+
+using namespace CPlusPlus;
+
+class CPlusPlus::SymbolTable
+{
+    SymbolTable(const SymbolTable &other);
+    void operator =(const SymbolTable &other);
+
+public:
+    typedef Symbol **iterator;
+
+public:
+    /// Constructs an empty Scope.
+    SymbolTable(Scope *owner = 0);
+
+    /// Destroy this scope.
+    ~SymbolTable();
+
+    /// Returns this scope's owner Symbol.
+    Scope *owner() const;
+
+    /// Sets this scope's owner Symbol.
+    void setOwner(Scope *owner); // ### remove me
+
+    /// Adds a Symbol to this Scope.
+    void enterSymbol(Symbol *symbol);
+
+    /// Returns true if this Scope is empty; otherwise returns false.
+    bool isEmpty() const;
+
+    /// Returns the number of symbols is in the scope.
+    unsigned symbolCount() const;
+
+    /// Returns the Symbol at the given position.
+    Symbol *symbolAt(unsigned index) const;
+
+    /// Returns the first Symbol in the scope.
+    iterator firstSymbol() const;
+
+    /// Returns the last Symbol in the scope.
+    iterator lastSymbol() const;
+
+    Symbol *lookat(const Identifier *id) const;
+    Symbol *lookat(OperatorNameId::Kind operatorId) const;
+
+private:
+    /// Returns the hash value for the given Symbol.
+    unsigned hashValue(Symbol *symbol) const;
+
+    /// Updates the hash table.
+    void rehash();
+
+private:
+    enum { DefaultInitialSize = 4 };
+
+    Scope *_owner;
+    Symbol **_symbols;
+    Symbol **_hash;
+    int _allocatedSymbols;
+    int _symbolCount;
+    int _hashSize;
+};
+
+SymbolTable::SymbolTable(Scope *owner)
+    : _owner(owner),
+      _symbols(0),
+      _hash(0),
+      _allocatedSymbols(0),
+      _symbolCount(-1),
+      _hashSize(0)
+{ }
+
+SymbolTable::~SymbolTable()
+{
+    if (_symbols)
+        free(_symbols);
+    if (_hash)
+        free(_hash);
+}
+
+void SymbolTable::enterSymbol(Symbol *symbol)
+{
+    CPP_ASSERT(! symbol->_enclosingScope || symbol->enclosingScope() == _owner, return);
+
+    if (++_symbolCount == _allocatedSymbols) {
+        _allocatedSymbols <<= 1;
+        if (! _allocatedSymbols)
+            _allocatedSymbols = DefaultInitialSize;
+
+        _symbols = reinterpret_cast<Symbol **>(realloc(_symbols, sizeof(Symbol *) * _allocatedSymbols));
+    }
+
+    symbol->_index = _symbolCount;
+    symbol->_enclosingScope = _owner;
+    _symbols[_symbolCount] = symbol;
+
+    if (_symbolCount * 5 >= _hashSize * 3)
+        rehash();
+    else {
+        const unsigned h = hashValue(symbol);
+        symbol->_next = _hash[h];
+        _hash[h] = symbol;
+    }
+}
+
+Symbol *SymbolTable::lookat(const Identifier *id) const
+{
+    if (! _hash || ! id)
+        return 0;
+
+    const unsigned h = id->hashCode() % _hashSize;
+    Symbol *symbol = _hash[h];
+    for (; symbol; symbol = symbol->_next) {
+        const Name *identity = symbol->unqualifiedName();
+        if (! identity) {
+            continue;
+        } else if (const Identifier *nameId = identity->asNameId()) {
+            if (nameId->identifier()->match(id))
+                break;
+        } else if (const TemplateNameId *t = identity->asTemplateNameId()) {
+            if (t->identifier()->match(id))
+                break;
+        } else if (const DestructorNameId *d = identity->asDestructorNameId()) {
+            if (d->identifier()->match(id))
+                break;
+        } else if (identity->isQualifiedNameId()) {
+            return 0;
+        } else if (const SelectorNameId *selectorNameId = identity->asSelectorNameId()) {
+            if (selectorNameId->identifier()->match(id))
+                break;
+        }
+    }
+    return symbol;
+}
+
+Symbol *SymbolTable::lookat(OperatorNameId::Kind operatorId) const
+{
+    if (! _hash)
+        return 0;
+
+    const unsigned h = operatorId % _hashSize;
+    Symbol *symbol = _hash[h];
+    for (; symbol; symbol = symbol->_next) {
+        if (const Name *identity = symbol->unqualifiedName()) {
+            if (const OperatorNameId *op = identity->asOperatorNameId()) {
+                if (op->kind() == operatorId)
+                    break;
+            }
+        }
+    }
+    return symbol;
+}
+
+void SymbolTable::rehash()
+{
+    _hashSize <<= 1;
+
+    if (! _hashSize)
+        _hashSize = DefaultInitialSize;
+
+    _hash = reinterpret_cast<Symbol **>(realloc(_hash, sizeof(Symbol *) * _hashSize));
+    std::memset(_hash, 0, sizeof(Symbol *) * _hashSize);
+
+    for (int index = 0; index < _symbolCount + 1; ++index) {
+        Symbol *symbol = _symbols[index];
+        const unsigned h = hashValue(symbol);
+        symbol->_next = _hash[h];
+        _hash[h] = symbol;
+    }
+}
+
+unsigned SymbolTable::hashValue(Symbol *symbol) const
+{
+    if (! symbol)
+        return 0;
+
+    return symbol->hashCode() % _hashSize;
+}
+
+bool SymbolTable::isEmpty() const
+{ return _symbolCount == -1; }
+
+unsigned SymbolTable::symbolCount() const
+{ return _symbolCount + 1; }
+
+Symbol *SymbolTable::symbolAt(unsigned index) const
+{
+    if (! _symbols)
+        return 0;
+    return _symbols[index];
+}
+
+SymbolTable::iterator SymbolTable::firstSymbol() const
+{ return _symbols; }
+
+SymbolTable::iterator SymbolTable::lastSymbol() const
+{ return _symbols + _symbolCount + 1; }
+
+Scope::Scope(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
+    : Symbol(translationUnit, sourceLocation, name),
+      _members(0),
+      _startOffset(0),
+      _endOffset(0)
+{ }
+
+Scope::Scope(Clone *clone, Subst *subst, Scope *original)
+    : Symbol(clone, subst, original)
+    , _members(0)
+    , _startOffset(original->_startOffset)
+    , _endOffset(original->_endOffset)
+{
+    for (iterator it = original->firstMember(), end = original->lastMember(); it != end; ++it)
+        addMember(clone->symbol(*it, subst));
+}
+
+Scope::~Scope()
+{ delete _members; }
+
+/// Adds a Symbol to this Scope.
+void Scope::addMember(Symbol *symbol)
+{
+    if (! _members)
+        _members = new SymbolTable(this);
+
+    _members->enterSymbol(symbol);
+}
+
+/// Returns true if this Scope is empty; otherwise returns false.
+bool Scope::isEmpty() const
+{ return _members ? _members->isEmpty() : true; }
+
+/// Returns the number of symbols is in the scope.
+unsigned Scope::memberCount() const
+{ return _members ? _members->symbolCount() : 0; }
+
+/// Returns the Symbol at the given position.
+Symbol *Scope::memberAt(unsigned index) const
+{ return _members ? _members->symbolAt(index) : 0; }
+
+/// Returns the first Symbol in the scope.
+Scope::iterator Scope::firstMember() const
+{ return _members ? _members->firstSymbol() : 0; }
+
+/// Returns the last Symbol in the scope.
+Scope::iterator Scope::lastMember() const
+{ return _members ? _members->lastSymbol() : 0; }
+
+Symbol *Scope::find(const Identifier *id) const
+{ return _members ? _members->lookat(id) : 0; }
+
+Symbol *Scope::find(OperatorNameId::Kind operatorId) const
+{ return _members ? _members->lookat(operatorId) : 0; }
+
+/// Set the start offset of the scope
+unsigned Scope::startOffset() const
+{ return _startOffset; }
+
+void Scope::setStartOffset(unsigned offset)
+{ _startOffset = offset; }
+
+/// Set the end offset of the scope
+unsigned Scope::endOffset() const
+{ return _endOffset; }
+
+void Scope::setEndOffset(unsigned offset)
+{ _endOffset = offset; }

+ 83 - 0
Source/ToolCore/JSBind/cplusplus/Scope.h

@@ -0,0 +1,83 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_SCOPE_H
+#define CPLUSPLUS_SCOPE_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include "Symbol.h"
+#include "Names.h"
+
+namespace CPlusPlus {
+
+class CPLUSPLUS_EXPORT Scope: public Symbol
+{
+public:
+    Scope(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name);
+    Scope(Clone *clone, Subst *subst, Scope *original);
+    virtual ~Scope();
+
+    /// Adds a Symbol to this Scope.
+    void addMember(Symbol *symbol);
+
+    /// Returns true if this Scope is empty; otherwise returns false.
+    bool isEmpty() const;
+
+    /// Returns the number of symbols is in the scope.
+    unsigned memberCount() const;
+
+    /// Returns the Symbol at the given position.
+    Symbol *memberAt(unsigned index) const;
+
+    typedef Symbol **iterator;
+
+    /// Returns the first Symbol in the scope.
+    iterator firstMember() const;
+
+    /// Returns the last Symbol in the scope.
+    iterator lastMember() const;
+
+    Symbol *find(const Identifier *id) const;
+    Symbol *find(OperatorNameId::Kind operatorId) const;
+
+    /// Set the start offset of the scope
+    unsigned startOffset() const;
+    void setStartOffset(unsigned offset);
+
+    /// Set the end offset of the scope
+    unsigned endOffset() const;
+    void setEndOffset(unsigned offset);
+
+    virtual const Scope *asScope() const
+    { return this; }
+
+    virtual Scope *asScope()
+    { return this; }
+
+private:
+    SymbolTable *_members;
+    unsigned _startOffset;
+    unsigned _endOffset;
+};
+
+} // namespace CPlusPlus
+
+
+#endif // CPLUSPLUS_SCOPE_H

+ 437 - 0
Source/ToolCore/JSBind/cplusplus/Symbol.cpp

@@ -0,0 +1,437 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "Symbol.h"
+#include "Symbols.h"
+#include "Control.h"
+#include "Names.h"
+#include "TranslationUnit.h"
+#include "Literals.h"
+#include "MemoryPool.h"
+#include "SymbolVisitor.h"
+#include "NameVisitor.h"
+#include "Scope.h"
+#include "Templates.h"
+
+#include "cppassert.h"
+
+
+using namespace CPlusPlus;
+
+class Symbol::HashCode: protected NameVisitor
+{
+public:
+    HashCode()
+        : _value(0)
+    { }
+
+    virtual ~HashCode()
+    { }
+
+    unsigned operator()(const Name *name)
+    {
+        unsigned previousValue = switchValue(0);
+        accept(name);
+        return switchValue(previousValue);
+    }
+
+protected:
+    unsigned switchValue(unsigned value)
+    {
+        unsigned previousValue = _value;
+        _value = value;
+        return previousValue;
+    }
+
+    virtual void visit(const Identifier *name)
+    { _value = name->identifier()->hashCode(); }
+
+    virtual void visit(const TemplateNameId *name)
+    { _value = name->identifier()->hashCode(); }
+
+    virtual void visit(const DestructorNameId *name)
+    { _value = name->identifier()->hashCode(); }
+
+    virtual void visit(const OperatorNameId *name)
+    { _value = unsigned(name->kind()); }
+
+    virtual void visit(const ConversionNameId *)
+    { _value = 0; } // ### TODO: implement me
+
+    virtual void visit(const QualifiedNameId *name)
+    { _value = operator()(name->name()); }
+
+    virtual void visit(const SelectorNameId *name)
+    { _value = name->identifier()->hashCode(); }
+
+private:
+    unsigned _value;
+};
+
+Symbol::Symbol(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
+    : _name(0),
+      _enclosingScope(0),
+      _next(0),
+      _fileId(0),
+      _sourceLocation(0),
+      _hashCode(0),
+      _storage(Symbol::NoStorage),
+      _visibility(Symbol::Public),
+      _index(0),
+      _line(0),
+      _column(0),
+      _isGenerated(false),
+      _isDeprecated(false),
+      _isUnavailable(false)
+{
+    setSourceLocation(sourceLocation, translationUnit);
+    setName(name);
+}
+
+Symbol::Symbol(Clone *clone, Subst *subst, Symbol *original)
+    : _name(clone->name(original->_name, subst)),
+      _enclosingScope(0),
+      _next(0),
+      _fileId(clone->control()->stringLiteral(original->fileName(), original->fileNameLength())),
+      _sourceLocation(original->_sourceLocation),
+      _hashCode(original->_hashCode),
+      _storage(original->_storage),
+      _visibility(original->_visibility),
+      _index(0),
+      _line(original->_line),
+      _column(original->_column),
+      _isGenerated(original->_isGenerated),
+      _isDeprecated(original->_isDeprecated),
+      _isUnavailable(original->_isUnavailable)
+{
+}
+
+Symbol::~Symbol()
+{ }
+
+void Symbol::visitSymbol(SymbolVisitor *visitor)
+{
+    if (visitor->preVisit(this))
+        visitSymbol0(visitor);
+    visitor->postVisit(this);
+}
+
+void Symbol::visitSymbol(Symbol *symbol, SymbolVisitor *visitor)
+{
+    if (! symbol)
+        return;
+
+    symbol->visitSymbol(visitor);
+}
+
+unsigned Symbol::sourceLocation() const
+{ return _sourceLocation; }
+
+bool Symbol::isGenerated() const
+{ return _isGenerated; }
+
+bool Symbol::isDeprecated() const
+{ return _isDeprecated; }
+
+void Symbol::setDeprecated(bool isDeprecated)
+{ _isDeprecated = isDeprecated; }
+
+bool Symbol::isUnavailable() const
+{ return _isUnavailable; }
+
+void Symbol::setUnavailable(bool isUnavailable)
+{ _isUnavailable = isUnavailable; }
+
+void Symbol::setSourceLocation(unsigned sourceLocation, TranslationUnit *translationUnit)
+{
+    _sourceLocation = sourceLocation;
+
+    if (translationUnit) {
+        const Token &tk = translationUnit->tokenAt(sourceLocation);
+        _isGenerated = tk.generated();
+        translationUnit->getPosition(tk.utf16charsBegin(), &_line, &_column, &_fileId);
+    } else {
+        _isGenerated = false;
+        _line = 0;
+        _column = 0;
+        _fileId = 0;
+    }
+}
+
+unsigned Symbol::line() const
+{
+    return _line;
+}
+
+unsigned Symbol::column() const
+{
+    return _column;
+}
+
+const StringLiteral *Symbol::fileId() const
+{
+    return _fileId;
+}
+
+const char *Symbol::fileName() const
+{ return fileId()->chars(); }
+
+unsigned Symbol::fileNameLength() const
+{ return fileId()->size(); }
+
+const Name *Symbol::unqualifiedName() const
+{
+    if (! _name)
+        return 0;
+
+    else if (const QualifiedNameId *q = _name->asQualifiedNameId())
+        return q->name();
+
+    return _name;
+}
+
+const Name *Symbol::name() const
+{ return _name; }
+
+void Symbol::setName(const Name *name)
+{
+    _name = name;
+
+    if (! _name)
+        _hashCode = 0;
+    else {
+        HashCode hh;
+        _hashCode = hh(unqualifiedName());
+    }
+}
+
+const Identifier *Symbol::identifier() const
+{
+    if (_name)
+        return _name->identifier();
+
+    return 0;
+}
+
+Scope *Symbol::enclosingScope() const
+{ return _enclosingScope; }
+
+void Symbol::setEnclosingScope(Scope *scope)
+{
+    CPP_CHECK(! _enclosingScope);
+    _enclosingScope = scope;
+}
+
+void Symbol::resetEnclosingScope()
+{
+    _enclosingScope = 0;
+}
+
+Namespace *Symbol::enclosingNamespace() const
+{
+    for (Scope *s = _enclosingScope; s; s = s->enclosingScope()) {
+        if (Namespace *ns = s->asNamespace())
+            return ns;
+    }
+    return 0;
+}
+
+Template *Symbol::enclosingTemplate() const
+{
+    for (Scope *s = _enclosingScope; s; s = s->enclosingScope()) {
+        if (Template *templ = s->asTemplate())
+            return templ;
+    }
+    return 0;
+}
+
+Class *Symbol::enclosingClass() const
+{
+    for (Scope *s = _enclosingScope; s; s = s->enclosingScope()) {
+        if (Class *klass = s->asClass())
+            return klass;
+    }
+    return 0;
+}
+
+Enum *Symbol::enclosingEnum() const
+{
+    for (Scope *s = _enclosingScope; s; s = s->enclosingScope()) {
+        if (Enum *e = s->asEnum())
+            return e;
+    }
+    return 0;
+}
+
+Function *Symbol::enclosingFunction() const
+{
+    for (Scope *s = _enclosingScope; s; s = s->enclosingScope()) {
+        if (Function *fun = s->asFunction())
+            return fun;
+    }
+    return 0;
+}
+
+Block *Symbol::enclosingBlock() const
+{
+    for (Scope *s = _enclosingScope; s; s = s->enclosingScope()) {
+        if (Block *block = s->asBlock())
+            return block;
+    }
+    return 0;
+}
+
+unsigned Symbol::index() const
+{ return _index; }
+
+Symbol *Symbol::next() const
+{ return _next; }
+
+unsigned Symbol::hashCode() const
+{ return _hashCode; }
+
+int Symbol::storage() const
+{ return _storage; }
+
+void Symbol::setStorage(int storage)
+{ _storage = storage; }
+
+int Symbol::visibility() const
+{ return _visibility; }
+
+void Symbol::setVisibility(int visibility)
+{ _visibility = visibility; }
+
+bool Symbol::isFriend() const
+{ return _storage == Friend; }
+
+bool Symbol::isRegister() const
+{ return _storage == Register; }
+
+bool Symbol::isStatic() const
+{ return _storage == Static; }
+
+bool Symbol::isExtern() const
+{ return _storage == Extern; }
+
+bool Symbol::isMutable() const
+{ return _storage == Mutable; }
+
+bool Symbol::isTypedef() const
+{ return _storage == Typedef; }
+
+bool Symbol::isPublic() const
+{ return _visibility == Public; }
+
+bool Symbol::isProtected() const
+{ return _visibility == Protected; }
+
+bool Symbol::isPrivate() const
+{ return _visibility == Private; }
+
+bool Symbol::isScope() const
+{ return asScope() != 0; }
+
+bool Symbol::isEnum() const
+{ return asEnum()  != 0; }
+
+bool Symbol::isFunction() const
+{ return asFunction() != 0; }
+
+bool Symbol::isNamespace() const
+{ return asNamespace() != 0; }
+
+bool Symbol::isTemplate() const
+{ return asTemplate() != 0; }
+
+bool Symbol::isClass() const
+{ return asClass() != 0; }
+
+bool Symbol::isForwardClassDeclaration() const
+{ return asForwardClassDeclaration() != 0; }
+
+bool Symbol::isQtPropertyDeclaration() const
+{ return asQtPropertyDeclaration() != 0; }
+
+bool Symbol::isQtEnum() const
+{ return asQtEnum() != 0; }
+
+bool Symbol::isBlock() const
+{ return asBlock() != 0; }
+
+bool Symbol::isUsingNamespaceDirective() const
+{ return asUsingNamespaceDirective() != 0; }
+
+bool Symbol::isUsingDeclaration() const
+{ return asUsingDeclaration() != 0; }
+
+bool Symbol::isDeclaration() const
+{ return asDeclaration() != 0; }
+
+bool Symbol::isArgument() const
+{ return asArgument() != 0; }
+
+bool Symbol::isTypenameArgument() const
+{ return asTypenameArgument() != 0; }
+
+bool Symbol::isBaseClass() const
+{ return asBaseClass() != 0; }
+
+bool Symbol::isObjCBaseClass() const
+{ return asObjCBaseClass() != 0; }
+
+bool Symbol::isObjCBaseProtocol() const
+{ return asObjCBaseProtocol() != 0; }
+
+bool Symbol::isObjCClass() const
+{ return asObjCClass() != 0; }
+
+bool Symbol::isObjCForwardClassDeclaration() const
+{ return asObjCForwardClassDeclaration() != 0; }
+
+bool Symbol::isObjCProtocol() const
+{ return asObjCProtocol() != 0; }
+
+bool Symbol::isObjCForwardProtocolDeclaration() const
+{ return asObjCForwardProtocolDeclaration() != 0; }
+
+bool Symbol::isObjCMethod() const
+{ return asObjCMethod() != 0; }
+
+bool Symbol::isObjCPropertyDeclaration() const
+{ return asObjCPropertyDeclaration() != 0; }
+
+void Symbol::copy(Symbol *other)
+{
+    _sourceLocation = other->_sourceLocation;
+    _name = other->_name;
+    _hashCode = other->_hashCode;
+    _storage = other->_storage;
+    _visibility = other->_visibility;
+    _enclosingScope = other->_enclosingScope;
+    _index = other->_index;
+    _next = other->_next;
+    _fileId = other->_fileId;
+    _line = other->_line;
+    _column = other->_column;
+
+    _isGenerated = other->_isGenerated;
+    _isDeprecated = other->_isDeprecated;
+}

+ 330 - 0
Source/ToolCore/JSBind/cplusplus/Symbol.h

@@ -0,0 +1,330 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_SYMBOL_H
+#define CPLUSPLUS_SYMBOL_H
+
+#include "CPlusPlusForwardDeclarations.h"
+
+
+namespace CPlusPlus {
+
+class CPLUSPLUS_EXPORT Symbol
+{
+    Symbol(const Symbol &other);
+    void operator =(const Symbol &other);
+
+public:
+    /// Storage class specifier
+    enum Storage {
+        NoStorage = 0,
+        Friend,
+        Auto,
+        Register,
+        Static,
+        Extern,
+        Mutable,
+        Typedef
+    };
+
+    /// Access specifier.
+    enum Visibility {
+        Public,
+        Protected,
+        Private,
+        Package
+    };
+
+public:
+    /// Constructs a Symbol with the given source location, name and translation unit.
+    Symbol(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name);
+    Symbol(Clone *clone, Subst *subst, Symbol *original);
+
+    /// Destroy this Symbol.
+    virtual ~Symbol();
+
+    /// Returns this Symbol's source location.
+    unsigned sourceLocation() const;
+
+    /// \returns this Symbol's line number. The line number is 1-based.
+    unsigned line() const;
+
+    /// \returns this Symbol's column number. The column number is 1-based.
+    unsigned column() const;
+
+    /// Returns this Symbol's file name.
+    const StringLiteral *fileId() const;
+
+    /// Returns this Symbol's file name.
+    const char *fileName() const;
+
+    /// Returns this Symbol's file name length.
+    unsigned fileNameLength() const;
+
+    /// Returns this Symbol's name.
+    const Name *name() const;
+
+    /// Sets this Symbol's name.
+    void setName(const Name *name); // ### dangerous
+
+    /// Returns this Symbol's (optional) identifier
+    const Identifier *identifier() const;
+
+    /// Returns this Symbol's storage class specifier.
+    int storage() const;
+
+    /// Sets this Symbol's storage class specifier.
+    void setStorage(int storage);
+
+    /// Returns this Symbol's visibility.
+    int visibility() const;
+
+    /// Sets this Symbol's visibility.
+    void setVisibility(int visibility);
+
+    /// Returns the next chained Symbol.
+    Symbol *next() const;
+
+    /// Returns true if this Symbol has friend storage specifier.
+    bool isFriend() const;
+
+    /// Returns true if this Symbol has register storage specifier.
+    bool isRegister() const;
+
+    /// Returns true if this Symbol has static storage specifier.
+    bool isStatic() const;
+
+    /// Returns true if this Symbol has extern storage specifier.
+    bool isExtern() const;
+
+    /// Returns true if this Symbol has mutable storage specifier.
+    bool isMutable() const;
+
+    /// Returns true if this Symbol has typedef storage specifier.
+    bool isTypedef() const;
+
+    /// Returns true if this Symbol's visibility is public.
+    bool isPublic() const;
+
+    /// Returns true if this Symbol's visibility is protected.
+    bool isProtected() const;
+
+    /// Returns true if this Symbol's visibility is private.
+    bool isPrivate() const;
+
+    /// Returns true if this Symbol is a Scope.
+    bool isScope() const;
+
+    /// Returns true if this Symbol is an Enum.
+    bool isEnum() const;
+
+    /// Returns true if this Symbol is an Function.
+    bool isFunction() const;
+
+    /// Returns true if this Symbol is a Namespace.
+    bool isNamespace() const;
+
+    /// Returns true if this Symbol is a Template.
+    bool isTemplate() const;
+
+    /// Returns true if this Symbol is a Class.
+    bool isClass() const;
+
+    /// Returns true if this Symbol is a Block.
+    bool isBlock() const;
+
+    /// Returns true if this Symbol is a UsingNamespaceDirective.
+    bool isUsingNamespaceDirective() const;
+
+    /// Returns true if this Symbol is a UsingDeclaration.
+    bool isUsingDeclaration() const;
+
+    /// Returns true if this Symbol is a Declaration.
+    bool isDeclaration() const;
+
+    /// Returns true if this Symbol is an Argument.
+    bool isArgument() const;
+
+    /// Returns true if this Symbol is a Typename argument.
+    bool isTypenameArgument() const;
+
+    /// Returns true if this Symbol is a BaseClass.
+    bool isBaseClass() const;
+
+    /// Returns true if this Symbol is a ForwardClassDeclaration.
+    bool isForwardClassDeclaration() const;
+
+    /// Returns true if this Symbol is a QtPropertyDeclaration.
+    bool isQtPropertyDeclaration() const;
+
+    /// Returns true if this Symbol is a QtEnum.
+    bool isQtEnum() const;
+
+    bool isObjCBaseClass() const;
+    bool isObjCBaseProtocol() const;
+
+    /// Returns true if this Symbol is an Objective-C Class declaration.
+    bool isObjCClass() const;
+
+    /// Returns true if this Symbol is an Objective-C Class forward declaration.
+    bool isObjCForwardClassDeclaration() const;
+
+    /// Returns true if this Symbol is an Objective-C Protocol declaration.
+    bool isObjCProtocol() const;
+
+    /// Returns true if this Symbol is an Objective-C Protocol forward declaration.
+    bool isObjCForwardProtocolDeclaration() const;
+
+    /// Returns true if this Symbol is an Objective-C method declaration.
+    bool isObjCMethod() const;
+
+    /// Returns true if this Symbol is an Objective-C @property declaration.
+    bool isObjCPropertyDeclaration() const;
+
+    virtual const Scope *asScope() const { return 0; }
+    virtual const Enum *asEnum() const { return 0; }
+    virtual const Function *asFunction() const { return 0; }
+    virtual const Namespace *asNamespace() const { return 0; }
+    virtual const Template *asTemplate() const { return 0; }
+    virtual const NamespaceAlias *asNamespaceAlias() const { return 0; }
+    virtual const Class *asClass() const { return 0; }
+    virtual const Block *asBlock() const { return 0; }
+    virtual const UsingNamespaceDirective *asUsingNamespaceDirective() const { return 0; }
+    virtual const UsingDeclaration *asUsingDeclaration() const { return 0; }
+    virtual const Declaration *asDeclaration() const { return 0; }
+    virtual const Argument *asArgument() const { return 0; }
+    virtual const TypenameArgument *asTypenameArgument() const { return 0; }
+    virtual const BaseClass *asBaseClass() const { return 0; }
+    virtual const ForwardClassDeclaration *asForwardClassDeclaration() const { return 0; }
+    virtual const QtPropertyDeclaration *asQtPropertyDeclaration() const { return 0; }
+    virtual const QtEnum *asQtEnum() const { return 0; }
+    virtual const ObjCBaseClass *asObjCBaseClass() const { return 0; }
+    virtual const ObjCBaseProtocol *asObjCBaseProtocol() const { return 0; }
+    virtual const ObjCClass *asObjCClass() const { return 0; }
+    virtual const ObjCForwardClassDeclaration *asObjCForwardClassDeclaration() const { return 0; }
+    virtual const ObjCProtocol *asObjCProtocol() const { return 0; }
+    virtual const ObjCForwardProtocolDeclaration *asObjCForwardProtocolDeclaration() const { return 0; }
+    virtual const ObjCMethod *asObjCMethod() const { return 0; }
+    virtual const ObjCPropertyDeclaration *asObjCPropertyDeclaration() const { return 0; }
+
+    virtual Scope *asScope() { return 0; }
+    virtual Enum *asEnum() { return 0; }
+    virtual Function *asFunction() { return 0; }
+    virtual Namespace *asNamespace() { return 0; }
+    virtual Template *asTemplate() { return 0; }
+    virtual NamespaceAlias *asNamespaceAlias() { return 0; }
+    virtual Class *asClass() { return 0; }
+    virtual Block *asBlock() { return 0; }
+    virtual UsingNamespaceDirective *asUsingNamespaceDirective() { return 0; }
+    virtual UsingDeclaration *asUsingDeclaration() { return 0; }
+    virtual Declaration *asDeclaration() { return 0; }
+    virtual Argument *asArgument() { return 0; }
+    virtual TypenameArgument *asTypenameArgument() { return 0; }
+    virtual BaseClass *asBaseClass() { return 0; }
+    virtual ForwardClassDeclaration *asForwardClassDeclaration() { return 0; }
+    virtual QtPropertyDeclaration *asQtPropertyDeclaration() { return 0; }
+    virtual QtEnum *asQtEnum() { return 0; }
+    virtual ObjCBaseClass *asObjCBaseClass() { return 0; }
+    virtual ObjCBaseProtocol *asObjCBaseProtocol() { return 0; }
+    virtual ObjCClass *asObjCClass() { return 0; }
+    virtual ObjCForwardClassDeclaration *asObjCForwardClassDeclaration() { return 0; }
+    virtual ObjCProtocol *asObjCProtocol() { return 0; }
+    virtual ObjCForwardProtocolDeclaration *asObjCForwardProtocolDeclaration() { return 0; }
+    virtual ObjCMethod *asObjCMethod() { return 0; }
+    virtual ObjCPropertyDeclaration *asObjCPropertyDeclaration() { return 0; }
+
+    /// Returns this Symbol's type.
+    virtual FullySpecifiedType type() const = 0;
+
+    /// Returns this Symbol's hash value.
+    unsigned hashCode() const;
+
+    /// Returns this Symbol's index.
+    unsigned index() const;
+
+    const Name *unqualifiedName() const;
+
+    bool isGenerated() const;
+
+    bool isDeprecated() const;
+    void setDeprecated(bool isDeprecated);
+
+    bool isUnavailable() const;
+    void setUnavailable(bool isUnavailable);
+
+    /// Returns this Symbol's eclosing scope.
+    Scope *enclosingScope() const;
+
+    /// Returns the eclosing namespace scope.
+    Namespace *enclosingNamespace() const;
+
+    /// Returns the eclosing template scope.
+    Template *enclosingTemplate() const;
+
+    /// Returns the enclosing class scope.
+    Class *enclosingClass() const;
+
+    /// Returns the enclosing enum scope.
+    Enum *enclosingEnum() const;
+
+    /// Returns the enclosing prototype scope.
+    Function *enclosingFunction() const;
+
+    /// Returns the enclosing Block scope.
+    Block *enclosingBlock() const;
+
+    void setEnclosingScope(Scope *enclosingScope); // ### make me private
+    void resetEnclosingScope(); // ### make me private
+    void setSourceLocation(unsigned sourceLocation, TranslationUnit *translationUnit); // ### make me private
+
+    void visitSymbol(SymbolVisitor *visitor);
+    static void visitSymbol(Symbol *symbol, SymbolVisitor *visitor);
+
+    virtual void copy(Symbol *other);
+
+protected:
+    virtual void visitSymbol0(SymbolVisitor *visitor) = 0;
+
+private:
+    const Name *_name;
+    Scope *_enclosingScope;
+    Symbol *_next;
+    const StringLiteral *_fileId;
+    unsigned _sourceLocation;
+    unsigned _hashCode;
+    int _storage;
+    int _visibility;
+    unsigned _index;
+    unsigned _line;
+    unsigned _column;
+
+    bool _isGenerated: 1;
+    bool _isDeprecated: 1;
+    bool _isUnavailable: 1;
+
+    class HashCode;
+
+    friend class SymbolTable;
+};
+
+} // namespace CPlusPlus
+
+
+#endif // CPLUSPLUS_SYMBOL_H

+ 34 - 0
Source/ToolCore/JSBind/cplusplus/SymbolVisitor.cpp

@@ -0,0 +1,34 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "SymbolVisitor.h"
+#include "Symbol.h"
+
+using namespace CPlusPlus;
+
+SymbolVisitor::SymbolVisitor()
+{ }
+
+SymbolVisitor::~SymbolVisitor()
+{ }
+
+void SymbolVisitor::accept(Symbol *symbol)
+{ Symbol::visitSymbol(symbol, this); }
+

+ 76 - 0
Source/ToolCore/JSBind/cplusplus/SymbolVisitor.h

@@ -0,0 +1,76 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef SYMBOLVISITOR_H
+#define SYMBOLVISITOR_H
+
+#include "CPlusPlusForwardDeclarations.h"
+
+
+namespace CPlusPlus {
+
+class CPLUSPLUS_EXPORT SymbolVisitor
+{
+    SymbolVisitor(const SymbolVisitor &other);
+    void operator =(const SymbolVisitor &other);
+
+public:
+    SymbolVisitor();
+    virtual ~SymbolVisitor();
+
+    void accept(Symbol *symbol);
+
+    virtual bool preVisit(Symbol *) { return true; }
+    virtual void postVisit(Symbol *) {}
+
+    virtual bool visit(UsingNamespaceDirective *) { return true; }
+    virtual bool visit(UsingDeclaration *) { return true; }
+    virtual bool visit(NamespaceAlias *) { return true; }
+    virtual bool visit(Declaration *) { return true; }
+    virtual bool visit(Argument *) { return true; }
+    virtual bool visit(TypenameArgument *) { return true; }
+    virtual bool visit(BaseClass *) { return true; }
+    virtual bool visit(Enum *) { return true; }
+    virtual bool visit(Function *) { return true; }
+    virtual bool visit(Namespace *) { return true; }
+    virtual bool visit(Template *) { return true; }
+    virtual bool visit(Class *) { return true; }
+    virtual bool visit(Block *) { return true; }
+    virtual bool visit(ForwardClassDeclaration *) { return true; }
+
+    // Qt
+    virtual bool visit(QtPropertyDeclaration *) { return true; }
+    virtual bool visit(QtEnum *) { return true; }
+
+    // Objective-C
+    virtual bool visit(ObjCBaseClass *) { return true; }
+    virtual bool visit(ObjCBaseProtocol *) { return true; }
+    virtual bool visit(ObjCClass *) { return true; }
+    virtual bool visit(ObjCForwardClassDeclaration *) { return true; }
+    virtual bool visit(ObjCProtocol *) { return true; }
+    virtual bool visit(ObjCForwardProtocolDeclaration *) { return true; }
+    virtual bool visit(ObjCMethod *) { return true; }
+    virtual bool visit(ObjCPropertyDeclaration *) { return true; }
+};
+
+} // namespace CPlusPlus
+
+
+#endif // SYMBOLVISITOR_H

+ 1097 - 0
Source/ToolCore/JSBind/cplusplus/Symbols.cpp

@@ -0,0 +1,1097 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "Symbols.h"
+#include "Names.h"
+#include "TypeVisitor.h"
+#include "SymbolVisitor.h"
+#include "Matcher.h"
+#include "Scope.h"
+#include "Templates.h"
+
+using namespace CPlusPlus;
+
+UsingNamespaceDirective::UsingNamespaceDirective(TranslationUnit *translationUnit,
+                                                 unsigned sourceLocation, const Name *name)
+    : Symbol(translationUnit, sourceLocation, name)
+{ }
+
+UsingNamespaceDirective::UsingNamespaceDirective(Clone *clone, Subst *subst, UsingNamespaceDirective *original)
+    : Symbol(clone, subst, original)
+{ }
+
+UsingNamespaceDirective::~UsingNamespaceDirective()
+{ }
+
+FullySpecifiedType UsingNamespaceDirective::type() const
+{ return FullySpecifiedType(); }
+
+void UsingNamespaceDirective::visitSymbol0(SymbolVisitor *visitor)
+{ visitor->visit(this); }
+
+NamespaceAlias::NamespaceAlias(TranslationUnit *translationUnit,
+                               unsigned sourceLocation, const Name *name)
+    : Symbol(translationUnit, sourceLocation, name), _namespaceName(0)
+{ }
+
+NamespaceAlias::NamespaceAlias(Clone *clone, Subst *subst, NamespaceAlias *original)
+    : Symbol(clone, subst, original)
+    , _namespaceName(clone->name(original->_namespaceName, subst))
+{ }
+
+NamespaceAlias::~NamespaceAlias()
+{ }
+
+const Name *NamespaceAlias::namespaceName() const
+{ return _namespaceName; }
+
+void NamespaceAlias::setNamespaceName(const Name *namespaceName)
+{ _namespaceName = namespaceName; }
+
+FullySpecifiedType NamespaceAlias::type() const
+{ return FullySpecifiedType(); }
+
+void NamespaceAlias::visitSymbol0(SymbolVisitor *visitor)
+{ visitor->visit(this); }
+
+
+UsingDeclaration::UsingDeclaration(TranslationUnit *translationUnit,
+                                   unsigned sourceLocation, const Name *name)
+    : Symbol(translationUnit, sourceLocation, name)
+{ }
+
+UsingDeclaration::UsingDeclaration(Clone *clone, Subst *subst, UsingDeclaration *original)
+    : Symbol(clone, subst, original)
+{ }
+
+UsingDeclaration::~UsingDeclaration()
+{ }
+
+FullySpecifiedType UsingDeclaration::type() const
+{ return FullySpecifiedType(); }
+
+void UsingDeclaration::visitSymbol0(SymbolVisitor *visitor)
+{ visitor->visit(this); }
+
+Declaration::Declaration(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
+    : Symbol(translationUnit, sourceLocation, name)
+    , _initializer(0)
+{ }
+
+Declaration::Declaration(Clone *clone, Subst *subst, Declaration *original)
+    : Symbol(clone, subst, original)
+    , _type(clone->type(original->_type, subst))
+    , _initializer(clone->stringLiteral(original->_initializer))
+{ }
+
+Declaration::~Declaration()
+{ }
+
+void Declaration::setType(const FullySpecifiedType &type)
+{ _type = type; }
+
+void Declaration::setInitializer(const StringLiteral *initializer)
+{
+    _initializer = initializer;
+}
+
+FullySpecifiedType Declaration::type() const
+{ return _type; }
+
+const StringLiteral *Declaration::getInitializer() const
+{
+    return _initializer;
+}
+
+void Declaration::visitSymbol0(SymbolVisitor *visitor)
+{ visitor->visit(this); }
+
+EnumeratorDeclaration::EnumeratorDeclaration(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
+    : Declaration(translationUnit, sourceLocation, name)
+    , _constantValue(0)
+{}
+
+EnumeratorDeclaration::~EnumeratorDeclaration()
+{}
+
+const StringLiteral *EnumeratorDeclaration::constantValue() const
+{ return _constantValue; }
+
+void EnumeratorDeclaration::setConstantValue(const StringLiteral *constantValue)
+{ _constantValue = constantValue; }
+
+Argument::Argument(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
+    : Symbol(translationUnit, sourceLocation, name),
+      _initializer(0)
+{ }
+
+Argument::Argument(Clone *clone, Subst *subst, Argument *original)
+    : Symbol(clone, subst, original)
+    , _initializer(clone->stringLiteral(original->_initializer))
+    , _type(clone->type(original->_type, subst))
+{ }
+
+Argument::~Argument()
+{ }
+
+bool Argument::hasInitializer() const
+{ return _initializer != 0; }
+
+const StringLiteral *Argument::initializer() const
+{ return _initializer; }
+
+void Argument::setInitializer(const StringLiteral *initializer)
+{ _initializer = initializer; }
+
+void Argument::setType(const FullySpecifiedType &type)
+{ _type = type; }
+
+FullySpecifiedType Argument::type() const
+{ return _type; }
+
+void Argument::visitSymbol0(SymbolVisitor *visitor)
+{ visitor->visit(this); }
+
+TypenameArgument::TypenameArgument(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
+    : Symbol(translationUnit, sourceLocation, name)
+{ }
+
+TypenameArgument::TypenameArgument(Clone *clone, Subst *subst, TypenameArgument *original)
+    : Symbol(clone, subst, original)
+    , _type(clone->type(original->_type, subst))
+{ }
+
+TypenameArgument::~TypenameArgument()
+{ }
+
+void TypenameArgument::setType(const FullySpecifiedType &type)
+{ _type = type; }
+
+FullySpecifiedType TypenameArgument::type() const
+{ return _type; }
+
+void TypenameArgument::visitSymbol0(SymbolVisitor *visitor)
+{ visitor->visit(this); }
+
+Function::Function(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
+    : Scope(translationUnit, sourceLocation, name),
+      _flags(0)
+{ }
+
+Function::Function(Clone *clone, Subst *subst, Function *original)
+    : Scope(clone, subst, original)
+    , _returnType(clone->type(original->_returnType, subst))
+    , _flags(original->_flags)
+{ }
+
+Function::~Function()
+{ }
+
+bool Function::isNormal() const
+{ return f._methodKey == NormalMethod; }
+
+bool Function::isSignal() const
+{ return f._methodKey == SignalMethod; }
+
+bool Function::isSlot() const
+{ return f._methodKey == SlotMethod; }
+
+bool Function::isInvokable() const
+{ return f._methodKey == InvokableMethod; }
+
+int Function::methodKey() const
+{ return f._methodKey; }
+
+void Function::setMethodKey(int key)
+{ f._methodKey = key; }
+
+bool Function::isSignatureEqualTo(const Function *other, Matcher *matcher) const
+{
+    if (! other)
+        return false;
+    else if (isConst() != other->isConst())
+        return false;
+    else if (isVolatile() != other->isVolatile())
+        return false;
+    else if (! Matcher::match(unqualifiedName(), other->unqualifiedName(), matcher))
+        return false;
+
+    const unsigned argc = argumentCount();
+    if (argc != other->argumentCount())
+        return false;
+    for (unsigned i = 0; i < argc; ++i) {
+        Symbol *l = argumentAt(i);
+        Symbol *r = other->argumentAt(i);
+        if (! l->type().match(r->type(), matcher))
+            return false;
+    }
+    return true;
+}
+
+void Function::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+bool Function::match0(const Type *otherType, Matcher *matcher) const
+{
+    if (const Function *otherTy = otherType->asFunctionType())
+        return matcher->match(this, otherTy);
+
+    return false;
+}
+
+FullySpecifiedType Function::type() const
+{
+    FullySpecifiedType ty(const_cast<Function *>(this));
+    ty.setConst(isConst());
+    ty.setVolatile(isVolatile());
+    return ty;
+}
+
+FullySpecifiedType Function::returnType() const
+{ return _returnType; }
+
+void Function::setReturnType(const FullySpecifiedType &returnType)
+{ _returnType = returnType; }
+
+bool Function::hasReturnType() const
+{
+    const FullySpecifiedType ty = returnType();
+    return ty.isValid() || ty.isSigned() || ty.isUnsigned();
+}
+
+unsigned Function::argumentCount() const
+{
+    const unsigned memCnt = memberCount();
+    if (memCnt > 0 && memberAt(0)->type()->isVoidType())
+        return 0;
+
+    // Definitions with function-try-blocks will have more than a block, and
+    // arguments with a lambda as default argument will also have more blocks.
+    unsigned argc = 0;
+    for (unsigned it = 0; it < memCnt; ++it)
+        if (memberAt(it)->isArgument())
+            ++argc;
+    return argc;
+}
+
+Symbol *Function::argumentAt(unsigned index) const
+{
+    for (unsigned it = 0, eit = memberCount(); it < eit; ++it) {
+        if (Argument *arg = memberAt(it)->asArgument()) {
+            if (index == 0)
+                return arg;
+            else
+                --index;
+        }
+    }
+
+    return 0;
+}
+
+bool Function::hasArguments() const
+{
+    unsigned argc = argumentCount();
+    return ! (argc == 0 || (argc == 1 && argumentAt(0)->type()->isVoidType()));
+}
+
+unsigned Function::minimumArgumentCount() const
+{
+    unsigned index = 0;
+
+    for (unsigned ei = argumentCount(); index < ei; ++index) {
+        if (Argument *arg = argumentAt(index)->asArgument()) {
+            if (arg->hasInitializer())
+                break;
+        }
+    }
+
+    return index;
+}
+
+bool Function::isVirtual() const
+{ return f._isVirtual; }
+
+void Function::setVirtual(bool isVirtual)
+{ f._isVirtual = isVirtual; }
+
+bool Function::isOverride() const
+{ return f._isOverride; }
+
+void Function::setOverride(bool isOverride)
+{ f._isOverride = isOverride; }
+
+bool Function::isFinal() const
+{ return f._isFinal; }
+
+void Function::setFinal(bool isFinal)
+{ f._isFinal = isFinal; }
+
+bool Function::isVariadic() const
+{ return f._isVariadic; }
+
+void Function::setVariadic(bool isVariadic)
+{ f._isVariadic = isVariadic; }
+
+bool Function::isConst() const
+{ return f._isConst; }
+
+void Function::setConst(bool isConst)
+{ f._isConst = isConst; }
+
+bool Function::isVolatile() const
+{ return f._isVolatile; }
+
+void Function::setVolatile(bool isVolatile)
+{ f._isVolatile = isVolatile; }
+
+bool Function::isPureVirtual() const
+{ return f._isPureVirtual; }
+
+void Function::setPureVirtual(bool isPureVirtual)
+{ f._isPureVirtual = isPureVirtual; }
+
+bool Function::isAmbiguous() const
+{ return f._isAmbiguous; }
+
+void Function::setAmbiguous(bool isAmbiguous)
+{ f._isAmbiguous = isAmbiguous; }
+
+void Function::visitSymbol0(SymbolVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        for (unsigned i = 0; i < memberCount(); ++i) {
+            visitSymbol(memberAt(i), visitor);
+        }
+    }
+}
+
+bool Function::maybeValidPrototype(unsigned actualArgumentCount) const
+{
+    const unsigned argc = argumentCount();
+    unsigned minNumberArguments = 0;
+
+    for (; minNumberArguments < argc; ++minNumberArguments) {
+        Argument *arg = argumentAt(minNumberArguments)->asArgument();
+
+        if (! arg)
+            return false;
+
+        if (arg->hasInitializer())
+            break;
+    }
+
+    if (actualArgumentCount < minNumberArguments) {
+        // not enough arguments.
+        return false;
+
+    } else if (!isVariadic() && actualArgumentCount > argc) {
+        // too many arguments.
+        return false;
+    }
+
+    return true;
+}
+
+
+Block::Block(TranslationUnit *translationUnit, unsigned sourceLocation)
+    : Scope(translationUnit, sourceLocation, /*name = */ 0)
+{ }
+
+Block::Block(Clone *clone, Subst *subst, Block *original)
+    : Scope(clone, subst, original)
+{ }
+
+Block::~Block()
+{ }
+
+FullySpecifiedType Block::type() const
+{ return FullySpecifiedType(); }
+
+void Block::visitSymbol0(SymbolVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        for (unsigned i = 0; i < memberCount(); ++i) {
+            visitSymbol(memberAt(i), visitor);
+        }
+    }
+}
+
+Enum::Enum(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
+    : Scope(translationUnit, sourceLocation, name)
+    , _isScoped(false)
+{ }
+
+Enum::Enum(Clone *clone, Subst *subst, Enum *original)
+    : Scope(clone, subst, original)
+    , _isScoped(original->isScoped())
+{ }
+
+Enum::~Enum()
+{ }
+
+FullySpecifiedType Enum::type() const
+{ return FullySpecifiedType(const_cast<Enum *>(this)); }
+
+bool Enum::isScoped() const
+{
+    return _isScoped;
+}
+
+void Enum::setScoped(bool scoped)
+{
+    _isScoped = scoped;
+}
+
+void Enum::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+bool Enum::match0(const Type *otherType, Matcher *matcher) const
+{
+    if (const Enum *otherTy = otherType->asEnumType())
+        return matcher->match(this, otherTy);
+
+    return false;
+}
+
+void Enum::visitSymbol0(SymbolVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        for (unsigned i = 0; i < memberCount(); ++i) {
+            visitSymbol(memberAt(i), visitor);
+        }
+    }
+}
+
+Template::Template(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
+    : Scope(translationUnit, sourceLocation, name)
+{ }
+
+Template::Template(Clone *clone, Subst *subst, Template *original)
+    : Scope(clone, subst, original)
+{ }
+
+Template::~Template()
+{ }
+
+unsigned Template::templateParameterCount() const
+{
+    if (declaration() != 0)
+        return memberCount() - 1;
+
+    return 0;
+}
+
+Symbol *Template::templateParameterAt(unsigned index) const
+{ return memberAt(index); }
+
+Symbol *Template::declaration() const
+{
+    if (isEmpty())
+        return 0;
+
+    if (Symbol *s = memberAt(memberCount() - 1)) {
+        if (s->isClass() || s->isForwardClassDeclaration() ||
+            s->isTemplate() || s->isFunction() || s->isDeclaration())
+            return s;
+    }
+
+    return 0;
+}
+
+FullySpecifiedType Template::type() const
+{ return FullySpecifiedType(const_cast<Template *>(this)); }
+
+void Template::visitSymbol0(SymbolVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        for (unsigned i = 0; i < memberCount(); ++i) {
+            visitSymbol(memberAt(i), visitor);
+        }
+    }
+}
+
+void Template::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+bool Template::match0(const Type *otherType, Matcher *matcher) const
+{
+    if (const Template *otherTy = otherType->asTemplateType())
+        return matcher->match(this, otherTy);
+    return false;
+}
+
+Namespace::Namespace(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
+    : Scope(translationUnit, sourceLocation, name)
+    , _isInline(false)
+{ }
+
+Namespace::Namespace(Clone *clone, Subst *subst, Namespace *original)
+    : Scope(clone, subst, original)
+    , _isInline(original->_isInline)
+{ }
+
+Namespace::~Namespace()
+{ }
+
+void Namespace::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+bool Namespace::match0(const Type *otherType, Matcher *matcher) const
+{
+    if (const Namespace *otherTy = otherType->asNamespaceType())
+        return matcher->match(this, otherTy);
+
+    return false;
+}
+
+void Namespace::visitSymbol0(SymbolVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        for (unsigned i = 0; i < memberCount(); ++i) {
+            visitSymbol(memberAt(i), visitor);
+        }
+    }
+}
+
+FullySpecifiedType Namespace::type() const
+{ return FullySpecifiedType(const_cast<Namespace *>(this)); }
+
+BaseClass::BaseClass(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
+    : Symbol(translationUnit, sourceLocation, name),
+      _isVirtual(false)
+{ }
+
+BaseClass::BaseClass(Clone *clone, Subst *subst, BaseClass *original)
+    : Symbol(clone, subst, original)
+    , _isVirtual(original->_isVirtual)
+    , _type(clone->type(original->_type, subst))
+{ }
+
+BaseClass::~BaseClass()
+{ }
+
+FullySpecifiedType BaseClass::type() const
+{ return _type; }
+
+void BaseClass::setType(const FullySpecifiedType &type)
+{ _type = type; }
+
+bool BaseClass::isVirtual() const
+{ return _isVirtual; }
+
+void BaseClass::setVirtual(bool isVirtual)
+{ _isVirtual = isVirtual; }
+
+void BaseClass::visitSymbol0(SymbolVisitor *visitor)
+{ visitor->visit(this); }
+
+ForwardClassDeclaration::ForwardClassDeclaration(TranslationUnit *translationUnit,
+                                                 unsigned sourceLocation, const Name *name)
+    : Symbol(translationUnit, sourceLocation, name)
+{ }
+
+ForwardClassDeclaration::ForwardClassDeclaration(Clone *clone, Subst *subst, ForwardClassDeclaration *original)
+    : Symbol(clone, subst, original)
+{ }
+
+ForwardClassDeclaration::~ForwardClassDeclaration()
+{ }
+
+FullySpecifiedType ForwardClassDeclaration::type() const
+{ return FullySpecifiedType(const_cast<ForwardClassDeclaration *>(this)); }
+
+void ForwardClassDeclaration::visitSymbol0(SymbolVisitor *visitor)
+{ visitor->visit(this); }
+
+void ForwardClassDeclaration::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+bool ForwardClassDeclaration::match0(const Type *otherType, Matcher *matcher) const
+{
+    if (const ForwardClassDeclaration *otherTy = otherType->asForwardClassDeclarationType())
+        return matcher->match(this, otherTy);
+
+    return false;
+}
+
+Class::Class(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
+    : Scope(translationUnit, sourceLocation, name),
+      _key(ClassKey)
+{ }
+
+Class::Class(Clone *clone, Subst *subst, Class *original)
+    : Scope(clone, subst, original)
+    , _key(original->_key)
+{
+    for (size_t i = 0; i < original->_baseClasses.size(); ++i)
+        addBaseClass(clone->symbol(original->_baseClasses.at(i), subst)->asBaseClass());
+}
+
+Class::~Class()
+{ }
+
+bool Class::isClass() const
+{ return _key == ClassKey; }
+
+bool Class::isStruct() const
+{ return _key == StructKey; }
+
+bool Class::isUnion() const
+{ return _key == UnionKey; }
+
+Class::Key Class::classKey() const
+{ return _key; }
+
+void Class::setClassKey(Key key)
+{ _key = key; }
+
+void Class::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+bool Class::match0(const Type *otherType, Matcher *matcher) const
+{
+    if (const Class *otherTy = otherType->asClassType())
+        return matcher->match(this, otherTy);
+
+    return false;
+}
+
+unsigned Class::baseClassCount() const
+{ return unsigned(_baseClasses.size()); }
+
+BaseClass *Class::baseClassAt(unsigned index) const
+{ return _baseClasses.at(index); }
+
+void Class::addBaseClass(BaseClass *baseClass)
+{ _baseClasses.push_back(baseClass); }
+
+FullySpecifiedType Class::type() const
+{ return FullySpecifiedType(const_cast<Class *>(this)); }
+
+void Class::visitSymbol0(SymbolVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        for (unsigned i = 0; i < _baseClasses.size(); ++i) {
+            visitSymbol(_baseClasses.at(i), visitor);
+        }
+        for (unsigned i = 0; i < memberCount(); ++i) {
+            visitSymbol(memberAt(i), visitor);
+        }
+    }
+}
+
+
+QtPropertyDeclaration::QtPropertyDeclaration(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
+    : Symbol(translationUnit, sourceLocation, name)
+    , _flags(NoFlags)
+{ }
+
+QtPropertyDeclaration::QtPropertyDeclaration(Clone *clone, Subst *subst, QtPropertyDeclaration *original)
+    : Symbol(clone, subst, original)
+    , _type(clone->type(original->_type, subst))
+    , _flags(original->_flags)
+{ }
+
+QtPropertyDeclaration::~QtPropertyDeclaration()
+{ }
+
+void QtPropertyDeclaration::setType(const FullySpecifiedType &type)
+{ _type = type; }
+
+void QtPropertyDeclaration::setFlags(int flags)
+{ _flags = flags; }
+
+int QtPropertyDeclaration::flags() const
+{ return _flags; }
+
+FullySpecifiedType QtPropertyDeclaration::type() const
+{ return _type; }
+
+void QtPropertyDeclaration::visitSymbol0(SymbolVisitor *visitor)
+{ visitor->visit(this); }
+
+
+QtEnum::QtEnum(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
+    : Symbol(translationUnit, sourceLocation, name)
+{ }
+
+QtEnum::QtEnum(Clone *clone, Subst *subst, QtEnum *original)
+    : Symbol(clone, subst, original)
+{ }
+
+QtEnum::~QtEnum()
+{ }
+
+FullySpecifiedType QtEnum::type() const
+{ return FullySpecifiedType(); }
+
+void QtEnum::visitSymbol0(SymbolVisitor *visitor)
+{ visitor->visit(this); }
+
+
+ObjCBaseClass::ObjCBaseClass(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
+    : Symbol(translationUnit, sourceLocation, name)
+{ }
+
+ObjCBaseClass::ObjCBaseClass(Clone *clone, Subst *subst, ObjCBaseClass *original)
+    : Symbol(clone, subst, original)
+{ }
+
+ObjCBaseClass::~ObjCBaseClass()
+{ }
+
+FullySpecifiedType ObjCBaseClass::type() const
+{ return FullySpecifiedType(); }
+
+void ObjCBaseClass::visitSymbol0(SymbolVisitor *visitor)
+{ visitor->visit(this); }
+
+ObjCBaseProtocol::ObjCBaseProtocol(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
+    : Symbol(translationUnit, sourceLocation, name)
+{ }
+
+ObjCBaseProtocol::ObjCBaseProtocol(Clone *clone, Subst *subst, ObjCBaseProtocol *original)
+    : Symbol(clone, subst, original)
+{ }
+
+ObjCBaseProtocol::~ObjCBaseProtocol()
+{ }
+
+FullySpecifiedType ObjCBaseProtocol::type() const
+{ return FullySpecifiedType(); }
+
+void ObjCBaseProtocol::visitSymbol0(SymbolVisitor *visitor)
+{ visitor->visit(this); }
+
+ObjCClass::ObjCClass(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name):
+    Scope(translationUnit, sourceLocation, name),
+    _categoryName(0),
+    _baseClass(0),
+    _isInterface(false)
+{ }
+
+ObjCClass::ObjCClass(Clone *clone, Subst *subst, ObjCClass *original)
+    : Scope(clone, subst, original)
+    , _categoryName(clone->name(original->_categoryName, subst))
+    , _baseClass(0)
+    , _isInterface(original->_isInterface)
+{
+    if (original->_baseClass)
+        _baseClass = clone->symbol(original->_baseClass, subst)->asObjCBaseClass();
+    for (size_t i = 0; i < original->_protocols.size(); ++i)
+        addProtocol(clone->symbol(original->_protocols.at(i), subst)->asObjCBaseProtocol());
+}
+
+ObjCClass::~ObjCClass()
+{}
+
+bool ObjCClass::isInterface() const
+{ return _isInterface; }
+
+void ObjCClass::setInterface(bool isInterface)
+{ _isInterface = isInterface; }
+
+bool ObjCClass::isCategory() const
+{ return _categoryName != 0; }
+
+const Name *ObjCClass::categoryName() const
+{ return _categoryName; }
+
+void ObjCClass::setCategoryName(const Name *categoryName)
+{ _categoryName = categoryName; }
+
+ObjCBaseClass *ObjCClass::baseClass() const
+{ return _baseClass; }
+
+void ObjCClass::setBaseClass(ObjCBaseClass *baseClass)
+{ _baseClass = baseClass; }
+
+unsigned ObjCClass::protocolCount() const
+{ return unsigned(_protocols.size()); }
+
+ObjCBaseProtocol *ObjCClass::protocolAt(unsigned index) const
+{ return _protocols.at(index); }
+
+void ObjCClass::addProtocol(ObjCBaseProtocol *protocol)
+{ _protocols.push_back(protocol); }
+
+FullySpecifiedType ObjCClass::type() const
+{ return FullySpecifiedType(const_cast<ObjCClass *>(this)); }
+
+void ObjCClass::visitSymbol0(SymbolVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        if (_baseClass)
+            visitSymbol(_baseClass, visitor);
+
+        for (unsigned i = 0; i < _protocols.size(); ++i)
+            visitSymbol(_protocols.at(i), visitor);
+
+        for (unsigned i = 0; i < memberCount(); ++i)
+            visitSymbol(memberAt(i), visitor);
+    }
+}
+
+void ObjCClass::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+bool ObjCClass::match0(const Type *otherType, Matcher *matcher) const
+{
+    if (const ObjCClass *otherTy = otherType->asObjCClassType())
+        return matcher->match(this, otherTy);
+
+    return false;
+}
+
+ObjCProtocol::ObjCProtocol(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name):
+        Scope(translationUnit, sourceLocation, name)
+{
+}
+
+ObjCProtocol::ObjCProtocol(Clone *clone, Subst *subst, ObjCProtocol *original)
+    : Scope(clone, subst, original)
+{
+    for (size_t i = 0; i < original->_protocols.size(); ++i)
+        addProtocol(clone->symbol(original->_protocols.at(i), subst)->asObjCBaseProtocol());
+}
+
+ObjCProtocol::~ObjCProtocol()
+{}
+
+unsigned ObjCProtocol::protocolCount() const
+{ return unsigned(_protocols.size()); }
+
+ObjCBaseProtocol *ObjCProtocol::protocolAt(unsigned index) const
+{ return _protocols.at(index); }
+
+void ObjCProtocol::addProtocol(ObjCBaseProtocol *protocol)
+{ _protocols.push_back(protocol); }
+
+FullySpecifiedType ObjCProtocol::type() const
+{ return FullySpecifiedType(const_cast<ObjCProtocol *>(this)); }
+
+void ObjCProtocol::visitSymbol0(SymbolVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        for (unsigned i = 0; i < _protocols.size(); ++i)
+            visitSymbol(_protocols.at(i), visitor);
+    }
+}
+
+void ObjCProtocol::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+bool ObjCProtocol::match0(const Type *otherType, Matcher *matcher) const
+{
+    if (const ObjCProtocol *otherTy = otherType->asObjCProtocolType())
+        return matcher->match(this, otherTy);
+
+    return false;
+}
+
+ObjCForwardClassDeclaration::ObjCForwardClassDeclaration(TranslationUnit *translationUnit, unsigned sourceLocation,
+                                                         const Name *name):
+        Symbol(translationUnit, sourceLocation, name)
+{
+}
+
+ObjCForwardClassDeclaration::ObjCForwardClassDeclaration(Clone *clone, Subst *subst, ObjCForwardClassDeclaration *original)
+    : Symbol(clone, subst, original)
+{ }
+
+ObjCForwardClassDeclaration::~ObjCForwardClassDeclaration()
+{}
+
+FullySpecifiedType ObjCForwardClassDeclaration::type() const
+{ return FullySpecifiedType(); }
+
+void ObjCForwardClassDeclaration::visitSymbol0(SymbolVisitor *visitor)
+{ visitor->visit(this); }
+
+void ObjCForwardClassDeclaration::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+bool ObjCForwardClassDeclaration::match0(const Type *otherType, Matcher *matcher) const
+{
+    if (const ObjCForwardClassDeclaration *otherTy = otherType->asObjCForwardClassDeclarationType())
+        return matcher->match(this, otherTy);
+
+    return false;
+}
+
+ObjCForwardProtocolDeclaration::ObjCForwardProtocolDeclaration(TranslationUnit *translationUnit, unsigned sourceLocation,
+                                                               const Name *name):
+        Symbol(translationUnit, sourceLocation, name)
+{
+}
+
+ObjCForwardProtocolDeclaration::ObjCForwardProtocolDeclaration(Clone *clone, Subst *subst, ObjCForwardProtocolDeclaration *original)
+    : Symbol(clone, subst, original)
+{ }
+
+ObjCForwardProtocolDeclaration::~ObjCForwardProtocolDeclaration()
+{}
+
+FullySpecifiedType ObjCForwardProtocolDeclaration::type() const
+{ return FullySpecifiedType(); }
+
+void ObjCForwardProtocolDeclaration::visitSymbol0(SymbolVisitor *visitor)
+{ visitor->visit(this); }
+
+void ObjCForwardProtocolDeclaration::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+bool ObjCForwardProtocolDeclaration::match0(const Type *otherType, Matcher *matcher) const
+{
+    if (const ObjCForwardProtocolDeclaration *otherTy = otherType->asObjCForwardProtocolDeclarationType())
+        return matcher->match(this, otherTy);
+
+    return false;
+}
+
+ObjCMethod::ObjCMethod(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
+    : Scope(translationUnit, sourceLocation, name),
+     _flags(0)
+{ }
+
+ObjCMethod::ObjCMethod(Clone *clone, Subst *subst, ObjCMethod *original)
+    : Scope(clone, subst, original)
+    , _returnType(clone->type(original->_returnType, subst))
+    , _flags(original->_flags)
+{ }
+
+ObjCMethod::~ObjCMethod()
+{ }
+
+void ObjCMethod::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+bool ObjCMethod::match0(const Type *otherType, Matcher *matcher) const
+{
+    if (const ObjCMethod *otherTy = otherType->asObjCMethodType())
+        return matcher->match(this, otherTy);
+
+    return false;
+}
+
+FullySpecifiedType ObjCMethod::type() const
+{ return FullySpecifiedType(const_cast<ObjCMethod *>(this)); }
+
+FullySpecifiedType ObjCMethod::returnType() const
+{ return _returnType; }
+
+void ObjCMethod::setReturnType(const FullySpecifiedType &returnType)
+{ _returnType = returnType; }
+
+bool ObjCMethod::hasReturnType() const
+{
+    const FullySpecifiedType ty = returnType();
+    return ty.isValid() || ty.isSigned() || ty.isUnsigned();
+}
+
+unsigned ObjCMethod::argumentCount() const
+{
+    const unsigned c = memberCount();
+    if (c > 0 && memberAt(c - 1)->isBlock())
+        return c - 1;
+    return c;
+}
+
+Symbol *ObjCMethod::argumentAt(unsigned index) const
+{
+    return memberAt(index);
+}
+
+bool ObjCMethod::hasArguments() const
+{
+    return ! (argumentCount() == 0 ||
+              (argumentCount() == 1 && argumentAt(0)->type()->isVoidType()));
+}
+
+bool ObjCMethod::isVariadic() const
+{ return f._isVariadic; }
+
+void ObjCMethod::setVariadic(bool isVariadic)
+{ f._isVariadic = isVariadic; }
+
+void ObjCMethod::visitSymbol0(SymbolVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        for (unsigned i = 0; i < memberCount(); ++i) {
+            visitSymbol(memberAt(i), visitor);
+        }
+    }
+}
+
+ObjCPropertyDeclaration::ObjCPropertyDeclaration(TranslationUnit *translationUnit,
+                                                 unsigned sourceLocation,
+                                                 const Name *name):
+    Symbol(translationUnit, sourceLocation, name),
+    _getterName(0),
+    _setterName(0),
+    _propertyAttributes(None)
+{}
+
+ObjCPropertyDeclaration::ObjCPropertyDeclaration(Clone *clone, Subst *subst, ObjCPropertyDeclaration *original)
+    : Symbol(clone, subst, original)
+    , _getterName(clone->name(original->_getterName, subst))
+    , _setterName(clone->name(original->_setterName, subst))
+    , _type(clone->type(original->_type, subst))
+    , _propertyAttributes(original->_propertyAttributes)
+{ }
+
+ObjCPropertyDeclaration::~ObjCPropertyDeclaration()
+{}
+
+bool ObjCPropertyDeclaration::hasAttribute(int attribute) const
+{ return _propertyAttributes & attribute; }
+
+void ObjCPropertyDeclaration::setAttributes(int attributes)
+{ _propertyAttributes = attributes; }
+
+bool ObjCPropertyDeclaration::hasGetter() const
+{ return hasAttribute(Getter); }
+
+bool ObjCPropertyDeclaration::hasSetter() const
+{ return hasAttribute(Setter); }
+
+const Name *ObjCPropertyDeclaration::getterName() const
+{ return _getterName; }
+
+void ObjCPropertyDeclaration::setGetterName(const Name *getterName)
+{ _getterName = getterName; }
+
+const Name *ObjCPropertyDeclaration::setterName() const
+{ return _setterName; }
+
+void ObjCPropertyDeclaration::setSetterName(const Name *setterName)
+{ _setterName = setterName; }
+
+void ObjCPropertyDeclaration::setType(const FullySpecifiedType &type)
+{ _type = type; }
+
+FullySpecifiedType ObjCPropertyDeclaration::type() const
+{ return _type; }
+
+void ObjCPropertyDeclaration::visitSymbol0(SymbolVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+    }
+}

+ 912 - 0
Source/ToolCore/JSBind/cplusplus/Symbols.h

@@ -0,0 +1,912 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_SYMBOLS_H
+#define CPLUSPLUS_SYMBOLS_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include "Symbol.h"
+#include "Type.h"
+#include "FullySpecifiedType.h"
+#include "Scope.h"
+#include <vector>
+
+namespace CPlusPlus {
+
+class CPLUSPLUS_EXPORT UsingNamespaceDirective: public Symbol
+{
+public:
+    UsingNamespaceDirective(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name);
+    UsingNamespaceDirective(Clone *clone, Subst *subst, UsingNamespaceDirective *original);
+    virtual ~UsingNamespaceDirective();
+
+    // Symbol's interface
+    virtual FullySpecifiedType type() const;
+
+    virtual const UsingNamespaceDirective *asUsingNamespaceDirective() const
+    { return this; }
+
+    virtual UsingNamespaceDirective *asUsingNamespaceDirective()
+    { return this; }
+
+protected:
+    virtual void visitSymbol0(SymbolVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT UsingDeclaration: public Symbol
+{
+public:
+    UsingDeclaration(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name);
+    UsingDeclaration(Clone *clone, Subst *subst, UsingDeclaration *original);
+    virtual ~UsingDeclaration();
+
+    // Symbol's interface
+    virtual FullySpecifiedType type() const;
+
+    virtual const UsingDeclaration *asUsingDeclaration() const
+    { return this; }
+
+    virtual UsingDeclaration *asUsingDeclaration()
+    { return this; }
+
+protected:
+    virtual void visitSymbol0(SymbolVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT NamespaceAlias: public Symbol
+{
+public:
+    NamespaceAlias(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name);
+    NamespaceAlias(Clone *clone, Subst *subst, NamespaceAlias *original);
+    virtual ~NamespaceAlias();
+
+    const Name *namespaceName() const;
+    void setNamespaceName(const Name *namespaceName);
+
+    // Symbol's interface
+    virtual FullySpecifiedType type() const;
+
+    virtual const NamespaceAlias *asNamespaceAlias() const
+    { return this; }
+
+    virtual NamespaceAlias *asNamespaceAlias()
+    { return this; }
+
+protected:
+    virtual void visitSymbol0(SymbolVisitor *visitor);
+
+private:
+    const Name *_namespaceName;
+};
+
+class CPLUSPLUS_EXPORT Declaration: public Symbol
+{
+public:
+    Declaration(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name);
+    Declaration(Clone *clone, Subst *subst, Declaration *original);
+    virtual ~Declaration();
+
+    void setType(const FullySpecifiedType &type);
+    void setInitializer(StringLiteral const* initializer);
+
+    // Symbol's interface
+    virtual FullySpecifiedType type() const;
+    const StringLiteral *getInitializer() const;
+
+    virtual const Declaration *asDeclaration() const
+    { return this; }
+
+    virtual Declaration *asDeclaration()
+    { return this; }
+
+    virtual EnumeratorDeclaration *asEnumeratorDeclarator()
+    { return 0; }
+
+    virtual const EnumeratorDeclaration *asEnumeratorDeclarator() const
+    { return 0; }
+
+protected:
+    virtual void visitSymbol0(SymbolVisitor *visitor);
+
+private:
+    FullySpecifiedType _type;
+    const StringLiteral *_initializer;
+};
+
+class CPLUSPLUS_EXPORT EnumeratorDeclaration: public Declaration
+{
+public:
+    EnumeratorDeclaration(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name);
+    virtual ~EnumeratorDeclaration();
+
+    const StringLiteral *constantValue() const;
+    void setConstantValue(const StringLiteral *constantValue);
+
+    virtual EnumeratorDeclaration *asEnumeratorDeclarator()
+    { return this; }
+
+    virtual const EnumeratorDeclaration *asEnumeratorDeclarator() const
+    { return this; }
+
+private:
+    const StringLiteral *_constantValue;
+};
+
+class CPLUSPLUS_EXPORT Argument: public Symbol
+{
+public:
+    Argument(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name);
+    Argument(Clone *clone, Subst *subst, Argument *original);
+    virtual ~Argument();
+
+    void setType(const FullySpecifiedType &type);
+
+    bool hasInitializer() const;
+
+    const StringLiteral *initializer() const;
+    void setInitializer(const StringLiteral *initializer);
+
+    // Symbol's interface
+    virtual FullySpecifiedType type() const;
+
+    virtual const Argument *asArgument() const
+    { return this; }
+
+    virtual Argument *asArgument()
+    { return this; }
+
+protected:
+    virtual void visitSymbol0(SymbolVisitor *visitor);
+
+private:
+    const StringLiteral *_initializer;
+    FullySpecifiedType _type;
+};
+
+class CPLUSPLUS_EXPORT TypenameArgument: public Symbol
+{
+public:
+    TypenameArgument(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name);
+    TypenameArgument(Clone *clone, Subst *subst, TypenameArgument *original);
+    virtual ~TypenameArgument();
+
+    void setType(const FullySpecifiedType &type);
+
+    // Symbol's interface
+    virtual FullySpecifiedType type() const;
+
+    virtual const TypenameArgument *asTypenameArgument() const
+    { return this; }
+
+    virtual TypenameArgument *asTypenameArgument()
+    { return this; }
+
+protected:
+    virtual void visitSymbol0(SymbolVisitor *visitor);
+
+private:
+    FullySpecifiedType _type;
+};
+
+class CPLUSPLUS_EXPORT Block: public Scope
+{
+public:
+    Block(TranslationUnit *translationUnit, unsigned sourceLocation);
+    Block(Clone *clone, Subst *subst, Block *original);
+    virtual ~Block();
+
+    // Symbol's interface
+    virtual FullySpecifiedType type() const;
+
+    virtual const Block *asBlock() const
+    { return this; }
+
+    virtual Block *asBlock()
+    { return this; }
+
+protected:
+    virtual void visitSymbol0(SymbolVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ForwardClassDeclaration: public Symbol, public Type
+{
+public:
+    ForwardClassDeclaration(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name);
+    ForwardClassDeclaration(Clone *clone, Subst *subst, ForwardClassDeclaration *original);
+    virtual ~ForwardClassDeclaration();
+
+    // Symbol's interface
+    virtual FullySpecifiedType type() const;
+
+    virtual const ForwardClassDeclaration *asForwardClassDeclaration() const
+    { return this; }
+
+    virtual ForwardClassDeclaration *asForwardClassDeclaration()
+    { return this; }
+
+    // Type's interface
+    virtual const ForwardClassDeclaration *asForwardClassDeclarationType() const
+    { return this; }
+
+    virtual ForwardClassDeclaration *asForwardClassDeclarationType()
+    { return this; }
+
+protected:
+    virtual void visitSymbol0(SymbolVisitor *visitor);
+    virtual void accept0(TypeVisitor *visitor);
+    virtual bool match0(const Type *otherType, Matcher *matcher) const;
+};
+
+class CPLUSPLUS_EXPORT Enum: public Scope, public Type
+{
+public:
+    Enum(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name);
+    Enum(Clone *clone, Subst *subst, Enum *original);
+    virtual ~Enum();
+
+    bool isScoped() const;
+    void setScoped(bool scoped);
+
+    // Symbol's interface
+    virtual FullySpecifiedType type() const;
+
+    virtual const Enum *asEnum() const
+    { return this; }
+
+    virtual Enum *asEnum()
+    { return this; }
+
+    // Type's interface
+    virtual const Enum *asEnumType() const
+    { return this; }
+
+    virtual Enum *asEnumType()
+    { return this; }
+
+protected:
+    virtual void visitSymbol0(SymbolVisitor *visitor);
+    virtual void accept0(TypeVisitor *visitor);
+    virtual bool match0(const Type *otherType, Matcher *matcher) const;
+
+private:
+    bool _isScoped;
+};
+
+class CPLUSPLUS_EXPORT Function: public Scope, public Type
+{
+public:
+    enum MethodKey {
+        NormalMethod,
+        SlotMethod,
+        SignalMethod,
+        InvokableMethod
+    };
+
+public:
+    Function(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name);
+    Function(Clone *clone, Subst *subst, Function *original);
+    virtual ~Function();
+
+    bool isNormal() const;
+    bool isSignal() const;
+    bool isSlot() const;
+    bool isInvokable() const;
+    int methodKey() const;
+    void setMethodKey(int key);
+
+    FullySpecifiedType returnType() const;
+    void setReturnType(const FullySpecifiedType &returnType);
+
+    /** Convenience function that returns whether the function returns something (including void). */
+    bool hasReturnType() const;
+
+    unsigned argumentCount() const;
+    Symbol *argumentAt(unsigned index) const;
+
+    /** Convenience function that returns whether the function receives any arguments. */
+    bool hasArguments() const;
+    unsigned minimumArgumentCount() const;
+
+    bool isVirtual() const;
+    void setVirtual(bool isVirtual);
+
+    bool isOverride() const;
+    void setOverride(bool isOverride);
+
+    bool isFinal() const;
+    void setFinal(bool isFinal);
+
+    bool isVariadic() const;
+    void setVariadic(bool isVariadic);
+
+    bool isConst() const;
+    void setConst(bool isConst);
+
+    bool isVolatile() const;
+    void setVolatile(bool isVolatile);
+
+    bool isPureVirtual() const;
+    void setPureVirtual(bool isPureVirtual);
+
+    bool isSignatureEqualTo(const Function *other, Matcher *matcher = 0) const;
+
+    bool isAmbiguous() const; // internal
+    void setAmbiguous(bool isAmbiguous); // internal
+
+    bool maybeValidPrototype(unsigned actualArgumentCount) const;
+
+    // Symbol's interface
+    virtual FullySpecifiedType type() const;
+
+    virtual const Function *asFunction() const
+    { return this; }
+
+    virtual Function *asFunction()
+    { return this; }
+
+    // Type's interface
+    virtual const Function *asFunctionType() const
+    { return this; }
+
+    virtual Function *asFunctionType()
+    { return this; }
+
+protected:
+    virtual void visitSymbol0(SymbolVisitor *visitor);
+    virtual void accept0(TypeVisitor *visitor);
+    virtual bool match0(const Type *otherType, Matcher *matcher) const;
+
+private:
+    FullySpecifiedType _returnType;
+    struct Flags {
+        unsigned _isVirtual: 1;
+        unsigned _isOverride: 1;
+        unsigned _isFinal: 1;
+        unsigned _isVariadic: 1;
+        unsigned _isPureVirtual: 1;
+        unsigned _isConst: 1;
+        unsigned _isVolatile: 1;
+        unsigned _isAmbiguous: 1;
+        unsigned _methodKey: 3;
+    };
+    union {
+        unsigned _flags;
+        Flags f;
+    };
+};
+
+class CPLUSPLUS_EXPORT Template: public Scope, public Type
+{
+public:
+    Template(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name);
+    Template(Clone *clone, Subst *subst, Template *original);
+    virtual ~Template();
+
+    unsigned templateParameterCount() const;
+    Symbol *templateParameterAt(unsigned index) const;
+    Symbol *declaration() const;
+
+    // Symbol's interface
+    virtual FullySpecifiedType type() const;
+
+    virtual const Template *asTemplate() const
+    { return this; }
+
+    virtual Template *asTemplate()
+    { return this; }
+
+    // Type's interface
+    virtual const Template *asTemplateType() const
+    { return this; }
+
+    virtual Template *asTemplateType()
+    { return this; }
+
+protected:
+    virtual void visitSymbol0(SymbolVisitor *visitor);
+    virtual void accept0(TypeVisitor *visitor);
+    virtual bool match0(const Type *otherType, Matcher *matcher) const;
+};
+
+
+class CPLUSPLUS_EXPORT Namespace: public Scope, public Type
+{
+public:
+    Namespace(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name);
+    Namespace(Clone *clone, Subst *subst, Namespace *original);
+    virtual ~Namespace();
+
+    // Symbol's interface
+    virtual FullySpecifiedType type() const;
+
+    virtual const Namespace *asNamespace() const
+    { return this; }
+
+    virtual Namespace *asNamespace()
+    { return this; }
+
+    // Type's interface
+    virtual const Namespace *asNamespaceType() const
+    { return this; }
+
+    virtual Namespace *asNamespaceType()
+    { return this; }
+
+    bool isInline() const
+    { return _isInline; }
+
+    void setInline(bool onoff)
+    { _isInline = onoff; }
+
+protected:
+    virtual void visitSymbol0(SymbolVisitor *visitor);
+    virtual void accept0(TypeVisitor *visitor);
+    virtual bool match0(const Type *otherType, Matcher *matcher) const;
+
+private:
+    bool _isInline;
+};
+
+class CPLUSPLUS_EXPORT BaseClass: public Symbol
+{
+public:
+    BaseClass(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name);
+    BaseClass(Clone *clone, Subst *subst, BaseClass *original);
+    virtual ~BaseClass();
+
+    bool isVirtual() const;
+    void setVirtual(bool isVirtual);
+
+    // Symbol's interface
+    virtual FullySpecifiedType type() const;
+    void setType(const FullySpecifiedType &type);
+
+    virtual const BaseClass *asBaseClass() const
+    { return this; }
+
+    virtual BaseClass *asBaseClass()
+    { return this; }
+
+protected:
+    virtual void visitSymbol0(SymbolVisitor *visitor);
+
+private:
+    bool _isVirtual;
+    FullySpecifiedType _type;
+};
+
+class CPLUSPLUS_EXPORT Class: public Scope, public Type
+{
+public:
+    Class(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name);
+    Class(Clone *clone, Subst *subst, Class *original);
+    virtual ~Class();
+
+    enum Key {
+        ClassKey,
+        StructKey,
+        UnionKey
+    };
+
+    bool isClass() const;
+    bool isStruct() const;
+    bool isUnion() const;
+    Key classKey() const;
+    void setClassKey(Key key);
+
+    unsigned baseClassCount() const;
+    BaseClass *baseClassAt(unsigned index) const;
+    void addBaseClass(BaseClass *baseClass);
+
+    // Symbol's interface
+    virtual FullySpecifiedType type() const;
+
+    virtual const Class *asClass() const
+    { return this; }
+
+    virtual Class *asClass()
+    { return this; }
+
+    // Type's interface
+    virtual const Class *asClassType() const
+    { return this; }
+
+    virtual Class *asClassType()
+    { return this; }
+
+protected:
+    virtual void visitSymbol0(SymbolVisitor *visitor);
+    virtual void accept0(TypeVisitor *visitor);
+    virtual bool match0(const Type *otherType, Matcher *matcher) const;
+
+private:
+    Key _key;
+    std::vector<BaseClass *> _baseClasses;
+};
+
+class CPLUSPLUS_EXPORT QtPropertyDeclaration: public Symbol
+{
+public:
+    enum Flag {
+        NoFlags = 0,
+        ReadFunction = 1 << 0,
+        WriteFunction = 1 << 1,
+        MemberVariable = 1 << 2,
+        ResetFunction = 1 << 3,
+        NotifyFunction = 1 << 4,
+        DesignableFlag = 1 << 5,
+        DesignableFunction = 1 << 6,
+        ScriptableFlag = 1 << 7,
+        ScriptableFunction = 1 << 8,
+        StoredFlag = 1 << 9,
+        StoredFunction = 1 << 10,
+        UserFlag = 1 << 11,
+        UserFunction = 1 << 12,
+        ConstantFlag = 1 << 13,
+        FinalFlag = 1 << 14
+    };
+
+public:
+    QtPropertyDeclaration(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name);
+    QtPropertyDeclaration(Clone *clone, Subst *subst, QtPropertyDeclaration *original);
+    virtual ~QtPropertyDeclaration();
+
+    void setType(const FullySpecifiedType &type);
+
+    void setFlags(int flags);
+    int flags() const;
+
+    // Symbol's interface
+    virtual FullySpecifiedType type() const;
+
+    virtual const QtPropertyDeclaration *asQtPropertyDeclaration() const
+    { return this; }
+
+    virtual QtPropertyDeclaration *asQtPropertyDeclaration()
+    { return this; }
+
+protected:
+    virtual void visitSymbol0(SymbolVisitor *visitor);
+
+private:
+    FullySpecifiedType _type;
+    int _flags;
+};
+
+class CPLUSPLUS_EXPORT QtEnum: public Symbol
+{
+public:
+    QtEnum(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name);
+    QtEnum(Clone *clone, Subst *subst, QtEnum *original);
+    virtual ~QtEnum();
+
+    // Symbol's interface
+    virtual FullySpecifiedType type() const;
+
+    virtual const QtEnum *asQtEnum() const
+    { return this; }
+
+    virtual QtEnum *asQtEnum()
+    { return this; }
+
+protected:
+    virtual void visitSymbol0(SymbolVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ObjCBaseClass: public Symbol
+{
+public:
+    ObjCBaseClass(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name);
+    ObjCBaseClass(Clone *clone, Subst *subst, ObjCBaseClass *original);
+    virtual ~ObjCBaseClass();
+
+    // Symbol's interface
+    virtual FullySpecifiedType type() const;
+
+    virtual const ObjCBaseClass *asObjCBaseClass() const
+    { return this; }
+
+    virtual ObjCBaseClass *asObjCBaseClass()
+    { return this; }
+
+protected:
+    virtual void visitSymbol0(SymbolVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ObjCBaseProtocol: public Symbol
+{
+public:
+    ObjCBaseProtocol(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name);
+    ObjCBaseProtocol(Clone *clone, Subst *subst, ObjCBaseProtocol *original);
+    virtual ~ObjCBaseProtocol();
+
+    // Symbol's interface
+    virtual FullySpecifiedType type() const;
+
+    virtual const ObjCBaseProtocol *asObjCBaseProtocol() const
+    { return this; }
+
+    virtual ObjCBaseProtocol *asObjCBaseProtocol()
+    { return this; }
+
+protected:
+    virtual void visitSymbol0(SymbolVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ObjCForwardProtocolDeclaration: public Symbol, public Type
+{
+public:
+    ObjCForwardProtocolDeclaration(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name);
+    ObjCForwardProtocolDeclaration(Clone *clone, Subst *subst, ObjCForwardProtocolDeclaration *original);
+    virtual ~ObjCForwardProtocolDeclaration();
+
+    // Symbol's interface
+    virtual FullySpecifiedType type() const;
+
+    virtual const ObjCForwardProtocolDeclaration *asObjCForwardProtocolDeclaration() const
+    { return this; }
+
+    virtual ObjCForwardProtocolDeclaration *asObjCForwardProtocolDeclaration()
+    { return this; }
+
+    // Type's interface
+    virtual const ObjCForwardProtocolDeclaration *asObjCForwardProtocolDeclarationType() const
+    { return this; }
+
+    virtual ObjCForwardProtocolDeclaration *asObjCForwardProtocolDeclarationType()
+    { return this; }
+
+protected:
+    virtual void visitSymbol0(SymbolVisitor *visitor);
+    virtual void accept0(TypeVisitor *visitor);
+    virtual bool match0(const Type *otherType, Matcher *matcher) const;
+};
+
+class CPLUSPLUS_EXPORT ObjCProtocol: public Scope, public Type
+{
+public:
+    ObjCProtocol(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name);
+    ObjCProtocol(Clone *clone, Subst *subst, ObjCProtocol *original);
+    virtual ~ObjCProtocol();
+
+    unsigned protocolCount() const;
+    ObjCBaseProtocol *protocolAt(unsigned index) const;
+    void addProtocol(ObjCBaseProtocol *protocol);
+
+    // Symbol's interface
+    virtual FullySpecifiedType type() const;
+
+    virtual const ObjCProtocol *asObjCProtocol() const
+    { return this; }
+
+    virtual ObjCProtocol *asObjCProtocol()
+    { return this; }
+
+    // Type's interface
+    virtual const ObjCProtocol *asObjCProtocolType() const
+    { return this; }
+
+    virtual ObjCProtocol *asObjCProtocolType()
+    { return this; }
+
+protected:
+    virtual void visitSymbol0(SymbolVisitor *visitor);
+    virtual void accept0(TypeVisitor *visitor);
+    virtual bool match0(const Type *otherType, Matcher *matcher) const;
+
+private:
+    std::vector<ObjCBaseProtocol *> _protocols;
+};
+
+class CPLUSPLUS_EXPORT ObjCForwardClassDeclaration: public Symbol, public Type
+{
+public:
+    ObjCForwardClassDeclaration(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name);
+    ObjCForwardClassDeclaration(Clone *clone, Subst *subst, ObjCForwardClassDeclaration *original);
+    virtual ~ObjCForwardClassDeclaration();
+
+    // Symbol's interface
+    virtual FullySpecifiedType type() const;
+
+    virtual const ObjCForwardClassDeclaration *asObjCForwardClassDeclaration() const
+    { return this; }
+
+    virtual ObjCForwardClassDeclaration *asObjCForwardClassDeclaration()
+    { return this; }
+
+    // Type's interface
+    virtual const ObjCForwardClassDeclaration *asObjCForwardClassDeclarationType() const
+    { return this; }
+
+    virtual ObjCForwardClassDeclaration *asObjCForwardClassDeclarationType()
+    { return this; }
+
+protected:
+    virtual void visitSymbol0(SymbolVisitor *visitor);
+    virtual void accept0(TypeVisitor *visitor);
+    virtual bool match0(const Type *otherType, Matcher *matcher) const;
+};
+
+class CPLUSPLUS_EXPORT ObjCClass: public Scope, public Type
+{
+public:
+    ObjCClass(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name);
+    ObjCClass(Clone *clone, Subst *subst, ObjCClass *original);
+    virtual ~ObjCClass();
+
+    bool isInterface() const;
+    void setInterface(bool isInterface);
+
+    bool isCategory() const;
+    const Name *categoryName() const;
+    void setCategoryName(const Name *categoryName);
+
+    ObjCBaseClass *baseClass() const;
+    void setBaseClass(ObjCBaseClass *baseClass);
+
+    unsigned protocolCount() const;
+    ObjCBaseProtocol *protocolAt(unsigned index) const;
+    void addProtocol(ObjCBaseProtocol *protocol);
+
+    // Symbol's interface
+    virtual FullySpecifiedType type() const;
+
+    virtual const ObjCClass *asObjCClass() const
+    { return this; }
+
+    virtual ObjCClass *asObjCClass()
+    { return this; }
+
+    // Type's interface
+    virtual const ObjCClass *asObjCClassType() const
+    { return this; }
+
+    virtual ObjCClass *asObjCClassType()
+    { return this; }
+
+protected:
+    virtual void visitSymbol0(SymbolVisitor *visitor);
+    virtual void accept0(TypeVisitor *visitor);
+    virtual bool match0(const Type *otherType, Matcher *matcher) const;
+
+private:
+    const Name *_categoryName;
+    ObjCBaseClass * _baseClass;
+    std::vector<ObjCBaseProtocol *> _protocols;
+    bool _isInterface;
+};
+
+class CPLUSPLUS_EXPORT ObjCMethod: public Scope, public Type
+{
+public:
+    ObjCMethod(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name);
+    ObjCMethod(Clone *clone, Subst *subst, ObjCMethod *original);
+    virtual ~ObjCMethod();
+
+    FullySpecifiedType returnType() const;
+    void setReturnType(const FullySpecifiedType &returnType);
+
+    /** Convenience function that returns whether the function returns something (including void). */
+    bool hasReturnType() const;
+
+    unsigned argumentCount() const;
+    Symbol *argumentAt(unsigned index) const;
+
+    /** Convenience function that returns whether the function receives any arguments. */
+    bool hasArguments() const;
+
+    bool isVariadic() const;
+    void setVariadic(bool isVariadic);
+
+    // Symbol's interface
+    virtual FullySpecifiedType type() const;
+
+    virtual const ObjCMethod *asObjCMethod() const
+    { return this; }
+
+    virtual ObjCMethod *asObjCMethod()
+    { return this; }
+
+    // Type's interface
+    virtual const ObjCMethod *asObjCMethodType() const
+    { return this; }
+
+    virtual ObjCMethod *asObjCMethodType()
+    { return this; }
+
+protected:
+    virtual void visitSymbol0(SymbolVisitor *visitor);
+    virtual void accept0(TypeVisitor *visitor);
+    virtual bool match0(const Type *otherType, Matcher *matcher) const;
+
+private:
+    FullySpecifiedType _returnType;
+    struct Flags {
+        unsigned _isVariadic: 1;
+    };
+    union {
+        unsigned _flags;
+        Flags f;
+    };
+};
+
+class CPLUSPLUS_EXPORT ObjCPropertyDeclaration: public Symbol
+{
+public:
+    enum PropertyAttributes {
+        None = 0,
+        Assign = 1 << 0,
+        Retain = 1 << 1,
+        Copy = 1 << 2,
+        ReadOnly = 1 << 3,
+        ReadWrite = 1 << 4,
+        Getter = 1 << 5,
+        Setter = 1 << 6,
+        NonAtomic = 1 << 7,
+
+        WritabilityMask = ReadOnly | ReadWrite,
+        SetterSemanticsMask = Assign | Retain | Copy
+    };
+
+public:
+    ObjCPropertyDeclaration(TranslationUnit *translationUnit,
+                            unsigned sourceLocation,
+                            const Name *name);
+    ObjCPropertyDeclaration(Clone *clone, Subst *subst, ObjCPropertyDeclaration *original);
+    virtual ~ObjCPropertyDeclaration();
+
+    bool hasAttribute(int attribute) const;
+    void setAttributes(int attributes);
+
+    bool hasGetter() const;
+    bool hasSetter() const;
+
+    const Name *getterName() const;
+
+    void setGetterName(const Name *getterName);
+
+    const Name *setterName() const;
+    void setSetterName(const Name *setterName);
+
+    void setType(const FullySpecifiedType &type);
+
+    // Symbol's interface
+    virtual FullySpecifiedType type() const;
+
+    virtual const ObjCPropertyDeclaration *asObjCPropertyDeclaration() const
+    { return this; }
+
+    virtual ObjCPropertyDeclaration *asObjCPropertyDeclaration()
+    { return this; }
+
+protected:
+    virtual void visitSymbol0(SymbolVisitor *visitor);
+
+private:
+    const Name *_getterName;
+    const Name *_setterName;
+    FullySpecifiedType _type;
+    int _propertyAttributes;
+};
+
+} // namespace CPlusPlus
+
+
+#endif // CPLUSPLUS_SYMBOLS_H

+ 578 - 0
Source/ToolCore/JSBind/cplusplus/Templates.cpp

@@ -0,0 +1,578 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "Templates.h"
+#include "CoreTypes.h"
+#include "Symbols.h"
+#include "Control.h"
+#include "Names.h"
+#include "Literals.h"
+
+#include "cppassert.h"
+
+#include <algorithm>
+
+
+using namespace CPlusPlus;
+
+CloneType::CloneType(Clone *clone)
+    : _clone(clone)
+    , _control(clone->control())
+    , _subst(0)
+{
+}
+
+FullySpecifiedType CloneType::cloneType(const FullySpecifiedType &type, Subst *subst)
+{
+    TypeSubstPair typeSubstPair = std::make_pair(type, subst);
+    if (_cache.find(typeSubstPair) != _cache.end())
+        return _cache[typeSubstPair];
+
+    std::swap(_subst, subst);
+    FullySpecifiedType ty(type);
+    std::swap(_type, ty);
+    accept(_type.type());
+    std::swap(_type, ty);
+    std::swap(_subst, subst);
+
+    _cache[typeSubstPair] = ty;
+    return ty;
+}
+
+void CloneType::visit(UndefinedType *type)
+{
+    _type.setType(type);
+}
+
+void CloneType::visit(VoidType *)
+{
+    _type.setType(_control->voidType());
+}
+
+void CloneType::visit(IntegerType *type)
+{
+    _type.setType(_control->integerType(type->kind()));
+}
+
+void CloneType::visit(FloatType *type)
+{
+    _type.setType(_control->floatType(type->kind()));
+}
+
+void CloneType::visit(PointerToMemberType *type)
+{
+    _type.setType(_control->pointerToMemberType(_clone->name(type->memberName(), _subst),
+                                                _clone->type(type->elementType(), _subst)));
+}
+
+void CloneType::visit(PointerType *type)
+{
+    _type.setType(_control->pointerType(_clone->type(type->elementType(), _subst)));
+}
+
+void CloneType::visit(ReferenceType *type)
+{
+    _type.setType(_control->referenceType(_clone->type(type->elementType(), _subst), type->isRvalueReference()));
+}
+
+void CloneType::visit(ArrayType *type)
+{
+    _type.setType(_control->arrayType(_clone->type(type->elementType(), _subst), type->size()));
+}
+
+void CloneType::visit(NamedType *type)
+{
+    const Name *name = _clone->name(type->name(), _subst);
+    FullySpecifiedType ty;
+    if (_subst)
+        ty = _subst->apply(name);
+    if (! ty.isValid())
+        ty = _control->namedType(name);
+    _type.setType(ty.type());
+}
+
+void CloneType::visit(Function *type)
+{
+    Function *f = _clone->symbol(type, _subst)->asFunction();
+    _type = f;
+}
+
+void CloneType::visit(Namespace *type)
+{
+    Namespace *ns = _clone->symbol(type, _subst)->asNamespace();
+    _type = ns;
+}
+
+void CloneType::visit(Template *type)
+{
+    Template *templ = _clone->symbol(type, _subst)->asTemplate();
+    _type = templ;
+}
+
+void CloneType::visit(Class *type)
+{
+    Class *klass = _clone->symbol(type, _subst)->asClass();
+    _type = klass;
+}
+
+void CloneType::visit(Enum *type)
+{
+    Enum *e = _clone->symbol(type, _subst)->asEnum();
+    _type = e;
+}
+
+void CloneType::visit(ForwardClassDeclaration *type)
+{
+    ForwardClassDeclaration *fwd = _clone->symbol(type, _subst)->asForwardClassDeclaration();
+    _type = fwd;
+}
+
+void CloneType::visit(ObjCClass *type)
+{
+    ObjCClass *klass = _clone->symbol(type, _subst)->asObjCClass();
+    _type = klass;
+}
+
+void CloneType::visit(ObjCProtocol *type)
+{
+    ObjCProtocol *proto = _clone->symbol(type, _subst)->asObjCProtocol();
+    _type = proto;
+}
+
+void CloneType::visit(ObjCMethod *type)
+{
+    ObjCMethod *meth = _clone->symbol(type, _subst)->asObjCMethod();
+    _type = meth;
+}
+
+void CloneType::visit(ObjCForwardClassDeclaration *type)
+{
+    ObjCForwardClassDeclaration *fwd = _clone->symbol(type, _subst)->asObjCForwardClassDeclaration();
+    _type = fwd;
+}
+
+void CloneType::visit(ObjCForwardProtocolDeclaration *type)
+{
+    ObjCForwardProtocolDeclaration *fwd = _clone->symbol(type, _subst)->asObjCForwardProtocolDeclaration();
+    _type = fwd;
+}
+
+CloneSymbol::CloneSymbol(Clone *clone)
+    : _clone(clone)
+    , _control(clone->control())
+    , _subst(0)
+    , _symbol(0)
+{
+}
+
+Symbol *CloneSymbol::cloneSymbol(Symbol *symbol, Subst *subst)
+{
+    if (! symbol)
+        return 0;
+
+    SymbolSubstPair symbolSubstPair = std::make_pair(symbol, subst);
+    if (_cache.find(symbolSubstPair) != _cache.end()) {
+        Symbol *cachedSymbol = _cache[symbolSubstPair];
+        if (cachedSymbol->enclosingScope() == symbol->enclosingScope())
+            return cachedSymbol;
+    }
+
+    Symbol *r = 0;
+    std::swap(_subst, subst);
+    std::swap(_symbol, r);
+    accept(symbol);
+    std::swap(_symbol, r);
+    std::swap(_subst, subst);
+
+    CPP_CHECK(r != 0);
+    _cache[symbolSubstPair] = r;
+    return r;
+}
+
+bool CloneSymbol::visit(UsingNamespaceDirective *symbol)
+{
+    UsingNamespaceDirective *u = new UsingNamespaceDirective(_clone, _subst, symbol);
+    _symbol = u;
+    _control->addSymbol(u);
+    return false;
+}
+
+bool CloneSymbol::visit(UsingDeclaration *symbol)
+{
+    UsingDeclaration *u = new UsingDeclaration(_clone, _subst, symbol);
+    _symbol = u;
+    _control->addSymbol(u);
+    return false;
+}
+
+bool CloneSymbol::visit(NamespaceAlias *symbol)
+{
+    NamespaceAlias *ns = new NamespaceAlias(_clone, _subst, symbol);
+    _symbol = ns;
+    _control->addSymbol(ns);
+    return false;
+}
+
+bool CloneSymbol::visit(Declaration *symbol)
+{
+    Declaration *decl = new Declaration(_clone, _subst, symbol);
+    _symbol = decl;
+    _control->addSymbol(decl);
+    return false;
+}
+
+bool CloneSymbol::visit(Argument *symbol)
+{
+    Argument *arg = new Argument(_clone, _subst, symbol);
+    _symbol = arg;
+    _control->addSymbol(arg);
+    return false;
+}
+
+bool CloneSymbol::visit(TypenameArgument *symbol)
+{
+    TypenameArgument *arg = new TypenameArgument(_clone, _subst, symbol);
+    _symbol = arg;
+    _control->addSymbol(arg);
+    return false;
+}
+
+bool CloneSymbol::visit(BaseClass *symbol)
+{
+    BaseClass *bc = new BaseClass(_clone, _subst, symbol);
+    _symbol = bc;
+    _control->addSymbol(bc);
+    return false;
+}
+
+bool CloneSymbol::visit(Enum *symbol)
+{
+    Enum *e = new Enum(_clone, _subst, symbol);
+    _symbol = e;
+    _control->addSymbol(e);
+    return false;
+}
+
+bool CloneSymbol::visit(Function *symbol)
+{
+    Function *fun = new Function(_clone, _subst, symbol);
+    _symbol = fun;
+    _control->addSymbol(fun);
+    return false;
+}
+
+bool CloneSymbol::visit(Namespace *symbol)
+{
+    Namespace *ns = new Namespace(_clone, _subst, symbol);
+    _symbol = ns;
+    _control->addSymbol(ns);
+    return false;
+}
+
+bool CloneSymbol::visit(Template *symbol)
+{
+    Template *templ = new Template(_clone, _subst, symbol);
+    _symbol = templ;
+    _control->addSymbol(templ);
+    return false;
+}
+
+bool CloneSymbol::visit(Class *symbol)
+{
+    Class *klass = new Class(_clone, _subst, symbol);
+    _symbol = klass;
+    _control->addSymbol(klass);
+    return false;
+}
+
+bool CloneSymbol::visit(Block *symbol)
+{
+    Block *block = new Block(_clone, _subst, symbol);
+    _symbol = block;
+    _control->addSymbol(block);
+    return false;
+}
+
+bool CloneSymbol::visit(ForwardClassDeclaration *symbol)
+{
+    ForwardClassDeclaration *fwd = new ForwardClassDeclaration(_clone, _subst, symbol);
+    _symbol = fwd;
+    _control->addSymbol(fwd);
+    return false;
+}
+
+bool CloneSymbol::visit(QtPropertyDeclaration *symbol)
+{
+    QtPropertyDeclaration *decl = new QtPropertyDeclaration(_clone, _subst, symbol);
+    _symbol = decl;
+    _control->addSymbol(decl);
+    return false;
+}
+
+bool CloneSymbol::visit(QtEnum *symbol)
+{
+    QtEnum *e = new QtEnum(_clone, _subst, symbol);
+    _symbol = e;
+    _control->addSymbol(e);
+    return false;
+}
+
+bool CloneSymbol::visit(ObjCBaseClass *symbol)
+{
+    ObjCBaseClass *bc = new ObjCBaseClass(_clone, _subst, symbol);
+    _symbol = bc;
+    _control->addSymbol(bc);
+    return false;
+}
+
+bool CloneSymbol::visit(ObjCBaseProtocol *symbol)
+{
+    ObjCBaseProtocol *bc = new ObjCBaseProtocol(_clone, _subst, symbol);
+    _symbol = bc;
+    _control->addSymbol(bc);
+    return false;
+}
+
+bool CloneSymbol::visit(ObjCClass *symbol)
+{
+    ObjCClass *klass = new ObjCClass(_clone, _subst, symbol);
+    _symbol = klass;
+    _control->addSymbol(klass);
+    return false;
+}
+
+bool CloneSymbol::visit(ObjCForwardClassDeclaration *symbol)
+{
+    ObjCForwardClassDeclaration *fwd = new ObjCForwardClassDeclaration(_clone, _subst, symbol);
+    _symbol = fwd;
+    _control->addSymbol(fwd);
+    return false;
+}
+
+bool CloneSymbol::visit(ObjCProtocol *symbol)
+{
+    ObjCProtocol *proto = new ObjCProtocol(_clone, _subst, symbol);
+    _symbol = proto;
+    _control->addSymbol(proto);
+    return false;
+}
+
+bool CloneSymbol::visit(ObjCForwardProtocolDeclaration *symbol)
+{
+    ObjCForwardProtocolDeclaration *fwd = new ObjCForwardProtocolDeclaration(_clone, _subst, symbol);
+    _symbol = fwd;
+    _control->addSymbol(fwd);
+    return false;
+}
+
+bool CloneSymbol::visit(ObjCMethod *symbol)
+{
+    ObjCMethod *meth = new ObjCMethod(_clone, _subst, symbol);
+    _symbol = meth;
+    _control->addSymbol(meth);
+    return false;
+}
+
+bool CloneSymbol::visit(ObjCPropertyDeclaration *symbol)
+{
+    ObjCPropertyDeclaration *decl = new ObjCPropertyDeclaration(_clone, _subst, symbol);
+    _symbol = decl;
+    _control->addSymbol(decl);
+    return false;
+}
+
+CloneName::CloneName(Clone *clone)
+    : _clone(clone)
+    , _control(clone->control())
+    , _subst(0)
+    , _name(0)
+{
+}
+
+const Name *CloneName::cloneName(const Name *name, Subst *subst)
+{
+    if (! name)
+        return 0;
+
+    NameSubstPair nameSubstPair = std::make_pair(name, subst);
+    if (_cache.find(nameSubstPair) != _cache.end())
+        return _cache[nameSubstPair];
+
+    const Name *r = 0;
+    std::swap(_subst, subst);
+    std::swap(_name, r);
+    accept(name);
+    std::swap(_name, r);
+    std::swap(_subst, subst);
+    CPP_CHECK(r != 0);
+    _cache[nameSubstPair] = r;
+    return r;
+}
+
+void CloneName::visit(const Identifier *name)
+{
+    _name = _control->identifier(name->chars(), name->size());
+}
+
+void CloneName::visit(const AnonymousNameId *name)
+{
+    _name = _control->anonymousNameId(name->classTokenIndex());
+}
+
+void CloneName::visit(const TemplateNameId *name)
+{
+    std::vector<FullySpecifiedType> args(name->templateArgumentCount());
+    for (unsigned i = 0; i < args.size(); ++i)
+        args[i] = _clone->type(name->templateArgumentAt(i), _subst);
+    if (args.empty())
+        _name = _control->templateNameId(_clone->identifier(name->identifier()), name->isSpecialization());
+    else
+        _name = _control->templateNameId(_clone->identifier(name->identifier()), name->isSpecialization(),
+                                         &args[0], unsigned(args.size()));
+}
+
+void CloneName::visit(const DestructorNameId *name)
+{
+    _name = _control->destructorNameId(_clone->identifier(name->identifier()));
+}
+
+void CloneName::visit(const OperatorNameId *name)
+{
+    _name = _control->operatorNameId(name->kind());
+}
+
+void CloneName::visit(const ConversionNameId *name)
+{
+    _name = _control->conversionNameId(_clone->type(name->type(), _subst));
+}
+
+void CloneName::visit(const QualifiedNameId *name)
+{
+    _name = _control->qualifiedNameId(_clone->name(name->base(), _subst),
+                                      _clone->name(name->name(), _subst));
+}
+
+void CloneName::visit(const SelectorNameId *name)
+{
+    CPP_CHECK(name->nameCount() > 0);
+    std::vector<const Name *> names(name->nameCount());
+    for (unsigned i = 0; i < names.size(); ++i)
+        names[i] = _clone->name(name->nameAt(i), _subst);
+    _name = _control->selectorNameId(&names[0], unsigned(names.size()), name->hasArguments());
+}
+
+
+Clone::Clone(Control *control)
+    : _control(control)
+    , _type(this)
+    , _name(this)
+    , _symbol(this)
+{
+}
+
+const StringLiteral *Clone::stringLiteral(const StringLiteral *literal)
+{
+    return literal ? _control->stringLiteral(literal->chars(), literal->size()) : 0;
+}
+
+const NumericLiteral *Clone::numericLiteral(const NumericLiteral *literal)
+{
+    return literal ? _control->numericLiteral(literal->chars(), literal->size()) : 0;
+}
+
+const Identifier *Clone::identifier(const Identifier *id)
+{
+    return id ? _control->identifier(id->chars(), id->size()) : 0;
+}
+
+FullySpecifiedType Clone::type(const FullySpecifiedType &type, Subst *subst)
+{
+    return _type(type, subst);
+}
+
+const Name *Clone::name(const Name *name, Subst *subst)
+{
+    return _name(name, subst);
+}
+
+Symbol *Clone::symbol(Symbol *symbol, Subst *subst)
+{
+    return _symbol(symbol, subst);
+}
+
+Symbol *Clone::instantiate(Template *templ, const FullySpecifiedType *const args, unsigned argc, Subst *s)
+{
+    Subst subst(_control, s);
+    for (unsigned i = 0, e = std::min(templ->templateParameterCount(), argc); i < e; ++i) {
+        Symbol *formal = templ->templateParameterAt(i);
+        FullySpecifiedType actual = args[i];
+        subst.bind(name(formal->name(), 0), actual);
+    }
+    if (argc < templ->templateParameterCount()) {
+        for (unsigned i = argc; i < templ->templateParameterCount(); ++i) {
+            Symbol *formal = templ->templateParameterAt(i);
+            if (TypenameArgument *tn = formal->asTypenameArgument())
+                subst.bind(name(formal->name(), &subst), type(tn->type(), &subst));
+        }
+    }
+    if (Symbol *inst = symbol(templ->declaration(), &subst)) {
+        inst->setEnclosingScope(templ->enclosingScope());
+        return inst;
+    }
+    return 0;
+}
+
+//
+// substitutions
+//
+
+
+FullySpecifiedType Subst::apply(const Name *name) const
+{
+    if (name) {
+        std::map<const Name *, FullySpecifiedType, Name::Compare>::const_iterator it = _map.find(name);
+        if (it != _map.end())
+            return it->second;
+        else if (_previous)
+            return _previous->apply(name);
+
+        else if (const QualifiedNameId *q = name->asQualifiedNameId()) {
+            const NamedType *baseNamedType = apply(q->base())->asNamedType();
+            const NamedType *unqualified = apply(q->name())->asNamedType();
+            if (baseNamedType) {
+                if (! unqualified) {
+                    const Name *qualifiedBase = baseNamedType->name();
+                    const Name *qualifiedName = q->name();
+                    return control()->namedType(control()->qualifiedNameId(qualifiedBase,
+                                                                           qualifiedName));
+                }
+                else if(baseNamedType->name()->identifier() != 0) {
+                    const QualifiedNameId *clonedQualifiedNameId
+                            = control()->qualifiedNameId(baseNamedType->name()->identifier(),
+                                                         unqualified->name());
+                    NamedType *clonedNamedType = control()->namedType(clonedQualifiedNameId);
+                    return clonedNamedType;
+                }
+            }
+        }
+
+    }
+    return FullySpecifiedType();
+}

+ 211 - 0
Source/ToolCore/JSBind/cplusplus/Templates.h

@@ -0,0 +1,211 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_TEMPLATES_H
+#define CPLUSPLUS_TEMPLATES_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include "TypeVisitor.h"
+#include "FullySpecifiedType.h"
+#include "Name.h"
+#include "NameVisitor.h"
+#include "SymbolVisitor.h"
+
+#include <map>
+#include <utility>
+
+namespace CPlusPlus {
+
+class Clone;
+
+class CPLUSPLUS_EXPORT Subst
+{
+    Subst(const Subst &other);
+    Subst &operator = (const Subst &other);
+
+public:
+    Subst(Control *control, Subst *previous = 0)
+        : _control(control)
+        , _previous(previous)
+    { }
+
+    Control *control() const { return _control; }
+    Subst *previous() const { return _previous; }
+
+    FullySpecifiedType apply(const Name *name) const;
+
+    void bind(const Name *name, const FullySpecifiedType &ty)
+    { _map.insert(std::make_pair(name, ty)); }
+
+    FullySpecifiedType &operator[](const Name *name) { return _map[name]; }
+
+    bool contains(const Name *name) const { return _map.find(name) != _map.end(); }
+
+private:
+    Control *_control;
+    Subst *_previous;
+    std::map<const Name *, FullySpecifiedType, Name::Compare> _map;
+};
+
+class CPLUSPLUS_EXPORT CloneType: protected TypeVisitor
+{
+public:
+    CloneType(Clone *clone);
+
+    FullySpecifiedType operator()(const FullySpecifiedType &type, Subst *subst) { return cloneType(type, subst); }
+    FullySpecifiedType cloneType(const FullySpecifiedType &type, Subst *subst);
+
+protected:
+    virtual void visit(UndefinedType *type);
+    virtual void visit(VoidType *type);
+    virtual void visit(IntegerType *type);
+    virtual void visit(FloatType *type);
+    virtual void visit(PointerToMemberType *type);
+    virtual void visit(PointerType *type);
+    virtual void visit(ReferenceType *type);
+    virtual void visit(ArrayType *type);
+    virtual void visit(NamedType *type);
+    virtual void visit(Function *type);
+    virtual void visit(Namespace *type);
+    virtual void visit(Template *type);
+    virtual void visit(Class *type);
+    virtual void visit(Enum *type);
+    virtual void visit(ForwardClassDeclaration *type);
+    virtual void visit(ObjCClass *type);
+    virtual void visit(ObjCProtocol *type);
+    virtual void visit(ObjCMethod *type);
+    virtual void visit(ObjCForwardClassDeclaration *type);
+    virtual void visit(ObjCForwardProtocolDeclaration *type);
+
+protected:
+    typedef std::pair <const FullySpecifiedType, Subst *> TypeSubstPair;
+    std::map<TypeSubstPair, FullySpecifiedType> _cache;
+
+    Clone *_clone;
+    Control *_control;
+    Subst *_subst;
+    FullySpecifiedType _type;
+};
+
+class CPLUSPLUS_EXPORT CloneName: protected NameVisitor
+{
+public:
+    CloneName(Clone *clone);
+
+    const Name *operator()(const Name *name, Subst *subst) { return cloneName(name, subst); }
+    const Name *cloneName(const Name *name, Subst *subst);
+
+protected:
+    virtual void visit(const Identifier *name);
+    virtual void visit(const AnonymousNameId *name);
+    virtual void visit(const TemplateNameId *name);
+    virtual void visit(const DestructorNameId *name);
+    virtual void visit(const OperatorNameId *name);
+    virtual void visit(const ConversionNameId *name);
+    virtual void visit(const QualifiedNameId *name);
+    virtual void visit(const SelectorNameId *name);
+
+protected:
+    typedef std::pair <const Name *, Subst *> NameSubstPair;
+    std::map<NameSubstPair, const Name *> _cache;
+
+    Clone *_clone;
+    Control *_control;
+    Subst *_subst;
+    const Name *_name;
+};
+
+class CPLUSPLUS_EXPORT CloneSymbol: protected SymbolVisitor
+{
+public:
+    CloneSymbol(Clone *clone);
+
+    Symbol *operator()(Symbol *symbol, Subst *subst) { return cloneSymbol(symbol, subst); }
+    Symbol *cloneSymbol(Symbol *symbol, Subst *subst);
+
+protected:
+    virtual bool visit(UsingNamespaceDirective *symbol);
+    virtual bool visit(UsingDeclaration *symbol);
+    virtual bool visit(NamespaceAlias *symbol);
+    virtual bool visit(Declaration *symbol);
+    virtual bool visit(Argument *symbol);
+    virtual bool visit(TypenameArgument *symbol);
+    virtual bool visit(BaseClass *symbol);
+    virtual bool visit(Enum *symbol);
+    virtual bool visit(Function *symbol);
+    virtual bool visit(Namespace *symbol);
+    virtual bool visit(Template *symbol);
+    virtual bool visit(Class *symbol);
+    virtual bool visit(Block *symbol);
+    virtual bool visit(ForwardClassDeclaration *symbol);
+
+    // Qt
+    virtual bool visit(QtPropertyDeclaration *symbol);
+    virtual bool visit(QtEnum *symbol);
+
+    // Objective-C
+    virtual bool visit(ObjCBaseClass *symbol);
+    virtual bool visit(ObjCBaseProtocol *symbol);
+    virtual bool visit(ObjCClass *symbol);
+    virtual bool visit(ObjCForwardClassDeclaration *symbol);
+    virtual bool visit(ObjCProtocol *symbol);
+    virtual bool visit(ObjCForwardProtocolDeclaration *symbol);
+    virtual bool visit(ObjCMethod *symbol);
+    virtual bool visit(ObjCPropertyDeclaration *symbol);
+
+protected:
+    typedef std::pair <Symbol *, Subst *> SymbolSubstPair;
+    std::map<SymbolSubstPair, Symbol *> _cache;
+
+    Clone *_clone;
+    Control *_control;
+    Subst *_subst;
+    Symbol *_symbol;
+};
+
+class CPLUSPLUS_EXPORT Clone
+{
+    Control *_control;
+
+public:
+    Clone(Control *control);
+
+    Control *control() const { return _control; }
+    const StringLiteral *stringLiteral(const StringLiteral *literal);
+    const NumericLiteral *numericLiteral(const NumericLiteral *literal);
+    const Identifier *identifier(const Identifier *id);
+
+    FullySpecifiedType type(const FullySpecifiedType &type, Subst *subst);
+    const Name *name(const Name *name, Subst *subst);
+    Symbol *symbol(Symbol *symbol, Subst *subst);
+
+    Symbol *instantiate(Template *templ,
+                        const FullySpecifiedType *const args, unsigned argc,
+                        Subst *subst = 0);
+
+private:
+    CloneType _type;
+    CloneName _name;
+    CloneSymbol _symbol;
+};
+
+} // end of namespace CPlusPlus
+
+#endif // CPLUSPLUS_TEMPLATES_H

+ 128 - 0
Source/ToolCore/JSBind/cplusplus/Token.cpp

@@ -0,0 +1,128 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "Token.h"
+#include "Literals.h"
+
+using namespace CPlusPlus;
+
+const char *token_names[] = {
+    (""), ("<error>"),
+
+    ("<C++ comment>"), ("<C++ doxy comment>"),
+    ("<comment>"), ("<doxy comment>"),
+
+    ("<identifier>"),
+
+    ("<numeric literal>"),
+    ("<char literal>"), ("<wide char literal>"), ("<utf16 char literal>"), ("<utf32 char literal>"),
+    ("<string literal>"), ("<wide string literal>"), ("<utf8 string literal>"),
+    ("<utf16 string literal>"), ("<utf32 string literal>"),
+    ("<raw string literal>"), ("<raw wide string literal>"), ("<raw utf8 string literal>"),
+    ("<raw utf16 string literal>"), ("<raw utf32 string literal>"),
+    ("<@string literal>"), ("<angle string literal>"),
+
+    ("&"), ("&&"), ("&="), ("->"), ("->*"), ("^"), ("^="), (":"), ("::"),
+    (","), ("/"), ("/="), ("."), ("..."), (".*"), ("="), ("=="), ("!"),
+    ("!="), (">"), (">="), (">>"), (">>="), ("{"), ("["), ("<"), ("<="),
+    ("<<"), ("<<="), ("("), ("-"), ("-="), ("--"), ("%"), ("%="), ("|"),
+    ("|="), ("||"), ("+"), ("+="), ("++"), ("#"), ("##"), ("?"), ("}"),
+    ("]"), (")"), (";"), ("*"), ("*="), ("~"), ("~="),
+
+    ("alignas"), ("alignof"), ("asm"), ("auto"), ("break"), ("case"), ("catch"),
+    ("class"), ("const"), ("const_cast"), ("constexpr"), ("continue"),
+    ("decltype"), ("default"),
+    ("delete"), ("do"), ("dynamic_cast"), ("else"), ("enum"),
+    ("explicit"), ("export"), ("extern"), ("false"), ("for"),
+    ("friend"), ("goto"), ("if"), ("inline"),
+    ("mutable"), ("namespace"), ("new"), ("noexcept"),
+    ("nullptr"), ("operator"), ("private"),
+    ("protected"), ("public"), ("register"), ("reinterpret_cast"),
+    ("return"), ("sizeof"), ("static"), ("static_assert"),
+    ("static_cast"), ("struct"), ("switch"), ("template"), ("this"), ("thread_local"),
+    ("throw"), ("true"), ("try"), ("typedef"), ("typeid"), ("typename"),
+    ("union"), ("using"), ("virtual"),
+    ("volatile"), ("while"),
+
+    // gnu
+    ("__attribute__"), ("__thread"), ("__typeof__"),
+
+    // objc @keywords
+    ("@catch"), ("@class"), ("@compatibility_alias"), ("@defs"), ("@dynamic"),
+    ("@encode"), ("@end"), ("@finally"), ("@implementation"), ("@interface"),
+    ("@not_keyword"), ("@optional"), ("@package"), ("@private"), ("@property"),
+    ("@protected"), ("@protocol"), ("@public"), ("@required"), ("@selector"),
+    ("@synchronized"), ("@synthesize"), ("@throw"), ("@try"),
+
+    // Primitive types
+    ("bool"), ("char"), ("char16_t"), ("char32_t"), ("double"), ("float"), ("int"),
+    ("long"), ("short"), ("signed"), ("unsigned"), ("void"), ("wchar_t"),
+
+    // Qt keywords
+    ("emit"), ("SIGNAL"), ("SLOT"), ("Q_SIGNAL"), ("Q_SLOT"), ("signals"), ("slots"),
+    ("Q_FOREACH"), ("Q_D"), ("Q_Q"),
+    ("Q_INVOKABLE"), ("Q_PROPERTY"), ("T_Q_PRIVATE_PROPERTY"),
+    ("Q_INTERFACES"), ("Q_EMIT"), ("Q_ENUMS"), ("Q_FLAGS"),
+    ("Q_PRIVATE_SLOT"), ("Q_DECLARE_INTERFACE"), ("Q_OBJECT"), ("Q_GADGET"),
+
+};
+
+void Token::reset()
+{
+    flags = 0;
+    byteOffset = 0;
+    utf16charOffset = 0;
+    ptr = 0;
+}
+
+const char *Token::name(int kind)
+{ return token_names[kind]; }
+
+const char *Token::spell() const
+{
+    switch (f.kind) {
+    case T_IDENTIFIER:
+        return identifier->chars();
+
+    case T_NUMERIC_LITERAL:
+    case T_CHAR_LITERAL:
+    case T_WIDE_CHAR_LITERAL:
+    case T_UTF16_CHAR_LITERAL:
+    case T_UTF32_CHAR_LITERAL:
+    case T_STRING_LITERAL:
+    case T_WIDE_STRING_LITERAL:
+    case T_UTF8_STRING_LITERAL:
+    case T_UTF16_STRING_LITERAL:
+    case T_UTF32_STRING_LITERAL:
+    case T_RAW_STRING_LITERAL:
+    case T_RAW_WIDE_STRING_LITERAL:
+    case T_RAW_UTF8_STRING_LITERAL:
+    case T_RAW_UTF16_STRING_LITERAL:
+    case T_RAW_UTF32_STRING_LITERAL:
+    case T_AT_STRING_LITERAL:
+    case T_ANGLE_STRING_LITERAL:
+        return literal->chars();
+
+    default:
+        return token_names[f.kind];
+    } // switch
+}
+
+

+ 410 - 0
Source/ToolCore/JSBind/cplusplus/Token.h

@@ -0,0 +1,410 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_TOKEN_H
+#define CPLUSPLUS_TOKEN_H
+
+#include "CPlusPlusForwardDeclarations.h"
+
+namespace CPlusPlus {
+
+enum Kind {
+    T_EOF_SYMBOL = 0,
+    T_ERROR,
+
+    T_CPP_COMMENT,
+    T_CPP_DOXY_COMMENT,
+    T_COMMENT,
+    T_DOXY_COMMENT,
+    T_IDENTIFIER,
+
+    T_FIRST_LITERAL,
+    T_NUMERIC_LITERAL = T_FIRST_LITERAL,
+    T_FIRST_CHAR_LITERAL,
+    T_CHAR_LITERAL = T_FIRST_CHAR_LITERAL,
+    T_WIDE_CHAR_LITERAL,
+    T_UTF16_CHAR_LITERAL,
+    T_UTF32_CHAR_LITERAL,
+    T_LAST_CHAR_LITERAL = T_UTF32_CHAR_LITERAL,
+    T_FIRST_STRING_LITERAL,
+    T_STRING_LITERAL = T_FIRST_STRING_LITERAL,
+    T_WIDE_STRING_LITERAL,
+    T_UTF8_STRING_LITERAL,
+    T_UTF16_STRING_LITERAL,
+    T_UTF32_STRING_LITERAL,
+    T_RAW_STRING_LITERAL,
+    T_RAW_WIDE_STRING_LITERAL,
+    T_RAW_UTF8_STRING_LITERAL,
+    T_RAW_UTF16_STRING_LITERAL,
+    T_RAW_UTF32_STRING_LITERAL,
+    T_AT_STRING_LITERAL,
+    T_ANGLE_STRING_LITERAL,
+    T_LAST_STRING_LITERAL = T_ANGLE_STRING_LITERAL,
+    T_LAST_LITERAL = T_ANGLE_STRING_LITERAL,
+
+    T_FIRST_OPERATOR,
+    T_AMPER = T_FIRST_OPERATOR,
+    T_AMPER_AMPER,
+    T_AMPER_EQUAL,
+    T_ARROW,
+    T_ARROW_STAR,
+    T_CARET,
+    T_CARET_EQUAL,
+    T_COLON,
+    T_COLON_COLON,
+    T_COMMA,
+    T_SLASH,
+    T_SLASH_EQUAL,
+    T_DOT,
+    T_DOT_DOT_DOT,
+    T_DOT_STAR,
+    T_EQUAL,
+    T_EQUAL_EQUAL,
+    T_EXCLAIM,
+    T_EXCLAIM_EQUAL,
+    T_GREATER,
+    T_GREATER_EQUAL,
+    T_GREATER_GREATER,
+    T_GREATER_GREATER_EQUAL,
+    T_LBRACE,
+    T_LBRACKET,
+    T_LESS,
+    T_LESS_EQUAL,
+    T_LESS_LESS,
+    T_LESS_LESS_EQUAL,
+    T_LPAREN,
+    T_MINUS,
+    T_MINUS_EQUAL,
+    T_MINUS_MINUS,
+    T_PERCENT,
+    T_PERCENT_EQUAL,
+    T_PIPE,
+    T_PIPE_EQUAL,
+    T_PIPE_PIPE,
+    T_PLUS,
+    T_PLUS_EQUAL,
+    T_PLUS_PLUS,
+    T_POUND,
+    T_POUND_POUND,
+    T_QUESTION,
+    T_RBRACE,
+    T_RBRACKET,
+    T_RPAREN,
+    T_SEMICOLON,
+    T_STAR,
+    T_STAR_EQUAL,
+    T_TILDE,
+    T_TILDE_EQUAL,
+    T_LAST_OPERATOR = T_TILDE_EQUAL,
+
+    T_FIRST_KEYWORD,
+    T_ALIGNAS = T_FIRST_KEYWORD,
+    T_ALIGNOF,
+    T_ASM,
+    T_AUTO,
+    T_BREAK,
+    T_CASE,
+    T_CATCH,
+    T_CLASS,
+    T_CONST,
+    T_CONST_CAST,
+    T_CONSTEXPR,
+    T_CONTINUE,
+    T_DECLTYPE,
+    T_DEFAULT,
+    T_DELETE,
+    T_DO,
+    T_DYNAMIC_CAST,
+    T_ELSE,
+    T_ENUM,
+    T_EXPLICIT,
+    T_EXPORT,
+    T_EXTERN,
+    T_FALSE,
+    T_FOR,
+    T_FRIEND,
+    T_GOTO,
+    T_IF,
+    T_INLINE,
+    T_MUTABLE,
+    T_NAMESPACE,
+    T_NEW,
+    T_NOEXCEPT,
+    T_NULLPTR,
+    T_OPERATOR,
+    T_PRIVATE,
+    T_PROTECTED,
+    T_PUBLIC,
+    T_REGISTER,
+    T_REINTERPRET_CAST,
+    T_RETURN,
+    T_SIZEOF,
+    T_STATIC,
+    T_STATIC_ASSERT,
+    T_STATIC_CAST,
+    T_STRUCT,
+    T_SWITCH,
+    T_TEMPLATE,
+    T_THIS,
+    T_THREAD_LOCAL,
+    T_THROW,
+    T_TRUE,
+    T_TRY,
+    T_TYPEDEF,
+    T_TYPEID,
+    T_TYPENAME,
+    T_UNION,
+    T_USING,
+    T_VIRTUAL,
+    T_VOLATILE,
+    T_WHILE,
+
+    T___ATTRIBUTE__,
+    T___THREAD,
+    T___TYPEOF__,
+
+    // obj c++ @ keywords
+    T_FIRST_OBJC_AT_KEYWORD,
+
+    T_AT_CATCH = T_FIRST_OBJC_AT_KEYWORD,
+    T_AT_CLASS,
+    T_AT_COMPATIBILITY_ALIAS,
+    T_AT_DEFS,
+    T_AT_DYNAMIC,
+    T_AT_ENCODE,
+    T_AT_END,
+    T_AT_FINALLY,
+    T_AT_IMPLEMENTATION,
+    T_AT_INTERFACE,
+    T_AT_NOT_KEYWORD,
+    T_AT_OPTIONAL,
+    T_AT_PACKAGE,
+    T_AT_PRIVATE,
+    T_AT_PROPERTY,
+    T_AT_PROTECTED,
+    T_AT_PROTOCOL,
+    T_AT_PUBLIC,
+    T_AT_REQUIRED,
+    T_AT_SELECTOR,
+    T_AT_SYNCHRONIZED,
+    T_AT_SYNTHESIZE,
+    T_AT_THROW,
+    T_AT_TRY,
+
+    T_LAST_OBJC_AT_KEYWORD = T_AT_TRY,
+
+    // Primitive types
+    T_FIRST_PRIMITIVE,
+    T_BOOL = T_FIRST_PRIMITIVE,
+    T_CHAR,
+    T_CHAR16_T,
+    T_CHAR32_T,
+    T_DOUBLE,
+    T_FLOAT,
+    T_INT,
+    T_LONG,
+    T_SHORT,
+    T_SIGNED,
+    T_UNSIGNED,
+    T_VOID,
+    T_WCHAR_T,
+    T_LAST_PRIMITIVE = T_WCHAR_T,
+
+    // Qt keywords
+    T_FIRST_QT_KEYWORD,
+    T_EMIT = T_FIRST_QT_KEYWORD,
+    T_SIGNAL,
+    T_SLOT,
+    T_Q_SIGNAL,
+    T_Q_SLOT,
+    T_Q_SIGNALS,
+    T_Q_SLOTS,
+    T_Q_FOREACH,
+    T_Q_D,
+    T_Q_Q,
+    T_Q_INVOKABLE,
+    T_Q_PROPERTY,
+    T_Q_PRIVATE_PROPERTY,
+    T_Q_INTERFACES,
+    T_Q_EMIT,
+    T_Q_ENUMS,
+    T_Q_FLAGS,
+    T_Q_PRIVATE_SLOT,
+    T_Q_DECLARE_INTERFACE,
+    T_Q_OBJECT,
+    T_Q_GADGET,
+    T_LAST_QT_KEYWORD = T_Q_GADGET,
+    T_LAST_KEYWORD = T_LAST_QT_KEYWORD,
+
+    // aliases
+    T_OR = T_PIPE_PIPE,
+    T_AND = T_AMPER_AMPER,
+    T_NOT = T_EXCLAIM,
+    T_XOR = T_CARET,
+    T_BITOR = T_PIPE,
+    T_COMPL = T_TILDE,
+    T_OR_EQ = T_PIPE_EQUAL,
+    T_AND_EQ = T_AMPER_EQUAL,
+    T_BITAND = T_AMPER,
+    T_NOT_EQ = T_EXCLAIM_EQUAL,
+    T_XOR_EQ = T_CARET_EQUAL,
+
+    T___ASM = T_ASM,
+    T___ASM__ = T_ASM,
+
+    T_TYPEOF = T___TYPEOF__,
+    T___TYPEOF = T___TYPEOF__,
+
+    T___DECLTYPE = T_DECLTYPE,
+
+    T___INLINE = T_INLINE,
+    T___INLINE__ = T_INLINE,
+
+    T___CONST = T_CONST,
+    T___CONST__ = T_CONST,
+
+    T___VOLATILE = T_VOLATILE,
+    T___VOLATILE__ = T_VOLATILE,
+
+    T___ATTRIBUTE = T___ATTRIBUTE__
+};
+
+class CPLUSPLUS_EXPORT Token
+{
+public:
+    Token() : flags(0), byteOffset(0), utf16charOffset(0), ptr(0) {}
+
+    inline bool is(unsigned k) const    { return f.kind == k; }
+    inline bool isNot(unsigned k) const { return f.kind != k; }
+    const char *spell() const;
+    void reset();
+
+    inline Kind kind() const { return static_cast<Kind>(f.kind); }
+    inline bool newline() const { return f.newline; }
+    inline bool whitespace() const { return f.whitespace; }
+    inline bool joined() const { return f.joined; }
+    inline bool expanded() const { return f.expanded; }
+    inline bool generated() const { return f.generated; }
+
+    inline unsigned bytes() const { return f.bytes; }
+    inline unsigned bytesBegin() const { return byteOffset; }
+    inline unsigned bytesEnd() const { return byteOffset + f.bytes; }
+
+    inline unsigned utf16chars() const { return f.utf16chars; }
+    inline unsigned utf16charsBegin() const { return utf16charOffset; }
+    inline unsigned utf16charsEnd() const { return utf16charOffset + f.utf16chars; }
+
+    inline bool isLiteral() const
+    { return f.kind >= T_FIRST_LITERAL && f.kind <= T_LAST_LITERAL; }
+
+    inline bool isCharLiteral() const
+    { return f.kind >= T_FIRST_CHAR_LITERAL && f.kind <= T_LAST_CHAR_LITERAL; }
+
+    inline bool isStringLiteral() const
+    { return f.kind >= T_FIRST_STRING_LITERAL && f.kind <= T_LAST_STRING_LITERAL; }
+
+    inline bool isOperator() const
+    { return f.kind >= T_FIRST_OPERATOR && f.kind <= T_LAST_OPERATOR; }
+
+    inline bool isKeyword() const
+    { return f.kind >= T_FIRST_KEYWORD && f.kind < T_FIRST_PRIMITIVE; }
+
+    inline bool isPrimitiveType() const
+    { return f.kind >= T_FIRST_PRIMITIVE && f.kind <= T_LAST_PRIMITIVE; }
+
+    inline bool isQtKeyword() const
+    { return f.kind >= T_FIRST_QT_KEYWORD && f.kind <= T_LAST_QT_KEYWORD; }
+
+    inline bool isComment() const
+    { return f.kind == T_COMMENT || f.kind == T_DOXY_COMMENT ||
+      f.kind == T_CPP_COMMENT || f.kind == T_CPP_DOXY_COMMENT; }
+
+    inline bool isObjCAtKeyword() const
+    { return f.kind >= T_FIRST_OBJC_AT_KEYWORD && f.kind <= T_LAST_OBJC_AT_KEYWORD; }
+
+    static const char *name(int kind);
+
+public:
+    struct Flags {
+        // The token kind.
+        unsigned kind          : 8;
+        // The token starts a new line.
+        unsigned newline       : 1;
+        // The token is preceeded by whitespace(s).
+        unsigned whitespace    : 1;
+        // The token is joined with the previous one.
+        unsigned joined        : 1;
+        // The token originates from a macro expansion.
+        unsigned expanded      : 1;
+        // The token originates from a macro expansion and does not correspond to an
+        // argument that went through substitution. Notice the example:
+        //
+        // #define FOO(a, b) a + b;
+        // FOO(1, 2)
+        //
+        // After preprocessing we would expect the following tokens: 1 + 2;
+        // Tokens '1', '+', '2', and ';' are all expanded. However only tokens '+' and ';'
+        // are generated.
+        unsigned generated     : 1;
+        // Unused...
+        unsigned pad           : 3;
+        // The token length in bytes and UTF16 chars.
+        unsigned bytes         : 16;
+        unsigned utf16chars    : 16;
+    };
+    union {
+        unsigned long flags;
+        Flags f;
+    };
+
+    unsigned byteOffset;
+    unsigned utf16charOffset;
+
+    union {
+        void *ptr;
+        const Literal *literal;
+        const NumericLiteral *number;
+        const StringLiteral *string;
+        const Identifier *identifier;
+        unsigned close_brace;
+        unsigned lineno;
+    };
+};
+
+struct LanguageFeatures
+{
+    LanguageFeatures() : flags(0) {}
+
+    union {
+        unsigned int flags;
+        struct {
+            unsigned int qtEnabled : 1; // If Qt is used.
+            unsigned int qtMocRunEnabled : 1;
+            unsigned int qtKeywordsEnabled : 1; // If Qt is used but QT_NO_KEYWORDS defined
+            unsigned int cxx11Enabled : 1;
+            unsigned int objCEnabled : 1;
+            unsigned int c99Enabled : 1;
+        };
+    };
+};
+
+} // namespace CPlusPlus
+
+#endif // CPLUSPLUS_TOKEN_H

+ 585 - 0
Source/ToolCore/JSBind/cplusplus/TranslationUnit.cpp

@@ -0,0 +1,585 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "TranslationUnit.h"
+#include "Control.h"
+#include "Parser.h"
+#include "Lexer.h"
+#include "MemoryPool.h"
+#include "AST.h"
+#include "Literals.h"
+#include "DiagnosticClient.h"
+#include <stack>
+#include <vector>
+#include <cstdarg>
+#include <algorithm>
+#include <utility>
+
+#if defined(_MSC_VER) && (_MSC_VER < 1800)
+#    define va_copy(dst, src) ((dst) = (src))
+#elif defined(__INTEL_COMPILER) && !defined(va_copy)
+#    define va_copy __va_copy
+#endif
+
+using namespace CPlusPlus;
+
+const Token TranslationUnit::nullToken;
+
+TranslationUnit::TranslationUnit(Control *control, const StringLiteral *fileId)
+    : _control(control),
+      _fileId(fileId),
+      _firstSourceChar(0),
+      _lastSourceChar(0),
+      _pool(0),
+      _ast(0),
+      _flags(0)
+{
+    _tokens = new std::vector<Token>();
+    _comments = new std::vector<Token>();
+    _previousTranslationUnit = control->switchTranslationUnit(this);
+    _pool = new MemoryPool();
+}
+
+TranslationUnit::~TranslationUnit()
+{
+    (void) _control->switchTranslationUnit(_previousTranslationUnit);
+    release();
+}
+
+Control *TranslationUnit::control() const
+{ return _control; }
+
+const StringLiteral *TranslationUnit::fileId() const
+{ return _fileId; }
+
+const char *TranslationUnit::fileName() const
+{ return _fileId->chars(); }
+
+unsigned TranslationUnit::fileNameLength() const
+{ return _fileId->size(); }
+
+const char *TranslationUnit::firstSourceChar() const
+{ return _firstSourceChar; }
+
+const char *TranslationUnit::lastSourceChar() const
+{ return _lastSourceChar; }
+
+unsigned TranslationUnit::sourceLength() const
+{ return _lastSourceChar - _firstSourceChar; }
+
+void TranslationUnit::setSource(const char *source, unsigned size)
+{
+    _firstSourceChar = source;
+    _lastSourceChar = source + size;
+}
+
+const char *TranslationUnit::spell(unsigned index) const
+{
+    if (! index)
+        return 0;
+
+    return tokenAt(index).spell();
+}
+
+unsigned TranslationUnit::commentCount() const
+{ return unsigned(_comments->size()); }
+
+const Token &TranslationUnit::commentAt(unsigned index) const
+{ return _comments->at(index); }
+
+const Identifier *TranslationUnit::identifier(unsigned index) const
+{ return tokenAt(index).identifier; }
+
+const Literal *TranslationUnit::literal(unsigned index) const
+{ return tokenAt(index).literal; }
+
+const StringLiteral *TranslationUnit::stringLiteral(unsigned index) const
+{ return tokenAt(index).string; }
+
+const NumericLiteral *TranslationUnit::numericLiteral(unsigned index) const
+{ return tokenAt(index).number; }
+
+unsigned TranslationUnit::matchingBrace(unsigned index) const
+{ return tokenAt(index).close_brace; }
+
+MemoryPool *TranslationUnit::memoryPool() const
+{ return _pool; }
+
+AST *TranslationUnit::ast() const
+{ return _ast; }
+
+bool TranslationUnit::isTokenized() const
+{ return f._tokenized; }
+
+bool TranslationUnit::isParsed() const
+{ return f._parsed; }
+
+void TranslationUnit::tokenize()
+{
+    if (isTokenized())
+        return;
+
+    f._tokenized = true;
+
+    Lexer lex(this);
+    lex.setLanguageFeatures(_languageFeatures);
+    lex.setScanCommentTokens(true);
+
+    std::stack<unsigned> braces;
+    _tokens->push_back(nullToken); // the first token needs to be invalid!
+
+    pushLineOffset(0);
+    pushPreprocessorLine(0, 1, fileId());
+
+    const Identifier *lineId   = control()->identifier("line");
+    const Identifier *expansionId = control()->identifier("expansion");
+    const Identifier *beginId = control()->identifier("begin");
+    const Identifier *endId = control()->identifier("end");
+
+    // We need to track information about the expanded tokens. A vector with an addition
+    // explicit index control is used instead of queue mainly for performance reasons.
+    std::vector<std::pair<unsigned, unsigned> > lineColumn;
+    unsigned lineColumnIdx = 0;
+
+    Token tk;
+    do {
+        lex(&tk);
+
+recognize:
+        if (tk.is(T_POUND) && tk.newline()) {
+            const unsigned utf16CharOffset = tk.utf16charOffset;
+            lex(&tk);
+
+            if (! tk.newline() && tk.is(T_IDENTIFIER) && tk.identifier == expansionId) {
+                // It's an expansion mark.
+                lex(&tk);
+
+                if (!tk.newline() && tk.is(T_IDENTIFIER)) {
+                    if (tk.identifier == beginId) {
+                        // Start of a macro expansion section.
+                        lex(&tk);
+
+                        // Gather where the expansion happens and its length.
+                        //unsigned macroOffset = static_cast<unsigned>(strtoul(tk.spell(), 0, 0));
+                        lex(&tk);
+                        lex(&tk); // Skip the separating comma
+                        //unsigned macroLength = static_cast<unsigned>(strtoul(tk.spell(), 0, 0));
+                        lex(&tk);
+
+                        // NOTE: We are currently not using the macro offset and length. They
+                        // are kept here for now because of future use.
+                        //Q_UNUSED(macroOffset)
+                        //Q_UNUSED(macroLength)
+
+                        // Now we need to gather the real line and columns from the upcoming
+                        // tokens. But notice this is only relevant for tokens which are expanded
+                        // but not generated.
+                        while (tk.isNot(T_EOF_SYMBOL) && !tk.newline()) {
+                            // When we get a ~ it means there's a number of generated tokens
+                            // following. Otherwise, we have actual data.
+                            if (tk.is(T_TILDE)) {
+                                lex(&tk);
+
+                                // Get the total number of generated tokens and specify "null"
+                                // information for them.
+                                unsigned totalGenerated =
+                                        static_cast<unsigned>(strtoul(tk.spell(), 0, 0));
+                                const std::size_t previousSize = lineColumn.size();
+                                lineColumn.resize(previousSize + totalGenerated);
+                                std::fill(lineColumn.begin() + previousSize,
+                                          lineColumn.end(),
+                                          std::make_pair(0, 0));
+
+                                lex(&tk);
+                            } else if (tk.is(T_NUMERIC_LITERAL)) {
+                                unsigned line = static_cast<unsigned>(strtoul(tk.spell(), 0, 0));
+                                lex(&tk);
+                                lex(&tk); // Skip the separating colon
+                                unsigned column = static_cast<unsigned>(strtoul(tk.spell(), 0, 0));
+
+                                // Store line and column for this non-generated token.
+                                lineColumn.push_back(std::make_pair(line, column));
+
+                                lex(&tk);
+                            }
+                        }
+                    } else if (tk.identifier == endId) {
+                        // End of a macro expansion.
+                        lineColumn.clear();
+                        lineColumnIdx = 0;
+
+                        lex(&tk);
+                    }
+                }
+            } else {
+                if (! tk.newline() && tk.is(T_IDENTIFIER) && tk.identifier == lineId)
+                    lex(&tk);
+                if (! tk.newline() && tk.is(T_NUMERIC_LITERAL)) {
+                    unsigned line = (unsigned) strtoul(tk.spell(), 0, 0);
+                    lex(&tk);
+                    if (! tk.newline() && tk.is(T_STRING_LITERAL)) {
+                        const StringLiteral *fileName =
+                                control()->stringLiteral(tk.string->chars(), tk.string->size());
+                        pushPreprocessorLine(utf16CharOffset, line, fileName);
+                        lex(&tk);
+                    }
+                }
+                while (tk.isNot(T_EOF_SYMBOL) && ! tk.newline())
+                    lex(&tk);
+            }
+            goto recognize;
+        } else if (tk.kind() == T_LBRACE) {
+            braces.push(unsigned(_tokens->size()));
+        } else if (tk.kind() == T_RBRACE && ! braces.empty()) {
+            const unsigned open_brace_index = braces.top();
+            braces.pop();
+            if (open_brace_index < tokenCount())
+                (*_tokens)[open_brace_index].close_brace = unsigned(_tokens->size());
+        } else if (tk.isComment()) {
+            _comments->push_back(tk);
+            continue; // comments are not in the regular token stream
+        }
+
+        bool currentExpanded = false;
+        bool currentGenerated = false;
+
+        if (!lineColumn.empty() && lineColumnIdx < lineColumn.size()) {
+            currentExpanded = true;
+            const std::pair<unsigned, unsigned> &p = lineColumn[lineColumnIdx];
+            if (p.first)
+                _expandedLineColumn.insert(std::make_pair(tk.utf16charsBegin(), p));
+            else
+                currentGenerated = true;
+
+            ++lineColumnIdx;
+        }
+
+        tk.f.expanded = currentExpanded;
+        tk.f.generated = currentGenerated;
+
+        _tokens->push_back(tk);
+    } while (tk.kind());
+
+    for (; ! braces.empty(); braces.pop()) {
+        unsigned open_brace_index = braces.top();
+        (*_tokens)[open_brace_index].close_brace = unsigned(_tokens->size());
+    }
+}
+
+bool TranslationUnit::skipFunctionBody() const
+{ return f._skipFunctionBody; }
+
+void TranslationUnit::setSkipFunctionBody(bool skipFunctionBody)
+{ f._skipFunctionBody = skipFunctionBody; }
+
+bool TranslationUnit::parse(ParseMode mode)
+{
+    if (isParsed())
+        return false;
+
+    if (! isTokenized())
+        tokenize();
+
+    f._parsed = true;
+
+    Parser parser(this);
+    bool parsed = false;
+
+    switch (mode) {
+    case ParseTranlationUnit: {
+        TranslationUnitAST *node = 0;
+        parsed = parser.parseTranslationUnit(node);
+        _ast = node;
+    } break;
+
+    case ParseDeclaration: {
+        DeclarationAST *node = 0;
+        parsed = parser.parseDeclaration(node);
+        _ast = node;
+    } break;
+
+    case ParseExpression: {
+        ExpressionAST *node = 0;
+        parsed = parser.parseExpression(node);
+        _ast = node;
+    } break;
+
+    case ParseDeclarator: {
+        DeclaratorAST *node = 0;
+        parsed = parser.parseDeclarator(node, /*decl_specifier_list =*/ 0);
+        _ast = node;
+    } break;
+
+    case ParseStatement: {
+        StatementAST *node = 0;
+        parsed = parser.parseStatement(node);
+        _ast = node;
+    } break;
+
+    default:
+        break;
+    } // switch
+
+    return parsed;
+}
+
+void TranslationUnit::pushLineOffset(unsigned offset)
+{ _lineOffsets.push_back(offset); }
+
+void TranslationUnit::pushPreprocessorLine(unsigned utf16charOffset,
+                                           unsigned line,
+                                           const StringLiteral *fileName)
+{ _ppLines.push_back(PPLine(utf16charOffset, line, fileName)); }
+
+unsigned TranslationUnit::findLineNumber(unsigned utf16charOffset) const
+{
+    std::vector<unsigned>::const_iterator it =
+        std::lower_bound(_lineOffsets.begin(), _lineOffsets.end(), utf16charOffset);
+
+    if (it != _lineOffsets.begin())
+        --it;
+
+    return it - _lineOffsets.begin();
+}
+
+TranslationUnit::PPLine TranslationUnit::findPreprocessorLine(unsigned utf16charOffset) const
+{
+    std::vector<PPLine>::const_iterator it =
+        std::lower_bound(_ppLines.begin(), _ppLines.end(), PPLine(utf16charOffset));
+
+    if (it != _ppLines.begin())
+        --it;
+
+    return *it;
+}
+
+unsigned TranslationUnit::findColumnNumber(unsigned utf16CharOffset, unsigned lineNumber) const
+{
+    if (! utf16CharOffset)
+        return 0;
+
+    return utf16CharOffset - _lineOffsets[lineNumber];
+}
+
+void TranslationUnit::getTokenPosition(unsigned index,
+                                       unsigned *line,
+                                       unsigned *column,
+                                       const StringLiteral **fileName) const
+{ return getPosition(tokenAt(index).utf16charsBegin(), line, column, fileName); }
+
+void TranslationUnit::getTokenStartPosition(unsigned index, unsigned *line,
+                                            unsigned *column,
+                                            const StringLiteral **fileName) const
+{ return getPosition(tokenAt(index).utf16charsBegin(), line, column, fileName); }
+
+void TranslationUnit::getTokenEndPosition(unsigned index, unsigned *line,
+                                          unsigned *column,
+                                          const StringLiteral **fileName) const
+{ return getPosition(tokenAt(index).utf16charsEnd(), line, column, fileName); }
+
+void TranslationUnit::getPosition(unsigned utf16charOffset,
+                                  unsigned *line,
+                                  unsigned *column,
+                                  const StringLiteral **fileName) const
+{
+    unsigned lineNumber = 0;
+    unsigned columnNumber = 0;
+    const StringLiteral *file = 0;
+
+    // If this token is expanded we already have the information directly from the expansion
+    // section header. Otherwise, we need to calculate it.
+    TokenLineColumn::const_iterator it = _expandedLineColumn.find(utf16charOffset);
+    if (it != _expandedLineColumn.end()) {
+        lineNumber = it->second.first;
+        columnNumber = it->second.second + 1;
+        file = _fileId;
+    } else {
+        // Identify line within the entire translation unit.
+        lineNumber = findLineNumber(utf16charOffset);
+
+        // Identify column.
+        columnNumber = findColumnNumber(utf16charOffset, lineNumber);
+
+        // Adjust the line in regards to the preprocessing markers.
+        const PPLine ppLine = findPreprocessorLine(utf16charOffset);
+        lineNumber -= findLineNumber(ppLine.utf16charOffset) + 1;
+        lineNumber += ppLine.line;
+
+        file = ppLine.fileName;
+    }
+
+    if (line)
+        *line = lineNumber;
+
+    if (column)
+        *column = columnNumber;
+
+    if (fileName)
+       *fileName = file;
+}
+
+void TranslationUnit::message(DiagnosticClient::Level level, unsigned index, const char *format, va_list args)
+{
+    if (f._blockErrors)
+        return;
+
+    index = std::min(index, tokenCount() - 1);
+
+    unsigned line = 0, column = 0;
+    const StringLiteral *fileName = 0;
+    getTokenPosition(index, &line, &column, &fileName);
+
+    if (DiagnosticClient *client = control()->diagnosticClient()) {
+        client->report(level, fileName, line, column, format, args);
+    } else {
+        fprintf(stderr, "%s:%u: ", fileName->chars(), line);
+        const char *l = "error";
+        if (level == DiagnosticClient::Warning)
+            l = "warning";
+        else if (level == DiagnosticClient::Fatal)
+            l = "fatal";
+        fprintf(stderr, "%s: ", l);
+
+        vfprintf(stderr, format, args);
+        fputc('\n', stderr);
+
+        showErrorLine(index, column, stderr);
+    }
+
+    if (level == DiagnosticClient::Fatal)
+        exit(EXIT_FAILURE);
+}
+
+void TranslationUnit::warning(unsigned index, const char *format, ...)
+{
+    if (f._blockErrors)
+        return;
+
+    va_list args, ap;
+    va_start(args, format);
+    va_copy(ap, args);
+    message(DiagnosticClient::Warning, index, format, args);
+    va_end(ap);
+    va_end(args);
+}
+
+void TranslationUnit::error(unsigned index, const char *format, ...)
+{
+    if (f._blockErrors)
+        return;
+
+    va_list args, ap;
+    va_start(args, format);
+    va_copy(ap, args);
+    message(DiagnosticClient::Error, index, format, args);
+    va_end(ap);
+    va_end(args);
+}
+
+void TranslationUnit::fatal(unsigned index, const char *format, ...)
+{
+    if (f._blockErrors)
+        return;
+
+    va_list args, ap;
+    va_start(args, format);
+    va_copy(ap, args);
+    message(DiagnosticClient::Fatal, index, format, args);
+    va_end(ap);
+    va_end(args);
+}
+
+unsigned TranslationUnit::findPreviousLineOffset(unsigned tokenIndex) const
+{
+    unsigned lineOffset = _lineOffsets[findLineNumber(tokenAt(tokenIndex).utf16charsBegin())];
+    return lineOffset;
+}
+
+bool TranslationUnit::maybeSplitGreaterGreaterToken(unsigned tokenIndex)
+{
+    if (tokenIndex >= tokenCount())
+        return false;
+    Token &tok = (*_tokens)[tokenIndex];
+    if (tok.kind() != T_GREATER_GREATER)
+        return false;
+
+    tok.f.kind = T_GREATER;
+    tok.f.bytes = 1;
+    tok.f.utf16chars = 1;
+
+    Token newGreater;
+    newGreater.f.kind = T_GREATER;
+    newGreater.f.expanded = tok.expanded();
+    newGreater.f.generated = tok.generated();
+    newGreater.f.bytes = 1;
+    newGreater.f.utf16chars = 1;
+    newGreater.byteOffset = tok.byteOffset + 1;
+    newGreater.utf16charOffset = tok.utf16charOffset + 1;
+
+    _tokens->insert(_tokens->begin() + tokenIndex + 1, newGreater);
+
+    TokenLineColumn::const_iterator it = _expandedLineColumn.find(tok.bytesBegin());
+    if (it != _expandedLineColumn.end()) {
+        const std::pair<unsigned, unsigned> newPosition(it->second.first, it->second.second + 1);
+        _expandedLineColumn.insert(std::make_pair(newGreater.bytesBegin(), newPosition));
+    }
+
+    return true;
+}
+
+void TranslationUnit::releaseTokensAndComments()
+{
+    delete _tokens;
+    _tokens = 0;
+    delete _comments;
+    _comments = 0;
+}
+
+void TranslationUnit::showErrorLine(unsigned index, unsigned column, FILE *out)
+{
+    unsigned lineOffset = _lineOffsets[findLineNumber(tokenAt(index).utf16charsBegin())];
+    for (const char *cp = _firstSourceChar + lineOffset + 1; *cp && *cp != '\n'; ++cp) {
+        fputc(*cp, out);
+    }
+    fputc('\n', out);
+
+    const char *end = _firstSourceChar + lineOffset + 1 + column - 1;
+    for (const char *cp = _firstSourceChar + lineOffset + 1; cp != end; ++cp) {
+        if (*cp != '\t')
+            fputc(' ', out);
+        else
+            fputc('\t', out);
+    }
+    fputc('^', out);
+    fputc('\n', out);
+}
+
+void TranslationUnit::resetAST()
+{
+    delete _pool;
+    _pool = 0;
+    _ast = 0;
+}
+
+void TranslationUnit::release()
+{
+    resetAST();
+    releaseTokensAndComments();
+}

+ 218 - 0
Source/ToolCore/JSBind/cplusplus/TranslationUnit.h

@@ -0,0 +1,218 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_TRANSLATIONUNIT_H
+#define CPLUSPLUS_TRANSLATIONUNIT_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include "ASTfwd.h"
+#include "Token.h"
+#include "DiagnosticClient.h"
+#include <cstdio>
+#include <vector>
+
+#if !(__cplusplus > 199711L || __GXX_EXPERIMENTAL_CXX0X__ || _MSC_VER >= 1600 || defined( _LIBCPP_VERSION )) \
+    || (defined(__GNUC_LIBSTD__) && ((__GNUC_LIBSTD__-0) * 100 + __GNUC_LIBSTD_MINOR__-0 <= 402))
+#define USE_TR1
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER < 1600
+#  include <map>
+#elif defined(USE_TR1)
+#  include <tr1/unordered_map>
+#else
+#  include <unordered_map>
+#endif
+
+namespace CPlusPlus {
+
+class CPLUSPLUS_EXPORT TranslationUnit
+{
+    TranslationUnit(const TranslationUnit &other);
+    void operator =(const TranslationUnit &other);
+
+public:
+    TranslationUnit(Control *control, const StringLiteral *fileId);
+    ~TranslationUnit();
+
+    Control *control() const;
+
+    const StringLiteral *fileId() const;
+    const char *fileName() const;
+    unsigned fileNameLength() const;
+
+    const char *firstSourceChar() const;
+    const char *lastSourceChar() const;
+    unsigned sourceLength() const;
+
+    void setSource(const char *source, unsigned size);
+
+    unsigned tokenCount() const { return _tokens ? unsigned(_tokens->size()) : unsigned(0); }
+    const Token &tokenAt(unsigned index) const
+    { return _tokens && index < tokenCount() ? (*_tokens)[index] : nullToken; }
+
+    Kind tokenKind(unsigned index) const { return tokenAt(index).kind(); }
+    const char *spell(unsigned index) const;
+
+    unsigned commentCount() const;
+    const Token &commentAt(unsigned index) const;
+
+    unsigned matchingBrace(unsigned index) const;
+    const Identifier *identifier(unsigned index) const;
+    const Literal *literal(unsigned index) const;
+    const StringLiteral *stringLiteral(unsigned index) const;
+    const NumericLiteral *numericLiteral(unsigned index) const;
+
+    MemoryPool *memoryPool() const;
+    AST *ast() const;
+
+    bool blockErrors() const { return f._blockErrors; }
+    bool blockErrors(bool block)
+    {
+        const bool previous = f._blockErrors;
+        f._blockErrors = block;
+        return previous;
+    }
+
+    void warning(unsigned index, const char *fmt, ...);
+    void error(unsigned index, const char *fmt, ...);
+    void fatal(unsigned index, const char *fmt, ...);
+
+    void message(DiagnosticClient::Level level, unsigned index,
+                 const char *format, va_list ap);
+
+    bool isTokenized() const;
+    void tokenize();
+
+    bool skipFunctionBody() const;
+    void setSkipFunctionBody(bool skipFunctionBody);
+
+    bool isParsed() const;
+
+    enum ParseMode {
+        ParseTranlationUnit,
+        ParseDeclaration,
+        ParseExpression,
+        ParseDeclarator,
+        ParseStatement
+    };
+
+    bool parse(ParseMode mode = ParseTranlationUnit);
+
+    void resetAST();
+    void release();
+
+    void getTokenStartPosition(unsigned index, unsigned *line,
+                               unsigned *column = 0,
+                               const StringLiteral **fileName = 0) const;
+
+    void getTokenEndPosition(unsigned index, unsigned *line,
+                             unsigned *column = 0,
+                             const StringLiteral **fileName = 0) const;
+
+    void getPosition(unsigned utf16charOffset,
+                     unsigned *line,
+                     unsigned *column = 0,
+                     const StringLiteral **fileName = 0) const;
+
+    void getTokenPosition(unsigned index,
+                          unsigned *line,
+                          unsigned *column = 0,
+                          const StringLiteral **fileName = 0) const;
+
+    void pushLineOffset(unsigned offset);
+    void pushPreprocessorLine(unsigned utf16charOffset,
+                              unsigned line,
+                              const StringLiteral *fileName);
+
+    unsigned findPreviousLineOffset(unsigned tokenIndex) const;
+
+    bool maybeSplitGreaterGreaterToken(unsigned tokenIndex);
+
+    LanguageFeatures languageFeatures() const { return _languageFeatures; }
+    void setLanguageFeatures(LanguageFeatures features) { _languageFeatures = features; }
+
+private:
+    struct PPLine {
+        unsigned utf16charOffset;
+        unsigned line;
+        const StringLiteral *fileName;
+
+        PPLine(unsigned utf16charOffset = 0,
+               unsigned line = 0,
+               const StringLiteral *fileName = 0)
+            : utf16charOffset(utf16charOffset), line(line), fileName(fileName)
+        { }
+
+        bool operator == (const PPLine &other) const
+        { return utf16charOffset == other.utf16charOffset; }
+
+        bool operator != (const PPLine &other) const
+        { return utf16charOffset != other.utf16charOffset; }
+
+        bool operator < (const PPLine &other) const
+        { return utf16charOffset < other.utf16charOffset; }
+    };
+
+    void releaseTokensAndComments();
+    unsigned findLineNumber(unsigned utf16charOffset) const;
+    unsigned findColumnNumber(unsigned utf16CharOffset, unsigned lineNumber) const;
+    PPLine findPreprocessorLine(unsigned utf16charOffset) const;
+    void showErrorLine(unsigned index, unsigned column, FILE *out);
+
+    static const Token nullToken;
+
+    Control *_control;
+    const StringLiteral *_fileId;
+    const char *_firstSourceChar;
+    const char *_lastSourceChar;
+    std::vector<Token> *_tokens;
+    std::vector<Token> *_comments;
+    std::vector<unsigned> _lineOffsets;
+    std::vector<PPLine> _ppLines;
+#if defined(_MSC_VER) && _MSC_VER < 1600
+    // MSVC2008 and earlier do not implement TR1.
+    typedef std::map<unsigned, std::pair<unsigned, unsigned> > TokenLineColumn;
+#elif defined(USE_TR1)
+    typedef std::tr1::unordered_map<unsigned, std::pair<unsigned, unsigned> > TokenLineColumn;
+#else
+    typedef std::unordered_map<unsigned, std::pair<unsigned, unsigned> > TokenLineColumn;
+#endif
+    TokenLineColumn _expandedLineColumn;
+    MemoryPool *_pool;
+    AST *_ast;
+    TranslationUnit *_previousTranslationUnit;
+    struct Flags {
+        unsigned _tokenized: 1;
+        unsigned _parsed: 1;
+        unsigned _blockErrors: 1;
+        unsigned _skipFunctionBody: 1;
+    };
+    union {
+        unsigned _flags;
+        Flags f;
+    };
+    LanguageFeatures _languageFeatures;
+};
+
+} // namespace CPlusPlus
+
+
+#endif // CPLUSPLUS_TRANSLATIONUNIT_H

+ 113 - 0
Source/ToolCore/JSBind/cplusplus/Type.cpp

@@ -0,0 +1,113 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "Matcher.h"
+#include "Type.h"
+#include "TypeVisitor.h"
+#include "CoreTypes.h"
+#include "Symbols.h"
+
+using namespace CPlusPlus;
+
+Type::Type()
+{ }
+
+Type::~Type()
+{ }
+
+bool Type::isUndefinedType() const
+{ return this == UndefinedType::instance(); }
+
+bool Type::isVoidType() const
+{ return asVoidType() != 0; }
+
+bool Type::isIntegerType() const
+{ return asIntegerType() != 0; }
+
+bool Type::isFloatType() const
+{ return asFloatType() != 0; }
+
+bool Type::isPointerType() const
+{ return asPointerType()  != 0; }
+
+bool Type::isPointerToMemberType() const
+{ return asPointerToMemberType() != 0; }
+
+bool Type::isReferenceType() const
+{ return asReferenceType() != 0; }
+
+bool Type::isArrayType() const
+{ return asArrayType() != 0; }
+
+bool Type::isNamedType() const
+{ return asNamedType() != 0; }
+
+bool Type::isFunctionType() const
+{ return asFunctionType() != 0; }
+
+bool Type::isNamespaceType() const
+{ return asNamespaceType() != 0; }
+
+bool Type::isTemplateType() const
+{ return asTemplateType() != 0; }
+
+bool Type::isClassType() const
+{ return asClassType() != 0; }
+
+bool Type::isEnumType() const
+{ return asEnumType() != 0; }
+
+bool Type::isForwardClassDeclarationType() const
+{ return asForwardClassDeclarationType() != 0; }
+
+bool Type::isObjCClassType() const
+{ return asObjCClassType() != 0; }
+
+bool Type::isObjCProtocolType() const
+{ return asObjCProtocolType() != 0; }
+
+bool Type::isObjCMethodType() const
+{ return asObjCMethodType() != 0; }
+
+bool Type::isObjCForwardClassDeclarationType() const
+{ return asObjCForwardClassDeclarationType() != 0; }
+
+bool Type::isObjCForwardProtocolDeclarationType() const
+{ return asObjCForwardProtocolDeclarationType() != 0; }
+
+void Type::accept(TypeVisitor *visitor)
+{
+    if (visitor->preVisit(this))
+        accept0(visitor);
+    visitor->postVisit(this);
+}
+
+void Type::accept(Type *type, TypeVisitor *visitor)
+{
+    if (! type)
+        return;
+
+    type->accept(visitor);
+}
+
+bool Type::match(const Type *other, Matcher *matcher) const
+{
+    return Matcher::match(this, other, matcher);
+}

+ 112 - 0
Source/ToolCore/JSBind/cplusplus/Type.h

@@ -0,0 +1,112 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_TYPE_H
+#define CPLUSPLUS_TYPE_H
+
+#include "CPlusPlusForwardDeclarations.h"
+
+namespace CPlusPlus {
+
+class CPLUSPLUS_EXPORT Type
+{
+public:
+    Type();
+    virtual ~Type();
+
+    bool isUndefinedType() const;
+    bool isVoidType() const;
+    bool isIntegerType() const;
+    bool isFloatType() const;
+    bool isPointerType() const;
+    bool isPointerToMemberType() const;
+    bool isReferenceType() const;
+    bool isArrayType() const;
+    bool isNamedType() const;
+    bool isFunctionType() const;
+    bool isNamespaceType() const;
+    bool isTemplateType() const;
+    bool isClassType() const;
+    bool isEnumType() const;
+    bool isForwardClassDeclarationType() const;
+    bool isObjCClassType() const;
+    bool isObjCProtocolType() const;
+    bool isObjCMethodType() const;
+    bool isObjCForwardClassDeclarationType() const;
+    bool isObjCForwardProtocolDeclarationType() const;
+
+    virtual const UndefinedType *asUndefinedType() const { return 0; }
+    virtual const VoidType *asVoidType() const { return 0; }
+    virtual const IntegerType *asIntegerType() const { return 0; }
+    virtual const FloatType *asFloatType() const { return 0; }
+    virtual const PointerType *asPointerType() const { return 0; }
+    virtual const PointerToMemberType *asPointerToMemberType() const { return 0; }
+    virtual const ReferenceType *asReferenceType() const { return 0; }
+    virtual const ArrayType *asArrayType() const { return 0; }
+    virtual const NamedType *asNamedType() const { return 0; }
+    virtual const Function *asFunctionType() const { return 0; }
+    virtual const Namespace *asNamespaceType() const { return 0; }
+    virtual const Template *asTemplateType() const { return 0; }
+    virtual const Class *asClassType() const { return 0; }
+    virtual const Enum *asEnumType() const { return 0; }
+    virtual const ForwardClassDeclaration *asForwardClassDeclarationType() const { return 0; }
+    virtual const ObjCClass *asObjCClassType() const { return 0; }
+    virtual const ObjCProtocol *asObjCProtocolType() const { return 0; }
+    virtual const ObjCMethod *asObjCMethodType() const { return 0; }
+    virtual const ObjCForwardClassDeclaration *asObjCForwardClassDeclarationType() const { return 0; }
+    virtual const ObjCForwardProtocolDeclaration *asObjCForwardProtocolDeclarationType() const { return 0; }
+
+    virtual UndefinedType *asUndefinedType() { return 0; }
+    virtual VoidType *asVoidType() { return 0; }
+    virtual IntegerType *asIntegerType() { return 0; }
+    virtual FloatType *asFloatType() { return 0; }
+    virtual PointerType *asPointerType() { return 0; }
+    virtual PointerToMemberType *asPointerToMemberType() { return 0; }
+    virtual ReferenceType *asReferenceType() { return 0; }
+    virtual ArrayType *asArrayType() { return 0; }
+    virtual NamedType *asNamedType() { return 0; }
+    virtual Function *asFunctionType() { return 0; }
+    virtual Namespace *asNamespaceType() { return 0; }
+    virtual Template *asTemplateType() { return 0; }
+    virtual Class *asClassType() { return 0; }
+    virtual Enum *asEnumType() { return 0; }
+    virtual ForwardClassDeclaration *asForwardClassDeclarationType() { return 0; }
+    virtual ObjCClass *asObjCClassType() { return 0; }
+    virtual ObjCProtocol *asObjCProtocolType() { return 0; }
+    virtual ObjCMethod *asObjCMethodType() { return 0; }
+    virtual ObjCForwardClassDeclaration *asObjCForwardClassDeclarationType() { return 0; }
+    virtual ObjCForwardProtocolDeclaration *asObjCForwardProtocolDeclarationType() { return 0; }
+
+    void accept(TypeVisitor *visitor);
+    static void accept(Type *type, TypeVisitor *visitor);
+
+    bool match(const Type *other, Matcher *matcher = 0) const;
+
+protected:
+    virtual void accept0(TypeVisitor *visitor) = 0;
+
+protected: // for Matcher
+    friend class Matcher;
+    virtual bool match0(const Type *otherType, Matcher *matcher) const = 0;
+};
+
+} // namespace CPlusPlus
+
+#endif // CPLUSPLUS_TYPE_H

+ 35 - 0
Source/ToolCore/JSBind/cplusplus/TypeVisitor.cpp

@@ -0,0 +1,35 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "TypeVisitor.h"
+#include "Type.h"
+
+using namespace CPlusPlus;
+
+TypeVisitor::TypeVisitor()
+{ }
+
+TypeVisitor::~TypeVisitor()
+{ }
+
+void TypeVisitor::accept(Type *type)
+{ Type::accept(type, this); }
+
+

+ 67 - 0
Source/ToolCore/JSBind/cplusplus/TypeVisitor.h

@@ -0,0 +1,67 @@
+// Copyright (c) 2008 Roberto Raggi <[email protected]>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_TYPEVISITOR_H
+#define CPLUSPLUS_TYPEVISITOR_H
+
+#include "CPlusPlusForwardDeclarations.h"
+
+namespace CPlusPlus {
+
+class CPLUSPLUS_EXPORT TypeVisitor
+{
+    TypeVisitor(const TypeVisitor &other);
+    void operator =(const TypeVisitor &other);
+
+public:
+    TypeVisitor();
+    virtual ~TypeVisitor();
+
+    void accept(Type *type);
+
+    virtual bool preVisit(Type *) { return true; }
+    virtual void postVisit(Type *) {}
+
+    virtual void visit(UndefinedType *) {}
+    virtual void visit(VoidType *) {}
+    virtual void visit(IntegerType *) {}
+    virtual void visit(FloatType *) {}
+    virtual void visit(PointerToMemberType *) {}
+    virtual void visit(PointerType *) {}
+    virtual void visit(ReferenceType *) {}
+    virtual void visit(ArrayType *) {}
+    virtual void visit(NamedType *) {}
+    virtual void visit(Function *) {}
+    virtual void visit(Namespace *) {}
+    virtual void visit(Template *) {}
+    virtual void visit(Class *) {}
+    virtual void visit(Enum *) {}
+    virtual void visit(ForwardClassDeclaration *) {}
+    virtual void visit(ObjCClass *) {}
+    virtual void visit(ObjCProtocol *) {}
+    virtual void visit(ObjCMethod *) {}
+    virtual void visit(ObjCForwardClassDeclaration *) {}
+    virtual void visit(ObjCForwardProtocolDeclaration*) {}
+};
+
+} // namespace CPlusPlus
+
+
+#endif // CPLUSPLUS_TYPEVISITOR_H

+ 71 - 0
Source/ToolCore/JSBind/cplusplus/cplusplus.pri

@@ -0,0 +1,71 @@
+HEADERS += \
+    $$PWD/cppassert.h \
+    $$PWD/CPlusPlus.h \
+    $$PWD/AST.h \
+    $$PWD/ASTVisitor.h \
+    $$PWD/ASTMatcher.h \
+    $$PWD/ASTPatternBuilder.h \
+    $$PWD/ASTfwd.h \
+    $$PWD/Matcher.h \
+    $$PWD/CPlusPlusForwardDeclarations.h \
+    $$PWD/Control.h \
+    $$PWD/CoreTypes.h \
+    $$PWD/DiagnosticClient.h \
+    $$PWD/FullySpecifiedType.h \
+    $$PWD/Lexer.h \
+    $$PWD/LiteralTable.h \
+    $$PWD/Literals.h \
+    $$PWD/MemoryPool.h \
+    $$PWD/Name.h \
+    $$PWD/NameVisitor.h \
+    $$PWD/Names.h \
+    $$PWD/Parser.h \
+    $$PWD/Scope.h \
+    $$PWD/Bind.h \
+    $$PWD/Symbol.h \
+    $$PWD/Symbols.h \
+    $$PWD/SymbolVisitor.h \
+    $$PWD/Token.h \
+    $$PWD/TranslationUnit.h \
+    $$PWD/Type.h \
+    $$PWD/TypeVisitor.h \
+    $$PWD/ObjectiveCTypeQualifiers.h \
+    $$PWD/QtContextKeywords.h \
+    $$PWD/Templates.h \
+    $$PWD/SafeMatcher.h
+
+SOURCES += \
+    $$PWD/AST.cpp \
+    $$PWD/ASTVisit.cpp \
+    $$PWD/ASTMatch0.cpp \
+    $$PWD/ASTVisitor.cpp \
+    $$PWD/ASTClone.cpp \
+    $$PWD/ASTPatternBuilder.cpp \
+    $$PWD/ASTMatcher.cpp \
+    $$PWD/Matcher.cpp \
+    $$PWD/Control.cpp \
+    $$PWD/CoreTypes.cpp \
+    $$PWD/DiagnosticClient.cpp \
+    $$PWD/FullySpecifiedType.cpp \
+    $$PWD/Keywords.cpp \
+    $$PWD/ObjectiveCAtKeywords.cpp \
+    $$PWD/ObjectiveCTypeQualifiers.cpp \
+    $$PWD/Lexer.cpp \
+    $$PWD/Literals.cpp \
+    $$PWD/MemoryPool.cpp \
+    $$PWD/Name.cpp \
+    $$PWD/NameVisitor.cpp \
+    $$PWD/Names.cpp \
+    $$PWD/Parser.cpp \
+    $$PWD/Scope.cpp \
+    $$PWD/Bind.cpp \
+    $$PWD/Symbol.cpp \
+    $$PWD/Symbols.cpp \
+    $$PWD/SymbolVisitor.cpp \
+    $$PWD/Token.cpp \
+    $$PWD/TranslationUnit.cpp \
+    $$PWD/Type.cpp \
+    $$PWD/TypeVisitor.cpp \
+    $$PWD/QtContextKeywords.cpp \
+    $$PWD/Templates.cpp \
+    $$PWD/SafeMatcher.cpp

+ 47 - 0
Source/ToolCore/JSBind/cplusplus/cppassert.h

@@ -0,0 +1,47 @@
+/****************************************************************************
+ * **
+ * ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+ * ** Contact: http://www.qt-project.org/legal
+ * **
+ * ** This file is part of Qt Creator.
+ * **
+ * ** Commercial License Usage
+ * ** Licensees holding valid commercial Qt licenses may use this file in
+ * ** accordance with the commercial license agreement provided with the
+ * ** Software or, alternatively, in accordance with the terms contained in
+ * ** a written agreement between you and Digia.  For licensing terms and
+ * ** conditions see http://www.qt.io/licensing.  For further information
+ * ** use the contact form at http://www.qt.io/contact-us.
+ * **
+ * ** GNU Lesser General Public License Usage
+ * ** Alternatively, this file may be used under the terms of the GNU Lesser
+ * ** General Public License version 2.1 or version 3 as published by the Free
+ * ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+ * ** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
+ * ** following information to ensure the GNU Lesser General Public License
+ * ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ * **
+ * ** In addition, as a special exception, Digia gives you certain additional
+ * ** rights.  These rights are described in the Digia Qt LGPL Exception
+ * ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ * **
+ * ****************************************************************************/
+
+#ifndef SOFT_ASSERT_H
+#define SOFT_ASSERT_H
+
+#include <iostream>
+
+#define CPP_ASSERT_STRINGIFY_HELPER(x) #x
+#define CPP_ASSERT_STRINGIFY(x) CPP_ASSERT_STRINGIFY_HELPER(x)
+#define CPP_ASSERT_STRING(cond) std::cerr \
+    << "SOFT ASSERT: \"" cond"\" in file " __FILE__ ", line " CPP_ASSERT_STRINGIFY(__LINE__) \
+    << std::endl;
+
+#define CPP_ASSERT(cond, action) if (cond) {} else { CPP_ASSERT_STRING(#cond); action; } do {} while (0)
+#define CPP_CHECK(cond) if (cond) {} else { CPP_ASSERT_STRING(#cond); } do {} while (0)
+
+#endif // SOFT_ASSERT_H
+
+