tools/porting/src/parser.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/porting/src/parser.cpp	Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,4526 @@
+/****************************************************************************
+**
+** Copyright (C) 2001-2004 Roberto Raggi
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "parser.h"
+#include "tokens.h"
+#include "errors.h"
+
+#include <QString>
+#include <QStringList>
+#include <QDateTime>
+
+QT_BEGIN_NAMESPACE
+
+#define TT (tokenStream->currentTokenText().data())
+
+#define ADVANCE(tk, descr) \
+{ \
+  if (tokenStream->lookAhead() != tk) { \
+    reportError(QString::fromLatin1("'%1' expected found '%2'").arg(QLatin1String(descr)).arg(QString::fromLatin1((tokenStream->currentTokenText().constData())))); \
+      return false; \
+  } \
+  advance(); \
+}
+
+#define ADVANCE_NR(tk, descr) \
+  do { \
+    if (tokenStream->lookAhead() != tk) { \
+        reportError(i18n("'%1' expected found '%2'").arg(QLatin1String(descr)).arg(QString::fromLatin1(tokenStream->currentTokenText().constData()))); \
+    } \
+    else \
+        advance(); \
+  } while (0)
+
+#define CHECK(tk, descr) \
+  do { \
+    if (tokenStream->lookAhead() != tk) { \
+        return false; \
+    } \
+    advance(); \
+  } while (0)
+
+#define MATCH(tk, descr) \
+  do { \
+    if (tokenStream->lookAhead() != tk) { \
+        reportError(Errors::SyntaxError); \
+        return false; \
+    } \
+  } while (0)
+
+#define UPDATE_POS(_node, start, end) \
+  do { \
+      (_node)->setPosition(start, end); \
+  } while (0)
+
+#define AST_FROM_TOKEN(node, tk) \
+    AST *node = CreateNode<AST>(m_pool); \
+    UPDATE_POS(node, (tk), (tk)+1);
+
+#define DUMP_AST(node) \
+  do { \
+    fprintf(stderr, "\n=================================================\n"); \
+    for (int i=node->startToken(); i<node->endToken(); ++i) \
+       fprintf(stderr, "%s", tokenStream->tokenText(i).constData()); \
+    fprintf(stderr, "\n=================================================\n"); \
+  } while (0)
+
+#define RXX_NO_ERROR
+
+QString i18n(const char *arg)
+{
+    return QLatin1String(arg);
+}
+
+
+//@todo remove me
+enum
+{
+    OBJC_CLASS,
+    OBJC_PROTOCOL,
+    OBJC_ALIAS
+};
+
+Parser::Parser()
+{
+    m_maxProblems = 5;
+    objcp = false;
+}
+
+Parser::~Parser()
+{
+}
+
+TranslationUnitAST *Parser::parse(TokenStreamAdapter::TokenStream *p_tokenStream, pool *p)
+{
+   //tokenStream->rewind(0);
+    m_pool = p;
+    tokenStream = p_tokenStream;
+    TranslationUnitAST *ast = 0;
+    parseTranslationUnit(ast);
+    return ast;
+}
+
+/*
+    Parses a part of the translation unit given by tokenStream. When the number
+    of nodes in the AST exeeds targetMaxASTnodes, this function will return as
+    soon as possible. The progress is stored by updating the cursor inside
+    tokenStream. done is set to true if the parser finished parsing the
+    tokenStream, and to false otherwise.
+*/
+TranslationUnitAST *Parser::parse(TokenStreamAdapter::TokenStream *p_tokenStream, pool *p, int targetMaxASTNodes, bool &done)
+{
+    m_pool = p;
+    tokenStream = p_tokenStream;
+    TranslationUnitAST *ast = 0;
+    // we always create one node, so target max nodes cannot be < 2.
+    if (targetMaxASTNodes < 2)
+        targetMaxASTNodes = 2;
+
+    // Advance past whitespace and comment tokens at the start.
+    while (tokenStream->isHidden(tokenStream->cursor())) {
+        tokenStream->nextToken();
+    }
+    int start = tokenStream->cursor();
+
+    AST::N = 0;
+    m_problems = 0;
+    ast = CreateNode<TranslationUnitAST>(m_pool);
+    while (tokenStream->lookAhead() && AST::N < targetMaxASTNodes) {
+        DeclarationAST *def = 0;
+        int startDecl = tokenStream->cursor();
+        if (!parseDeclaration(def)) {
+            // error recovery
+            if (startDecl == tokenStream->cursor())
+                advance(); // skip at least one token
+            skipUntilDeclaration();
+        }
+        ast->addDeclaration(def);
+    }
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+
+    done = tokenStream->tokenAtEnd();
+    return ast;
+}
+
+
+bool Parser::reportError(const Error& err)
+{
+Q_UNUSED(err);
+#ifndef RXX_NO_ERROR
+    if (m_problems < m_maxProblems) {
+        ++m_problems;
+        int line=0, col=0;
+        QByteArray fileName;
+        tokenStream->getTokenStartPosition(tokenStream->cursor(), &line, &col, &fileName);
+
+        QString s = tokenStream->currentTokenText();
+        s = s.left(30).trimmed();
+        if (s.isEmpty())
+            s = i18n("<eof>");
+
+        if (fileName.isEmpty())
+            //fileName = m_file->fileName;
+            fileName = "implement me";
+
+        //        m_driver->addProblem(m_driver->currentFileName(), Problem(err.text.arg(s), line, col));
+        fprintf(stderr, "%s: error %s at line %d column %d\n",
+                fileName.constData(),
+                err.text.arg(s).toLatin1().constData(), line, col);
+    }
+#endif // RXX_NO_ERROR
+    return true;
+}
+
+bool Parser::reportError(const QString& msg)
+{
+Q_UNUSED(msg);
+#ifndef RXX_NO_ERROR
+    if (m_problems < m_maxProblems) {
+        ++m_problems;
+        int line=0, col=0;
+        QByteArray fileName;
+        tokenStream->getTokenStartPosition(tokenStream->cursor(), &line, &col, &fileName);
+
+        if (fileName.isEmpty())
+            //fileName = m_file->fileName;
+            fileName = "implement me";
+
+        //        m_driver->addProblem(m_driver->currentFileName(), Problem(msg, line, col));
+        fprintf(stderr, "%s: error %s at line %d column %d\n",
+                fileName.constData(),
+                msg.toLatin1().constData(), line, col);
+    }
+#endif // RXX_NO_ERROR
+    return true;
+}
+
+void Parser::syntaxError()
+{
+    (void) reportError(Errors::SyntaxError);
+}
+
+bool Parser::skipUntil(int token)
+{
+    while (tokenStream->lookAhead()) {
+        if (tokenStream->lookAhead() == token)
+            return true;
+
+        advance();
+    }
+
+    return false;
+}
+
+bool Parser::skipUntilDeclaration()
+{
+    while (tokenStream->lookAhead()) {
+
+        switch(tokenStream->lookAhead()) {
+        case ';':
+        case '~':
+        case Token_scope:
+        case Token_identifier:
+        case Token_operator:
+        case Token_char:
+        case Token_wchar_t:
+        case Token_bool:
+        case Token_short:
+        case Token_int:
+        case Token_long:
+        case Token_signed:
+        case Token_unsigned:
+        case Token_float:
+        case Token_double:
+        case Token_void:
+        case Token_extern:
+        case Token_namespace:
+        case Token_using:
+        case Token_typedef:
+        case Token_asm:
+        case Token_template:
+        case Token_export:
+
+        case Token_const:       // cv
+        case Token_volatile:    // cv
+
+        case Token_public:
+        case Token_protected:
+        case Token_private:
+        case Token_signals:      // Qt
+        case Token_slots:        // Qt
+              return true;
+
+        default:
+            advance();
+        }
+    }
+
+    return false;
+}
+
+bool Parser::skipUntilStatement()
+{
+    while (tokenStream->lookAhead()) {
+        switch(tokenStream->lookAhead()) {
+                case ';':
+                case '{':
+                case '}':
+                case Token_const:
+                case Token_volatile:
+                case Token_identifier:
+                case Token_case:
+                case Token_default:
+                case Token_if:
+                case Token_switch:
+                case Token_while:
+                case Token_do:
+                case Token_for:
+                case Token_break:
+                case Token_continue:
+                case Token_return:
+                case Token_goto:
+                case Token_try:
+                case Token_catch:
+                case Token_throw:
+                case Token_char:
+                case Token_wchar_t:
+                case Token_bool:
+                case Token_short:
+                case Token_int:
+                case Token_long:
+                case Token_signed:
+                case Token_unsigned:
+                case Token_float:
+                case Token_double:
+                case Token_void:
+                case Token_class:
+                case Token_struct:
+                case Token_union:
+                case Token_enum:
+                case Token_scope:
+                case Token_template:
+                case Token_using:
+                    return true;
+
+            default:
+                  advance();
+        }
+    }
+
+    return false;
+}
+
+bool Parser::skip(int l, int r)
+{
+    int count = 0;
+    while (tokenStream->lookAhead()) {
+        int tk = tokenStream->lookAhead();
+
+        if (tk == l)
+            ++count;
+        else if (tk == r)
+            --count;
+        else if (l != '{' && (tk == '{' || tk == '}' || tk == ';'))
+            return false;
+
+        if (count == 0)
+            return true;
+
+        advance();
+    }
+
+    return false;
+}
+
+bool Parser::skipCommaExpression(AbstractExpressionAST *&node)
+{
+#ifndef RXX_NO_PARSE_EXPRESSION
+    return parseCommaExpression(node);
+#else
+    int start = tokenStream->cursor();
+
+    AbstractExpressionAST *expr = 0;
+    if (!skipExpression(expr))
+        return false;
+
+    while (tokenStream->lookAhead() == ',') {
+        advance();
+
+        if (!skipExpression(expr)) {
+            reportError(i18n("expression expected"));
+            return false;
+        }
+    }
+
+    AbstractExpressionAST *ast = CreateNode<AbstractExpressionAST>(m_pool);
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+#endif // RXX_NO_PARSE_EXPRESSION
+}
+
+bool Parser::skipExpression(AbstractExpressionAST *&node)
+{
+#ifndef RXX_NO_PARSE_EXPRESSION
+    return parseExpression(node);
+#else
+    int start = tokenStream->cursor();
+    int count = 0;
+
+    while (tokenStream->lookAhead()) {
+        int tk = tokenStream->lookAhead();
+
+        switch(tk) {
+        case '(':
+        case '[':
+        case '{':
+            ++count;
+            advance();
+            break;
+
+        case ']':
+        case ')':
+        case '}':
+            if (count == 0) {
+                AbstractExpressionAST *ast = CreateNode<AbstractExpressionAST>(m_pool);
+                UPDATE_POS(ast, start, tokenStream->cursor());
+                node = ast;
+                return true;
+            }
+            --count;
+            advance();
+            break;
+
+        case Token_struct:
+        case Token_union:
+        case Token_class: {
+            int c = tokenStream->cursor();
+            TypeSpecifierAST *spec = 0;
+            if (!parseClassSpecifier(spec))
+                tokenStream->rewind(c + 1);
+        }
+        break;
+
+        case ',':
+        case ';':
+        case Token_case:
+        case Token_default:
+        case Token_if:
+        case Token_while:
+        case Token_do:
+        case Token_for:
+        case Token_break:
+        case Token_continue:
+        case Token_return:
+        case Token_goto:
+        {
+            if ((tk == ',' || tk == ';') && count > 0) {
+                advance();
+                break;
+            }
+
+            AbstractExpressionAST *ast = CreateNode<AbstractExpressionAST>(m_pool);
+            UPDATE_POS(ast, start, tokenStream->cursor());
+            node = ast;
+        }
+        return true;
+
+        default:
+            advance();
+        }
+    }
+
+    return false;
+#endif // RXX_NO_PARSE_EXPRESSION
+}
+
+bool Parser::parseName(NameAST *&node, bool parseTemplateId)
+{
+    AST *winDeclSpec = 0;
+    parseWinDeclSpec(winDeclSpec);
+
+    int start = tokenStream->cursor();
+
+    NameAST *ast = CreateNode<NameAST>(m_pool);
+
+    if (tokenStream->lookAhead() == Token_scope) {
+        ast->setGlobal(true);
+        advance();
+    }
+
+    int idx = tokenStream->cursor();
+
+    while (true) {
+        ClassOrNamespaceNameAST *n = 0;
+        if (!parseUnqualifiedName(n))
+            return false;
+
+        if (tokenStream->lookAhead() == Token_scope) {
+            advance();
+            ast->addClassOrNamespaceName(n);
+            if (tokenStream->lookAhead() == Token_template)
+                advance(); /// skip optional template     #### @todo CHECK
+        } else if (!parseTemplateId && n) {
+            tokenStream->rewind(n->startToken());
+            parseUnqualifiedName(n, parseTemplateId);
+            ast->setUnqualifiedName(n);
+            break;
+        } else {
+            ast->setUnqualifiedName(n);
+            break;
+        }
+    }
+
+    if (idx == tokenStream->cursor())
+        return false;
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+}
+
+bool Parser::parseTranslationUnit(TranslationUnitAST *&node)
+{
+    QTime t;
+    t.start();
+
+    advance();
+    int start = tokenStream->cursor();
+
+    m_problems = 0;
+    TranslationUnitAST *tun = CreateNode<TranslationUnitAST>(m_pool);
+    node = tun;
+    while (tokenStream->lookAhead()) {
+        DeclarationAST *def = 0;
+        int startDecl = tokenStream->cursor();
+        if (!parseDeclaration(def)) {
+            // error recovery
+            if (startDecl == tokenStream->cursor())
+                advance(); // skip at least one token
+            skipUntilDeclaration();
+        }
+        node->addDeclaration(def);
+    }
+
+    UPDATE_POS(node, start, tokenStream->cursor());
+
+    return m_problems == 0;
+}
+
+bool Parser::parseDeclaration(DeclarationAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    switch(tokenStream->lookAhead()) {
+
+    case ';':
+        advance();
+        return true;
+
+    case Token_extern:
+        return parseLinkageSpecification(node);
+
+    case Token_namespace:
+        return parseNamespace(node);
+
+    case Token_using:
+        return parseUsing(node);
+
+    case Token_typedef:
+        return parseTypedef(node);
+
+    case Token_asm:
+        return parseAsmDefinition(node);
+
+    case Token_template:
+    case Token_export:
+        return parseTemplateDeclaration(node);
+
+    default:
+        {
+            // tokenStream->rewind(start);
+
+            if (objcp && parseObjcDef(node))
+                return true;
+
+            tokenStream->rewind(start);
+
+            AST *storageSpec = 0;
+            parseStorageClassSpecifier(storageSpec);
+
+            AST *cv = 0;
+            parseCvQualify(cv);
+
+            TypeSpecifierAST *spec = 0;
+            if (parseEnumSpecifier(spec) || parseClassSpecifier(spec)) {
+                spec->setCvQualify(cv);
+
+                AST *cv2 = 0;
+                parseCvQualify(cv2);
+                spec->setCv2Qualify(cv2);
+
+                InitDeclaratorListAST *declarators = 0;
+                parseInitDeclaratorList(declarators);
+                ADVANCE(';', ";");
+
+                SimpleDeclarationAST *ast = CreateNode<SimpleDeclarationAST>(m_pool);
+                ast->setStorageSpecifier(storageSpec);
+                ast->setTypeSpec(spec);
+                ast->setInitDeclaratorList(declarators);
+                UPDATE_POS(ast, start, tokenStream->cursor());
+                node = ast;
+
+                return true;
+            }
+
+            tokenStream->rewind(start);
+            return parseDeclarationInternal(node);
+        }
+
+    } // end switch
+}
+
+bool Parser::parseLinkageSpecification(DeclarationAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    if (tokenStream->lookAhead() != Token_extern) {
+        return false;
+    }
+    advance();
+
+    LinkageSpecificationAST *ast = CreateNode<LinkageSpecificationAST>(m_pool);
+
+    int startExternType = tokenStream->cursor();
+    if (tokenStream->lookAhead() == Token_string_literal) {
+        advance();
+        AST *externType = CreateNode<AST>(m_pool);
+        UPDATE_POS(externType, startExternType, tokenStream->cursor());
+
+        ast->setExternType(externType);
+    }
+
+    if (tokenStream->lookAhead() == '{') {
+        LinkageBodyAST *linkageBody = 0;
+        parseLinkageBody(linkageBody);
+        ast->setLinkageBody(linkageBody);
+    } else {
+        DeclarationAST *decl = 0;
+        if (!parseDeclaration(decl)) {
+            reportError(i18n("Declaration syntax error"));
+        }
+        ast->setDeclaration(decl);
+    }
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+
+    node = ast;
+
+    return true;
+}
+
+bool Parser::parseLinkageBody(LinkageBodyAST *&node)
+{
+
+    int start = tokenStream->cursor();
+
+    if (tokenStream->lookAhead() != '{') {
+        return false;
+    }
+    advance();
+
+    LinkageBodyAST *lba = CreateNode<LinkageBodyAST>(m_pool);
+    node = lba;
+
+    while (tokenStream->lookAhead()) {
+        int tk = tokenStream->lookAhead();
+
+        if (tk == '}')
+            break;
+
+        DeclarationAST *def = 0;
+        int startDecl = tokenStream->cursor();
+        if (parseDeclaration(def)) {
+            node->addDeclaration(def);
+        } else {
+            // error recovery
+            if (startDecl == tokenStream->cursor())
+                advance(); // skip at least one token
+            skipUntilDeclaration();
+        }
+    }
+
+    if (tokenStream->lookAhead() != '}') {
+        reportError(i18n("} expected"));
+    } else
+        advance();
+
+    UPDATE_POS(node, start, tokenStream->cursor());
+    return true;
+}
+
+bool Parser::parseNamespace(DeclarationAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    if (tokenStream->lookAhead() != Token_namespace) {
+        return false;
+    }
+    advance();
+
+    int startNamespaceName = tokenStream->cursor();
+    if (tokenStream->lookAhead() == Token_identifier) {
+        advance();
+    }
+    AST *namespaceName = CreateNode<AST>(m_pool);
+    UPDATE_POS(namespaceName, startNamespaceName, tokenStream->cursor());
+
+    if (tokenStream->lookAhead() == '=') {
+        // namespace alias
+        advance();
+
+        NameAST *name = 0;
+        if (parseName(name)) {
+            ADVANCE(';', ";");
+
+            NamespaceAliasAST *ast = CreateNode<NamespaceAliasAST>(m_pool);
+            ast->setNamespaceName(namespaceName);
+            ast->setAliasName(name);
+            UPDATE_POS(ast, start, tokenStream->cursor());
+            node = ast;
+            return true;
+        } else {
+            reportError(i18n("namespace expected"));
+            return false;
+        }
+    } else if (tokenStream->lookAhead() != '{') {
+        reportError(i18n("{ expected"));
+        return false;
+    }
+
+    NamespaceAST *ast = CreateNode<NamespaceAST>(m_pool);
+    ast->setNamespaceName(namespaceName);
+
+    LinkageBodyAST *linkageBody = 0;
+    parseLinkageBody(linkageBody);
+
+    ast->setLinkageBody(linkageBody);
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+}
+
+bool Parser::parseUsing(DeclarationAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    if (tokenStream->lookAhead() != Token_using) {
+        return false;
+    }
+    advance();
+
+    if (tokenStream->lookAhead() == Token_namespace) {
+        if (!parseUsingDirective(node)) {
+            return false;
+        }
+        UPDATE_POS(node, start, tokenStream->cursor());
+        return true;
+    }
+
+    UsingAST *ast = CreateNode<UsingAST>(m_pool);
+
+    int startTypeName = tokenStream->cursor();
+    if (tokenStream->lookAhead() == Token_typename) {
+        advance();
+        AST *tn = CreateNode<AST>(m_pool);
+        UPDATE_POS(tn, startTypeName, tokenStream->cursor());
+        ast->setTypeName(tn);
+    }
+
+    NameAST *name = 0;
+    if (!parseName(name))
+        return false;
+
+    ast->setName(name);
+
+    ADVANCE(';', ";");
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+}
+
+bool Parser::parseUsingDirective(DeclarationAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    if (tokenStream->lookAhead() != Token_namespace) {
+        return false;
+    }
+    advance();
+
+    NameAST *name = 0;
+    if (!parseName(name)) {
+        reportError(i18n("Namespace name expected"));
+        return false;
+    }
+
+    ADVANCE(';', ";");
+
+    UsingDirectiveAST *ast = CreateNode<UsingDirectiveAST>(m_pool);
+    ast->setName(name);
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+}
+
+
+bool Parser::parseOperatorFunctionId(AST *&node)
+{
+    int start = tokenStream->cursor();
+
+    if (tokenStream->lookAhead() != Token_operator) {
+        return false;
+    }
+    advance();
+
+    AST *op = 0;
+    if (parseOperator(op)) {
+        AST *asn = CreateNode<AST>(m_pool);
+        node = asn;
+        UPDATE_POS(node, start, tokenStream->cursor());
+        return true;
+    } else {
+        // parse cast operator
+        AST *cv = 0;
+        parseCvQualify(cv);
+
+        TypeSpecifierAST *spec = 0;
+        if (!parseSimpleTypeSpecifier(spec)) {
+            syntaxError();
+            return false;
+        }
+        spec->setCvQualify(cv);
+
+        AST *cv2 = 0;
+        parseCvQualify(cv2);
+        spec->setCv2Qualify(cv2);
+
+        AST *ptrOp = 0;
+        while (parsePtrOperator(ptrOp))
+              ;
+
+        AST *asn = CreateNode<AST>(m_pool);
+        node = asn;
+        UPDATE_POS(node, start, tokenStream->cursor());
+        return true;
+    }
+}
+
+bool Parser::parseTemplateArgumentList(TemplateArgumentListAST *&node, bool reportError)
+{
+    int start = tokenStream->cursor();
+
+    TemplateArgumentListAST *ast = CreateNode<TemplateArgumentListAST>(m_pool);
+
+    AST *templArg = 0;
+    if (!parseTemplateArgument(templArg))
+        return false;
+    ast->addArgument(templArg);
+
+    while (tokenStream->lookAhead() == ',') {
+        advance();
+
+        if (!parseTemplateArgument(templArg)) {
+            if (reportError) {
+               syntaxError();
+               break;
+            } else
+               return false;
+        }
+        ast->addArgument(templArg);
+    }
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+}
+
+bool Parser::parseTypedef(DeclarationAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    if (tokenStream->lookAhead() != Token_typedef) {
+        return false;
+    }
+    advance();
+
+    TypeSpecifierAST *spec = 0;
+    if (!parseTypeSpecifierOrClassSpec(spec)) {
+        reportError(i18n("Need a type specifier to declare"));
+        return false;
+    }
+
+    InitDeclaratorListAST *declarators = 0;
+    if (!parseInitDeclaratorList(declarators)) {
+        //reportError(i18n("Need an identifier to declare"));
+        //return false;
+    }
+
+    ADVANCE(';', ";");
+
+    TypedefAST *ast = CreateNode<TypedefAST>(m_pool);
+    ast->setTypeSpec(spec);
+    ast->setInitDeclaratorList(declarators);
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+}
+
+bool Parser::parseAsmDefinition(DeclarationAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    ADVANCE(Token_asm, "asm");
+
+    AST *cv = 0;
+    parseCvQualify(cv);
+
+    skip('(', ')');
+    advance();
+    ADVANCE(';', ";");
+
+    DeclarationAST *ast = CreateNode<DeclarationAST>(m_pool);
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+}
+
+bool Parser::parseTemplateDeclaration(DeclarationAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    AST *exp = 0;
+
+    int startExport = tokenStream->cursor();
+    if (tokenStream->lookAhead() == Token_export) {
+        advance();
+        AST *n = CreateNode<AST>(m_pool);
+        UPDATE_POS(n, startExport, tokenStream->cursor());
+        exp = n;
+    }
+
+    if (tokenStream->lookAhead() != Token_template) {
+        return false;
+    }
+    advance();
+
+    TemplateParameterListAST *params = 0;
+    if (tokenStream->lookAhead() == '<') {
+        advance();
+        parseTemplateParameterList(params);
+
+        ADVANCE('>', ">");
+    }
+
+    DeclarationAST *def = 0;
+    if (!parseDeclaration(def)) {
+        reportError(i18n("expected a declaration"));
+    }
+
+    TemplateDeclarationAST *ast = CreateNode<TemplateDeclarationAST>(m_pool);
+    ast->setExported(exp);
+    ast->setTemplateParameterList(params);
+    ast->setDeclaration(def);
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+}
+
+bool Parser::parseOperator(AST *&/*node*/)
+{
+    QString text(QString::fromLatin1(tokenStream->currentTokenText().constData()));
+
+    switch(tokenStream->lookAhead()) {
+    case Token_new:
+    case Token_delete:
+        advance();
+        if (tokenStream->lookAhead() == '[' && tokenStream->lookAhead(1) == ']') {
+            advance();
+            advance();
+            text += QLatin1String("[]");
+        }
+        return true;
+
+    case '+':
+    case '-':
+    case '*':
+    case '/':
+    case '%':
+    case '^':
+    case '&':
+    case '|':
+    case '~':
+    case '!':
+    case '=':
+    case '<':
+    case '>':
+    case ',':
+    case Token_assign:
+    case Token_shift:
+    case Token_eq:
+    case Token_not_eq:
+    case Token_leq:
+    case Token_geq:
+    case Token_and:
+    case Token_or:
+    case Token_incr:
+    case Token_decr:
+    case Token_ptrmem:
+    case Token_arrow:
+        advance();
+        return true;
+
+    default:
+        if (tokenStream->lookAhead() == '(' && tokenStream->lookAhead(1) == ')') {
+            advance();
+            advance();
+            return true;
+        } else if (tokenStream->lookAhead() == '[' && tokenStream->lookAhead(1) == ']') {
+            advance();
+            advance();
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool Parser::parseCvQualify(AST *&node)
+{
+    int start = tokenStream->cursor();
+
+    AST *ast = CreateNode<AST>(m_pool);
+
+    int n = 0;
+    while (tokenStream->lookAhead()) {
+        int tk = tokenStream->lookAhead();
+        if (tk == Token_const || tk == Token_volatile) {
+            ++n;
+            int startWord = tokenStream->cursor();
+            advance();
+            AST *word = CreateNode<AST>(m_pool);
+            UPDATE_POS(word, startWord, tokenStream->cursor());
+            word->setParent(ast);
+        } else
+            break;
+    }
+
+    if (n == 0)
+        return false;
+
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+
+    node = ast;
+    return true;
+}
+
+bool Parser::parseSimpleTypeSpecifier(TypeSpecifierAST *&node, bool onlyIntegral)
+{
+    int start = tokenStream->cursor();
+    bool isIntegral = false;
+    bool done = false;
+
+    while (!done) {
+        switch(tokenStream->lookAhead()) {
+            case Token_char:
+            case Token_wchar_t:
+            case Token_bool:
+            case Token_short:
+            case Token_int:
+            case Token_long:
+            case Token_signed:
+            case Token_unsigned:
+            case Token_float:
+            case Token_double:
+            case Token_void:
+                isIntegral = true;
+                advance();
+                break;
+
+            default:
+                done = true;
+        }
+    }
+
+    TypeSpecifierAST *ast = CreateNode<TypeSpecifierAST>(m_pool);
+    if (isIntegral) {
+        ClassOrNamespaceNameAST *cl = CreateNode<ClassOrNamespaceNameAST>(m_pool);
+
+        AST *n = CreateNode<AST>(m_pool);
+        UPDATE_POS(n, start, tokenStream->cursor());
+        cl->setName(n);
+        UPDATE_POS(cl, start, tokenStream->cursor());
+
+        NameAST *name = CreateNode<NameAST>(m_pool);
+        name->setUnqualifiedName(cl);
+        UPDATE_POS(name, start, tokenStream->cursor());
+        ast->setName(name);
+    } else if (tokenStream->lookAhead() == Token___typeof) {
+        advance();
+        if (tokenStream->lookAhead() == '(') {
+            advance();
+            TypeIdAST *typeId = 0;
+            parseTypeId(typeId);
+            ADVANCE(')', ")");
+        } else {
+            AbstractExpressionAST *e = 0;
+            parseUnaryExpression(e);
+        }
+    } else if (onlyIntegral) {
+        tokenStream->rewind(start);
+        return false;
+    } else {
+        NameAST *name = 0;
+        if (!parseName(name)) {
+            tokenStream->rewind(start);
+            return false;
+        }
+        ast->setName(name);
+    }
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+    return true;
+}
+
+bool Parser::parsePtrOperator(AST *&node)
+{
+    int start = tokenStream->cursor();
+    int tok = tokenStream->lookAhead();
+    AST *memPtr = 0;
+
+    switch (tok) {
+        case '&':
+        case '*':
+            advance();
+            break;
+
+        case Token_scope:
+        case Token_identifier:
+            if (!parsePtrToMember(memPtr)) {
+                tokenStream->rewind(start);
+                return false;
+            }
+            break;
+
+        default:
+            return false;
+    }
+
+    AST *cv = 0;
+    parseCvQualify(cv);
+
+    AST *ast = CreateNode<AST>(m_pool);
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+}
+
+
+bool Parser::parseTemplateArgument(AST *&node)
+{
+    int start = tokenStream->cursor();
+
+    TypeIdAST *typeId = 0;
+    if (parseTypeId(typeId)) {
+        if (tokenStream->lookAhead() == ',' || tokenStream->lookAhead() == '>') {
+            node = typeId;
+            return true;
+        }
+    }
+
+    tokenStream->rewind(start);
+    AbstractExpressionAST *expr = 0;
+    if (!parseLogicalOrExpression(expr, true)) {
+        return false;
+    }
+    node = expr;
+
+    return true;
+}
+
+bool Parser::parseTypeSpecifier(TypeSpecifierAST *&spec)
+{
+    AST *cv = 0;
+    parseCvQualify(cv);
+
+    if (parseElaboratedTypeSpecifier(spec) || parseSimpleTypeSpecifier(spec)) {
+        spec->setCvQualify(cv);
+
+        AST *cv2 = 0;
+        parseCvQualify(cv2);
+        spec->setCv2Qualify(cv2);
+
+        return true;
+    }
+
+    return false;
+}
+
+bool Parser::parseDeclarator(DeclaratorAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    DeclaratorAST *ast = CreateNode<DeclaratorAST>(m_pool);
+
+    DeclaratorAST *decl = 0;
+    NameAST *declId = 0;
+
+    AST *ptrOp = 0;
+    while (parsePtrOperator(ptrOp)) {
+        ast->addPtrOp(ptrOp);
+    }
+
+    if (tokenStream->lookAhead() == '(') {
+        advance();
+
+        if (!parseDeclarator(decl)) {
+            return false;
+        }
+        ast->setSubDeclarator(decl);
+
+        if (tokenStream->lookAhead() != ')') {
+            return false;
+        }
+        advance();
+    } else {
+        if (tokenStream->lookAhead() == ':') {
+             // unnamed bitfield
+        } else if (parseDeclaratorId(declId)) {
+            ast->setDeclaratorId(declId);
+        } else {
+            tokenStream->rewind(start);
+            return false;
+        }
+
+        if (tokenStream->lookAhead() == ':') {
+            advance();
+            AbstractExpressionAST *expr = 0;
+            if (!parseConstantExpression(expr)) {
+                reportError(i18n("Constant expression expected"));
+            }
+            goto update_pos;
+        }
+    }
+
+    {
+        bool isVector = false;
+
+        while (tokenStream->lookAhead() == '[') {
+            int startArray = tokenStream->cursor();
+            advance();
+            AbstractExpressionAST *expr = 0;
+            parseCommaExpression(expr);
+
+            ADVANCE(']', "]");
+            AST *array = CreateNode<AST>(m_pool);
+            UPDATE_POS(array, startArray, tokenStream->cursor());
+            ast->addArrayDimension(array);
+            isVector = true;
+        }
+
+        bool skipParen = false;
+        if (tokenStream->lookAhead() == Token_identifier
+                && tokenStream->lookAhead(1) == '('
+                && tokenStream->lookAhead(2) == '(') {
+            advance();
+            advance();
+            skipParen = true;
+        }
+
+        int tok = tokenStream->lookAhead();
+        if (ast->subDeclarator() && !(isVector || tok == '(' || tok == ',' || tok == ';' || tok == '=')) {
+            tokenStream->rewind(start);
+            return false;
+        }
+
+        int index = tokenStream->cursor();
+        if (tokenStream->lookAhead() == '(') {
+            advance();
+
+            ParameterDeclarationClauseAST *params = 0;
+            if (!parseParameterDeclarationClause(params)) {
+                tokenStream->rewind(index);
+                goto update_pos;
+            }
+            ast->setParameterDeclarationClause(params);
+
+            if (tokenStream->lookAhead() != ')') {
+                tokenStream->rewind(index);
+                goto update_pos;
+            }
+
+            advance();  // skip ')'
+
+            AST *constant = 0;
+            parseCvQualify(constant);
+            ast->setConstant(constant);
+
+            AST *except = 0;
+            if (parseExceptionSpecification(except)) {
+                ast->setExceptionSpecification(except);
+            }
+        }
+
+        if (skipParen) {
+            if (tokenStream->lookAhead() != ')') {
+                reportError(i18n("')' expected"));
+            } else
+                advance();
+        }
+    }
+
+update_pos:
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+}
+
+bool Parser::parseAbstractDeclarator(DeclaratorAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    DeclaratorAST *ast = CreateNode<DeclaratorAST>(m_pool);
+    DeclaratorAST *decl = 0;
+
+    AST *ptrOp = 0;
+    while (parsePtrOperator(ptrOp)) {
+        ast->addPtrOp(ptrOp);
+    }
+
+    int index = tokenStream->cursor();
+    if (tokenStream->lookAhead() == '(') {
+        advance();
+
+        if (!parseAbstractDeclarator(decl)) {
+            tokenStream->rewind(index);
+            goto label1;
+        }
+
+        ast->setSubDeclarator(decl);
+
+        if (tokenStream->lookAhead() != ')'){
+            tokenStream->rewind(start);
+            return false;
+        }
+        advance();
+    } else if (tokenStream->lookAhead() == ':') {
+        advance();
+        AbstractExpressionAST *expr = 0;
+        if (!parseConstantExpression(expr)) {
+            reportError(i18n("Constant expression expected"));
+        }
+        goto update_pos;
+    }
+
+label1:
+    {
+        bool isVector = false;
+
+        while (tokenStream->lookAhead() == '[') {
+            int startArray = tokenStream->cursor();
+            advance();
+            AbstractExpressionAST *expr = 0;
+            parseCommaExpression(expr);
+
+            ADVANCE(']', "]");
+            AST *array = CreateNode<AST>(m_pool);
+            UPDATE_POS(array, startArray, tokenStream->cursor());
+            ast->addArrayDimension(array);
+            isVector = true;
+        }
+
+        int tok = tokenStream->lookAhead();
+        if (ast->subDeclarator() && !(isVector || tok == '(' || tok == ',' || tok == ';' || tok == '=')) {
+            tokenStream->rewind(start);
+            return false;
+        }
+
+        int index = tokenStream->cursor();
+        if (tokenStream->lookAhead() == '(') {
+            advance();
+
+            ParameterDeclarationClauseAST *params = 0;
+            if (!parseParameterDeclarationClause(params)) {
+                tokenStream->rewind(index);
+                goto update_pos;
+            }
+            ast->setParameterDeclarationClause(params);
+
+            if (tokenStream->lookAhead() != ')') {
+                tokenStream->rewind(index);
+                goto update_pos;
+            }
+
+            advance();  // skip ')'
+
+            AST *constant = 0;
+            parseCvQualify(constant);
+            ast->setConstant(constant);
+
+            AST *except = 0;
+            if (parseExceptionSpecification(except)) {
+                ast->setExceptionSpecification(except);
+            }
+        }
+    }
+
+update_pos:
+    if (tokenStream->cursor() == start)
+        return false;
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+}
+
+bool Parser::parseEnumSpecifier(TypeSpecifierAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    if (tokenStream->lookAhead() != Token_enum) {
+        return false;
+    }
+
+    advance();
+
+    NameAST *name = 0;
+    parseName(name);
+
+    if (tokenStream->lookAhead() != '{') {
+        tokenStream->rewind(start);
+        return false;
+    }
+    advance();
+
+    EnumSpecifierAST *ast = CreateNode<EnumSpecifierAST>(m_pool);
+    ast->setName(name);
+
+    EnumeratorAST *enumerator = 0;
+    if (parseEnumerator(enumerator)) {
+        ast->addEnumerator(enumerator);
+
+        while (tokenStream->lookAhead() == ',') {
+            advance();
+
+            if (!parseEnumerator(enumerator)) {
+                //reportError(i18n("Enumerator expected"));
+                break;
+            }
+
+            ast->addEnumerator(enumerator);
+        }
+    }
+
+    if (tokenStream->lookAhead() != '}')
+        reportError(i18n("} missing"));
+    else
+        advance();
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+}
+
+bool Parser::parseTemplateParameterList(TemplateParameterListAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    TemplateParameterListAST *ast = CreateNode<TemplateParameterListAST>(m_pool);
+
+    TemplateParameterAST *param = 0;
+    if (!parseTemplateParameter(param)) {
+        return false;
+    }
+    ast->addTemplateParameter(param);
+
+    while (tokenStream->lookAhead() == ',') {
+        advance();
+
+        if (!parseTemplateParameter(param)) {
+            syntaxError();
+            break;
+        } else {
+            ast->addTemplateParameter(param);
+        }
+    }
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+}
+
+bool Parser::parseTemplateParameter(TemplateParameterAST *&node)
+{
+    int start = tokenStream->cursor();
+    TemplateParameterAST *ast = CreateNode<TemplateParameterAST>(m_pool);
+
+    TypeParameterAST *typeParameter = 0;
+    ParameterDeclarationAST *param = 0;
+
+    int tk = tokenStream->lookAhead();
+
+    if ((tk == Token_class || tk == Token_typename || tk == Token_template) && parseTypeParameter(typeParameter)) {
+        ast->setTypeParameter(typeParameter);
+        goto ok;
+    }
+
+    if (!parseParameterDeclaration(param))
+        return false;
+    ast->setTypeValueParameter(param);
+
+ok:
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+}
+
+bool Parser::parseTypeParameter(TypeParameterAST *&node)
+{
+    int start = tokenStream->cursor();
+    TypeParameterAST *ast = CreateNode<TypeParameterAST>(m_pool);
+
+    AST_FROM_TOKEN(kind, tokenStream->cursor());
+    ast->setKind(kind);
+
+    switch(tokenStream->lookAhead()) {
+
+    case Token_class:
+    case Token_typename:
+        {
+            advance(); // skip class
+
+            // parse optional name
+            NameAST *name = 0;
+            if(parseName(name)){
+                ast->setName(name);
+
+                if (tokenStream->lookAhead() == '='){
+                    advance();
+
+                    TypeIdAST *typeId = 0;
+                    if(!parseTypeId(typeId)){
+                        //syntaxError();
+                        tokenStream->rewind(start);
+                        return false;
+                    }
+                    ast->setTypeId(typeId);
+                } else if (!(tokenStream->lookAhead() == ',' || tokenStream->lookAhead() == '>')) {
+                    tokenStream->rewind(start);
+                    return false;
+                }
+            }
+        }
+        break;
+
+    case Token_template:
+        {
+            advance(); // skip template
+            ADVANCE('<', "<");
+
+            TemplateParameterListAST *params = 0;
+            if (!parseTemplateParameterList(params)) {
+                return false;
+            }
+            ast->setTemplateParameterList(params);
+
+            ADVANCE('>', ">");
+
+            if (tokenStream->lookAhead() == Token_class)
+                advance();
+
+            // parse optional name
+            NameAST *name = 0;
+            if (parseName(name)) {
+                ast->setName(name);
+                if (tokenStream->lookAhead() == '=') {
+                    advance();
+
+                    TypeIdAST *typeId = 0;
+                    if (!parseTypeId(typeId)) {
+                        syntaxError();
+                        return false;
+                    }
+                    ast->setTypeId(typeId);
+                }
+            }
+
+            if (tokenStream->lookAhead() == '=') {
+                advance();
+
+                NameAST *templ_name = 0;
+                parseName(templ_name);
+            }
+        }
+        break;
+
+    default:
+        return false;
+
+    } // end switch
+
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+    return true;
+}
+
+bool Parser::parseStorageClassSpecifier(AST *&node)
+{
+    int start = tokenStream->cursor();
+    AST *ast = CreateNode<AST>(m_pool);
+
+    while (tokenStream->lookAhead()) {
+        int tk = tokenStream->lookAhead();
+        if (tk == Token_friend || tk == Token_auto || tk == Token_register || tk == Token_static ||
+                tk == Token_extern || tk == Token_mutable) {
+            int startNode = tokenStream->cursor();
+            advance();
+
+            AST *n = CreateNode<AST>(m_pool);
+            UPDATE_POS(n, startNode, tokenStream->cursor());
+            n->setParent(ast);
+        } else
+            break;
+    }
+
+    if (length(ast->children()) == 0)
+       return false;
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+    return true;
+}
+
+bool Parser::parseFunctionSpecifier(AST *&node)
+{
+    int start = tokenStream->cursor();
+    AST *ast = CreateNode<AST>(m_pool);
+
+    while (tokenStream->lookAhead()) {
+        int tk = tokenStream->lookAhead();
+        if (tk == Token_inline || tk == Token_virtual || tk == Token_explicit) {
+            int startNode = tokenStream->cursor();
+            advance();
+
+            AST *n = CreateNode<AST>(m_pool);
+            UPDATE_POS(n, startNode, tokenStream->cursor());
+            n->setParent(ast);
+        } else {
+            break;
+    }
+    }
+
+    if (length(ast->children()) == 0)
+       return false;
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+    return true;
+}
+
+bool Parser::parseTypeId(TypeIdAST *&node)
+{
+    /// @todo implement the AST for typeId
+    int start = tokenStream->cursor();
+
+    TypeSpecifierAST *spec = 0;
+    if (!parseTypeSpecifier(spec)) {
+        tokenStream->rewind(start);
+        return false;
+    }
+
+    DeclaratorAST *decl = 0;
+    parseAbstractDeclarator(decl);
+
+    TypeIdAST *ast = CreateNode<TypeIdAST>(m_pool);
+    ast->setTypeSpecifier(spec);
+    ast->setDeclarator(decl);
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+}
+
+bool Parser::parseInitDeclaratorList(InitDeclaratorListAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    InitDeclaratorListAST *ast = CreateNode<InitDeclaratorListAST>(m_pool);
+    InitDeclaratorAST *decl = 0;
+
+    if (!parseInitDeclarator(decl)) {
+        return false;
+    }
+    ast->addInitDeclarator(decl);
+
+    while (tokenStream->lookAhead() == ',') {
+        advance();
+
+        if (!parseInitDeclarator(decl)) {
+            syntaxError();
+            break;
+        }
+        ast->addInitDeclarator(decl);
+    }
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+}
+
+bool Parser::parseParameterDeclarationClause(ParameterDeclarationClauseAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    ParameterDeclarationClauseAST *ast = CreateNode<ParameterDeclarationClauseAST>(m_pool);
+
+    ParameterDeclarationListAST *params = 0;
+    if (!parseParameterDeclarationList(params)) {
+
+        if (tokenStream->lookAhead() == ')')
+            goto good;
+
+        if (tokenStream->lookAhead() == Token_ellipsis && tokenStream->lookAhead(1) == ')') {
+            AST_FROM_TOKEN(ellipsis, tokenStream->cursor());
+            ast->setEllipsis(ellipsis);
+            advance();
+            goto good;
+        }
+        return false;
+    }
+
+    if (tokenStream->lookAhead() == Token_ellipsis) {
+        AST_FROM_TOKEN(ellipsis, tokenStream->cursor());
+        ast->setEllipsis(ellipsis);
+        advance();
+    }
+
+good:
+    ast->setParameterDeclarationList(params);
+
+    /// @todo add ellipsis
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+}
+
+bool Parser::parseParameterDeclarationList(ParameterDeclarationListAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    ParameterDeclarationListAST *ast = CreateNode<ParameterDeclarationListAST>(m_pool);
+
+    ParameterDeclarationAST *param = 0;
+    if (!parseParameterDeclaration(param)) {
+        tokenStream->rewind(start);
+        return false;
+    }
+    ast->addParameter(param);
+
+    while (tokenStream->lookAhead() == ',') {
+        advance();
+
+        if (tokenStream->lookAhead() == Token_ellipsis)
+            break;
+
+        if (!parseParameterDeclaration(param)) {
+            tokenStream->rewind(start);
+            return false;
+        }
+        ast->addParameter(param);
+    }
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+}
+
+bool Parser::parseParameterDeclaration(ParameterDeclarationAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    AST *storage = 0;
+    parseStorageClassSpecifier(storage);
+
+    // parse decl spec
+    TypeSpecifierAST *spec = 0;
+    if (!parseTypeSpecifier(spec)) {
+        tokenStream->rewind(start);
+        return false;
+    }
+
+    int index = tokenStream->cursor();
+
+    DeclaratorAST *decl = 0;
+    if (!parseDeclarator(decl)) {
+        tokenStream->rewind(index);
+
+        // try with abstract declarator
+        parseAbstractDeclarator(decl);
+    }
+
+    AbstractExpressionAST *expr = 0;
+    if (tokenStream->lookAhead() == '=') {
+        advance();
+        if (!parseLogicalOrExpression(expr,true)) {
+            //reportError(i18n("Expression expected"));
+        }
+    }
+
+    ParameterDeclarationAST *ast = CreateNode<ParameterDeclarationAST>(m_pool);
+    ast->setTypeSpec(spec);
+    ast->setDeclarator(decl);
+    ast->setExpression(expr);
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+}
+
+bool Parser::parseClassSpecifier(TypeSpecifierAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    AST *classKey = 0;
+    int classKeyStart = tokenStream->cursor();
+
+    int kind = tokenStream->lookAhead();
+    if (kind == Token_class || kind == Token_struct || kind == Token_union) {
+        AST *asn = CreateNode<AST>(m_pool);
+        classKey = asn;
+        advance();
+        UPDATE_POS(classKey, classKeyStart, tokenStream->cursor());
+    } else {
+        return false;
+    }
+
+    AST *winDeclSpec = 0;
+    parseWinDeclSpec(winDeclSpec);
+
+    while (tokenStream->lookAhead() == Token_identifier && tokenStream->lookAhead(1) == Token_identifier)
+            advance();
+
+    NameAST *name = 0;
+    parseName(name);
+
+    BaseClauseAST *bases = 0;
+    if (tokenStream->lookAhead() == ':') {
+        if (!parseBaseClause(bases)) {
+            skipUntil('{');
+        }
+    }
+
+    if (tokenStream->lookAhead() != '{') {
+        tokenStream->rewind(start);
+        return false;
+    }
+
+    ADVANCE('{', "{");
+
+    ClassSpecifierAST *ast = CreateNode<ClassSpecifierAST>(m_pool);
+    ast->setWinDeclSpec(winDeclSpec);
+    ast->setClassKey(classKey);
+    ast->setName(name);
+    ast->setBaseClause(bases);
+
+    while (tokenStream->lookAhead()) {
+        if (tokenStream->lookAhead() == '}')
+            break;
+
+        DeclarationAST *memSpec = 0;
+        int startDecl = tokenStream->cursor();
+        if (!parseMemberSpecification(memSpec)) {
+            if (startDecl == tokenStream->cursor())
+                advance(); // skip at least one token
+            skipUntilDeclaration();
+        } else
+            ast->addDeclaration(memSpec);
+    }
+
+    if (tokenStream->lookAhead() != '}') {
+        reportError(i18n("} missing"));
+    } else
+        advance();
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+}
+
+bool Parser::parseAccessSpecifier(AST *&node)
+{
+    int start = tokenStream->cursor();
+
+    switch(tokenStream->lookAhead()) {
+    case Token_public:
+    case Token_protected:
+    case Token_private: {
+        AST *asn = CreateNode<AST>(m_pool);
+        node = asn;
+        advance();
+        UPDATE_POS(node, start, tokenStream->cursor());
+        return true;
+        }
+    }
+
+    return false;
+}
+
+bool Parser::parseMemberSpecification(DeclarationAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    AST *access = 0;
+
+    if (tokenStream->lookAhead() == ';') {
+        advance();
+        return true;
+    } else if (tokenStream->lookAhead() == Token_Q_OBJECT || tokenStream->lookAhead() == Token_K_DCOP) {
+        advance();
+        return true;
+    } else if (tokenStream->lookAhead() == Token_signals
+            || tokenStream->lookAhead() == Token_k_dcop
+            || tokenStream->lookAhead() == Token_k_dcop_signals) {
+        AccessDeclarationAST *ast = CreateNode<AccessDeclarationAST>(m_pool);
+        advance();
+        AST *n = CreateNode<AST>(m_pool);
+        UPDATE_POS(n, start, tokenStream->cursor());
+        ast->addAccess(n);
+        ADVANCE(':', ":");
+        UPDATE_POS(ast, start, tokenStream->cursor());
+        node = ast;
+        return true;
+    } else if (parseTypedef(node)) {
+        return true;
+    } else if (parseUsing(node)) {
+        return true;
+    } else if (parseTemplateDeclaration(node)) {
+        return true;
+    } else if (parseAccessSpecifier(access)) {
+        AccessDeclarationAST *ast = CreateNode<AccessDeclarationAST>(m_pool);
+        ast->addAccess(access);
+
+        int startSlot = tokenStream->cursor();
+        if (tokenStream->lookAhead() == Token_slots) {
+            advance();
+            AST *sl = CreateNode<AST>(m_pool);
+            UPDATE_POS(sl, startSlot, tokenStream->cursor());
+            ast->addAccess(sl);
+        }
+        ADVANCE(':', ":");
+        UPDATE_POS(ast, start, tokenStream->cursor());
+        node = ast;
+        return true;
+    }
+
+    tokenStream->rewind(start);
+
+    AST *storageSpec = 0;
+    parseStorageClassSpecifier(storageSpec);
+
+    AST *cv = 0;
+    parseCvQualify(cv);
+
+    TypeSpecifierAST *spec = 0;
+    if (parseEnumSpecifier(spec) || parseClassSpecifier(spec)) {
+        spec->setCvQualify(cv);
+
+        AST *cv2 = 0;
+        parseCvQualify(cv2);
+        spec->setCv2Qualify(cv2);
+
+            InitDeclaratorListAST *declarators = 0;
+        parseInitDeclaratorList(declarators);
+        ADVANCE(';', ";");
+
+        SimpleDeclarationAST *ast = CreateNode<SimpleDeclarationAST>(m_pool);
+        ast->setTypeSpec(spec);
+        ast->setInitDeclaratorList(declarators);
+        UPDATE_POS(ast, start, tokenStream->cursor());
+        node = ast;
+
+        return true;
+    }
+
+    tokenStream->rewind(start);
+    return parseDeclarationInternal(node);
+}
+
+bool Parser::parseCtorInitializer(AST *&/*node*/)
+{
+    if (tokenStream->lookAhead() != ':') {
+        return false;
+    }
+    advance();
+
+    AST *inits = 0;
+    if (!parseMemInitializerList(inits)) {
+        reportError(i18n("Member initializers expected"));
+    }
+
+    return true;
+}
+
+bool Parser::parseElaboratedTypeSpecifier(TypeSpecifierAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    int tk = tokenStream->lookAhead();
+    if (tk == Token_class  ||
+        tk == Token_struct ||
+        tk == Token_union  ||
+        tk == Token_enum   ||
+        tk == Token_typename)
+    {
+        AST *kind = CreateNode<AST>(m_pool);
+        advance();
+        UPDATE_POS(kind, start, tokenStream->cursor());
+
+        NameAST *name = 0;
+
+        if (parseName(name)) {
+            ElaboratedTypeSpecifierAST *ast = CreateNode<ElaboratedTypeSpecifierAST>(m_pool);
+            ast->setKind(kind);
+            ast->setName(name);
+            UPDATE_POS(ast, start, tokenStream->cursor());
+            node = ast;
+
+            return true;
+        }
+    }
+
+    tokenStream->rewind(start);
+    return false;
+}
+
+bool Parser::parseDeclaratorId(NameAST *&node)
+{
+    return parseName(node);
+}
+
+bool Parser::parseExceptionSpecification(AST *&node)
+{
+    if (tokenStream->lookAhead() != Token_throw) {
+        return false;
+    }
+    advance();
+
+    ADVANCE('(', "(");
+    if (tokenStream->lookAhead() == Token_ellipsis) {
+        // extension found in MSVC++ 7.x headers
+        int start = tokenStream->cursor();
+        AST *ast = CreateNode<AST>(m_pool);
+        AST_FROM_TOKEN(ellipsis, tokenStream->cursor());
+        ellipsis->setParent(ast);
+        advance();
+        UPDATE_POS(ast, start, tokenStream->cursor());
+        node = ast;
+    } else {
+        parseTypeIdList(node);
+    }
+    ADVANCE(')', ")");
+
+    return true;
+}
+
+bool Parser::parseEnumerator(EnumeratorAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    if (tokenStream->lookAhead() != Token_identifier) {
+        return false;
+    }
+    advance();
+
+    EnumeratorAST *ena = CreateNode<EnumeratorAST>(m_pool);
+    node = ena;
+
+    AST *id = CreateNode<AST>(m_pool);
+    UPDATE_POS(id, start, tokenStream->cursor());
+    node->setId(id);
+
+    if (tokenStream->lookAhead() == '=') {
+        advance();
+
+        AbstractExpressionAST *expr = 0;
+        if (!parseConstantExpression(expr)) {
+            reportError(i18n("Constant expression expected"));
+        }
+        node->setExpression(expr);
+    }
+
+    UPDATE_POS(node, start, tokenStream->cursor());
+
+    return true;
+}
+
+bool Parser::parseInitDeclarator(InitDeclaratorAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    DeclaratorAST *decl = 0;
+    AST *init = 0;
+    if (!parseDeclarator(decl)) {
+        return false;
+    }
+
+    parseInitializer(init);
+
+    InitDeclaratorAST *ast = CreateNode<InitDeclaratorAST>(m_pool);
+    ast->setDeclarator(decl);
+    ast->setInitializer(init);
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+}
+
+
+
+bool Parser::parseBaseClause(BaseClauseAST *&node)
+{
+    int start = tokenStream->cursor();
+    if (tokenStream->lookAhead() != ':') {
+        return false;
+    }
+    advance();
+
+    BaseClauseAST *bca = CreateNode<BaseClauseAST>(m_pool);
+
+    BaseSpecifierAST *baseSpec = 0;
+    if (parseBaseSpecifier(baseSpec)) {
+        bca->addBaseSpecifier(baseSpec);
+
+        while (tokenStream->lookAhead() == ',') {
+            advance();
+
+            if (!parseBaseSpecifier(baseSpec)) {
+                reportError(i18n("Base class specifier expected"));
+                return false;
+            }
+            bca->addBaseSpecifier(baseSpec);
+        }
+    } else
+        return false;
+
+    UPDATE_POS(bca, start, tokenStream->cursor());
+    node = bca;
+
+    return true;
+}
+
+bool Parser::parseInitializer(AST *&node)
+{
+    if (tokenStream->lookAhead() == '=') {
+        advance();
+
+        if (!parseInitializerClause(node)) {
+            reportError(i18n("Initializer clause expected"));
+            return false;
+        }
+        return true;
+    } else if (tokenStream->lookAhead() == '(') {
+        advance();
+        AbstractExpressionAST *expr = 0;
+        skipCommaExpression(expr);
+        CHECK(')', ")");
+        node = expr;
+        return true;
+    }
+
+    return false;
+}
+
+bool Parser::parseMemInitializerList(AST *&/*node*/)
+{
+    AST *init = 0;
+    if (!parseMemInitializer(init)) {
+        return false;
+    }
+
+    while (tokenStream->lookAhead() == ',') {
+        advance();
+
+        if (!parseMemInitializer(init)) {
+            break;
+        }
+    }
+
+    return true;
+}
+
+bool Parser::parseMemInitializer(AST *&/*node*/)
+{
+    NameAST *initId = 0;
+    if (!parseMemInitializerId(initId)) {
+        reportError(i18n("Identifier expected"));
+        return false;
+    }
+    ADVANCE('(', "(");
+    AbstractExpressionAST *expr = 0;
+    skipCommaExpression(expr);
+    ADVANCE(')', ")");
+
+    return true;
+}
+
+bool Parser::parseTypeIdList(AST *&node)
+{
+
+    int start = tokenStream->cursor();
+
+    TypeIdAST *typeId = 0;
+    if (!parseTypeId(typeId)) {
+        return false;
+    }
+
+    AST *ast = CreateNode<AST>(m_pool);
+    typeId->setParent(ast);
+
+    while (tokenStream->lookAhead() == ',') {
+        advance();
+        if (parseTypeId(typeId)) {
+            typeId->setParent(ast);
+        } else {
+            reportError(i18n("Type id expected"));
+            break;
+        }
+    }
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+    return true;
+}
+
+bool Parser::parseBaseSpecifier(BaseSpecifierAST *&node)
+{
+    int start = tokenStream->cursor();
+    BaseSpecifierAST *ast = CreateNode<BaseSpecifierAST>(m_pool);
+
+    AST *access = 0;
+    if (tokenStream->lookAhead() == Token_virtual) {
+        AST_FROM_TOKEN(virt, tokenStream->cursor());
+        ast->setIsVirtual(virt);
+
+        advance();
+
+        parseAccessSpecifier(access);
+    } else {
+        parseAccessSpecifier(access);
+
+        if (tokenStream->lookAhead() == Token_virtual) {
+            AST_FROM_TOKEN(virt, tokenStream->cursor());
+            ast->setIsVirtual(virt);
+            advance();
+        }
+    }
+
+    NameAST *name = 0;
+    if (!parseName(name)) {
+        reportError(i18n("Class name expected"));
+    }
+
+    ast->setAccess(access);
+    ast->setName(name);
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+}
+
+
+bool Parser::parseInitializerClause(AST *&node)
+{
+    if (tokenStream->lookAhead() == '{') {
+        if (!skip('{','}')) {
+            reportError(i18n("} missing"));
+        } else
+            advance();
+    } else {
+        AbstractExpressionAST *expr = 0;
+        if (!parseAssignmentExpression(expr)) {
+            //reportError(i18n("Expression expected"));
+        }
+        node = expr;
+    }
+
+    return true;
+}
+
+bool Parser::parseMemInitializerId(NameAST *&node)
+{
+
+    return parseName(node);
+}
+
+bool Parser::parsePtrToMember(AST *&/*node*/)     /// ### create the AST node
+{
+    int start = tokenStream->cursor();
+
+    if (tokenStream->lookAhead() == Token_scope)
+        advance();
+
+    ClassOrNamespaceNameAST *name = 0;
+    while (tokenStream->lookAhead() == Token_identifier) {
+
+        if (!parseUnqualifiedName(name))
+            break;
+
+        if (tokenStream->lookAhead() == Token_scope
+                && tokenStream->lookAhead(1) == '*') {
+            advance();
+            advance();
+            return true;
+        }
+
+        if (tokenStream->lookAhead() == Token_scope)
+            advance();
+    }
+
+    tokenStream->rewind(start);
+    return false;
+}
+
+bool Parser::parseUnqualifiedName(ClassOrNamespaceNameAST *&node, bool parseTemplateId)
+{
+    int start = tokenStream->cursor();
+    bool isDestructor = false;
+
+    ClassOrNamespaceNameAST *ast = CreateNode<ClassOrNamespaceNameAST>(m_pool);
+
+    if (tokenStream->lookAhead() == Token_identifier) {
+        int startName = tokenStream->cursor();
+        AST *n = CreateNode<AST>(m_pool);
+        advance();
+        UPDATE_POS(n, startName, tokenStream->cursor());
+        ast->setName(n);
+    } else if (tokenStream->lookAhead() == '~' && tokenStream->lookAhead(1) == Token_identifier) {
+        int startName = tokenStream->cursor();
+        AST *n = CreateNode<AST>(m_pool);
+        advance(); // skip ~
+        advance(); // skip classname
+        UPDATE_POS(n, startName, tokenStream->cursor());
+        ast->setName(n);
+        isDestructor = true;
+    } else if (tokenStream->lookAhead() == Token_operator) {
+        AST *n = 0;
+        if (!parseOperatorFunctionId(n))
+            return false;
+        ast->setName(n);
+    } else {
+        return false;
+    }
+
+    if (parseTemplateId && !isDestructor) {
+
+        int index = tokenStream->cursor();
+
+        if (tokenStream->lookAhead() == '<') {
+            advance();
+
+            // optional template arguments
+            TemplateArgumentListAST *args = 0;
+            parseTemplateArgumentList(args);
+
+            if (tokenStream->lookAhead() != '>') {
+                tokenStream->rewind(index);
+            } else {
+                advance();
+                ast->setTemplateArgumentList(args);
+            }
+        }
+    }
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+}
+
+bool Parser::parseStringLiteral(AST *&node)
+{
+    int start = tokenStream->cursor();
+
+    while (tokenStream->lookAhead()) {
+        if (tokenStream->lookAhead() == Token_identifier &&
+            tokenStream->currentTokenText() == "L" && tokenStream->lookAhead(1) == Token_string_literal) {
+
+            advance();
+            advance();
+        } else if (tokenStream->lookAhead() == Token_string_literal) {
+            advance();
+        } else
+            return false;
+    }
+
+    AST *ast = CreateNode<AST>(m_pool);
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+    return true;
+}
+
+bool Parser::skipExpressionStatement(StatementAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    AbstractExpressionAST *expr = 0;
+    skipCommaExpression(expr);
+
+    ADVANCE(';', ";");
+
+    ExpressionStatementAST *ast = CreateNode<ExpressionStatementAST>(m_pool);
+    ast->setExpression(expr);
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+}
+
+bool Parser::parseStatement(StatementAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    switch(tokenStream->lookAhead()) {
+
+    case Token_while:
+        return parseWhileStatement(node);
+
+    case Token_do:
+        return parseDoStatement(node);
+
+    case Token_for:
+        return parseForStatement(node);
+
+    case Token_if:
+        return parseIfStatement(node);
+
+    case Token_switch:
+        return parseSwitchStatement(node);
+
+    case Token_try:
+        return parseTryBlockStatement(node);
+
+    case Token_case:
+    case Token_default:
+        return parseLabeledStatement(node);
+
+    case Token_break:
+    case Token_continue:
+        advance();
+        ADVANCE(';', ";");
+        return true;
+
+    case Token_goto:
+        advance();
+        ADVANCE(Token_identifier, "identifier");
+        ADVANCE(';', ";");
+        return true;
+
+    case Token_return:
+    {
+        advance();
+        AbstractExpressionAST *expr = 0;
+        skipCommaExpression(expr);
+
+        ADVANCE(';', ";");
+
+        ReturnStatementAST *ast = CreateNode<ReturnStatementAST>(m_pool);
+        ast->setExpression(expr);
+        UPDATE_POS(ast, start, tokenStream->cursor());
+        node = ast;
+    }
+    return true;
+
+    case '{':
+        return parseCompoundStatement(node);
+
+    case Token_identifier:
+        if (parseLabeledStatement(node))
+            return true;
+        break;
+    }
+
+    if (parseDeclarationStatement(node))
+        return true;
+
+    return skipExpressionStatement(node);
+}
+
+bool Parser::parseCondition(ConditionAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    ConditionAST *ast = CreateNode<ConditionAST>(m_pool);
+    TypeSpecifierAST *spec = 0;
+
+    if (parseTypeSpecifier(spec)) {
+        DeclaratorAST *decl = 0;
+        if (parseDeclarator(decl) && tokenStream->lookAhead() == '=') {
+            advance();
+
+            AbstractExpressionAST *expr = 0;
+            if (parseExpression(expr)) {
+                ast->setTypeSpec(spec);
+                ast->setDeclarator(decl);
+                ast->setExpression(expr);
+
+                UPDATE_POS(ast, start, tokenStream->cursor());
+                node = ast;
+
+                return true;
+            }
+        }
+    }
+
+    tokenStream->rewind(start);
+
+    AbstractExpressionAST *expr = 0;
+    if (!skipCommaExpression(expr)) {
+        return false;
+    }
+
+    ast->setExpression(expr);
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+    return true;
+}
+
+
+bool Parser::parseWhileStatement(StatementAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    ADVANCE(Token_while, "while");
+    ADVANCE('(' , "(");
+
+    ConditionAST *cond = 0;
+    if (!parseCondition(cond)) {
+        reportError(i18n("condition expected"));
+        return false;
+    }
+    ADVANCE(')', ")");
+
+    StatementAST *body = 0;
+    if (!parseStatement(body)) {
+        reportError(i18n("statement expected"));
+        return false;
+    }
+
+    WhileStatementAST *ast = CreateNode<WhileStatementAST>(m_pool);
+    ast->setCondition(cond);
+    ast->setStatement(body);
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+}
+
+bool Parser::parseDoStatement(StatementAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    ADVANCE(Token_do, "do");
+
+    StatementAST *body = 0;
+    if (!parseStatement(body)) {
+        reportError(i18n("statement expected"));
+        //return false;
+    }
+
+    ADVANCE_NR(Token_while, "while");
+    ADVANCE_NR('(' , "(");
+
+    AbstractExpressionAST *expr = 0;
+    if (!skipCommaExpression(expr)) {
+        reportError(i18n("expression expected"));
+        //return false;
+    }
+
+    ADVANCE_NR(')', ")");
+    ADVANCE_NR(';', ";");
+
+    DoStatementAST *ast = CreateNode<DoStatementAST>(m_pool);
+    ast->setStatement(body);
+    //ast->setCondition(condition);
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+}
+
+bool Parser::parseForStatement(StatementAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    ADVANCE(Token_for, "for");
+    ADVANCE('(', "(");
+
+    StatementAST *init = 0;
+    if (!parseForInitStatement(init)) {
+        reportError(i18n("for initialization expected"));
+        return false;
+    }
+
+    ConditionAST *cond = 0;
+    parseCondition(cond);
+    ADVANCE(';', ";");
+
+    AbstractExpressionAST *expr = 0;
+    skipCommaExpression(expr);
+    ADVANCE(')', ")");
+
+    StatementAST *body = 0;
+    if (!parseStatement(body))
+        return false;
+
+    ForStatementAST *ast = CreateNode<ForStatementAST>(m_pool);
+    ast->setInitStatement(init);
+    ast->setCondition(cond);
+    // ast->setExpression(expression);
+    ast->setStatement(body);
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+}
+
+bool Parser::parseForInitStatement(StatementAST *&node)
+{
+    if (parseDeclarationStatement(node))
+        return true;
+
+    return skipExpressionStatement(node);
+}
+
+bool Parser::parseCompoundStatement(StatementAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    if (tokenStream->lookAhead() != '{') {
+        return false;
+    }
+    advance();
+
+    StatementListAST *ast = CreateNode<StatementListAST>(m_pool);
+
+    while (tokenStream->lookAhead()) {
+        if (tokenStream->lookAhead() == '}')
+            break;
+
+        StatementAST *stmt = 0;
+        int startStmt = tokenStream->cursor();
+        if (!parseStatement(stmt)) {
+            if (startStmt == tokenStream->cursor())
+                advance();
+            skipUntilStatement();
+        } else {
+            ast->addStatement(stmt);
+        }
+    }
+
+    if (tokenStream->lookAhead() != '}') {
+        reportError(i18n("} expected"));
+    } else {
+        advance();
+    }
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+}
+
+bool Parser::parseIfStatement(StatementAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    ADVANCE(Token_if, "if");
+
+    ADVANCE('(' , "(");
+
+    IfStatementAST *ast = CreateNode<IfStatementAST>(m_pool);
+
+    ConditionAST *cond = 0;
+    if (!parseCondition(cond)) {
+        reportError(i18n("condition expected"));
+        return false;
+    }
+    ADVANCE(')', ")");
+
+    StatementAST *stmt = 0;
+    if (!parseStatement(stmt)) {
+        reportError(i18n("statement expected"));
+        return false;
+    }
+
+    ast->setCondition(cond);
+    ast->setStatement(stmt);
+
+    if (tokenStream->lookAhead() == Token_else) {
+        advance();
+        StatementAST *elseStmt = 0;
+        if (!parseStatement(elseStmt)) {
+            reportError(i18n("statement expected"));
+            return false;
+        }
+        ast->setElseStatement(elseStmt);
+    }
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+}
+
+bool Parser::parseSwitchStatement(StatementAST *&node)
+{
+    int start = tokenStream->cursor();
+    ADVANCE(Token_switch, "switch");
+
+    ADVANCE('(' , "(");
+
+    ConditionAST *cond = 0;
+    if (!parseCondition(cond)) {
+        reportError(i18n("condition expected"));
+        return false;
+    }
+    ADVANCE(')', ")");
+
+    StatementAST *stmt = 0;
+    if (!parseStatement(stmt)) {
+          syntaxError();
+        return false;
+    }
+
+    SwitchStatementAST *ast = CreateNode<SwitchStatementAST>(m_pool);
+    ast->setCondition(cond);
+    ast->setStatement(stmt);
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+}
+
+bool Parser::parseLabeledStatement(StatementAST *&node)
+{
+    switch(tokenStream->lookAhead()) {
+    case Token_identifier:
+    case Token_default:
+        if (tokenStream->lookAhead(1) == ':') {
+            advance();
+            advance();
+
+            StatementAST *stmt = 0;
+            LabeledStatementAST *ast = CreateNode<LabeledStatementAST>(m_pool);
+            node = ast;
+            if (parseStatement(stmt)) {
+                ast->setStatement(stmt);
+                return true;
+            }
+        }
+        break;
+
+    case Token_case:
+    {
+        advance();
+        AbstractExpressionAST *expr = 0;
+        if (!parseConstantExpression(expr)) {
+            reportError(i18n("expression expected"));
+        } else if (tokenStream->lookAhead() == Token_ellipsis) {
+            advance();
+
+            AbstractExpressionAST *expr2 = 0;
+            if (!parseConstantExpression(expr2)) {
+                reportError(i18n("expression expected"));
+            }
+        }
+        ADVANCE(':', ":");
+
+        StatementAST *stmt = 0;
+        LabeledStatementAST *ast = CreateNode<LabeledStatementAST>(m_pool);
+        node = ast;
+        ast->setExpression(expr);
+
+        if (parseStatement(stmt)) {
+            ast->setStatement(stmt);
+            return true;
+        }
+    }
+    break;
+
+    }
+    return false;
+}
+
+bool Parser::parseBlockDeclaration(DeclarationAST *&node)
+{
+    switch(tokenStream->lookAhead()) {
+    case Token_typedef:
+        return parseTypedef(node);
+    case Token_using:
+        return parseUsing(node);
+    case Token_asm:
+        return parseAsmDefinition(node);
+    case Token_namespace:
+        return parseNamespaceAliasDefinition(node);
+    }
+
+    int start = tokenStream->cursor();
+
+    AST *storageSpec = 0;
+    parseStorageClassSpecifier(storageSpec);
+
+    AST *cv = 0;
+    parseCvQualify(cv);
+
+    TypeSpecifierAST *spec = 0;
+    if (!parseTypeSpecifierOrClassSpec(spec)) { // replace with simpleTypeSpecifier?!?!
+        tokenStream->rewind(start);
+        return false;
+    }
+    spec->setCvQualify(cv);
+
+    AST *cv2 = 0;
+    parseCvQualify(cv2);
+    spec->setCv2Qualify(cv2);
+
+    InitDeclaratorListAST *declarators = 0;
+    parseInitDeclaratorList(declarators);
+
+    if (tokenStream->lookAhead() != ';') {
+        tokenStream->rewind(start);
+        return false;
+    }
+    advance();
+
+    SimpleDeclarationAST *ast = CreateNode<SimpleDeclarationAST>(m_pool);
+    ast->setTypeSpec(spec);
+    ast->setInitDeclaratorList(declarators);
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+}
+
+bool Parser::parseNamespaceAliasDefinition(DeclarationAST *&/*node*/)
+{
+    if (tokenStream->lookAhead() != Token_namespace) {
+        return false;
+    }
+    advance();
+
+    ADVANCE(Token_identifier,  "identifier");
+    ADVANCE('=', "=");
+
+    NameAST *name = 0;
+    if (!parseName(name)) {
+        reportError(i18n("Namespace name expected"));
+    }
+
+    ADVANCE(';', ";");
+
+    return true;
+
+}
+
+bool Parser::parseDeclarationStatement(StatementAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    DeclarationAST *decl = 0;
+    if (!parseBlockDeclaration(decl))
+        return false;
+
+    DeclarationStatementAST *ast = CreateNode<DeclarationStatementAST>(m_pool);
+    ast->setDeclaration(decl);
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+}
+
+bool Parser::parseDeclarationInternal(DeclarationAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    // that is for the case '__declspec(dllexport) int ...' or
+    // '__declspec(dllexport) inline int ...', etc.
+    AST *winDeclSpec = 0;
+    parseWinDeclSpec(winDeclSpec);
+
+    AST *funSpec = 0;
+    bool hasFunSpec = parseFunctionSpecifier(funSpec);
+
+    AST *storageSpec = 0;
+    bool hasStorageSpec = parseStorageClassSpecifier(storageSpec);
+
+    if (hasStorageSpec && !hasFunSpec)
+        hasFunSpec = parseFunctionSpecifier(funSpec);
+
+    // that is for the case 'friend __declspec(dllexport) ....'
+    AST *winDeclSpec2 = 0;
+    parseWinDeclSpec(winDeclSpec2);
+
+    AST *cv = 0;
+    parseCvQualify(cv);
+
+    int index = tokenStream->cursor();
+    NameAST *name = 0;
+    if (parseName(name) && tokenStream->lookAhead() == '(') {
+        // no type specifier, maybe a constructor or a cast operator??
+
+        tokenStream->rewind(index);
+
+        InitDeclaratorAST *declarator = 0;
+        if (parseInitDeclarator(declarator)) {
+            switch(tokenStream->lookAhead()) {
+            case ';':
+                {
+                    advance();
+
+                    InitDeclaratorListAST *declarators = CreateNode<InitDeclaratorListAST>(m_pool);
+
+                    // update declarators position
+                    if (declarator)
+                        declarators->setPosition(declarator->startToken(), declarator->endToken());
+                    declarators->addInitDeclarator(declarator);
+
+                    SimpleDeclarationAST *ast = CreateNode<SimpleDeclarationAST>(m_pool);
+                    ast->setInitDeclaratorList(declarators);
+                    node = ast;
+                    UPDATE_POS(node, start, tokenStream->cursor());
+                    return true;
+
+                }
+                break;
+
+            case ':':
+                {
+                    AST *ctorInit = 0;
+                    StatementListAST *funBody = 0;
+                    if (parseCtorInitializer(ctorInit) && parseFunctionBody(funBody)) {
+                        FunctionDefinitionAST *ast = CreateNode<FunctionDefinitionAST>(m_pool);
+                        ast->setStorageSpecifier(storageSpec);
+                        ast->setFunctionSpecifier(funSpec);
+                        ast->setInitDeclarator(declarator);
+                        ast->setFunctionBody(funBody);
+                        node = ast;
+                        UPDATE_POS(node, start, tokenStream->cursor());
+                        return true;
+                    }
+                }
+                break;
+
+            case '{':
+                {
+                    StatementListAST *funBody = 0;
+                    if (parseFunctionBody(funBody)) {
+                        FunctionDefinitionAST *ast = CreateNode<FunctionDefinitionAST>(m_pool);
+                        ast->setStorageSpecifier(storageSpec);
+                        ast->setFunctionSpecifier(funSpec);
+                        ast->setInitDeclarator(declarator);
+                        ast->setFunctionBody(funBody);
+                        node = ast;
+                        UPDATE_POS(node, start, tokenStream->cursor());
+                        return true;
+                    }
+                }
+                break;
+
+            case '(':
+            case '[':
+                // ops!! it seems a declarator
+                goto start_decl;
+                break;
+            }
+
+        }
+    }
+
+start_decl:
+    tokenStream->rewind(index);
+
+    if (tokenStream->lookAhead() == Token_const && tokenStream->lookAhead(1) == Token_identifier && tokenStream->lookAhead(2) == '=') {
+        // constant definition
+        advance();
+        InitDeclaratorListAST *declarators = 0;
+        if (parseInitDeclaratorList(declarators)) {
+            ADVANCE(';', ";");
+            DeclarationAST *ast = CreateNode<DeclarationAST>(m_pool);
+            node = ast;
+            UPDATE_POS(node, start, tokenStream->cursor());
+            return true;
+        }
+        syntaxError();
+        return false;
+    }
+
+    TypeSpecifierAST *spec = 0;
+    if (parseTypeSpecifier(spec)) {
+        if (!hasFunSpec)
+            parseFunctionSpecifier(funSpec);         // e.g. "void inline"
+        spec->setCvQualify(cv);
+
+        InitDeclaratorListAST *declarators = 0;
+
+        InitDeclaratorAST *decl = 0;
+        int startDeclarator = tokenStream->cursor();
+        bool maybeFunctionDefinition = false;
+
+        if (tokenStream->lookAhead() != ';') {
+            if (parseInitDeclarator(decl) && tokenStream->lookAhead() == '{') {
+                // function definition
+                maybeFunctionDefinition = true;
+            } else {
+                tokenStream->rewind(startDeclarator);
+                if (!parseInitDeclaratorList(declarators)) {
+                    syntaxError();
+                    return false;
+                }
+            }
+        }
+
+        switch(tokenStream->lookAhead()) {
+        case ';':
+            {
+                advance();
+                SimpleDeclarationAST *ast = CreateNode<SimpleDeclarationAST>(m_pool);
+                ast->setStorageSpecifier(storageSpec);
+                ast->setFunctionSpecifier(funSpec);
+                ast->setTypeSpec(spec);
+                ast->setWinDeclSpec(winDeclSpec);
+                ast->setInitDeclaratorList(declarators);
+                node = ast;
+                UPDATE_POS(node, start, tokenStream->cursor());
+            }
+            return true;
+
+        case '{':
+            {
+                if (!maybeFunctionDefinition) {
+                    syntaxError();
+                    return false;
+                }
+                StatementListAST *funBody = 0;
+                if (parseFunctionBody(funBody)) {
+                    FunctionDefinitionAST *ast = CreateNode<FunctionDefinitionAST>(m_pool);
+                    ast->setWinDeclSpec(winDeclSpec);
+                    ast->setStorageSpecifier(storageSpec);
+                    ast->setFunctionSpecifier(funSpec);
+                    ast->setTypeSpec(spec);
+                    ast->setInitDeclarator(decl);
+                    ast->setFunctionBody(funBody);
+                    node = ast;
+                    UPDATE_POS(node, start, tokenStream->cursor());
+                    return true;
+                }
+            }
+            break;
+
+        }
+    }
+
+    syntaxError();
+    return false;
+}
+
+bool Parser::parseFunctionBody(StatementListAST *&node)
+{
+    int start = tokenStream->cursor();
+    if (tokenStream->lookAhead() != '{') {
+        return false;
+    }
+    advance();
+
+    StatementListAST *ast = CreateNode<StatementListAST>(m_pool);
+
+    while (tokenStream->lookAhead()) {
+        if (tokenStream->lookAhead() == '}')
+            break;
+
+        StatementAST *stmt = 0;
+        int startStmt = tokenStream->cursor();
+        if (!parseStatement(stmt)) {
+            syntaxError();
+            if (startStmt == tokenStream->cursor())
+                advance();
+            skipUntilStatement();
+        } else
+            ast->addStatement(stmt);
+    }
+
+    if (tokenStream->lookAhead() != '}') {
+        reportError(i18n("} expected"));
+    } else
+        advance();
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+}
+
+bool Parser::parseTypeSpecifierOrClassSpec(TypeSpecifierAST *&node)
+{
+    if (parseClassSpecifier(node))
+        return true;
+    else if (parseEnumSpecifier(node))
+        return true;
+    else if (parseTypeSpecifier(node))
+        return true;
+
+    return false;
+}
+
+bool Parser::parseTryBlockStatement(StatementAST *&node)
+{
+    if (tokenStream->lookAhead() != Token_try) {
+        return false;
+    }
+    advance();
+
+    StatementAST *stmt = 0;
+    if (!parseCompoundStatement(stmt)) {
+        syntaxError();
+        return false;
+    }
+
+    if (tokenStream->lookAhead() != Token_catch) {
+        reportError(i18n("catch expected"));
+        return false;
+    }
+
+    while (tokenStream->lookAhead() == Token_catch) {
+        advance();
+        ADVANCE('(', "(");
+        ConditionAST *cond = 0;
+        if (tokenStream->lookAhead() == Token_ellipsis) {
+            advance();
+        } else if (!parseCondition(cond)) {
+            reportError(i18n("condition expected"));
+            return false;
+        }
+        ADVANCE(')', ")");
+
+        StatementAST *body = 0;
+        if (!parseCompoundStatement(body)) {
+            syntaxError();
+            return false;
+        }
+    }
+
+    node = stmt;
+    return true;
+}
+
+bool Parser::parsePrimaryExpression(AbstractExpressionAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    AbstractExpressionAST *ast = CreateExpression<NodeType_PrimaryExpression>(m_pool);
+
+    switch(tokenStream->lookAhead()) {
+        case Token_string_literal:
+        {
+            AST *lit = 0;
+            parseStringLiteral(lit);
+            if (lit)
+                lit->setParent(ast);
+        }
+        break;
+
+        case Token_number_literal:
+        case Token_char_literal:
+        case Token_true:
+        case Token_false:
+        case Token_this:
+            {
+                AST_FROM_TOKEN(opNode, tokenStream->cursor());
+                opNode->setParent(ast);
+                advance();
+            }
+            break;
+
+        case '(':
+            {
+                advance();
+
+                if (tokenStream->lookAhead() == '{') {
+                    StatementAST *stmt = 0;
+                    if (!parseCompoundStatement(stmt))
+                        return false;
+                    if (stmt)
+                        stmt->setParent(ast);
+                } else {
+                    AbstractExpressionAST *expr = 0;
+                    if (!parseExpression(expr)) {
+                        return false;
+                    }
+                    if (expr)
+                        expr->setParent(ast);
+                }
+                CHECK(')', ")");
+            }
+            break;
+
+        default:
+            {
+/*  ### reenable me
+                TypeSpecifierAST *typeSpec = 0;
+                if (parseSimpleTypeSpecifier(typeSpec) && tokenStream->lookAhead() == '(') {
+                    Q_ASSERT (0);
+                    advance();
+                    AbstractExpressionAST *expr = 0;
+                    parseCommaExpression(expr);
+                    CHECK(')', ")");
+                    break;
+
+                    if (typeSpec)
+                        typeSpec->setParent(ast);
+
+                    if (expr)
+                        expr->setParent(ast);
+                }
+
+                tokenStream->rewind(start);
+*/
+
+                NameAST *name = 0;
+                if (!parseName(name, false))
+                    return false;
+
+                if (name)
+                    name->setParent(ast);
+
+                break;
+            }
+    }
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+    return true;
+}
+
+
+/*
+   postfix-expression-internal:
+     [ expression ]
+     ( expression-list [opt] )
+     (.|->) template [opt] id-expression
+     (.|->) pseudo-destructor-name
+     ++
+     --
+*/
+bool Parser::parsePostfixExpressionInternal(AbstractExpressionAST *postfixExpr, AbstractExpressionAST *&node)
+{
+    Q_ASSERT (postfixExpr);
+
+    int start = tokenStream->cursor();
+
+    switch (tokenStream->lookAhead()) {
+        case '[':
+        {
+            advance();
+            AbstractExpressionAST *expr = 0;
+            parseExpression(expr);
+            CHECK(']', "]");
+
+            SubscriptingAST *ast = CreateNode<SubscriptingAST>(m_pool);
+            ast->setExpression(postfixExpr);
+            ast->setSubscript(expr);
+            UPDATE_POS(ast, start, tokenStream->cursor());
+            node = ast;
+        }
+        return true;
+
+        case '(':
+        {
+            advance();
+            AbstractExpressionAST *expr = 0;
+            parseExpression(expr);
+            CHECK(')', ")");
+
+            FunctionCallAST *ast = CreateNode<FunctionCallAST>(m_pool);
+            ast->setExpression(postfixExpr);
+            ast->setArguments(expr);
+            UPDATE_POS(ast, start, tokenStream->cursor());
+            node = ast;
+        }
+        return true;
+
+        case '.':
+        case Token_arrow:
+        {
+            AST_FROM_TOKEN(op, tokenStream->cursor());
+
+            advance();
+            if (tokenStream->lookAhead() == Token_template)
+                advance();
+
+            NameAST *name = 0;
+            if (!parseName(name))
+                return false;
+
+            ClassMemberAccessAST *ast = CreateNode<ClassMemberAccessAST>(m_pool);
+            ast->setOp(op);
+            ast->setExpression(postfixExpr);
+            ast->setName(name);
+            UPDATE_POS(ast, start, tokenStream->cursor());
+            node = ast;
+        }
+        return true;
+
+        case Token_incr:
+        case Token_decr:
+        {
+            AST_FROM_TOKEN(op, tokenStream->cursor());
+            advance();
+
+            IncrDecrAST *ast = CreateNode<IncrDecrAST>(m_pool);
+            ast->setExpression(postfixExpr);
+            ast->setOp(op);
+            UPDATE_POS(ast, start, tokenStream->cursor());
+            node = ast;
+        }
+        return true;
+
+        default:
+            return false;
+    }
+}
+
+/*
+   postfix-expression:
+     simple-type-specifier ( expression-list [opt] )
+     primary-expression postfix-expression-internal*
+*/
+bool Parser::parsePostfixExpression(AbstractExpressionAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    switch (tokenStream->lookAhead()) {
+        case Token_dynamic_cast:
+        case Token_static_cast:
+        case Token_reinterpret_cast:
+        case Token_const_cast:
+        {
+            AST_FROM_TOKEN(castOp, tokenStream->cursor());
+
+            advance();
+            CHECK('<', "<");
+            TypeIdAST *typeId = 0;
+            parseTypeId(typeId);
+            CHECK('>', ">");
+
+            CHECK('(', ")");
+            AbstractExpressionAST *expr = 0;
+            parseCommaExpression(expr);
+            CHECK(')', ")");
+
+            CppCastExpressionAST *tmp = CreateNode<CppCastExpressionAST>(m_pool);
+            tmp->setCastOp(castOp);
+            tmp->setTypeId(typeId);
+            tmp->setExpression(expr);
+
+            AbstractExpressionAST *ast = tmp;
+            AbstractExpressionAST *e = 0;
+            while (parsePostfixExpressionInternal(ast, e)) {
+                ast = e;
+            }
+
+            UPDATE_POS(ast, start, tokenStream->cursor());
+            node = ast;
+        }
+        return true;
+
+        case Token_typename:
+        {
+            advance();
+
+            NameAST* name = 0;
+            if (!parseName(name))
+                return false;
+
+            CHECK('(', "(");
+            AbstractExpressionAST *expr = 0;
+            parseCommaExpression(expr);
+            CHECK(')', ")");
+
+            // ### AST
+        }
+        return true;
+
+        case Token_typeid:
+        {
+            advance();
+
+            CHECK('(', "(");
+            AbstractExpressionAST *expr = 0;
+            parseCommaExpression(expr);
+            CHECK(')', ")");
+
+            // ### AST
+        }
+        return true;
+
+        default:
+            break;
+    }
+
+    TypeSpecifierAST *typeSpec = 0;
+    AbstractExpressionAST *expr = 0;
+
+    if (parseSimpleTypeSpecifier(typeSpec/*, true*/) && tokenStream->lookAhead() == '(') {
+        advance(); // skip '('
+        parseCommaExpression(expr);
+        CHECK(')', ")");
+    } else {
+        tokenStream->rewind(start);
+
+        if (!parsePrimaryExpression(expr))
+            return false;
+    }
+
+    AbstractExpressionAST *ast = CreateExpression<NodeType_PostfixExpression>(m_pool);
+    if (typeSpec)
+        typeSpec->setParent(ast);
+
+    if (expr)
+        expr->setParent(ast);
+
+    AbstractExpressionAST *e = 0;
+    while (parsePostfixExpressionInternal(ast, e)) {
+        ast = e;
+    }
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+    return true;
+}
+
+bool Parser::parseUnaryExpression(AbstractExpressionAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    switch(tokenStream->lookAhead()) {
+        case Token_incr:
+        case Token_decr:
+        case '*':
+        case '&':
+        case '+':
+        case '-':
+        case '!':
+        case '~':
+        {
+            AST_FROM_TOKEN(opNode, tokenStream->cursor());
+
+            advance();
+            AbstractExpressionAST *expr = 0;
+            if (!parseCastExpression(expr))
+                return false;
+
+            AbstractExpressionAST *ast = CreateExpression<NodeType_UnaryExpression>(m_pool);
+
+            opNode->setParent(ast);
+            if (expr)
+                expr->setParent(ast);
+
+            UPDATE_POS(ast, start, tokenStream->cursor());
+            node = ast;
+            return true;
+        }
+
+        case Token_sizeof:
+        {
+            AbstractExpressionAST *ast = CreateExpression<NodeType_UnaryExpression>(m_pool);
+
+            AST_FROM_TOKEN(opNode, tokenStream->cursor());
+            opNode->setParent(ast);
+
+            advance();
+            int index = tokenStream->cursor();
+            if (tokenStream->lookAhead() == '(') {
+                advance();
+                TypeIdAST *typeId = 0;
+                if (parseTypeId(typeId) && tokenStream->lookAhead() == ')') {
+                    if (typeId)
+                        typeId->setParent(ast);
+
+                    advance();
+
+                    UPDATE_POS(ast, start, tokenStream->cursor());
+                    node = ast;
+                    return true;
+                }
+                tokenStream->rewind(index);
+            }
+            AbstractExpressionAST *expr = 0;
+            if (!parseUnaryExpression(expr))
+                return false;
+
+            UPDATE_POS(ast, start, tokenStream->cursor());
+            node = ast;
+            return true;
+        }
+
+        case Token_new:
+            return parseNewExpression(node);
+
+        case Token_delete:
+            return parseDeleteExpression(node);
+    }
+
+    return parsePostfixExpression(node);
+}
+
+bool Parser::parseNewExpression(AbstractExpressionAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    AbstractExpressionAST *ast = CreateExpression<NodeType_NewExpression>(m_pool);
+
+    if (tokenStream->lookAhead() == Token_scope && tokenStream->lookAhead(1) == Token_new) {
+        AST_FROM_TOKEN(scopeNode, tokenStream->cursor());
+        scopeNode->setParent(ast);
+        advance();
+    }
+
+    AST_FROM_TOKEN(newNode, tokenStream->cursor());
+    newNode->setParent(ast);
+
+    CHECK(Token_new, "new");
+
+    if (tokenStream->lookAhead() == '(') {
+        advance();
+        AbstractExpressionAST *expr = 0;
+        parseCommaExpression(expr);
+        if (expr)
+            expr->setParent(ast);
+        CHECK(')', ")");
+    }
+
+    if (tokenStream->lookAhead() == '(') {
+        advance();
+        TypeIdAST *typeId = 0;
+        parseTypeId(typeId);
+        if (typeId)
+            typeId->setParent(ast);
+        CHECK(')', ")");
+    } else {
+        AbstractExpressionAST *typeId = 0;
+        parseNewTypeId(typeId);
+        if (typeId)
+            typeId->setParent(ast);
+    }
+
+    AbstractExpressionAST *init = 0;
+    parseNewInitializer(init);
+    if (init)
+        init->setParent(ast);
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+    return true;
+}
+
+bool Parser::parseNewTypeId(AbstractExpressionAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    TypeSpecifierAST *typeSpec = 0;
+    if (!parseTypeSpecifier(typeSpec))
+        return false;
+
+    AbstractExpressionAST *ast = CreateExpression<NodeType_NewTypeId>(m_pool);
+
+    if (typeSpec)
+        typeSpec->setParent(ast);
+
+    AbstractExpressionAST *declarator = 0;
+    parseNewDeclarator(declarator);
+    if (declarator)
+        declarator->setParent(ast);
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+    return true;
+}
+
+bool Parser::parseNewDeclarator(AbstractExpressionAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    AbstractExpressionAST *ast = CreateExpression<NodeType_NewInitializer>(m_pool);
+
+    AST *ptrOp = 0;
+    if (parsePtrOperator(ptrOp)) {
+        if (ptrOp)
+            ptrOp->setParent(ast);
+
+        AbstractExpressionAST *declarator = 0;
+        parseNewDeclarator(declarator);
+
+        if (declarator)
+            declarator->setParent(ast);
+    }
+
+    while (tokenStream->lookAhead() == '[') {
+        advance();
+        AbstractExpressionAST *expr = 0;
+        parseExpression(expr);
+        ADVANCE(']', "]");
+
+        if (expr)
+            expr->setParent(ast);
+    }
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+    return true;
+}
+
+bool Parser::parseNewInitializer(AbstractExpressionAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    if (tokenStream->lookAhead() != '(')
+        return false;
+
+    AbstractExpressionAST *ast = CreateExpression<NodeType_NewInitializer>(m_pool);
+
+    advance();
+    AbstractExpressionAST *expr = 0;
+    parseCommaExpression(expr);
+
+    if (expr)
+        expr->setParent(ast);
+
+    CHECK(')', ")");
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+    return true;
+}
+
+bool Parser::parseDeleteExpression(AbstractExpressionAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    AbstractExpressionAST *ast = CreateExpression<NodeType_DeleteExpression>(m_pool);
+
+    if (tokenStream->lookAhead() == Token_scope && tokenStream->lookAhead(1) == Token_delete) {
+        AST_FROM_TOKEN(scopeNode, tokenStream->cursor());
+        scopeNode->setParent(ast);
+        advance();
+    }
+
+    AST_FROM_TOKEN(deleteNode, tokenStream->cursor());
+    deleteNode->setParent(ast);
+
+    CHECK(Token_delete, "delete");
+
+    if (tokenStream->lookAhead() == '[') {
+        int beg = tokenStream->cursor();
+        advance();
+        CHECK(']', "]");
+
+        AST *n = CreateNode<AST>(m_pool);
+        UPDATE_POS(n, beg, tokenStream->cursor());
+        n->setParent(ast);
+    }
+
+    AbstractExpressionAST *expr = 0;
+    if (!parseCastExpression(expr))
+        return false;
+
+    if (expr)
+        expr->setParent(ast);
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+    return true;
+}
+
+bool Parser::parseCastExpression(AbstractExpressionAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    if (tokenStream->lookAhead() == '(') {
+        AbstractExpressionAST *ast = CreateExpression<NodeType_CastExpression>(m_pool);
+
+        advance();
+        TypeIdAST *typeId = 0;
+        if (parseTypeId(typeId)) {
+
+            if (typeId)
+                typeId->setParent(ast);
+
+            if (tokenStream->lookAhead() == ')') {
+                advance();
+
+                AbstractExpressionAST *expr = 0;
+                if (parseCastExpression(expr)) {
+                    if (expr)
+                        expr->setParent(ast);
+
+                    UPDATE_POS(ast, start, tokenStream->cursor());
+                    node = ast;
+                    return true;
+                }
+            }
+        }
+    }
+
+    tokenStream->rewind(start);
+    return parseUnaryExpression(node);
+}
+
+bool Parser::parsePmExpression(AbstractExpressionAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    AbstractExpressionAST *ast = 0;
+    if (!parseCastExpression(ast) || !ast) // ### fixme
+        return false;
+
+    while (tokenStream->lookAhead() == Token_ptrmem) {
+        int startOp = tokenStream->cursor();
+        AST_FROM_TOKEN(op, startOp);
+        advance();
+
+        AbstractExpressionAST *rightExpr = 0;
+        if (!parseCastExpression(rightExpr))
+            return false;
+
+        BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool);
+        tmp->setOp(op);
+        tmp->setLeftExpression(ast);
+        tmp->setRightExpression(rightExpr);
+        UPDATE_POS(tmp, startOp, tokenStream->cursor());
+        ast = tmp;
+    }
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+    return true;
+}
+
+bool Parser::parseMultiplicativeExpression(AbstractExpressionAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    AbstractExpressionAST *ast = 0;
+    if (!parsePmExpression(ast))
+        return false;
+
+    while (tokenStream->lookAhead() == '*' || tokenStream->lookAhead() == '/' || tokenStream->lookAhead() == '%') {
+        int startOp = tokenStream->cursor();
+        AST_FROM_TOKEN(op, startOp);
+        advance();
+
+        AbstractExpressionAST *rightExpr = 0;
+        if (!parsePmExpression(rightExpr))
+            return false;
+
+        BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool);
+        tmp->setOp(op);
+        tmp->setLeftExpression(ast);
+        tmp->setRightExpression(rightExpr);
+        UPDATE_POS(tmp, startOp, tokenStream->cursor());
+        ast = tmp;
+    }
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+    return true;
+}
+
+
+bool Parser::parseAdditiveExpression(AbstractExpressionAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    AbstractExpressionAST *ast = 0;
+    if (!parseMultiplicativeExpression(ast))
+        return false;
+
+    while (tokenStream->lookAhead() == '+' || tokenStream->lookAhead() == '-') {
+        int startOp = tokenStream->cursor();
+        AST_FROM_TOKEN(op, startOp);
+        advance();
+
+        AbstractExpressionAST *rightExpr = 0;
+        if (!parseMultiplicativeExpression(rightExpr))
+            return false;
+
+        BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool);
+        tmp->setOp(op);
+        tmp->setLeftExpression(ast);
+        tmp->setRightExpression(rightExpr);
+        UPDATE_POS(tmp, startOp, tokenStream->cursor());
+        ast = tmp;
+    }
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+    return true;
+}
+
+bool Parser::parseShiftExpression(AbstractExpressionAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    AbstractExpressionAST *ast = 0;
+    if (!parseAdditiveExpression(ast))
+        return false;
+
+    while (tokenStream->lookAhead() == Token_shift) {
+        int startOp = tokenStream->cursor();
+        AST_FROM_TOKEN(op, startOp);
+        advance();
+
+        AbstractExpressionAST *rightExpr = 0;
+        if (!parseAdditiveExpression(rightExpr))
+            return false;
+
+        BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool);
+        tmp->setOp(op);
+        tmp->setLeftExpression(ast);
+        tmp->setRightExpression(rightExpr);
+        UPDATE_POS(tmp, startOp, tokenStream->cursor());
+        ast = tmp;
+    }
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+    return true;
+}
+
+bool Parser::parseRelationalExpression(AbstractExpressionAST *&node, bool templArgs)
+{
+    int start = tokenStream->cursor();
+
+    AbstractExpressionAST *ast = 0;
+    if (!parseShiftExpression(ast))
+        return false;
+
+    while (tokenStream->lookAhead() == '<' || (tokenStream->lookAhead() == '>' && !templArgs) ||
+           tokenStream->lookAhead() == Token_leq || tokenStream->lookAhead() == Token_geq) {
+        int startOp = tokenStream->cursor();
+        AST_FROM_TOKEN(op, startOp);
+        advance();
+
+        AbstractExpressionAST *rightExpr = 0;
+        if (!parseShiftExpression(rightExpr))
+            return false;
+
+        BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool);
+        tmp->setOp(op);
+        tmp->setLeftExpression(ast);
+        tmp->setRightExpression(rightExpr);
+        UPDATE_POS(tmp, startOp, tokenStream->cursor());
+        ast = tmp;
+    }
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+    return true;
+}
+
+bool Parser::parseEqualityExpression(AbstractExpressionAST *&node, bool templArgs)
+{
+    int start = tokenStream->cursor();
+
+    AbstractExpressionAST *ast = 0;
+    if (!parseRelationalExpression(ast, templArgs))
+        return false;
+
+    while (tokenStream->lookAhead() == Token_eq || tokenStream->lookAhead() == Token_not_eq) {
+        int startOp = tokenStream->cursor();
+        AST_FROM_TOKEN(op, startOp);
+        advance();
+
+        AbstractExpressionAST *rightExpr = 0;
+        if (!parseRelationalExpression(rightExpr, templArgs))
+            return false;
+
+        BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool);
+        tmp->setOp(op);
+        tmp->setLeftExpression(ast);
+        tmp->setRightExpression(rightExpr);
+        UPDATE_POS(tmp, startOp, tokenStream->cursor());
+        ast = tmp;
+    }
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+    return true;
+}
+
+bool Parser::parseAndExpression(AbstractExpressionAST *&node, bool templArgs)
+{
+    int start = tokenStream->cursor();
+
+    AbstractExpressionAST *ast = 0;
+    if (!parseEqualityExpression(ast, templArgs))
+        return false;
+
+    while (tokenStream->lookAhead() == '&') {
+        int startOp = tokenStream->cursor();
+        AST_FROM_TOKEN(op, startOp);
+        advance();
+
+        AbstractExpressionAST *rightExpr = 0;
+        if (!parseEqualityExpression(rightExpr, templArgs))
+            return false;
+
+        BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool);
+        tmp->setOp(op);
+        tmp->setLeftExpression(ast);
+        tmp->setRightExpression(rightExpr);
+        UPDATE_POS(tmp, startOp, tokenStream->cursor());
+        ast = tmp;
+    }
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+    return true;
+}
+
+bool Parser::parseExclusiveOrExpression(AbstractExpressionAST *&node, bool templArgs)
+{
+    int start = tokenStream->cursor();
+
+    AbstractExpressionAST *ast = 0;
+    if (!parseAndExpression(ast, templArgs))
+        return false;
+
+    while (tokenStream->lookAhead() == '^') {
+        int startOp = tokenStream->cursor();
+        AST_FROM_TOKEN(op, startOp);
+        advance();
+
+        AbstractExpressionAST *rightExpr = 0;
+        if (!parseAndExpression(rightExpr, templArgs))
+            return false;
+
+        BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool);
+        tmp->setOp(op);
+        tmp->setLeftExpression(ast);
+        tmp->setRightExpression(rightExpr);
+        UPDATE_POS(tmp, startOp, tokenStream->cursor());
+        ast = tmp;
+    }
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+    return true;
+}
+
+bool Parser::parseInclusiveOrExpression(AbstractExpressionAST *&node, bool templArgs)
+{
+    int start = tokenStream->cursor();
+
+    AbstractExpressionAST *ast = 0;
+    if (!parseExclusiveOrExpression(ast, templArgs))
+        return false;
+
+    while (tokenStream->lookAhead() == '|') {
+        int startOp = tokenStream->cursor();
+        AST_FROM_TOKEN(op, startOp);
+        advance();
+
+        AbstractExpressionAST *rightExpr = 0;
+        if (!parseExclusiveOrExpression(rightExpr, templArgs))
+            return false;
+
+        BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool);
+        tmp->setOp(op);
+        tmp->setLeftExpression(ast);
+        tmp->setRightExpression(rightExpr);
+        UPDATE_POS(tmp, startOp, tokenStream->cursor());
+        ast = tmp;
+    }
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+    return true;
+}
+
+bool Parser::parseLogicalAndExpression(AbstractExpressionAST *&node, bool templArgs)
+{
+    int start = tokenStream->cursor();
+
+    AbstractExpressionAST *ast = 0;
+    if (!parseInclusiveOrExpression(ast, templArgs))
+        return false;
+
+    while (tokenStream->lookAhead() == Token_and) {
+        int startOp = tokenStream->cursor();
+        AST_FROM_TOKEN(op, startOp);
+        advance();
+
+        AbstractExpressionAST *rightExpr = 0;
+        if (!parseInclusiveOrExpression(rightExpr, templArgs))
+            return false;
+
+        BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool);
+        tmp->setOp(op);
+        tmp->setLeftExpression(ast);
+        tmp->setRightExpression(rightExpr);
+        UPDATE_POS(tmp, startOp, tokenStream->cursor());
+        ast = tmp;
+    }
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+    return true;
+}
+
+bool Parser::parseLogicalOrExpression(AbstractExpressionAST *&node, bool templArgs)
+{
+    int start = tokenStream->cursor();
+
+    AbstractExpressionAST *ast = 0;
+    if (!parseLogicalAndExpression(ast, templArgs))
+        return false;
+
+    while (tokenStream->lookAhead() == Token_or) {
+        int startOp = tokenStream->cursor();
+        AST_FROM_TOKEN(op, startOp);
+        advance();
+
+        AbstractExpressionAST *rightExpr = 0;
+        if (!parseLogicalAndExpression(rightExpr, templArgs))
+            return false;
+
+        BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool);
+        tmp->setOp(op);
+        tmp->setLeftExpression(ast);
+        tmp->setRightExpression(rightExpr);
+        UPDATE_POS(tmp, startOp, tokenStream->cursor());
+        ast = tmp;
+    }
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+    return true;
+}
+
+bool Parser::parseConditionalExpression(AbstractExpressionAST *&node)
+{
+    int start = tokenStream->cursor();
+    AbstractExpressionAST *ast = 0;
+    if (!parseLogicalOrExpression(ast))
+        return false;
+
+    if (tokenStream->lookAhead() == '?') {
+        advance();
+
+        AbstractExpressionAST *leftExpr = 0;
+        if (!parseExpression(leftExpr))
+            return false;
+
+        CHECK(':', ":");
+
+        AbstractExpressionAST *rightExpr = 0;
+        if (!parseAssignmentExpression(rightExpr))
+            return false;
+
+        ConditionalExpressionAST *tmp = CreateNode<ConditionalExpressionAST>(m_pool);
+        tmp->setCondition(ast);
+        tmp->setLeftExpression(leftExpr);
+        tmp->setRightExpression(rightExpr);
+        ast = tmp;
+    }
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+    return true;
+}
+
+bool Parser::parseAssignmentExpression(AbstractExpressionAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    AbstractExpressionAST *ast = 0;
+    if (tokenStream->lookAhead() == Token_throw && !parseThrowExpression(ast))
+        return false;
+    else if (!parseConditionalExpression(ast))
+        return false;
+
+    while (tokenStream->lookAhead() == Token_assign || tokenStream->lookAhead() == '=') {
+        int startOp = tokenStream->cursor();
+        AST_FROM_TOKEN(op, startOp);
+        advance();
+
+        AbstractExpressionAST *rightExpr = 0;
+        if (!parseConditionalExpression(rightExpr))
+            return false;
+
+        BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool);
+        tmp->setOp(op);
+        tmp->setLeftExpression(ast);
+        tmp->setRightExpression(rightExpr);
+        UPDATE_POS(tmp, startOp, tokenStream->cursor());
+        ast = tmp;
+    }
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+    return true;
+}
+
+bool Parser::parseConstantExpression(AbstractExpressionAST *&node)
+{
+    return parseConditionalExpression(node);
+}
+
+bool Parser::parseExpression(AbstractExpressionAST *&node)
+{
+    return parseCommaExpression(node);
+}
+
+bool Parser::parseCommaExpression(AbstractExpressionAST *&node)
+{
+    int start = tokenStream->cursor();
+
+    AbstractExpressionAST *ast = 0;
+    if (!parseAssignmentExpression(ast))
+        return false;
+
+    while (tokenStream->lookAhead() == ',') {
+        int startOp = tokenStream->cursor();
+        AST_FROM_TOKEN(op, startOp);
+        advance();
+
+        AbstractExpressionAST *rightExpr = 0;
+        if (!parseAssignmentExpression(rightExpr))
+            return false;
+
+        BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool);
+        tmp->setOp(op);
+        tmp->setLeftExpression(ast);
+        tmp->setRightExpression(rightExpr);
+        UPDATE_POS(tmp, startOp, tokenStream->cursor());
+        ast = tmp;
+    }
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+    return true;
+}
+
+bool Parser::parseThrowExpression(AbstractExpressionAST *&node)
+{
+    if (tokenStream->lookAhead() != Token_throw)
+        return false;
+
+    int start = tokenStream->cursor();
+
+    AST_FROM_TOKEN(throwNode, tokenStream->cursor());
+    CHECK(Token_throw, "throw");
+    AbstractExpressionAST *expr = 0;
+    if (!parseAssignmentExpression(expr))
+        return false;
+
+    AbstractExpressionAST *ast = CreateExpression<NodeType_ThrowExpression>(m_pool);
+    throwNode->setParent(ast);
+    if (expr)
+        expr->setParent(ast);
+
+    UPDATE_POS(ast, start, tokenStream->cursor());
+    node = ast;
+
+    return true;
+}
+
+
+// ### Objective C++
+bool Parser::parseIvarDeclList(AST *& node)
+{
+    Q_UNUSED(node);
+    return false;
+}
+
+bool Parser::parseIvarDecls(AST *& node)
+{
+    Q_UNUSED(node);
+    return false;
+}
+
+bool Parser::parseIvarDecl(AST *& node)
+{
+    Q_UNUSED(node);
+    return false;
+}
+
+bool Parser::parseIvars(AST *& node)
+{
+    Q_UNUSED(node);
+    return false;
+}
+
+bool Parser::parseIvarDeclarator(AST *& node)
+{
+    Q_UNUSED(node);
+    return false;
+}
+
+bool Parser::parseMethodDecl(AST *& node)
+{
+    Q_UNUSED(node);
+    return false;
+}
+
+bool Parser::parseUnarySelector(AST *& node)
+{
+    Q_UNUSED(node);
+    return false;
+}
+
+bool Parser::parseKeywordSelector(AST *& node)
+{
+    Q_UNUSED(node);
+    return false;
+}
+
+bool Parser::parseSelector(AST *& node)
+{
+    Q_UNUSED(node);
+    return false;
+}
+
+bool Parser::parseKeywordDecl(AST *& node)
+{
+    Q_UNUSED(node);
+    return false;
+}
+
+bool Parser::parseReceiver(AST *& node)
+{
+    Q_UNUSED(node);
+    return false;
+}
+
+bool Parser::parseObjcMessageExpr(AST *& node)
+{
+    Q_UNUSED(node);
+    return false;
+}
+
+bool Parser::parseMessageArgs(AST *& node)
+{
+    Q_UNUSED(node);
+    return false;
+}
+
+bool Parser::parseKeywordExpr(AST *& node)
+{
+    Q_UNUSED(node);
+    return false;
+}
+
+bool Parser::parseKeywordArgList(AST *& node)
+{
+    Q_UNUSED(node);
+    return false;
+}
+
+bool Parser::parseKeywordArg(AST *& node)
+{
+    Q_UNUSED(node);
+    return false;
+}
+
+bool Parser::parseReservedWord(AST *& node)
+{
+    Q_UNUSED(node);
+    return false;
+}
+
+bool Parser::parseMyParms(AST *& node)
+{
+    Q_UNUSED(node);
+    return false;
+}
+
+bool Parser::parseMyParm(AST *& node)
+{
+    Q_UNUSED(node);
+    return false;
+}
+
+bool Parser::parseOptParmList(AST *& node)
+{
+    Q_UNUSED(node);
+    return false;
+}
+
+bool Parser::parseObjcSelectorExpr(AST *& node)
+{
+    Q_UNUSED(node);
+    return false;
+}
+
+bool Parser::parseSelectorArg(AST *& node)
+{
+    Q_UNUSED(node);
+    return false;
+}
+
+bool Parser::parseKeywordNameList(AST *& node)
+{
+    Q_UNUSED(node);
+    return false;
+}
+
+bool Parser::parseKeywordName(AST *& node)
+{
+    Q_UNUSED(node);
+    return false;
+}
+
+bool Parser::parseObjcEncodeExpr(AST *& node)
+{
+    Q_UNUSED(node);
+    return false;
+}
+
+bool Parser::parseObjcString(AST *& node)
+{
+    Q_UNUSED(node);
+    return false;
+}
+
+bool Parser::parseProtocolRefs(AST *& node)
+{
+    Q_UNUSED(node);
+    return false;
+}
+
+bool Parser::parseIdentifierList(AST *& node)
+{
+    int start = tokenStream->cursor();
+
+    if (tokenStream->lookAhead() != Token_identifier)
+        return false;
+
+    AST *ast = CreateNode<AST>(m_pool);
+
+    AST_FROM_TOKEN(tk, tokenStream->cursor());
+    tk->setParent(ast);
+    advance();
+
+    while (tokenStream->lookAhead() == ',') {
+        advance();
+        if (tokenStream->lookAhead() == Token_identifier) {
+            AST_FROM_TOKEN(tk, tokenStream->cursor());
+            tk->setParent(ast);
+            advance();
+        }
+        ADVANCE(Token_identifier, "identifier");
+    }
+
+    node = ast;
+    UPDATE_POS(node, start, tokenStream->cursor());
+    return true;
+}
+
+bool Parser::parseIdentifierColon(AST *& node)
+{
+    Q_UNUSED(node);
+
+    if (tokenStream->lookAhead() == Token_identifier && tokenStream->lookAhead(1) == ':') {
+        advance();
+        advance();
+        return true;
+    } // ### else if PTYPENAME -> return true ;
+
+    return false;
+}
+
+bool Parser::parseObjcProtocolExpr(AST *& node)
+{
+    Q_UNUSED(node);
+    return false;
+}
+
+bool Parser::parseObjcOpenBracketExpr(AST *& node)
+{
+    Q_UNUSED(node);
+    return false;
+}
+
+bool Parser::parseObjcCloseBracket(AST *& node)
+{
+    Q_UNUSED(node);
+    return false;
+}
+
+bool Parser::parseObjcDef(DeclarationAST *& node)
+{
+    Q_UNUSED(node);
+    return false;
+}
+
+bool Parser::parseObjcClassDef(DeclarationAST *& node)
+{
+    Q_UNUSED(node);
+    return false;
+}
+
+bool Parser::parseObjcClassDecl(DeclarationAST *& node)
+{
+    Q_UNUSED(node);
+
+    ADVANCE(OBJC_CLASS, "@class");
+
+    AST *idList = 0;
+    parseIdentifierList(idList);
+    ADVANCE(';', ";");
+
+    return true;
+}
+
+bool Parser::parseObjcProtocolDecl(DeclarationAST *& node)
+{
+    Q_UNUSED(node);
+
+    ADVANCE(OBJC_PROTOCOL, "@protocol");
+
+    AST *idList = 0;
+    parseIdentifierList(idList);
+    ADVANCE(';', ";");
+
+    return true;
+}
+
+bool Parser::parseObjcAliasDecl(DeclarationAST *& node)
+{
+    Q_UNUSED(node);
+
+    ADVANCE(OBJC_ALIAS, "@alias");
+
+    AST *idList = 0;
+    parseIdentifierList(idList);
+    ADVANCE(';', ";");
+
+    return true;
+}
+
+bool Parser::parseObjcProtocolDef(DeclarationAST *& node)
+{
+    Q_UNUSED(node);
+    return false;
+}
+
+bool Parser::parseObjcMethodDef(DeclarationAST *& node)
+{
+    Q_UNUSED(node);
+    return false;
+}
+
+bool Parser::parseWinDeclSpec(AST *& node)
+{
+    if (tokenStream->lookAhead() == Token_identifier
+            && tokenStream->lookAhead(1) == '('
+            && tokenStream->currentTokenText() == "__declspec") {
+        int start = tokenStream->cursor();
+        advance();
+        advance(); // skip '('
+
+        parseIdentifierList(node);
+        ADVANCE(')', ")");
+
+        UPDATE_POS(node, start, tokenStream->cursor());
+        return true;
+    }
+
+    return false;
+}
+
+void Parser::advance()
+{
+    for (;;) {
+        tokenStream->nextToken();
+        if (!tokenStream->isHidden(tokenStream->cursor()))
+            break;
+    }
+}
+
+QT_END_NAMESPACE