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