aboutsummaryrefslogtreecommitdiffstats
path: root/parser/parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'parser/parser.cpp')
-rw-r--r--parser/parser.cpp4056
1 files changed, 4056 insertions, 0 deletions
diff --git a/parser/parser.cpp b/parser/parser.cpp
new file mode 100644
index 000000000..d65d5f3e4
--- /dev/null
+++ b/parser/parser.cpp
@@ -0,0 +1,4056 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+/* -*- 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>
+
+#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)
+ 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);
+ 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);
+
+ //fprintf(stderr, "[%s-%s] ast->ptr_ops: %p\n", __FILE__, __FUNCTION__, ast->ptr_ops);
+
+ 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)
+ 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 && expr_ast);
+ 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);
+
+ 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
+ && 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);
+
+ 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;
+