diff generator/parser/parser.cpp @ 1:e78566595089

initial import
author mandel
date Mon, 11 May 2009 16:01:50 +0000
parents
children 09a0f1d048f2
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/generator/parser/parser.cpp	Mon May 11 16:01:50 2009 +0000
@@ -0,0 +1,4438 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Nokia. All rights reserved.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+**
+** This file is part of Qt Jambi.
+**
+** * Commercial Usage
+* Licensees holding valid Qt Commercial licenses may use this file in
+* accordance with the Qt Commercial License Agreement provided with the
+* Software or, alternatively, in accordance with the terms contained in
+* a written agreement between you and Nokia.
+*
+*
+* GNU General Public License Usage
+* Alternatively, this file may be used under the terms of the GNU
+* General Public License versions 2.0 or 3.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.fsf.org/licensing/licenses/info/GPLv2.html and
+* http://www.gnu.org/copyleft/gpl.html.  In addition, as a special
+* exception, Nokia gives you certain additional rights. These rights
+* are described in the Nokia Qt GPL Exception version 1.2, included in
+* the file GPL_EXCEPTION.txt in this package.
+* 
+* Qt for Windows(R) Licensees
+* As a special exception, Nokia, as the sole copyright holder for Qt
+* Designer, grants users of the Qt/Eclipse Integration plug-in the
+* right for the Qt/Eclipse Integration to link to functionality
+* provided by Qt Designer and its related libraries.
+*
+*
+* If you are unsure which license is appropriate for your use, please
+* contact the sales department at qt-sales@nokia.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.
+**
+****************************************************************************/
+
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+
+
+// c++ support
+#include "parser.h"
+#include "tokens.h"
+#include "lexer.h"
+#include "control.h"
+
+#include <cstdlib>
+#include <iostream>
+
+#define ADVANCE(tk, descr) \
+{ \
+  if (token_stream.lookAhead() != tk) { \
+      tokenRequiredError(tk); \
+      return false; \
+  } \
+  token_stream.nextToken(); \
+}
+
+#define ADVANCE_NR(tk, descr) \
+  do { \
+    if (token_stream.lookAhead() != tk) { \
+      tokenRequiredError(tk); \
+    } \
+    else \
+        token_stream.nextToken(); \
+  } while (0)
+
+#define CHECK(tk) \
+  do { \
+    if (token_stream.lookAhead() != tk) { \
+        return false; \
+    } \
+    token_stream.nextToken(); \
+  } while (0)
+
+#define UPDATE_POS(_node, start, end) \
+  do { \
+      (_node)->start_token = start; \
+      (_node)->end_token = end; \
+  } while (0)
+
+Parser::Parser(Control *c)
+  : _M_location(token_stream, location_table, line_table),
+    control(c),
+    lexer(_M_location, control)
+{
+  _M_block_errors = false;
+}
+
+Parser::~Parser()
+{
+}
+
+void Parser::advance()
+{
+  token_stream.nextToken();
+}
+
+TranslationUnitAST *Parser::parse(const char *contents,
+                                  std::size_t size, pool *p)
+{
+  _M_block_errors = false;
+  _M_pool = p;
+  lexer.tokenize(contents, size);
+  token_stream.nextToken(); // skip the first token
+
+  Lexer *oldLexer = control->changeLexer (&lexer);
+  Parser *oldParser = control->changeParser (this);
+
+  TranslationUnitAST *ast = 0;
+  parseTranslationUnit(ast);
+
+  control->changeLexer (oldLexer);
+  control->changeParser (oldParser);
+
+  return ast;
+}
+
+bool Parser::parseWinDeclSpec(WinDeclSpecAST *&node)
+{
+  if (token_stream.lookAhead() != Token_identifier)
+    return false;
+
+  std::size_t start = token_stream.cursor();
+
+  const NameSymbol *name_symbol = token_stream.symbol(token_stream.cursor());
+  QString name = name_symbol->as_string();
+  if (name != QLatin1String("__declspec"))
+    return false;
+  std::size_t specifier = token_stream.cursor();
+
+  token_stream.nextToken();
+  if (token_stream.lookAhead() != '(')
+    return false;
+
+  token_stream.nextToken();
+  if (token_stream.lookAhead() != Token_identifier)
+    return false;
+  std::size_t modifier = token_stream.cursor();
+
+  token_stream.nextToken();
+  if (token_stream.lookAhead() != ')')
+    return false;
+
+  token_stream.nextToken();
+
+  node = CreateNode<WinDeclSpecAST>(_M_pool);
+  node->specifier = specifier;
+  node->modifier = modifier;
+
+  UPDATE_POS(node, start, token_stream.cursor());
+
+  return true;
+}
+
+void Parser::tokenRequiredError(int token)
+{
+  QString err;
+
+  err += "expected token ";
+  err += "``";
+  err += token_name(token);
+  err += "'' found ``";
+  err += token_name(token_stream.lookAhead());
+  err += "''";
+
+  reportError(err);
+}
+
+void Parser::syntaxError()
+{
+  QString err;
+
+  err += "unexpected token ";
+  err += "``";
+  err += token_name(token_stream.lookAhead());
+  err += "''";
+
+  reportError(err);
+}
+
+void Parser::reportError(const QString& msg)
+{
+    if (!_M_block_errors)
+    {
+        int line, column;
+        QString fileName;
+
+        std::size_t tok = token_stream.cursor();
+        location().positionAt(token_stream.position(tok),
+            &line, &column, &fileName);
+
+        Control::ErrorMessage errmsg;
+        errmsg.setLine(line + 1);
+        errmsg.setColumn(column);
+        errmsg.setFileName(fileName);
+        errmsg.setMessage(QLatin1String("** PARSER ERROR ") + msg);
+        control->reportError(errmsg);
+    }
+}
+
+bool Parser::skipUntil(int token)
+{
+  while (token_stream.lookAhead())
+    {
+      if (token_stream.lookAhead() == token)
+        return true;
+
+      token_stream.nextToken();
+    }
+
+  return false;
+}
+
+bool Parser::skipUntilDeclaration()
+{
+  while (token_stream.lookAhead())
+    {
+
+      switch(token_stream.lookAhead())
+        {
+        case ';':
+        case '~':
+        case Token_scope:
+        case Token_identifier:
+        case Token_operator:
+        case Token_char:
+        case Token_wchar_t:
+        case Token_bool:
+        case Token_short:
+        case Token_int:
+        case Token_long:
+        case Token_signed:
+        case Token_unsigned:
+        case Token_float:
+        case Token_double:
+        case Token_void:
+        case Token_extern:
+        case Token_namespace:
+        case Token_using:
+        case Token_typedef:
+        case Token_asm:
+        case Token_template:
+        case Token_export:
+
+        case Token_const:       // cv
+        case Token_volatile:    // cv
+
+        case Token_public:
+        case Token_protected:
+        case Token_private:
+        case Token_signals:      // Qt
+        case Token_slots:        // Qt
+          return true;
+
+        default:
+          token_stream.nextToken();
+        }
+    }
+
+  return false;
+}
+
+bool Parser::skipUntilStatement()
+{
+  while (token_stream.lookAhead())
+    {
+      switch(token_stream.lookAhead())
+        {
+        case ';':
+        case '{':
+        case '}':
+        case Token_const:
+        case Token_volatile:
+        case Token_identifier:
+        case Token_case:
+        case Token_default:
+        case Token_if:
+        case Token_switch:
+        case Token_while:
+        case Token_do:
+        case Token_for:
+        case Token_break:
+        case Token_continue:
+        case Token_return:
+        case Token_goto:
+        case Token_try:
+        case Token_catch:
+        case Token_throw:
+        case Token_char:
+        case Token_wchar_t:
+        case Token_bool:
+        case Token_short:
+        case Token_int:
+        case Token_long:
+        case Token_signed:
+        case Token_unsigned:
+        case Token_float:
+        case Token_double:
+        case Token_void:
+        case Token_class:
+        case Token_struct:
+        case Token_union:
+        case Token_enum:
+        case Token_scope:
+        case Token_template:
+        case Token_using:
+          return true;
+
+        default:
+          token_stream.nextToken();
+        }
+    }
+
+  return false;
+}
+
+bool Parser::skip(int l, int r)
+{
+  int count = 0;
+  while (token_stream.lookAhead())
+    {
+      int tk = token_stream.lookAhead();
+
+      if (tk == l)
+        ++count;
+      else if (tk == r)
+        --count;
+      else if (l != '{' && (tk == '{' || tk == '}' || tk == ';'))
+        return false;
+
+      if (count == 0)
+        return true;
+
+      token_stream.nextToken();
+    }
+
+  return false;
+}
+
+bool Parser::parseName(NameAST *&node, bool acceptTemplateId)
+{
+  std::size_t start = token_stream.cursor();
+
+  WinDeclSpecAST *winDeclSpec = 0;
+  parseWinDeclSpec(winDeclSpec);
+
+  NameAST *ast = CreateNode<NameAST>(_M_pool);
+
+  if (token_stream.lookAhead() == Token_scope)
+    {
+      ast->global = true;
+      token_stream.nextToken();
+    }
+
+  std::size_t idx = token_stream.cursor();
+
+  while (true)
+    {
+      UnqualifiedNameAST *n = 0;
+      if (!parseUnqualifiedName(n))
+        return false;
+
+      if (token_stream.lookAhead() == Token_scope)
+        {
+          token_stream.nextToken();
+
+          ast->qualified_names
+            = snoc(ast->qualified_names, n, _M_pool);
+
+          if (token_stream.lookAhead() == Token_template)
+            {
+              /// skip optional template     #### @todo CHECK
+              token_stream.nextToken();
+            }
+        }
+      else
+        {
+          Q_ASSERT(n != 0);
+          if (!acceptTemplateId)
+            {
+              token_stream.rewind((int) n->start_token);
+              parseUnqualifiedName(n, false);
+            }
+
+          ast->unqualified_name = n;
+          break;
+        }
+    }
+
+  if (idx == token_stream.cursor())
+    return false;
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseTranslationUnit(TranslationUnitAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+  TranslationUnitAST *ast = CreateNode<TranslationUnitAST>(_M_pool);
+
+  while (token_stream.lookAhead())
+    {
+      std::size_t startDecl = token_stream.cursor();
+
+      DeclarationAST *declaration = 0;
+      if (parseDeclaration(declaration))
+        {
+          ast->declarations =
+            snoc(ast->declarations, declaration, _M_pool);
+        }
+      else
+        {
+          // error recovery
+          if (startDecl == token_stream.cursor())
+            {
+              // skip at least one token
+              token_stream.nextToken();
+            }
+
+          skipUntilDeclaration();
+        }
+    }
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseDeclaration(DeclarationAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  switch(token_stream.lookAhead())
+    {
+    case ';':
+      token_stream.nextToken();
+      return true;
+
+    case Token_extern:
+      return parseLinkageSpecification(node);
+
+    case Token_namespace:
+      return parseNamespace(node);
+
+    case Token_using:
+      return parseUsing(node);
+
+    case Token_typedef:
+      return parseTypedef(node);
+
+    case Token_asm:
+      return parseAsmDefinition(node);
+
+    case Token_Q_ENUMS:
+        return parseQ_ENUMS(node);
+
+    case Token_template:
+    case Token_export:
+      return parseTemplateDeclaration(node);
+
+    default:
+      {
+        const ListNode<std::size_t> *cv = 0;
+        parseCvQualify(cv);
+
+        const ListNode<std::size_t> *storageSpec = 0;
+        parseStorageClassSpecifier(storageSpec);
+
+        parseCvQualify(cv);
+
+        TypeSpecifierAST *spec = 0;
+        if (parseEnumSpecifier(spec)
+            || parseClassSpecifier(spec)
+            || parseForwardDeclarationSpecifier(spec))
+          {
+            parseCvQualify(cv);
+
+            spec->cv = cv;
+
+            const ListNode<InitDeclaratorAST*> *declarators = 0;
+            parseInitDeclaratorList(declarators);
+            ADVANCE(';', ";");
+
+            SimpleDeclarationAST *ast =
+              CreateNode<SimpleDeclarationAST>(_M_pool);
+
+            ast->storage_specifiers = storageSpec;
+            ast->type_specifier = spec;
+            ast->init_declarators = declarators;
+            UPDATE_POS(ast, start, token_stream.cursor());
+            node = ast;
+
+            return true;
+          }
+      }
+    } // end switch
+
+  token_stream.rewind((int) start);
+  return parseDeclarationInternal(node);
+}
+
+bool Parser::parseLinkageSpecification(DeclarationAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  CHECK(Token_extern);
+
+  LinkageSpecificationAST *ast = CreateNode<LinkageSpecificationAST>(_M_pool);
+
+  if (token_stream.lookAhead() == Token_string_literal)
+    {
+      ast->extern_type = token_stream.cursor();
+      token_stream.nextToken();
+    }
+
+  if (token_stream.lookAhead() == '{')
+    {
+      parseLinkageBody(ast->linkage_body);
+    }
+  else if (!parseDeclaration(ast->declaration))
+    {
+      reportError(("Declaration syntax error"));
+    }
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseLinkageBody(LinkageBodyAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  CHECK('{');
+
+  LinkageBodyAST *ast = CreateNode<LinkageBodyAST>(_M_pool);
+
+  while (token_stream.lookAhead())
+    {
+      int tk = token_stream.lookAhead();
+
+      if (tk == '}')
+        break;
+
+      std::size_t startDecl = token_stream.cursor();
+
+      DeclarationAST *declaration = 0;
+      if (parseDeclaration(declaration))
+        {
+          ast->declarations = snoc(ast->declarations, declaration, _M_pool);
+        }
+      else
+        {
+          // error recovery
+          if (startDecl == token_stream.cursor())
+            {
+              // skip at least one token
+              token_stream.nextToken();
+            }
+
+          skipUntilDeclaration();
+        }
+    }
+
+  if (token_stream.lookAhead() != '}')
+    reportError(("} expected"));
+  else
+    token_stream.nextToken();
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseNamespace(DeclarationAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  CHECK(Token_namespace);
+
+  std::size_t namespace_name = 0;
+  if (token_stream.lookAhead() == Token_identifier)
+    {
+      namespace_name = token_stream.cursor();
+      token_stream.nextToken();
+    }
+
+  if (token_stream.lookAhead() == '=')
+    {
+      // namespace alias
+      token_stream.nextToken();
+
+      NameAST *name = 0;
+      if (parseName(name))
+        {
+          ADVANCE(';', ";");
+
+          NamespaceAliasDefinitionAST *ast
+            = CreateNode<NamespaceAliasDefinitionAST>(_M_pool);
+          ast->namespace_name = namespace_name;
+          ast->alias_name = name;
+          UPDATE_POS(ast, start, token_stream.cursor());
+          node = ast;
+          return true;
+        }
+      else
+        {
+          reportError(("namespace expected"));
+          return false;
+        }
+    }
+  else if (token_stream.lookAhead() != '{')
+    {
+      reportError(("{ expected"));
+      return false;
+    }
+
+  NamespaceAST *ast = CreateNode<NamespaceAST>(_M_pool);
+  ast->namespace_name = namespace_name;
+  parseLinkageBody(ast->linkage_body);
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseUsing(DeclarationAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  CHECK(Token_using);
+
+  if (token_stream.lookAhead() == Token_namespace)
+    return parseUsingDirective(node);
+
+  UsingAST *ast = CreateNode<UsingAST>(_M_pool);
+
+  if (token_stream.lookAhead() == Token_typename)
+    {
+      ast->type_name = token_stream.cursor();
+      token_stream.nextToken();
+    }
+
+  if (!parseName(ast->name))
+    return false;
+
+  ADVANCE(';', ";");
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseUsingDirective(DeclarationAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  CHECK(Token_namespace);
+
+  NameAST *name = 0;
+  if (!parseName(name))
+    {
+      reportError(("Namespace name expected"));
+      return false;
+    }
+
+  ADVANCE(';', ";");
+
+  UsingDirectiveAST *ast = CreateNode<UsingDirectiveAST>(_M_pool);
+  ast->name = name;
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+
+bool Parser::parseOperatorFunctionId(OperatorFunctionIdAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  CHECK(Token_operator);
+
+  OperatorFunctionIdAST *ast = CreateNode<OperatorFunctionIdAST>(_M_pool);
+
+  if (!parseOperator(ast->op))
+    {
+      ast->op = 0;
+
+      // parse cast operator
+      const ListNode<std::size_t> *cv = 0;
+      parseCvQualify(cv);
+
+      if (!parseSimpleTypeSpecifier(ast->type_specifier))
+        {
+          syntaxError();
+          return false;
+        }
+
+      parseCvQualify(cv);
+      ast->type_specifier->cv = cv;
+
+      PtrOperatorAST *ptr_op = 0;
+      while (parsePtrOperator(ptr_op))
+        ast->ptr_ops = snoc(ast->ptr_ops, ptr_op, _M_pool);
+    }
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+  return true;
+}
+
+bool Parser::parseTemplateArgumentList(const ListNode<TemplateArgumentAST*> *&node,
+                                       bool reportError)
+{
+  TemplateArgumentAST *templArg = 0;
+  if (!parseTemplateArgument(templArg))
+    return false;
+
+  node = snoc(node, templArg, _M_pool);
+
+  while (token_stream.lookAhead() == ',')
+    {
+      token_stream.nextToken();
+
+      if (!parseTemplateArgument(templArg))
+        {
+          if (reportError)
+            {
+              syntaxError();
+              break;
+            }
+
+          node = 0;
+          return false;
+        }
+
+      node = snoc(node, templArg, _M_pool);
+    }
+
+  return true;
+}
+
+bool Parser::parseTypedef(DeclarationAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  CHECK(Token_typedef);
+
+  TypeSpecifierAST *spec = 0;
+  if (!parseTypeSpecifierOrClassSpec(spec))
+    {
+      reportError(("Need a type specifier to declare"));
+      return false;
+    }
+
+  const ListNode<InitDeclaratorAST*> *declarators = 0;
+  if (!parseInitDeclaratorList(declarators))
+    {
+      //reportError(("Need an identifier to declare"));
+      //return false;
+    }
+
+  ADVANCE(';', ";");
+
+  TypedefAST *ast = CreateNode<TypedefAST>(_M_pool);
+  ast->type_specifier = spec;
+  ast->init_declarators = declarators;
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseAsmDefinition(DeclarationAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  ADVANCE(Token_asm, "asm");
+
+  const ListNode<std::size_t> *cv = 0;
+  parseCvQualify(cv);
+
+#if defined(__GNUC__)
+#warning "implement me"
+#endif
+  skip('(', ')');
+  token_stream.nextToken();
+  ADVANCE(';', ";");
+
+  AsmDefinitionAST *ast = CreateNode<AsmDefinitionAST>(_M_pool);
+  ast->cv = cv;
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseTemplateDeclaration(DeclarationAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  std::size_t exported = 0;
+  if (token_stream.lookAhead() == Token_export)
+    {
+      exported = token_stream.cursor();
+      token_stream.nextToken();
+    }
+
+  CHECK(Token_template);
+
+  const ListNode<TemplateParameterAST*> *params = 0;
+  if (token_stream.lookAhead() == '<')
+    {
+      token_stream.nextToken();
+      parseTemplateParameterList(params);
+
+      ADVANCE('>', ">");
+    }
+
+  DeclarationAST *declaration = 0;
+  if (!parseDeclaration(declaration))
+    {
+      reportError(("expected a declaration"));
+    }
+
+  TemplateDeclarationAST *ast = CreateNode<TemplateDeclarationAST>(_M_pool);
+  ast->exported = exported;
+  ast->template_parameters = params;
+  ast->declaration = declaration;
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseOperator(OperatorAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  OperatorAST *ast = CreateNode<OperatorAST>(_M_pool);
+
+  switch(token_stream.lookAhead())
+    {
+    case Token_new:
+    case Token_delete:
+      {
+        ast->op = token_stream.cursor();
+        token_stream.nextToken();
+
+        if (token_stream.lookAhead() == '['
+            && token_stream.lookAhead(1) == ']')
+          {
+            ast->open = token_stream.cursor();
+            token_stream.nextToken();
+
+            ast->close = token_stream.cursor();
+            token_stream.nextToken();
+          }
+      }
+      break;
+
+    case '+':
+    case '-':
+    case '*':
+    case '/':
+    case '%':
+    case '^':
+    case '&':
+    case '|':
+    case '~':
+    case '!':
+    case '=':
+    case '<':
+    case '>':
+    case ',':
+    case Token_assign:
+    case Token_shift:
+    case Token_eq:
+    case Token_not_eq:
+    case Token_leq:
+    case Token_geq:
+    case Token_and:
+    case Token_or:
+    case Token_incr:
+    case Token_decr:
+    case Token_ptrmem:
+    case Token_arrow:
+      ast->op = token_stream.cursor();
+      token_stream.nextToken();
+      break;
+
+    default:
+      if (token_stream.lookAhead() == '('
+          && token_stream.lookAhead(1) == ')')
+        {
+          ast->op = ast->open = token_stream.cursor();
+          token_stream.nextToken();
+          ast->close = token_stream.cursor();
+          token_stream.nextToken();
+        }
+      else if (token_stream.lookAhead() == '['
+               && token_stream.lookAhead(1) == ']')
+        {
+          ast->op = ast->open = token_stream.cursor();
+          token_stream.nextToken();
+          ast->close = token_stream.cursor();
+          token_stream.nextToken();
+        }
+      else
+        {
+          return false;
+        }
+    }
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseCvQualify(const ListNode<std::size_t> *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  int tk;
+  while (0 != (tk = token_stream.lookAhead())
+         && (tk == Token_const || tk == Token_volatile))
+    {
+      node = snoc(node, token_stream.cursor(), _M_pool);
+      token_stream.nextToken();
+    }
+
+  return start != token_stream.cursor();
+}
+
+bool Parser::parseSimpleTypeSpecifier(TypeSpecifierAST *&node,
+                                      bool onlyIntegral)
+{
+  std::size_t start = token_stream.cursor();
+  bool isIntegral = false;
+  bool done = false;
+
+  const ListNode<std::size_t> *integrals = 0;
+
+  while (!done)
+    {
+      switch(token_stream.lookAhead())
+        {
+        case Token_char:
+        case Token_wchar_t:
+        case Token_bool:
+        case Token_short:
+        case Token_int:
+        case Token_long:
+        case Token_signed:
+        case Token_unsigned:
+        case Token_float:
+        case Token_double:
+        case Token_void:
+          integrals = snoc(integrals, token_stream.cursor(), _M_pool);
+          isIntegral = true;
+          token_stream.nextToken();
+          break;
+
+        default:
+          done = true;
+        }
+    }
+
+  SimpleTypeSpecifierAST *ast = CreateNode<SimpleTypeSpecifierAST>(_M_pool);
+  if (isIntegral)
+    {
+      ast->integrals = integrals;
+    }
+  else if (token_stream.lookAhead() == Token___typeof)
+    {
+      ast->type_of = token_stream.cursor();
+      token_stream.nextToken();
+
+      if (token_stream.lookAhead() == '(')
+        {
+          token_stream.nextToken();
+
+          std::size_t saved = token_stream.cursor();
+          parseTypeId(ast->type_id);
+          if (token_stream.lookAhead() != ')')
+            {
+              ast->type_id = 0;
+              token_stream.rewind((int) saved);
+              parseUnaryExpression(ast->expression);
+            }
+          ADVANCE(')', ")");
+        }
+      else
+        {
+          parseUnaryExpression(ast->expression);
+        }
+    }
+  else if (onlyIntegral)
+    {
+      token_stream.rewind((int) start);
+      return false;
+    }
+  else
+    {
+      if (!parseName(ast->name, true))
+        {
+          ast->name = 0;
+          token_stream.rewind((int) start);
+          return false;
+        }
+    }
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parsePtrOperator(PtrOperatorAST *&node)
+{
+  int tk = token_stream.lookAhead();
+
+  if (tk != '&' && tk != '*'
+      && tk != Token_scope && tk != Token_identifier)
+    {
+      return false;
+    }
+
+  std::size_t start = token_stream.cursor();
+
+  PtrOperatorAST *ast = CreateNode<PtrOperatorAST>(_M_pool);
+
+  switch (token_stream.lookAhead())
+    {
+    case '&':
+    case '*':
+      ast->op = token_stream.cursor();
+      token_stream.nextToken();
+      break;
+
+    case Token_scope:
+    case Token_identifier:
+      {
+        if (!parsePtrToMember(ast->mem_ptr))
+          {
+            token_stream.rewind((int) start);
+            return false;
+          }
+      }
+      break;
+
+    default:
+      Q_ASSERT(0);
+      break;
+    }
+
+  parseCvQualify(ast->cv);
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseTemplateArgument(TemplateArgumentAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  TypeIdAST *typeId = 0;
+  ExpressionAST *expr = 0;
+
+  if (!parseTypeId(typeId) || (token_stream.lookAhead() != ','
+                               && token_stream.lookAhead() != '>'))
+    {
+      token_stream.rewind((int) start);
+
+      if (!parseLogicalOrExpression(expr, true))
+        return false;
+    }
+
+  TemplateArgumentAST *ast = CreateNode<TemplateArgumentAST>(_M_pool);
+  ast->type_id = typeId;
+  ast->expression = expr;
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseTypeSpecifier(TypeSpecifierAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  const ListNode<std::size_t> *cv = 0;
+  parseCvQualify(cv);
+
+  TypeSpecifierAST *ast = 0;
+  if (!parseElaboratedTypeSpecifier(ast) && !parseSimpleTypeSpecifier(ast))
+    {
+      token_stream.rewind((int) start);
+      return false;
+    }
+
+  parseCvQualify(cv);
+  ast->cv = cv;
+
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseDeclarator(DeclaratorAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  DeclaratorAST *ast = CreateNode<DeclaratorAST>(_M_pool);
+
+  DeclaratorAST *decl = 0;
+  NameAST *declId = 0;
+
+  PtrOperatorAST *ptrOp = 0;
+  while (parsePtrOperator(ptrOp))
+    {
+      ast->ptr_ops = snoc(ast->ptr_ops, ptrOp, _M_pool);
+    }
+
+  if (token_stream.lookAhead() == '(')
+    {
+      token_stream.nextToken();
+
+      if (!parseDeclarator(decl))
+        return false;
+
+      ast->sub_declarator = decl;
+
+      CHECK(')');
+    }
+  else
+    {
+      if (token_stream.lookAhead() == ':')
+        {
+          // unnamed bitfield
+        }
+      else if (parseName(declId, true))
+        {
+          ast->id = declId;
+        }
+      else
+        {
+          token_stream.rewind((int) start);
+          return false;
+        }
+
+      if (token_stream.lookAhead() == ':')
+        {
+          token_stream.nextToken();
+
+          if (!parseConstantExpression(ast->bit_expression))
+            {
+              reportError(("Constant expression expected"));
+            }
+          goto update_pos;
+        }
+    }
+
+  {
+    bool isVector = true;
+
+    while (token_stream.lookAhead() == '[')
+      {
+        token_stream.nextToken();
+
+        ExpressionAST *expr = 0;
+        parseCommaExpression(expr);
+
+        ADVANCE(']', "]");
+
+        ast->array_dimensions = snoc(ast->array_dimensions, expr, _M_pool);
+        isVector = true;
+      }
+
+    bool skipParen = false;
+    if (token_stream.lookAhead() == Token_identifier
+        && token_stream.lookAhead(1) == '('
+        && token_stream.lookAhead(2) == '(')
+      {
+        token_stream.nextToken();
+        token_stream.nextToken();
+        skipParen = true;
+      }
+
+    int tok = token_stream.lookAhead();
+    if (ast->sub_declarator
+        && !(isVector || tok == '(' || tok == ','
+             || tok == ';' || tok == '='))
+      {
+        token_stream.rewind((int) start);
+        return false;
+      }
+
+    std::size_t index = token_stream.cursor();
+    if (token_stream.lookAhead() == '(')
+      {
+        token_stream.nextToken();
+
+        ParameterDeclarationClauseAST *params = 0;
+        if (!parseParameterDeclarationClause(params))
+          {
+            token_stream.rewind((int) index);
+            goto update_pos;
+          }
+
+        ast->parameter_declaration_clause = params;
+
+        if (token_stream.lookAhead() != ')')
+          {
+            token_stream.rewind((int) index);
+            goto update_pos;
+          }
+
+        token_stream.nextToken();  // skip ')'
+
+        parseCvQualify(ast->fun_cv);
+        parseExceptionSpecification(ast->exception_spec);
+
+        if (token_stream.lookAhead() == Token___attribute__)
+          {
+          parse_Attribute__();
+          }
+      }
+
+    if (skipParen)
+      {
+        if (token_stream.lookAhead() != ')')
+          {
+            reportError(("')' expected"));
+          }
+        else
+          token_stream.nextToken();
+      }
+  }
+
+ update_pos:
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseAbstractDeclarator(DeclaratorAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  DeclaratorAST *ast = CreateNode<DeclaratorAST>(_M_pool);
+  DeclaratorAST *decl = 0;
+
+  PtrOperatorAST *ptrOp = 0;
+  while (parsePtrOperator(ptrOp))
+    {
+      ast->ptr_ops = snoc(ast->ptr_ops, ptrOp, _M_pool);
+    }
+
+  int index = (int) token_stream.cursor();
+  if (token_stream.lookAhead() == '(')
+    {
+      token_stream.nextToken();
+
+      if (!parseAbstractDeclarator(decl))
+        {
+          token_stream.rewind((int) index);
+          goto label1;
+        }
+
+      ast->sub_declarator = decl;
+
+      if (token_stream.lookAhead() != ')')
+        {
+          token_stream.rewind((int) start);
+          return false;
+        }
+      token_stream.nextToken();
+    }
+  else if (token_stream.lookAhead() == ':')
+    {
+      token_stream.nextToken();
+      if (!parseConstantExpression(ast->bit_expression))
+        {
+          ast->bit_expression = 0;
+          reportError(("Constant expression expected"));
+        }
+      goto update_pos;
+    }
+
+ label1:
+  {
+    bool isVector = true;
+
+    while (token_stream.lookAhead() == '[')
+      {
+        token_stream.nextToken();
+
+        ExpressionAST *expr = 0;
+        parseCommaExpression(expr);
+
+        ADVANCE(']', "]");
+
+        ast->array_dimensions = snoc(ast->array_dimensions, expr, _M_pool);
+        isVector = true;
+      }
+
+    int tok = token_stream.lookAhead();
+    if (ast->sub_declarator
+        && !(isVector || tok == '(' || tok == ','
+             || tok == ';' || tok == '='))
+      {
+        token_stream.rewind((int) start);
+        return false;
+      }
+
+    int index = (int) token_stream.cursor();
+    if (token_stream.lookAhead() == '(')
+      {
+        token_stream.nextToken();
+
+        ParameterDeclarationClauseAST *params = 0;
+        if (!parseParameterDeclarationClause(params))
+          {
+            token_stream.rewind((int) index);
+            goto update_pos;
+          }
+
+        ast->parameter_declaration_clause = params;
+
+        if (token_stream.lookAhead() != ')')
+          {
+            token_stream.rewind((int) index);
+            goto update_pos;
+          }
+
+        token_stream.nextToken();  // skip ')'
+
+        parseCvQualify(ast->fun_cv);
+        parseExceptionSpecification(ast->exception_spec);
+      }
+  }
+
+ update_pos:
+  if (token_stream.cursor() == start)
+    return false;
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseEnumSpecifier(TypeSpecifierAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  CHECK(Token_enum);
+
+  NameAST *name = 0;
+  parseName(name);
+
+  if (token_stream.lookAhead() != '{')
+    {
+      token_stream.rewind((int) start);
+      return false;
+    }
+  token_stream.nextToken();
+
+  EnumSpecifierAST *ast = CreateNode<EnumSpecifierAST>(_M_pool);
+  ast->name = name;
+
+  EnumeratorAST *enumerator = 0;
+  if (parseEnumerator(enumerator))
+    {
+      ast->enumerators = snoc(ast->enumerators, enumerator, _M_pool);
+
+      while (token_stream.lookAhead() == ',')
+        {
+          token_stream.nextToken();
+
+          if (!parseEnumerator(enumerator))
+            {
+              //reportError(("Enumerator expected"));
+              break;
+            }
+
+          ast->enumerators = snoc(ast->enumerators, enumerator, _M_pool);
+        }
+    }
+
+  ADVANCE_NR('}', "}");
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseTemplateParameterList(const ListNode<TemplateParameterAST*> *&node)
+{
+  TemplateParameterAST *param = 0;
+  if (!parseTemplateParameter(param))
+    return false;
+
+  node = snoc(node, param, _M_pool);
+
+  while (token_stream.lookAhead() == ',')
+    {
+      token_stream.nextToken();
+
+      if (!parseTemplateParameter(param))
+        {
+          syntaxError();
+          break;
+        }
+      else
+        {
+          node = snoc(node, param, _M_pool);
+        }
+    }
+
+  return true;
+}
+
+bool Parser::parseTemplateParameter(TemplateParameterAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+  TemplateParameterAST *ast = CreateNode<TemplateParameterAST>(_M_pool);
+
+  int tk = token_stream.lookAhead();
+
+  if ((tk == Token_class || tk == Token_typename || tk == Token_template)
+      && parseTypeParameter(ast->type_parameter))
+    {
+      // nothing to do
+    }
+  else if (!parseParameterDeclaration(ast->parameter_declaration))
+    return false;
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseTypeParameter(TypeParameterAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  TypeParameterAST *ast = CreateNode<TypeParameterAST>(_M_pool);
+  ast->type = start;
+
+  switch(token_stream.lookAhead())
+    {
+    case Token_class:
+    case Token_typename:
+      {
+        token_stream.nextToken(); // skip class
+
+        // parse optional name
+        if(parseName(ast->name, true))
+          {
+            if (token_stream.lookAhead() == '=')
+              {
+                token_stream.nextToken();
+
+                if(!parseTypeId(ast->type_id))
+                  {
+                    //syntaxError();
+                    token_stream.rewind((int) start);
+                    return false;
+                  }
+              }
+            else if (token_stream.lookAhead() != ','
+                     && token_stream.lookAhead() != '>')
+              {
+                token_stream.rewind((int) start);
+                return false;
+              }
+          }
+      }
+      break;
+
+    case Token_template:
+      {
+        token_stream.nextToken(); // skip template
+        ADVANCE('<', "<");
+
+        if (!parseTemplateParameterList(ast->template_parameters))
+          return false;
+
+        ADVANCE('>', ">");
+
+        if (token_stream.lookAhead() == Token_class)
+          token_stream.nextToken();
+
+        // parse optional name
+        if (parseName(ast->name, true))
+          {
+            if (token_stream.lookAhead() == '=')
+              {
+                token_stream.nextToken();
+
+                if (!parseTypeId(ast->type_id))
+                  {
+                    syntaxError();
+                    return false;
+                  }
+              }
+          }
+
+        if (token_stream.lookAhead() == '=')
+          {
+            token_stream.nextToken();
+
+            parseName(ast->template_name, true);
+          }
+      }
+      break;
+
+    default:
+      return false;
+
+    } // end switch
+
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+  return true;
+}
+
+bool Parser::parseStorageClassSpecifier(const ListNode<std::size_t> *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  int tk;
+  while (0 != (tk = token_stream.lookAhead())
+         && (tk == Token_friend || tk == Token_auto
+             || tk == Token_register || tk == Token_static
+             || tk == Token_extern || tk == Token_mutable))
+    {
+      node = snoc(node, token_stream.cursor(), _M_pool);
+      token_stream.nextToken();
+    }
+
+  return start != token_stream.cursor();
+}
+
+bool Parser::parseFunctionSpecifier(const ListNode<std::size_t> *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  int tk;
+  while (0 != (tk = token_stream.lookAhead())
+         && (tk == Token_inline || tk == Token_virtual
+             || tk == Token_explicit || tk == Token_Q_INVOKABLE))
+    {
+      node = snoc(node, token_stream.cursor(), _M_pool);
+      token_stream.nextToken();
+    }
+
+  return start != token_stream.cursor();
+}
+
+bool Parser::parseTypeId(TypeIdAST *&node)
+{
+  /// @todo implement the AST for typeId
+  std::size_t start = token_stream.cursor();
+
+  TypeSpecifierAST *spec = 0;
+  if (!parseTypeSpecifier(spec))
+    {
+      token_stream.rewind((int) start);
+      return false;
+    }
+
+  DeclaratorAST *decl = 0;
+  parseAbstractDeclarator(decl);
+
+  TypeIdAST *ast = CreateNode<TypeIdAST>(_M_pool);
+  ast->type_specifier = spec;
+  ast->declarator = decl;
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseInitDeclaratorList(const ListNode<InitDeclaratorAST*> *&node)
+{
+  InitDeclaratorAST *decl = 0;
+  if (!parseInitDeclarator(decl))
+    return false;
+
+  node = snoc(node, decl, _M_pool);
+
+  while (token_stream.lookAhead() == ',')
+    {
+      token_stream.nextToken();
+
+      if (!parseInitDeclarator(decl))
+        {
+          syntaxError();
+          break;
+        }
+      node = snoc(node, decl, _M_pool);
+    }
+
+  return true;
+}
+
+bool Parser::parseParameterDeclarationClause(ParameterDeclarationClauseAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  ParameterDeclarationClauseAST *ast
+    = CreateNode<ParameterDeclarationClauseAST>(_M_pool);
+
+  if (!parseParameterDeclarationList(ast->parameter_declarations))
+    {
+      if (token_stream.lookAhead() == ')')
+        goto good;
+
+      if (token_stream.lookAhead() == Token_ellipsis
+          && token_stream.lookAhead(1) == ')')
+        {
+          ast->ellipsis = token_stream.cursor();
+          goto good;
+        }
+
+      return false;
+    }
+
+ good:
+
+  if (token_stream.lookAhead() == Token_ellipsis)
+    {
+      ast->ellipsis = token_stream.cursor();
+      token_stream.nextToken();
+    }
+
+  /// @todo add ellipsis
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseParameterDeclarationList(const ListNode<ParameterDeclarationAST*> *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  ParameterDeclarationAST *param = 0;
+  if (!parseParameterDeclaration(param))
+    {
+      token_stream.rewind((int) start);
+      return false;
+    }
+
+  node = snoc(node, param, _M_pool);
+
+  while (token_stream.lookAhead() == ',')
+    {
+      token_stream.nextToken();
+
+      if (token_stream.lookAhead() == Token_ellipsis)
+        break;
+
+      if (!parseParameterDeclaration(param))
+        {
+          token_stream.rewind((int) start);
+          return false;
+        }
+      node = snoc(node, param, _M_pool);
+    }
+
+  return true;
+}
+
+bool Parser::parseParameterDeclaration(ParameterDeclarationAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  const ListNode<std::size_t> *storage = 0;
+  parseStorageClassSpecifier(storage);
+
+  // parse decl spec
+  TypeSpecifierAST *spec = 0;
+  if (!parseTypeSpecifier(spec))
+    {
+      token_stream.rewind((int) start);
+      return false;
+    }
+
+  int index = (int) token_stream.cursor();
+
+  DeclaratorAST *decl = 0;
+  if (!parseDeclarator(decl))
+    {
+      token_stream.rewind((int) index);
+
+      // try with abstract declarator
+      parseAbstractDeclarator(decl);
+    }
+
+  ExpressionAST *expr = 0;
+  if (token_stream.lookAhead() == '=')
+    {
+      token_stream.nextToken();
+      if (!parseLogicalOrExpression(expr,true))
+        {
+          //reportError(("Expression expected"));
+        }
+    }
+
+  ParameterDeclarationAST *ast = CreateNode<ParameterDeclarationAST>(_M_pool);
+  ast->type_specifier = spec;
+  ast->declarator = decl;
+  ast->expression = expr;
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parse_Attribute__() {
+    token_stream.nextToken();
+
+    ADVANCE('(', "(");
+
+    ExpressionAST *expr = 0;
+    parseExpression(expr);
+
+    if (token_stream.lookAhead() != ')')
+    {
+        reportError(("')' expected"));
+        return false;
+    }
+    else
+    {
+        token_stream.nextToken();
+    }
+    return true;
+}
+
+QString Parser::tokenText(AST *ast) const
+{
+    if (ast == 0) return QString();
+
+    int start_token = ast->start_token;
+    int end_token = ast->end_token;
+
+    Token const &tk = token_stream.token (start_token);
+    Token const &end_tk = token_stream.token(end_token);
+
+    return QString::fromLatin1 (&tk.text[tk.position],(int) (end_tk.position - tk.position)).trimmed();
+}
+
+bool Parser::parseForwardDeclarationSpecifier(TypeSpecifierAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  int kind = token_stream.lookAhead();
+  if (kind != Token_class && kind != Token_struct && kind != Token_union)
+    return false;
+
+  std::size_t class_key = token_stream.cursor();
+  token_stream.nextToken();
+
+  NameAST *name = 0;
+  if (!parseName(name, false)) {
+      token_stream.rewind((int) start);
+      return false;
+  }
+
+  BaseClauseAST *bases = 0;
+  if (token_stream.lookAhead() == ':')
+    {
+      if (!parseBaseClause(bases))
+        {
+          token_stream.rewind((int) start);
+          return false;
+        }
+    }
+
+  if (token_stream.lookAhead() != ';')
+    {
+        token_stream.rewind((int) start);
+        return false;
+    }
+
+  ForwardDeclarationSpecifierAST *ast = CreateNode<ForwardDeclarationSpecifierAST>(_M_pool);
+  ast->class_key = class_key;
+  ast->name = name;
+  ast->base_clause = bases;
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseClassSpecifier(TypeSpecifierAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  int kind = token_stream.lookAhead();
+  if (kind != Token_class && kind != Token_struct && kind != Token_union)
+    return false;
+
+  std::size_t class_key = token_stream.cursor();
+  token_stream.nextToken();
+
+  WinDeclSpecAST *winDeclSpec = 0;
+  parseWinDeclSpec(winDeclSpec);
+
+  if (token_stream.lookAhead() == Token___attribute__) {
+      parse_Attribute__();
+  }
+
+  while (token_stream.lookAhead() == Token_identifier
+         && token_stream.lookAhead(1) == Token_identifier)
+    {
+      token_stream.nextToken();
+    }
+
+  NameAST *name = 0;
+  parseName(name, true);
+
+  BaseClauseAST *bases = 0;
+
+  if (token_stream.lookAhead() == ':')
+    {
+      if (!parseBaseClause(bases))
+        {
+          skipUntil('{');
+        }
+    }
+
+  if (token_stream.lookAhead() != '{')
+    {
+
+      token_stream.rewind((int) start);
+      return false;
+    }
+
+  ADVANCE('{', "{");
+
+  ClassSpecifierAST *ast = CreateNode<ClassSpecifierAST>(_M_pool);
+  ast->win_decl_specifiers = winDeclSpec;
+  ast->class_key = class_key;
+  ast->name = name;
+  ast->base_clause = bases;
+
+  while (token_stream.lookAhead())
+    {
+      if (token_stream.lookAhead() == '}')
+        break;
+
+      std::size_t startDecl = token_stream.cursor();
+
+      DeclarationAST *memSpec = 0;
+      if (!parseMemberSpecification(memSpec))
+        {
+          if (startDecl == token_stream.cursor())
+            token_stream.nextToken(); // skip at least one token
+          skipUntilDeclaration();
+        }
+      else
+        ast->member_specs = snoc(ast->member_specs, memSpec, _M_pool);
+    }
+
+  ADVANCE_NR('}', "}");
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseAccessSpecifier(DeclarationAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  const ListNode<std::size_t> *specs = 0;
+
+  bool done = false;
+  while (!done)
+    {
+      switch(token_stream.lookAhead())
+        {
+        case Token_signals:
+        case Token_slots:
+        case Token_k_dcop:
+        case Token_k_dcop_signals:
+        case Token_public:
+        case Token_protected:
+        case Token_private:
+          specs = snoc(specs, token_stream.cursor(), _M_pool);
+          token_stream.nextToken();
+          break;
+
+        default:
+          done = true;
+          break;
+        }
+    }
+
+  if (!specs)
+    return false;
+
+  ADVANCE(':', ":");
+
+  AccessSpecifierAST *ast = CreateNode<AccessSpecifierAST>(_M_pool);
+  ast->specs = specs;
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseMemberSpecification(DeclarationAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  if (token_stream.lookAhead() == ';')
+    {
+      token_stream.nextToken();
+      return true;
+    }
+  else if (token_stream.lookAhead() == Token_Q_OBJECT || token_stream.lookAhead() == Token_K_DCOP)
+    {
+      token_stream.nextToken();
+      return true;
+    }
+  else if (parseTypedef(node))
+    {
+      return true;
+    }
+  else if (parseUsing(node))
+    {
+      return true;
+    }
+  else if (parseTemplateDeclaration(node))
+    {
+      return true;
+    }
+  else if (parseAccessSpecifier(node))
+    {
+      return true;
+    }
+  else if (parseQ_PROPERTY(node))
+    {
+      return true;
+    }
+  else if (parseQ_ENUMS(node))
+    {
+      return true;
+    }
+
+  token_stream.rewind((int) start);
+
+  const ListNode<std::size_t> *cv = 0;
+  parseCvQualify(cv);
+
+  const ListNode<std::size_t> *storageSpec = 0;
+  parseStorageClassSpecifier(storageSpec);
+
+  parseCvQualify(cv);
+
+  TypeSpecifierAST *spec = 0;
+  if (parseEnumSpecifier(spec) || parseClassSpecifier(spec))
+    {
+      parseCvQualify(cv);
+      spec->cv = cv;
+
+      const ListNode<InitDeclaratorAST*> *declarators = 0;
+      parseInitDeclaratorList(declarators);
+      ADVANCE(';', ";");
+
+      SimpleDeclarationAST *ast = CreateNode<SimpleDeclarationAST>(_M_pool);
+      ast->type_specifier = spec;
+      ast->init_declarators = declarators;
+      UPDATE_POS(ast, start, token_stream.cursor());
+      node = ast;
+
+      return true;
+    }
+
+  token_stream.rewind((int) start);
+  return parseDeclarationInternal(node);
+}
+
+bool Parser::parseCtorInitializer(CtorInitializerAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  CHECK(':');
+
+  CtorInitializerAST *ast = CreateNode<CtorInitializerAST>(_M_pool);
+  ast->colon = start;
+
+  if (!parseMemInitializerList(ast->member_initializers))
+    {
+      reportError(("Member initializers expected"));
+    }
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseElaboratedTypeSpecifier(TypeSpecifierAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  int tk = token_stream.lookAhead();
+  if (tk == Token_class  ||
+      tk == Token_struct ||
+      tk == Token_union  ||
+      tk == Token_enum   ||
+      tk == Token_typename)
+    {
+      std::size_t type = token_stream.cursor();
+      token_stream.nextToken();
+
+      NameAST *name = 0;
+      if (parseName(name, true))
+        {
+          ElaboratedTypeSpecifierAST *ast
+            = CreateNode<ElaboratedTypeSpecifierAST>(_M_pool);
+
+          ast->type = type;
+          ast->name = name;
+
+          UPDATE_POS(ast, start, token_stream.cursor());
+          node = ast;
+
+          return true;
+        }
+    }
+
+  token_stream.rewind((int) start);
+  return false;
+}
+
+bool Parser::parseExceptionSpecification(ExceptionSpecificationAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  CHECK(Token_throw);
+  ADVANCE('(', "(");
+
+  ExceptionSpecificationAST *ast
+    = CreateNode<ExceptionSpecificationAST>(_M_pool);
+
+  if (token_stream.lookAhead() == Token_ellipsis)
+    {
+      ast->ellipsis = token_stream.cursor();
+      token_stream.nextToken();
+    }
+  else
+    {
+      parseTypeIdList(ast->type_ids);
+    }
+
+  ADVANCE(')', ")");
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseEnumerator(EnumeratorAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  CHECK(Token_identifier);
+  std::size_t id = token_stream.cursor() - 1;
+
+  EnumeratorAST *ast = CreateNode<EnumeratorAST>(_M_pool);
+  ast->id = id;
+
+  if (token_stream.lookAhead() == '=')
+    {
+      token_stream.nextToken();
+
+      if (!parseConstantExpression(ast->expression))
+        {
+          reportError(("Constant expression expected"));
+        }
+    }
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseInitDeclarator(InitDeclaratorAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  DeclaratorAST *decl = 0;
+  if (!parseDeclarator(decl))
+    {
+      return false;
+    }
+
+  if (token_stream.lookAhead(0) == Token_asm)
+    {
+      token_stream.nextToken();
+      skip('(', ')');
+      token_stream.nextToken();
+    }
+
+  InitializerAST *init = 0;
+  parseInitializer(init);
+
+  InitDeclaratorAST *ast = CreateNode<InitDeclaratorAST>(_M_pool);
+  ast->declarator = decl;
+  ast->initializer = init;
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseBaseClause(BaseClauseAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  CHECK(':');
+
+  BaseSpecifierAST *baseSpec = 0;
+  if (!parseBaseSpecifier(baseSpec))
+    return false;
+
+  BaseClauseAST *ast = CreateNode<BaseClauseAST>(_M_pool);
+  ast->base_specifiers = snoc(ast->base_specifiers, baseSpec, _M_pool);
+
+  while (token_stream.lookAhead() == ',')
+    {
+      token_stream.nextToken();
+
+      if (!parseBaseSpecifier(baseSpec))
+        {
+          reportError(("Base class specifier expected"));
+          break;
+        }
+      ast->base_specifiers = snoc(ast->base_specifiers, baseSpec, _M_pool);
+    }
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseInitializer(InitializerAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  int tk = token_stream.lookAhead();
+  if (tk != '=' && tk != '(')
+    return false;
+
+  InitializerAST *ast = CreateNode<InitializerAST>(_M_pool);
+
+  if (tk == '=')
+    {
+      token_stream.nextToken();
+
+      if (!parseInitializerClause(ast->initializer_clause))
+        {
+          reportError(("Initializer clause expected"));
+        }
+    }
+  else if (tk == '(')
+    {
+      token_stream.nextToken();
+      parseCommaExpression(ast->expression);
+      CHECK(')');
+    }
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseMemInitializerList(const ListNode<MemInitializerAST*> *&node)
+{
+  MemInitializerAST *init = 0;
+
+  if (!parseMemInitializer(init))
+    return false;
+
+  node = snoc(node, init, _M_pool);
+
+  while (token_stream.lookAhead() == ',')
+    {
+      token_stream.nextToken();
+
+      if (!parseMemInitializer(init))
+        break;
+
+      node = snoc(node, init, _M_pool);
+    }
+
+  return true;
+}
+
+bool Parser::parseMemInitializer(MemInitializerAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  NameAST *initId = 0;
+  if (!parseName(initId, true))
+    {
+      reportError(("Identifier expected"));
+      return false;
+    }
+
+  ADVANCE('(', "(");
+  ExpressionAST *expr = 0;
+  parseCommaExpression(expr);
+  ADVANCE(')', ")");
+
+  MemInitializerAST *ast = CreateNode<MemInitializerAST>(_M_pool);
+  ast->initializer_id = initId;
+  ast->expression = expr;
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseTypeIdList(const ListNode<TypeIdAST*> *&node)
+{
+  TypeIdAST *typeId = 0;
+  if (!parseTypeId(typeId))
+    return false;
+
+  node = snoc(node, typeId, _M_pool);
+
+  while (token_stream.lookAhead() == ',')
+    {
+      token_stream.nextToken();
+      if (parseTypeId(typeId))
+        {
+          node = snoc(node, typeId, _M_pool);
+        }
+      else
+        {
+          reportError(("Type id expected"));
+          break;
+        }
+    }
+
+  return true;
+}
+
+bool Parser::parseBaseSpecifier(BaseSpecifierAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  BaseSpecifierAST *ast = CreateNode<BaseSpecifierAST>(_M_pool);
+
+  if (token_stream.lookAhead() == Token_virtual)
+    {
+      ast->virt = token_stream.cursor();
+      token_stream.nextToken();
+
+      int tk = token_stream.lookAhead();
+      if (tk == Token_public || tk == Token_protected
+          || tk == Token_private)
+        {
+          ast->access_specifier = token_stream.cursor();
+          token_stream.nextToken();
+        }
+    }
+  else
+    {
+      int tk = token_stream.lookAhead();
+      if (tk == Token_public || tk == Token_protected
+          || tk == Token_private)
+        {
+          ast->access_specifier = token_stream.cursor();
+          token_stream.nextToken();
+        }
+
+      if (token_stream.lookAhead() == Token_virtual)
+        {
+          ast->virt = token_stream.cursor();
+          token_stream.nextToken();
+        }
+    }
+
+  if (!parseName(ast->name, true))
+    reportError(("Class name expected"));
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseInitializerClause(InitializerClauseAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  InitializerClauseAST *ast = CreateNode<InitializerClauseAST>(_M_pool);
+
+  if (token_stream.lookAhead() == '{')
+    {
+#if defined(__GNUC__)
+#warning "implement me"
+#endif
+      if (skip('{','}'))
+        token_stream.nextToken();
+      else
+        reportError(("} missing"));
+    }
+  else
+    {
+      if (!parseAssignmentExpression(ast->expression))
+        {
+          //reportError(("Expression expected"));
+        }
+    }
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parsePtrToMember(PtrToMemberAST *&node)
+{
+#if defined(__GNUC__)
+#warning "implemente me (AST)"
+#endif
+
+  std::size_t start = token_stream.cursor();
+
+  std::size_t global_scope = 0;
+  if (token_stream.lookAhead() == Token_scope)
+    {
+      global_scope = token_stream.cursor();
+      token_stream.nextToken();
+    }
+
+  UnqualifiedNameAST *name = 0;
+  while (token_stream.lookAhead() == Token_identifier)
+    {
+      if (!parseUnqualifiedName(name))
+        break;
+
+      if (token_stream.lookAhead() == Token_scope
+          && token_stream.lookAhead(1) == '*')
+        {
+          token_stream.nextToken();
+          token_stream.nextToken();
+
+          PtrToMemberAST *ast = CreateNode<PtrToMemberAST>(_M_pool);
+          UPDATE_POS(ast, start, token_stream.cursor());
+          node = ast;
+
+          return true;
+        }
+
+      if (token_stream.lookAhead() == Token_scope)
+        token_stream.nextToken();
+    }
+
+  token_stream.rewind((int) start);
+  return false;
+}
+
+bool Parser::parseUnqualifiedName(UnqualifiedNameAST *&node,
+                                  bool parseTemplateId)
+{
+  std::size_t start = token_stream.cursor();
+
+  std::size_t tilde = 0;
+  std::size_t id = 0;
+  OperatorFunctionIdAST *operator_id = 0;
+
+  if (token_stream.lookAhead() == Token_identifier)
+    {
+      id = token_stream.cursor();
+      token_stream.nextToken();
+    }
+  else if (token_stream.lookAhead() == '~'
+           && token_stream.lookAhead(1) == Token_identifier)
+    {
+      tilde = token_stream.cursor();
+      token_stream.nextToken(); // skip ~
+
+      id = token_stream.cursor();
+      token_stream.nextToken(); // skip classname
+    }
+  else if (token_stream.lookAhead() == Token_operator)
+    {
+      if (!parseOperatorFunctionId(operator_id))
+        return false;
+    }
+  else
+    {
+      return false;
+    }
+
+  UnqualifiedNameAST *ast = CreateNode<UnqualifiedNameAST>(_M_pool);
+  ast->tilde = tilde;
+  ast->id = id;
+  ast->operator_id = operator_id;
+
+  if (parseTemplateId && !tilde)
+    {
+      std::size_t index = token_stream.cursor();
+
+      if (token_stream.lookAhead() == '<')
+        {
+          token_stream.nextToken();
+
+          // optional template arguments
+          parseTemplateArgumentList(ast->template_arguments);
+
+          if (token_stream.lookAhead() == '>')
+            {
+              token_stream.nextToken();
+            }
+          else
+            {
+              ast->template_arguments = 0;
+              token_stream.rewind((int) index);
+            }
+        }
+    }
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseStringLiteral(StringLiteralAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  if (token_stream.lookAhead() != Token_string_literal)
+    return false;
+
+  StringLiteralAST *ast = CreateNode<StringLiteralAST>(_M_pool);
+
+  while (token_stream.lookAhead() == Token_string_literal)
+    {
+      ast->literals = snoc(ast->literals, token_stream.cursor(), _M_pool);
+      token_stream.nextToken();
+    }
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseExpressionStatement(StatementAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  ExpressionAST *expr = 0;
+  parseCommaExpression(expr);
+
+  ADVANCE(';', ";");
+
+  ExpressionStatementAST *ast = CreateNode<ExpressionStatementAST>(_M_pool);
+  ast->expression = expr;
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseStatement(StatementAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  switch(token_stream.lookAhead())
+    {
+    case Token_while:
+      return parseWhileStatement(node);
+
+    case Token_do:
+      return parseDoStatement(node);
+
+    case Token_for:
+      return parseForStatement(node);
+
+    case Token_if:
+      return parseIfStatement(node);
+
+    case Token_switch:
+      return parseSwitchStatement(node);
+
+    case Token_try:
+      return parseTryBlockStatement(node);
+
+    case Token_case:
+    case Token_default:
+      return parseLabeledStatement(node);
+
+    case Token_break:
+    case Token_continue:
+#if defined(__GNUC__)
+#warning "implement me"
+#endif
+      token_stream.nextToken();
+      ADVANCE(';', ";");
+      return true;
+
+    case Token_goto:
+#if defined(__GNUC__)
+#warning "implement me"
+#endif
+      token_stream.nextToken();
+      ADVANCE(Token_identifier, "identifier");
+      ADVANCE(';', ";");
+      return true;
+
+    case Token_return:
+      {
+        token_stream.nextToken();
+        ExpressionAST *expr = 0;
+        parseCommaExpression(expr);
+
+        ADVANCE(';', ";");
+
+        ReturnStatementAST *ast = CreateNode<ReturnStatementAST>(_M_pool);
+        ast->expression = expr;
+
+        UPDATE_POS(ast, start, token_stream.cursor());
+        node = ast;
+      }
+      return true;
+
+    case '{':
+      return parseCompoundStatement(node);
+
+    case Token_identifier:
+      if (parseLabeledStatement(node))
+        return true;
+      break;
+    }
+
+  return parseExpressionOrDeclarationStatement(node);
+}
+
+bool Parser::parseExpressionOrDeclarationStatement(StatementAST *&node)
+{
+  bool blocked = block_errors(true);
+
+  std::size_t start = token_stream.cursor();
+
+  StatementAST *decl_ast = 0;
+  bool maybe_amb = parseDeclarationStatement(decl_ast);
+  maybe_amb &= token_stream.kind(token_stream.cursor() - 1) == ';';
+
+  std::size_t end = token_stream.cursor();
+
+  token_stream.rewind((int) start);
+  StatementAST *expr_ast = 0;
+  maybe_amb &= parseExpressionStatement(expr_ast);
+  maybe_amb &= token_stream.kind(token_stream.cursor() - 1) == ';';
+
+  if (maybe_amb)
+    {
+      Q_ASSERT(decl_ast != 0 && expr_ast != 0);
+      ExpressionOrDeclarationStatementAST *ast
+        = CreateNode<ExpressionOrDeclarationStatementAST>(_M_pool);
+      ast->declaration = decl_ast;
+      ast->expression = expr_ast;
+
+      UPDATE_POS(ast, start, token_stream.cursor());
+      node = ast;
+    }
+  else
+    {
+      token_stream.rewind((int) std::max(end, token_stream.cursor()));
+
+      node = decl_ast;
+      if (!node)
+        node = expr_ast;
+    }
+
+  block_errors(blocked);
+
+  if (!node)
+    syntaxError();
+
+  return node != 0;
+}
+
+bool Parser::parseCondition(ConditionAST *&node, bool initRequired)
+{
+  std::size_t start = token_stream.cursor();
+
+  ConditionAST *ast = CreateNode<ConditionAST>(_M_pool);
+  TypeSpecifierAST *spec = 0;
+
+  if (parseTypeSpecifier(spec))
+    {
+      ast->type_specifier = spec;
+
+      std::size_t declarator_start = token_stream.cursor();
+
+      DeclaratorAST *decl = 0;
+      if (!parseDeclarator(decl))
+        {
+          token_stream.rewind((int) declarator_start);
+          if (!initRequired && !parseAbstractDeclarator(decl))
+            decl = 0;
+        }
+
+      if (decl && (!initRequired || token_stream.lookAhead() == '='))
+        {
+          ast->declarator = decl;
+
+          if (token_stream.lookAhead() == '=')
+            {
+              token_stream.nextToken();
+
+              parseExpression(ast->expression);
+            }
+
+          UPDATE_POS(ast, start, token_stream.cursor());
+          node = ast;
+
+          return true;
+        }
+    }
+
+  token_stream.rewind((int) start);
+
+  if (!parseCommaExpression(ast->expression))
+    return false;
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+
+bool Parser::parseWhileStatement(StatementAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  ADVANCE(Token_while, "while");
+  ADVANCE('(' , "(");
+
+  ConditionAST *cond = 0;
+  if (!parseCondition(cond))
+    {
+      reportError(("condition expected"));
+      return false;
+    }
+  ADVANCE(')', ")");
+
+  StatementAST *body = 0;
+  if (!parseStatement(body))
+    {
+      reportError(("statement expected"));
+      return false;
+    }
+
+  WhileStatementAST *ast = CreateNode<WhileStatementAST>(_M_pool);
+  ast->condition = cond;
+  ast->statement = body;
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseDoStatement(StatementAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  ADVANCE(Token_do, "do");
+
+  StatementAST *body = 0;
+  if (!parseStatement(body))
+    {
+      reportError(("statement expected"));
+      //return false;
+    }
+
+  ADVANCE_NR(Token_while, "while");
+  ADVANCE_NR('(' , "(");
+
+  ExpressionAST *expr = 0;
+  if (!parseCommaExpression(expr))
+    {
+      reportError(("expression expected"));
+      //return false;
+    }
+
+  ADVANCE_NR(')', ")");
+  ADVANCE_NR(';', ";");
+
+  DoStatementAST *ast = CreateNode<DoStatementAST>(_M_pool);
+  ast->statement = body;
+  ast->expression = expr;
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseForStatement(StatementAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  ADVANCE(Token_for, "for");
+  ADVANCE('(', "(");
+
+  StatementAST *init = 0;
+  if (!parseForInitStatement(init))
+    {
+      reportError(("for initialization expected"));
+      return false;
+    }
+
+  ConditionAST *cond = 0;
+  parseCondition(cond);
+  ADVANCE(';', ";");
+
+  ExpressionAST *expr = 0;
+  parseCommaExpression(expr);
+  ADVANCE(')', ")");
+
+  StatementAST *body = 0;
+  if (!parseStatement(body))
+    return false;
+
+  ForStatementAST *ast = CreateNode<ForStatementAST>(_M_pool);
+  ast->init_statement = init;
+  ast->condition = cond;
+  ast->expression = expr;
+  ast->statement = body;
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseForInitStatement(StatementAST *&node)
+{
+  if (parseDeclarationStatement(node))
+    return true;
+
+  return parseExpressionStatement(node);
+}
+
+bool Parser::parseCompoundStatement(StatementAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  CHECK('{');
+
+  CompoundStatementAST *ast = CreateNode<CompoundStatementAST>(_M_pool);
+
+  while (token_stream.lookAhead())
+    {
+      if (token_stream.lookAhead() == '}')
+        break;
+
+      std::size_t startStmt = token_stream.cursor();
+
+      StatementAST *stmt = 0;
+      if (!parseStatement(stmt))
+        {
+          if (startStmt == token_stream.cursor())
+            token_stream.nextToken();
+
+          skipUntilStatement();
+        }
+      else
+        {
+          ast->statements = snoc(ast->statements, stmt, _M_pool);
+        }
+    }
+
+  ADVANCE_NR('}', "}");
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseIfStatement(StatementAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  ADVANCE(Token_if, "if");
+
+  ADVANCE('(' , "(");
+
+  IfStatementAST *ast = CreateNode<IfStatementAST>(_M_pool);
+
+  ConditionAST *cond = 0;
+  if (!parseCondition(cond))
+    {
+      reportError(("condition expected"));
+      return false;
+    }
+  ADVANCE(')', ")");
+
+  StatementAST *stmt = 0;
+  if (!parseStatement(stmt))
+    {
+      reportError(("statement expected"));
+      return false;
+    }
+
+  ast->condition = cond;
+  ast->statement = stmt;
+
+  if (token_stream.lookAhead() == Token_else)
+    {
+      token_stream.nextToken();
+
+      if (!parseStatement(ast->else_statement))
+        {
+          reportError(("statement expected"));
+          return false;
+        }
+    }
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseSwitchStatement(StatementAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+  ADVANCE(Token_switch, "switch");
+
+  ADVANCE('(' , "(");
+
+  ConditionAST *cond = 0;
+  if (!parseCondition(cond))
+    {
+      reportError(("condition expected"));
+      return false;
+    }
+  ADVANCE(')', ")");
+
+  StatementAST *stmt = 0;
+  if (!parseCompoundStatement(stmt))
+    {
+      syntaxError();
+      return false;
+    }
+
+  SwitchStatementAST *ast = CreateNode<SwitchStatementAST>(_M_pool);
+  ast->condition = cond;
+  ast->statement = stmt;
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseLabeledStatement(StatementAST *&node)
+{
+  switch(token_stream.lookAhead())
+    {
+    case Token_identifier:
+    case Token_default:
+      if (token_stream.lookAhead(1) == ':')
+        {
+          token_stream.nextToken();
+          token_stream.nextToken();
+
+          StatementAST *stmt = 0;
+          if (parseStatement(stmt))
+            {
+              node = stmt;
+              return true;
+            }
+        }
+      break;
+
+    case Token_case:
+      {
+        token_stream.nextToken();
+        ExpressionAST *expr = 0;
+        if (!parseConstantExpression(expr))
+          {
+            reportError(("expression expected"));
+          }
+        else if (token_stream.lookAhead() == Token_ellipsis)
+          {
+            token_stream.nextToken();
+
+            ExpressionAST *expr2 = 0;
+            if (!parseConstantExpression(expr2))
+              {
+                reportError(("expression expected"));
+              }
+          }
+        ADVANCE(':', ":");
+
+        StatementAST *stmt = 0;
+        if (parseStatement(stmt))
+          {
+            node = stmt;
+            return true;
+          }
+      }
+      break;
+
+    }
+
+  return false;
+}
+
+bool Parser::parseBlockDeclaration(DeclarationAST *&node)
+{
+  switch(token_stream.lookAhead())
+    {
+    case Token_typedef:
+      return parseTypedef(node);
+    case Token_using:
+      return parseUsing(node);
+    case Token_asm:
+      return parseAsmDefinition(node);
+    case Token_namespace:
+      return parseNamespaceAliasDefinition(node);
+    }
+
+  std::size_t start = token_stream.cursor();
+
+  const ListNode<std::size_t> *cv = 0;
+  parseCvQualify(cv);
+
+  const ListNode<std::size_t> *storageSpec = 0;
+  parseStorageClassSpecifier(storageSpec);
+
+  parseCvQualify(cv);
+
+  TypeSpecifierAST *spec = 0;
+  if (!parseTypeSpecifierOrClassSpec(spec))
+    { // replace with simpleTypeSpecifier?!?!
+      token_stream.rewind((int) start);
+      return false;
+    }
+
+  parseCvQualify(cv);
+  spec->cv = cv;
+
+  const ListNode<InitDeclaratorAST*> *declarators = 0;
+  parseInitDeclaratorList(declarators);
+
+  if (token_stream.lookAhead() != ';')
+    {
+      token_stream.rewind((int) start);
+      return false;
+    }
+  token_stream.nextToken();
+
+  SimpleDeclarationAST *ast = CreateNode<SimpleDeclarationAST>(_M_pool);
+  ast->type_specifier = spec;
+  ast->init_declarators = declarators;
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseNamespaceAliasDefinition(DeclarationAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  CHECK(Token_namespace);
+
+  NamespaceAliasDefinitionAST *ast
+    = CreateNode<NamespaceAliasDefinitionAST>(_M_pool);
+
+  ADVANCE(Token_identifier,  "identifier");
+  ast->namespace_name = token_stream.cursor() - 1;
+
+  ADVANCE('=', "=");
+
+  if (!parseName(ast->alias_name))
+    {
+      reportError(("Namespace name expected"));
+    }
+
+  ADVANCE(';', ";");
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseDeclarationStatement(StatementAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  DeclarationAST *decl = 0;
+  if (!parseBlockDeclaration(decl))
+    return false;
+
+  DeclarationStatementAST *ast = CreateNode<DeclarationStatementAST>(_M_pool);
+  ast->declaration = decl;
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseDeclarationInternal(DeclarationAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  // that is for the case '__declspec(dllexport) int ...' or
+  // '__declspec(dllexport) inline int ...', etc.
+  WinDeclSpecAST *winDeclSpec = 0;
+  parseWinDeclSpec(winDeclSpec);
+
+  const ListNode<std::size_t> *funSpec = 0;
+  bool hasFunSpec = parseFunctionSpecifier(funSpec);
+
+  const ListNode<std::size_t> *cv = 0;
+  parseCvQualify(cv);
+
+  const ListNode<std::size_t> *storageSpec = 0;
+  bool hasStorageSpec = parseStorageClassSpecifier(storageSpec);
+
+  if (hasStorageSpec && !hasFunSpec)
+    hasFunSpec = parseFunctionSpecifier(funSpec);
+
+  // that is for the case 'friend __declspec(dllexport) ....'
+  parseWinDeclSpec(winDeclSpec);
+
+  if (!cv)
+    parseCvQualify(cv);
+
+  int index = (int) token_stream.cursor();
+  NameAST *name = 0;
+  if (parseName(name, true) && token_stream.lookAhead() == '(')
+    {
+      // no type specifier, maybe a constructor or a cast operator??
+
+      token_stream.rewind((int) index);
+
+      InitDeclaratorAST *declarator = 0;
+      if (parseInitDeclarator(declarator))
+        {
+          switch(token_stream.lookAhead())
+            {
+            case ';':
+              {
+                token_stream.nextToken();
+
+                SimpleDeclarationAST *ast
+                  = CreateNode<SimpleDeclarationAST>(_M_pool);
+
+                ast->storage_specifiers = storageSpec;
+                ast->function_specifiers = funSpec;
+                ast->init_declarators = snoc(ast->init_declarators,
+                                             declarator, _M_pool);
+
+                UPDATE_POS(ast, start, token_stream.cursor());
+                node = ast;
+              }
+              return true;
+
+            case ':':
+              {
+                CtorInitializerAST *ctorInit = 0;
+                StatementAST *funBody = 0;
+
+                if (parseCtorInitializer(ctorInit)
+                    && parseFunctionBody(funBody))
+                  {
+                    FunctionDefinitionAST *ast
+                      = CreateNode<FunctionDefinitionAST>(_M_pool);
+
+                    ast->storage_specifiers = storageSpec;
+                    ast->function_specifiers = funSpec;
+                    ast->init_declarator = declarator;
+                    ast->function_body = funBody;
+
+                    UPDATE_POS(ast, start, token_stream.cursor());
+                    node = ast;
+
+                    return true;
+                  }
+              }
+              break;
+
+            case '{':
+              {
+                StatementAST *funBody = 0;
+                if (parseFunctionBody(funBody))
+                  {
+                    FunctionDefinitionAST *ast
+                      = CreateNode<FunctionDefinitionAST>(_M_pool);
+
+                    ast->storage_specifiers = storageSpec;
+                    ast->function_specifiers = funSpec;
+                    ast->init_declarator = declarator;
+                    ast->function_body = funBody;
+
+                    UPDATE_POS(ast, start, token_stream.cursor());
+                    node = ast;
+
+                    return true;
+                  }
+              }
+              break;
+
+            case '(':
+            case '[':
+              // ops!! it seems a declarator
+              goto start_decl;
+              break;
+            }
+
+        }
+    }
+
+ start_decl:
+  token_stream.rewind((int) index);
+
+  if (token_stream.lookAhead() == Token_const
+      && token_stream.lookAhead(1) == Token_identifier
+      && token_stream.lookAhead(2) == '=')
+    {
+      // constant definition
+      token_stream.nextToken(); // skip const
+
+      const ListNode<InitDeclaratorAST*> *declarators = 0;
+      if (!parseInitDeclaratorList(declarators))
+        {
+          syntaxError();
+          return false;
+        }
+
+      ADVANCE(';', ";");
+
+#if defined(__GNUC__)
+#warning "mark the ast as constant"
+#endif
+      SimpleDeclarationAST *ast = CreateNode<SimpleDeclarationAST>(_M_pool);
+      ast->init_declarators = declarators;
+
+      UPDATE_POS(ast, start, token_stream.cursor());
+      node = ast;
+
+      return true;
+    }
+
+  TypeSpecifierAST *spec = 0;
+  if (parseTypeSpecifier(spec))
+    {
+      Q_ASSERT(spec != 0);
+
+      if (!hasFunSpec)
+        parseFunctionSpecifier(funSpec);         // e.g. "void inline"
+
+      spec->cv = cv;
+
+      const ListNode<InitDeclaratorAST*> *declarators = 0;
+      InitDeclaratorAST *decl = 0;
+      int startDeclarator = (int) token_stream.cursor();
+      bool maybeFunctionDefinition = false;
+
+      if (token_stream.lookAhead() != ';')
+        {
+          if (parseInitDeclarator(decl) && token_stream.lookAhead() == '{')
+            {
+              // function definition
+              maybeFunctionDefinition = true;
+            }
+          else
+            {
+              token_stream.rewind((int) startDeclarator);
+              if (!parseInitDeclaratorList(declarators))
+                {
+                  syntaxError();
+                  return false;
+                }
+            }
+        }
+
+      switch(token_stream.lookAhead())
+        {
+        case ';':
+          {
+            token_stream.nextToken();
+            SimpleDeclarationAST *ast
+              = CreateNode<SimpleDeclarationAST>(_M_pool);
+
+            ast->storage_specifiers = storageSpec;
+            ast->function_specifiers = funSpec;
+            ast->type_specifier = spec;
+            ast->win_decl_specifiers = winDeclSpec;
+            ast->init_declarators = declarators;
+
+            UPDATE_POS(ast, start, token_stream.cursor());
+            node = ast;
+          }
+          return true;
+
+        case '{':
+          {
+            if (!maybeFunctionDefinition)
+              {
+                syntaxError();
+                return false;
+              }
+
+            StatementAST *funBody = 0;
+            if (parseFunctionBody(funBody))
+              {
+                FunctionDefinitionAST *ast
+                  = CreateNode<FunctionDefinitionAST>(_M_pool);
+
+                ast->win_decl_specifiers = winDeclSpec;
+                ast->storage_specifiers = storageSpec;
+                ast->function_specifiers = funSpec;
+                ast->type_specifier = spec;
+                ast->init_declarator = decl;
+                ast->function_body = funBody;
+
+                UPDATE_POS(ast, start, token_stream.cursor());
+                node = ast;
+
+                return true;
+              }
+          }
+          break;
+        } // end switch
+    }
+
+  syntaxError();
+  return false;
+}
+
+bool Parser::skipFunctionBody(StatementAST *&)
+{
+#if defined(__GNUC__)
+#warning "Parser::skipFunctionBody() -- implement me"
+#endif
+  Q_ASSERT(0); // ### not implemented
+  return 0;
+}
+
+bool Parser::parseFunctionBody(StatementAST *&node)
+{
+  if (control->skipFunctionBody())
+    return skipFunctionBody(node);
+
+  return parseCompoundStatement(node);
+}
+
+bool Parser::parseTypeSpecifierOrClassSpec(TypeSpecifierAST *&node)
+{
+  if (parseClassSpecifier(node))
+    return true;
+  else if (parseEnumSpecifier(node))
+    return true;
+  else if (parseTypeSpecifier(node))
+    return true;
+
+  return false;
+}
+
+bool Parser::parseTryBlockStatement(StatementAST *&node)
+{
+#if defined(__GNUC__)
+#warning "implement me"
+#endif
+  CHECK(Token_try);
+
+  StatementAST *stmt = 0;
+  if (!parseCompoundStatement(stmt))
+    {
+      syntaxError();
+      return false;
+    }
+
+  if (token_stream.lookAhead() != Token_catch)
+    {
+      reportError(("catch expected"));
+      return false;
+    }
+
+  while (token_stream.lookAhead() == Token_catch)
+    {
+      token_stream.nextToken();
+      ADVANCE('(', "(");
+      ConditionAST *cond = 0;
+      if (token_stream.lookAhead() == Token_ellipsis)
+        {
+          token_stream.nextToken();
+        }
+      else if (!parseCondition(cond, false))
+        {
+          reportError(("condition expected"));
+          return false;
+        }
+      ADVANCE(')', ")");
+
+      StatementAST *body = 0;
+      if (!parseCompoundStatement(body))
+        {
+          syntaxError();
+          return false;
+        }
+    }
+
+  node = stmt;
+  return true;
+}
+
+bool Parser::parsePrimaryExpression(ExpressionAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  PrimaryExpressionAST *ast = CreateNode<PrimaryExpressionAST>(_M_pool);
+
+  switch(token_stream.lookAhead())
+    {
+    case Token_string_literal:
+      parseStringLiteral(ast->literal);
+      break;
+
+    case Token_number_literal:
+    case Token_char_literal:
+    case Token_true:
+    case Token_false:
+    case Token_this:
+      ast->token = token_stream.cursor();
+      token_stream.nextToken();
+      break;
+
+    case '(':
+      token_stream.nextToken();
+
+      if (token_stream.lookAhead() == '{')
+        {
+          if (!parseCompoundStatement(ast->expression_statement))
+            return false;
+        }
+      else
+        {
+          if (!parseExpression(ast->sub_expression))
+            return false;
+        }
+
+      CHECK(')');
+      break;
+
+    default:
+      if (!parseName(ast->name))
+        return false;
+
+      break;
+    }
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+
+/*
+  postfix-expression-internal:
+  [ expression ]
+  ( expression-list [opt] )
+  (.|->) template [opt] id-expression
+  (.|->) pseudo-destructor-name
+  ++
+  --
+*/
+bool Parser::parsePostfixExpressionInternal(ExpressionAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  switch (token_stream.lookAhead())
+    {
+    case '[':
+      {
+        token_stream.nextToken();
+        ExpressionAST *expr = 0;
+        parseExpression(expr);
+        CHECK(']');
+
+        SubscriptExpressionAST *ast
+          = CreateNode<SubscriptExpressionAST>(_M_pool);
+
+        ast->subscript = expr;
+
+        UPDATE_POS(ast, start, token_stream.cursor());
+        node = ast;
+      }
+      return true;
+
+    case '(':
+      {
+        token_stream.nextToken();
+        ExpressionAST *expr = 0;
+        parseExpression(expr);
+        CHECK(')');
+
+        FunctionCallAST *ast = CreateNode<FunctionCallAST>(_M_pool);
+        ast->arguments = expr;
+
+        UPDATE_POS(ast, start, token_stream.cursor());
+        node = ast;
+      }
+      return true;
+
+    case '.':
+    case Token_arrow:
+      {
+        std::size_t op = token_stream.cursor();
+        token_stream.nextToken();
+
+        std::size_t templ = 0;
+        if (token_stream.lookAhead() == Token_template)
+          {
+            templ = token_stream.cursor();
+            token_stream.nextToken();
+          }
+
+        int saved = int(token_stream.cursor());
+        NameAST *name = 0;
+
+        if (parseName(name, true) && name->unqualified_name
+            && name->unqualified_name->template_arguments != 0
+            && token_stream.lookAhead() == '(') {
+          // a template method call
+          // ### reverse the logic
+        } else {
+          token_stream.rewind(saved);
+          name = 0;
+
+          if (! parseName (name, templ != 0))
+            return false;
+        }
+
+        ClassMemberAccessAST *ast = CreateNode<ClassMemberAccessAST>(_M_pool);
+        ast->op = op;
+        ast->name = name;
+
+        UPDATE_POS(ast, start, token_stream.cursor());
+        node = ast;
+      }
+      return true;
+
+    case Token_incr:
+    case Token_decr:
+      {
+        std::size_t op = token_stream.cursor();
+        token_stream.nextToken();
+
+        IncrDecrExpressionAST *ast = CreateNode<IncrDecrExpressionAST>(_M_pool);
+        ast->op = op;
+
+        UPDATE_POS(ast, start, token_stream.cursor());
+        node = ast;
+      }
+      return true;
+
+    default:
+      return false;
+    }
+}
+
+/*
+  postfix-expression:
+  simple-type-specifier ( expression-list [opt] )
+  primary-expression postfix-expression-internal*
+*/
+bool Parser::parsePostfixExpression(ExpressionAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  switch (token_stream.lookAhead())
+    {
+    case Token_dynamic_cast:
+    case Token_static_cast:
+    case Token_reinterpret_cast:
+    case Token_const_cast:
+      {
+        std::size_t castOp = token_stream.cursor();
+        token_stream.nextToken();
+
+        CHECK('<');
+        TypeIdAST *typeId = 0;
+        parseTypeId(typeId);
+        CHECK('>');
+
+        CHECK('(');
+        ExpressionAST *expr = 0;
+        parseCommaExpression(expr);
+        CHECK(')');
+
+        CppCastExpressionAST *ast = CreateNode<CppCastExpressionAST>(_M_pool);
+        ast->op = castOp;
+        ast->type_id = typeId;
+        ast->expression = expr;
+
+        ExpressionAST *e = 0;
+        while (parsePostfixExpressionInternal(e))
+          {
+            ast->sub_expressions = snoc(ast->sub_expressions, e, _M_pool);
+          }
+
+        UPDATE_POS(ast, start, token_stream.cursor());
+        node = ast;
+      }
+      return true;
+
+    case Token_typename:
+      {
+        std::size_t token = token_stream.cursor();
+        token_stream.nextToken();
+
+        NameAST* name = 0;
+        if (!parseName(name, true))
+          return false;
+
+        CHECK('(');
+        ExpressionAST *expr = 0;
+        parseCommaExpression(expr);
+        CHECK(')');
+
+        TypeIdentificationAST *ast = CreateNode<TypeIdentificationAST>(_M_pool);
+        ast->typename_token = token;
+        ast->name = name;
+        ast->expression = expr;
+
+        UPDATE_POS(ast, start, token_stream.cursor());
+        node = ast;
+      }
+      return true;
+
+    case Token_typeid:
+      {
+        token_stream.nextToken();
+
+        CHECK('(');
+        TypeIdAST *typeId = 0;
+        parseTypeId(typeId);
+        CHECK(')');
+
+        TypeIdentificationAST *ast = CreateNode<TypeIdentificationAST>(_M_pool);
+        UPDATE_POS(ast, start, token_stream.cursor());
+        node = ast;
+      }
+      return true;
+
+    default:
+      break;
+    }
+
+  std::size_t saved_pos = token_stream.cursor();
+
+  TypeSpecifierAST *typeSpec = 0;
+  ExpressionAST *expr = 0;
+
+  // let's try to parse a type
+  NameAST *name = 0;
+  if (parseName(name, true))
+    {
+      Q_ASSERT(name->unqualified_name != 0);
+
+      bool has_template_args
+        = name->unqualified_name->template_arguments != 0;
+
+      if (has_template_args && token_stream.lookAhead() == '(')
+        {
+          ExpressionAST *cast_expr = 0;
+          if (parseCastExpression(cast_expr)
+              && cast_expr->kind == AST::Kind_CastExpression)
+            {
+              token_stream.rewind((int) saved_pos);
+              parsePrimaryExpression(expr);
+              goto L_no_rewind;
+            }
+        }
+    }
+
+  token_stream.rewind((int) saved_pos);
+
+ L_no_rewind:
+  if (!expr && parseSimpleTypeSpecifier(typeSpec)
+      && token_stream.lookAhead() == '(')
+    {
+      token_stream.nextToken(); // skip '('
+      parseCommaExpression(expr);
+      CHECK(')');
+    }
+  else if (expr)
+    {
+      typeSpec = 0;
+    }
+  else
+    {
+      typeSpec = 0;
+      token_stream.rewind((int) start);
+
+      if (!parsePrimaryExpression(expr))
+        return false;
+    }
+
+  const ListNode<ExpressionAST*> *sub_expressions = 0;
+  ExpressionAST *sub_expression = 0;
+
+  while (parsePostfixExpressionInternal(sub_expression))
+    sub_expressions = snoc(sub_expressions, sub_expression, _M_pool);
+
+  if (sub_expressions || ! expr || (typeSpec && expr))
+    {
+      PostfixExpressionAST *ast = CreateNode<PostfixExpressionAST>(_M_pool);
+      ast->type_specifier = typeSpec;
+      ast->expression = expr;
+      ast->sub_expressions = sub_expressions;
+
+      UPDATE_POS(ast, start, token_stream.cursor());
+      node = ast;
+    }
+  else
+    node = expr;
+
+  return true;
+}
+
+bool Parser::parseUnaryExpression(ExpressionAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  switch(token_stream.lookAhead())
+    {
+    case Token_incr:
+    case Token_decr:
+    case '*':
+    case '&':
+    case '+':
+    case '-':
+    case '!':
+    case '~':
+      {
+        std::size_t op = token_stream.cursor();
+        token_stream.nextToken();
+
+        ExpressionAST *expr = 0;
+        if (!parseCastExpression(expr))
+          return false;
+
+        UnaryExpressionAST *ast = CreateNode<UnaryExpressionAST>(_M_pool);
+        ast->op = op;
+        ast->expression = expr;
+
+        UPDATE_POS(ast, start, token_stream.cursor());
+        node = ast;
+      }
+      return true;
+
+    case Token_sizeof:
+      {
+        std::size_t sizeof_token = token_stream.cursor();
+        token_stream.nextToken();
+
+        SizeofExpressionAST *ast = CreateNode<SizeofExpressionAST>(_M_pool);
+        ast->sizeof_token = sizeof_token;
+
+        std::size_t index = token_stream.cursor();
+        if (token_stream.lookAhead() == '(')
+          {
+            token_stream.nextToken();
+            if (parseTypeId(ast->type_id) && token_stream.lookAhead() == ')')
+              {
+                token_stream.nextToken(); // skip )
+
+                UPDATE_POS(ast, start, token_stream.cursor());
+                node = ast;
+                return true;
+              }
+
+            ast->type_id = 0;
+            token_stream.rewind((int) index);
+          }
+
+        if (!parseUnaryExpression(ast->expression))
+          return false;
+
+        UPDATE_POS(ast, start, token_stream.cursor());
+        node = ast;
+        return true;
+      }
+
+    default:
+      break;
+    }
+
+  int token = token_stream.lookAhead();
+
+  if (token == Token_new
+      || (token == Token_scope && token_stream.lookAhead(1) == Token_new))
+    return parseNewExpression(node);
+
+  if (token == Token_delete
+      || (token == Token_scope && token_stream.lookAhead(1) == Token_delete))
+    return parseDeleteExpression(node);
+
+  return parsePostfixExpression(node);
+}
+
+bool Parser::parseNewExpression(ExpressionAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  NewExpressionAST *ast = CreateNode<NewExpressionAST>(_M_pool);
+
+  if (token_stream.lookAhead() == Token_scope
+      && token_stream.lookAhead(1) == Token_new)
+    {
+      ast->scope_token = token_stream.cursor();
+      token_stream.nextToken();
+    }
+
+  CHECK(Token_new);
+  ast->new_token = token_stream.cursor() - 1;
+
+  if (token_stream.lookAhead() == '(')
+    {
+      token_stream.nextToken();
+      parseCommaExpression(ast->expression);
+      CHECK(')');
+    }
+
+  if (token_stream.lookAhead() == '(')
+    {
+      token_stream.nextToken();
+      parseTypeId(ast->type_id);
+      CHECK(')');
+    }
+  else
+    {
+      parseNewTypeId(ast->new_type_id);
+    }
+
+  parseNewInitializer(ast->new_initializer);
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseNewTypeId(NewTypeIdAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  TypeSpecifierAST *typeSpec = 0;
+  if (!parseTypeSpecifier(typeSpec))
+    return false;
+
+  NewTypeIdAST *ast = CreateNode<NewTypeIdAST>(_M_pool);
+  ast->type_specifier = typeSpec;
+
+  parseNewDeclarator(ast->new_declarator);
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseNewDeclarator(NewDeclaratorAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  NewDeclaratorAST *ast = CreateNode<NewDeclaratorAST>(_M_pool);
+
+  PtrOperatorAST *ptrOp = 0;
+  if (parsePtrOperator(ptrOp))
+    {
+      ast->ptr_op = ptrOp;
+      parseNewDeclarator(ast->sub_declarator);
+    }
+
+  while (token_stream.lookAhead() == '[')
+    {
+      token_stream.nextToken();
+      ExpressionAST *expr = 0;
+      parseExpression(expr);
+      ast->expressions = snoc(ast->expressions, expr, _M_pool);
+      ADVANCE(']', "]");
+    }
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseNewInitializer(NewInitializerAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  CHECK('(');
+
+  NewInitializerAST *ast = CreateNode<NewInitializerAST>(_M_pool);
+
+  parseCommaExpression(ast->expression);
+
+  CHECK(')');
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseDeleteExpression(ExpressionAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  DeleteExpressionAST *ast = CreateNode<DeleteExpressionAST>(_M_pool);
+
+  if (token_stream.lookAhead() == Token_scope
+      && token_stream.lookAhead(1) == Token_delete)
+    {
+      ast->scope_token = token_stream.cursor();
+      token_stream.nextToken();
+    }
+
+  CHECK(Token_delete);
+  ast->delete_token = token_stream.cursor() - 1;
+
+  if (token_stream.lookAhead() == '[')
+    {
+      ast->lbracket_token = token_stream.cursor();
+      token_stream.nextToken();
+      CHECK(']');
+      ast->rbracket_token = token_stream.cursor() - 1;
+    }
+
+  if (!parseCastExpression(ast->expression))
+    return false;
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseCastExpression(ExpressionAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  if (token_stream.lookAhead() == '(')
+    {
+      token_stream.nextToken();
+
+      CastExpressionAST *ast = CreateNode<CastExpressionAST>(_M_pool);
+
+      if (parseTypeId(ast->type_id))
+        {
+          if (token_stream.lookAhead() == ')')
+            {
+              token_stream.nextToken();
+
+              if (parseCastExpression(ast->expression))
+                {
+                  UPDATE_POS(ast, start, token_stream.cursor());
+                  node = ast;
+
+                  return true;
+                }
+            }
+        }
+    }
+
+  token_stream.rewind((int) start);
+  return parseUnaryExpression(node);
+}
+
+bool Parser::parsePmExpression(ExpressionAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  if (!parseCastExpression(node) || !node) // ### fixme
+    return false;
+
+  while (token_stream.lookAhead() == Token_ptrmem)
+    {
+      std::size_t op = token_stream.cursor();
+      token_stream.nextToken();
+
+      ExpressionAST *rightExpr = 0;
+      if (!parseCastExpression(rightExpr))
+        return false;
+
+      BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+      ast->op = op;
+      ast->left_expression = node;
+      ast->right_expression = rightExpr;
+
+      UPDATE_POS(ast, start, token_stream.cursor());
+      node = ast;
+    }
+
+  return true;
+}
+
+bool Parser::parseMultiplicativeExpression(ExpressionAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  if (!parsePmExpression(node))
+    return false;
+
+  while (token_stream.lookAhead() == '*'
+         || token_stream.lookAhead() == '/'
+         || token_stream.lookAhead() == '%')
+    {
+      std::size_t op = token_stream.cursor();
+      token_stream.nextToken();
+
+      ExpressionAST *rightExpr = 0;
+      if (!parsePmExpression(rightExpr))
+        return false;
+
+      BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+      ast->op = op;
+      ast->left_expression = node;
+      ast->right_expression = rightExpr;
+
+      UPDATE_POS(ast, start, token_stream.cursor());
+      node = ast;
+    }
+
+  return true;
+}
+
+
+bool Parser::parseAdditiveExpression(ExpressionAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  if (!parseMultiplicativeExpression(node))
+    return false;
+
+  while (token_stream.lookAhead() == '+' || token_stream.lookAhead() == '-')
+    {
+      std::size_t op = token_stream.cursor();
+      token_stream.nextToken();
+
+      ExpressionAST *rightExpr = 0;
+      if (!parseMultiplicativeExpression(rightExpr))
+        return false;
+
+      BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+      ast->op = op;
+      ast->left_expression = node;
+      ast->right_expression = rightExpr;
+
+      UPDATE_POS(ast, start, token_stream.cursor());
+      node = ast;
+    }
+
+  return true;
+}
+
+bool Parser::parseShiftExpression(ExpressionAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  if (!parseAdditiveExpression(node))
+    return false;
+
+  while (token_stream.lookAhead() == Token_shift)
+    {
+      std::size_t op = token_stream.cursor();
+      token_stream.nextToken();
+
+      ExpressionAST *rightExpr = 0;
+      if (!parseAdditiveExpression(rightExpr))
+        return false;
+
+      BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+      ast->op = op;
+      ast->left_expression = node;
+      ast->right_expression = rightExpr;
+
+      UPDATE_POS(ast, start, token_stream.cursor());
+      node = ast;
+    }
+
+  return true;
+}
+
+bool Parser::parseRelationalExpression(ExpressionAST *&node, bool templArgs)
+{
+  std::size_t start = token_stream.cursor();
+
+  if (!parseShiftExpression(node))
+    return false;
+
+  while (token_stream.lookAhead() == '<'
+         || (token_stream.lookAhead() == '>' && !templArgs)
+         || token_stream.lookAhead() == Token_leq
+         || token_stream.lookAhead() == Token_geq)
+    {
+      std::size_t op = token_stream.cursor();
+      token_stream.nextToken();
+
+      ExpressionAST *rightExpr = 0;
+      if (!parseShiftExpression(rightExpr))
+        return false;
+
+      BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+      ast->op = op;
+      ast->left_expression = node;
+      ast->right_expression = rightExpr;
+
+      UPDATE_POS(ast, start, token_stream.cursor());
+      node = ast;
+    }
+
+  return true;
+}
+
+bool Parser::parseEqualityExpression(ExpressionAST *&node, bool templArgs)
+{
+  std::size_t start = token_stream.cursor();
+
+  if (!parseRelationalExpression(node, templArgs))
+    return false;
+
+  while (token_stream.lookAhead() == Token_eq
+         || token_stream.lookAhead() == Token_not_eq)
+    {
+      std::size_t op = token_stream.cursor();
+      token_stream.nextToken();
+
+      ExpressionAST *rightExpr = 0;
+      if (!parseRelationalExpression(rightExpr, templArgs))
+        return false;
+
+      BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+      ast->op = op;
+      ast->left_expression = node;
+      ast->right_expression = rightExpr;
+
+      UPDATE_POS(ast, start, token_stream.cursor());
+      node = ast;
+    }
+
+  return true;
+}
+
+bool Parser::parseAndExpression(ExpressionAST *&node, bool templArgs)
+{
+  std::size_t start = token_stream.cursor();
+
+  if (!parseEqualityExpression(node, templArgs))
+    return false;
+
+  while (token_stream.lookAhead() == '&')
+    {
+      std::size_t op = token_stream.cursor();
+      token_stream.nextToken();
+
+      ExpressionAST *rightExpr = 0;
+      if (!parseEqualityExpression(rightExpr, templArgs))
+        return false;
+
+      BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+      ast->op = op;
+      ast->left_expression = node;
+      ast->right_expression = rightExpr;
+
+      UPDATE_POS(ast, start, token_stream.cursor());
+      node = ast;
+    }
+
+  return true;
+}
+
+bool Parser::parseExclusiveOrExpression(ExpressionAST *&node, bool templArgs)
+{
+  std::size_t start = token_stream.cursor();
+
+  if (!parseAndExpression(node, templArgs))
+    return false;
+
+  while (token_stream.lookAhead() == '^')
+    {
+      std::size_t op = token_stream.cursor();
+      token_stream.nextToken();
+
+      ExpressionAST *rightExpr = 0;
+      if (!parseAndExpression(rightExpr, templArgs))
+        return false;
+
+      BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+      ast->op = op;
+      ast->left_expression = node;
+      ast->right_expression = rightExpr;
+
+      UPDATE_POS(ast, start, token_stream.cursor());
+      node = ast;
+    }
+
+  return true;
+}
+
+bool Parser::parseInclusiveOrExpression(ExpressionAST *&node, bool templArgs)
+{
+  std::size_t start = token_stream.cursor();
+
+  if (!parseExclusiveOrExpression(node, templArgs))
+    return false;
+
+  while (token_stream.lookAhead() == '|')
+    {
+      std::size_t op = token_stream.cursor();
+      token_stream.nextToken();
+
+      ExpressionAST *rightExpr = 0;
+      if (!parseExclusiveOrExpression(rightExpr, templArgs))
+        return false;
+
+      BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+      ast->op = op;
+      ast->left_expression = node;
+      ast->right_expression = rightExpr;
+
+      UPDATE_POS(ast, start, token_stream.cursor());
+      node = ast;
+    }
+
+  return true;
+}
+
+bool Parser::parseLogicalAndExpression(ExpressionAST *&node, bool templArgs)
+{
+  std::size_t start = token_stream.cursor();
+
+  if (!parseInclusiveOrExpression(node, templArgs))
+    return false;
+
+  while (token_stream.lookAhead() == Token_and)
+    {
+      std::size_t op = token_stream.cursor();
+      token_stream.nextToken();
+
+      ExpressionAST *rightExpr = 0;
+      if (!parseInclusiveOrExpression(rightExpr, templArgs))
+        return false;
+
+      BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+      ast->op = op;
+      ast->left_expression = node;
+      ast->right_expression = rightExpr;
+
+      UPDATE_POS(ast, start, token_stream.cursor());
+      node = ast;
+    }
+
+  return true;
+}
+
+bool Parser::parseLogicalOrExpression(ExpressionAST *&node, bool templArgs)
+{
+  std::size_t start = token_stream.cursor();
+
+  if (!parseLogicalAndExpression(node, templArgs))
+    return false;
+
+  while (token_stream.lookAhead() == Token_or)
+    {
+      std::size_t op = token_stream.cursor();
+      token_stream.nextToken();
+
+      ExpressionAST *rightExpr = 0;
+      if (!parseLogicalAndExpression(rightExpr, templArgs))
+        return false;
+
+      BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+      ast->op = op;
+      ast->left_expression = node;
+      ast->right_expression = rightExpr;
+
+      UPDATE_POS(ast, start, token_stream.cursor());
+      node = ast;
+    }
+
+  return true;
+}
+
+bool Parser::parseConditionalExpression(ExpressionAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  if (!parseLogicalOrExpression(node))
+    return false;
+
+  if (token_stream.lookAhead() == '?')
+    {
+      token_stream.nextToken();
+
+      ExpressionAST *leftExpr = 0;
+      if (!parseExpression(leftExpr))
+        return false;
+
+      CHECK(':');
+
+      ExpressionAST *rightExpr = 0;
+      if (!parseAssignmentExpression(rightExpr))
+        return false;
+
+      ConditionalExpressionAST *ast
+        = CreateNode<ConditionalExpressionAST>(_M_pool);
+
+      ast->condition = node;
+      ast->left_expression = leftExpr;
+      ast->right_expression = rightExpr;
+
+      UPDATE_POS(ast, start, token_stream.cursor());
+      node = ast;
+    }
+
+  return true;
+}
+
+bool Parser::parseAssignmentExpression(ExpressionAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  if (token_stream.lookAhead() == Token_throw && !parseThrowExpression(node))
+    return false;
+  else if (!parseConditionalExpression(node))
+    return false;
+
+  while (token_stream.lookAhead() == Token_assign
+         || token_stream.lookAhead() == '=')
+    {
+      std::size_t op = token_stream.cursor();
+      token_stream.nextToken();
+
+      ExpressionAST *rightExpr = 0;
+      if (!parseConditionalExpression(rightExpr))
+        return false;
+
+      BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+      ast->op = op;
+      ast->left_expression = node;
+      ast->right_expression = rightExpr;
+
+      UPDATE_POS(ast, start, token_stream.cursor());
+      node = ast;
+    }
+
+  return true;
+}
+
+bool Parser::parseConstantExpression(ExpressionAST *&node)
+{
+  return parseConditionalExpression(node);
+}
+
+bool Parser::parseExpression(ExpressionAST *&node)
+{
+  return parseCommaExpression(node);
+}
+
+bool Parser::parseCommaExpression(ExpressionAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  if (!parseAssignmentExpression(node))
+    return false;
+
+  while (token_stream.lookAhead() == ',')
+    {
+      std::size_t op = token_stream.cursor();
+      token_stream.nextToken();
+
+      ExpressionAST *rightExpr = 0;
+      if (!parseAssignmentExpression(rightExpr))
+        return false;
+
+      BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+      ast->op = op;
+      ast->left_expression = node;
+      ast->right_expression = rightExpr;
+
+      UPDATE_POS(ast, start, token_stream.cursor());
+      node = ast;
+    }
+
+  return true;
+}
+
+bool Parser::parseThrowExpression(ExpressionAST *&node)
+{
+  std::size_t start = token_stream.cursor();
+
+  CHECK(Token_throw);
+
+  ThrowExpressionAST *ast = CreateNode<ThrowExpressionAST>(_M_pool);
+  ast->throw_token = token_stream.cursor() - 1;
+
+  parseAssignmentExpression(ast->expression);
+
+  UPDATE_POS(ast, start, token_stream.cursor());
+  node = ast;
+
+  return true;
+}
+
+bool Parser::parseQ_ENUMS(DeclarationAST *&node)
+{
+  if (token_stream.lookAhead() != Token_Q_ENUMS)
+    return false;
+
+  if (token_stream.lookAhead(1) != '(')
+    return false;
+
+  token_stream.nextToken();
+  token_stream.nextToken();
+
+  int firstToken = token_stream.cursor();
+  while (token_stream.lookAhead() != ')') {
+    token_stream.nextToken();
+  }
+  QEnumsAST *ast = CreateNode<QEnumsAST>(_M_pool);
+  UPDATE_POS(ast, firstToken, token_stream.cursor());
+  node = ast;
+
+  token_stream.nextToken();
+
+  return true;
+}
+
+bool Parser::parseQ_PROPERTY(DeclarationAST *&node)
+{
+  if (token_stream.lookAhead() != Token_Q_PROPERTY)
+    return false;
+
+  if (token_stream.lookAhead(1) != '(')
+    return false;
+
+  token_stream.nextToken();
+  token_stream.nextToken();
+
+  int firstToken = token_stream.cursor();
+  while (token_stream.lookAhead() != ')') {
+    token_stream.nextToken();
+  }
+  QPropertyAST *ast = CreateNode<QPropertyAST>(_M_pool);
+  UPDATE_POS(ast, firstToken, token_stream.cursor());
+  node = ast;
+
+//   const Token &t1 = token_stream[firstToken];
+//   const Token &t2 = token_stream[token_stream.cursor()];
+//   printf("property: %s\n",
+//          qPrintable(QString::fromLatin1(t1.text + t1.position, t2.position - t1.position)));
+
+  token_stream.nextToken();
+
+  return true;
+}
+
+bool Parser::block_errors(bool block)
+{
+  bool current = _M_block_errors;
+  _M_block_errors = block;
+  return current;
+}
+
+
+// kate: space-indent on; indent-width 2; replace-tabs on;