/****************************************************************************
**
** Copyright (C) 2004-2007 Trolltech ASA. All rights reserved.
** Copyright (C) 2001-2004 Roberto Raggi
**
** This file is part of the qt3to4 porting application of the Qt Toolkit.
**
** This file may be used under the terms of the GNU General Public
** License version 2.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of
** this file.  Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
** http://www.trolltech.com/products/qt/opensource.html
**
** If you are unsure which license is appropriate for your use, please
** review the following information:
** http://www.trolltech.com/products/qt/licensing.html or contact the
** sales department at sales@trolltech.com.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/

#include "parser.h"
#include "tokens.h"
#include "errors.h"

#include <QString>
#include <QStringList>
#include <QDateTime>

#define TT (tokenStream->currentTokenText().data())

#define ADVANCE(tk, descr) \
{ \
  if (tokenStream->lookAhead() != tk) { \
    reportError(QString("'%1' expected found '%2'").arg(QString(descr)).arg(QString(tokenStream->currentTokenText()))); \
      return false; \
  } \
  advance(); \
}

#define ADVANCE_NR(tk, descr) \
  do { \
    if (tokenStream->lookAhead() != tk) { \
        reportError(i18n("'%1' expected found '%2'").arg(QString(descr)).arg(QString(tokenStream->currentTokenText()))); \
    } \
    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(QString arg)
{
    return 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 = tokenStream->currentTokenText();

    switch(tokenStream->lookAhead()) {
    case Token_new:
    case Token_delete:
        advance();
        if (tokenStream->lookAhead() == '[' && tokenStream->lookAhead(1) == ']') {
            advance();
            advance();
            text += "[]";
        }
        return true;

    case '+':
    case '-':
    case '*':
    case '/':
    case '%':
    case '^':
    case '&':
    case '|':
    case '~':
    case '!':
    case '=':
    case '<':
    case '>':
    case ',':
    case Token_assign:
    case Token_shift:
    case Token_eq:
    case Token_not_eq:
    case Token_leq:
    case Token_geq:
    case Token_and:
    case Token_or:
    case Token_incr:
    case Token_decr:
    case Token_ptrmem:
    case Token_arrow:
        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;
    }
}
