diff options
Diffstat (limited to 'lib/cppparser/parser.cpp')
-rw-r--r-- | lib/cppparser/parser.cpp | 4330 |
1 files changed, 4330 insertions, 0 deletions
diff --git a/lib/cppparser/parser.cpp b/lib/cppparser/parser.cpp new file mode 100644 index 00000000..b790f5a1 --- /dev/null +++ b/lib/cppparser/parser.cpp @@ -0,0 +1,4330 @@ +/* This file is part of KDevelop + Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +// c++ support +#include "driver.h" +#include "lexer.h" +#include "parser.h" +#include "errors.h" + +// qt +#include <qstring.h> +#include <qstringlist.h> +#include <qasciidict.h> + +#include <kdebug.h> +#include <klocale.h> + +using namespace std; + +#define ADVANCE(tk, descr) \ +{ \ + const Token& token = lex->lookAhead( 0 ); \ + if( token != tk ){ \ + reportError( i18n("'%1' expected found '%2'").arg(descr).arg(token.text()) ); \ + return false; \ + } \ + nextToken(); \ +} + +#define ADVANCE_NR(tk, descr) \ +{ \ + const Token& token = lex->lookAhead( 0 ); \ + if( token != tk ){ \ + reportError( i18n("'%1' expected found '%2'").arg(descr).arg(token.text()) ); \ + } \ + else \ + nextToken(); \ +} + +#define CHECK(tk, descr) \ +{ \ + const Token& token = lex->lookAhead( 0 ); \ + if( token != tk ){ \ + return false; \ + } \ + nextToken(); \ +} + +#define MATCH(tk, descr) \ +{ \ + const Token& token = lex->lookAhead( 0 ); \ + if( token != tk ){ \ + reportError( Errors::SyntaxError ); \ + return false; \ + } \ +} + + + +#define UPDATE_POS(node, start, end) \ +{ \ + int line, col; \ + const Token &a = lex->tokenAt(start); \ + const Token &b = lex->tokenAt( end!=start ? end-1 : end ); \ + a.getStartPosition( &line, &col ); \ + (node)->setStartPosition( line, col ); \ + b.getEndPosition( &line, &col ); \ + (node)->setEndPosition( line, col ); \ + if( (node)->nodeType() == NodeType_Generic ) { \ + if ((start) == (end) || (end) == (start)+1) \ + (node)->setSlice(lex->source(), a.position(), a.length()); \ + else \ + (node)->setText( toString((start),(end)) ); \ + } \ +} + +#define AST_FROM_TOKEN(node, tk) \ + AST::Node node = CreateNode<AST>(); \ + UPDATE_POS( node, (tk), (tk)+1 ); + + +//@todo remove me +enum +{ + OBJC_CLASS, + OBJC_PROTOCOL, + OBJC_ALIAS +}; + +struct ParserPrivateData +{ + ParserPrivateData() + {} +}; + +Parser::Parser( Driver* driver, Lexer* lexer ) + : m_driver( driver ), + lex( lexer ), m_problems(0) +{ + d = new ParserPrivateData(); + + m_maxProblems = 5; + objcp = false; +} + +Parser::~Parser() +{ + delete d; + d = 0; +} + +bool Parser::reportError( const Error& err ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::reportError()" << endl; + if( m_problems < m_maxProblems ){ + ++m_problems; + int line=0, col=0; + const Token& token = lex->lookAhead( 0 ); + lex->getTokenPosition( token, &line, &col ); + + QString s = lex->lookAhead(0).text(); + s = s.left( 30 ).stripWhiteSpace(); + if( s.isEmpty() ) + s = i18n( "<eof>" ); + + m_driver->addProblem( m_driver->currentFileName(), Problem(err.text.arg(s), line, col) ); + } + + return true; +} + +bool Parser::reportError( const QString& msg ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::reportError()" << endl; + if( m_problems < m_maxProblems ){ + ++m_problems; + int line=0, col=0; + const Token& token = lex->lookAhead( 0 ); + lex->getTokenPosition( token, &line, &col ); + + m_driver->addProblem( m_driver->currentFileName(), Problem(msg, line, col) ); + } + + return true; +} + +void Parser::syntaxError() +{ + (void) reportError( Errors::SyntaxError ); +} + +bool Parser::skipUntil( int token ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::skipUntil()" << endl; + while( !lex->lookAhead(0).isNull() ){ + if( lex->lookAhead(0) == token ) + return true; + + nextToken(); + } + + return false; +} + +bool Parser::skipUntilDeclaration() +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::skipUntilDeclaration()" << endl; + clearComment(); + + while( !lex->lookAhead(0).isNull() ){ + + switch( lex->lookAhead(0) ){ + 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: + nextToken(); + } + } + + return false; +} + +bool Parser::skipUntilStatement() +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::skipUntilStatement() -- token = " << lex->lookAhead(0).text() << endl; + + while( !lex->lookAhead(0).isNull() ){ + switch( lex->lookAhead(0) ){ + 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: + nextToken(); + } + } + + return false; +} + +bool Parser::skip( int l, int r ) +{ + int count = 0; + while( !lex->lookAhead(0).isNull() ){ + int tk = lex->lookAhead( 0 ); + + if( tk == l ) + ++count; + else if( tk == r ) + --count; + else if( l != '{' && (tk == '{' || tk == '}' || tk == ';') ) + return false; + + if( count == 0 ) + return true; + + nextToken(); + } + + return false; +} + +bool Parser::skipCommaExpression( AST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::skipCommaExpression()" << endl; + + int start = lex->index(); + + AST::Node expr; + if( !skipExpression(expr) ) + return false; + + while( lex->lookAhead(0) == ',' ){ + nextToken(); + + if( !skipExpression(expr) ){ + reportError( i18n("expression expected") ); + return false; + } + } + + AST::Node ast = CreateNode<AST>(); + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; +} + +bool Parser::skipExpression( AST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::skipExpression()" << endl; + + int start = lex->index(); + + while( !lex->lookAhead(0).isNull() ){ + int tk = lex->lookAhead( 0 ); + + switch( tk ){ + case '(': + skip( '(', ')' ); + nextToken(); + break; + + case '[': + skip( '[', ']' ); + nextToken(); + break; + +#if 0 + case Token_identifier: + nextToken(); + if( lex->lookAhead( 0 ) == Token_identifier ) + return true; + break; +#endif + + case ';': + case ',': + case ']': + case ')': + 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: + { + AST::Node ast = CreateNode<AST>(); + UPDATE_POS( ast, start, lex->index() ); + node = ast; + } + return true; + + default: + nextToken(); + } + } + + return false; +} + +bool Parser::parseName( NameAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseName()" << endl; + + GroupAST::Node winDeclSpec; + parseWinDeclSpec( winDeclSpec ); + + int start = lex->index(); + + NameAST::Node ast = CreateNode<NameAST>(); + + if( lex->lookAhead(0) == Token_scope ){ + ast->setGlobal( true ); + nextToken(); + } + + int idx = lex->index(); + + while( true ){ + ClassOrNamespaceNameAST::Node n; + if( !parseUnqualifiedName(n) ) { + return false; + } + + if( lex->lookAhead(0) == Token_scope ){ + nextToken(); + ast->addClassOrNamespaceName( n ); + if( lex->lookAhead(0) == Token_template ) + nextToken(); /// skip optional template #### @todo CHECK + } else { + ast->setUnqualifiedName( n ); + break; + } + } + + if( idx == lex->index() ) + return false; + + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; +} + +bool Parser::parseTranslationUnit( TranslationUnitAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTranslationUnit()" << endl; + + int start = lex->index(); + + m_problems = 0; + TranslationUnitAST::Node tun = CreateNode<TranslationUnitAST>(); + node = tun; + if( lex->lookAhead(0) == Token_comment ) { + node->setComment( lex->lookAhead(0).text() ); + nextToken(); + } + + while( !lex->lookAhead(0).isNull() ){ + DeclarationAST::Node def; + int startDecl = lex->index(); + if( !parseDeclaration(def) ){ + // error recovery + if( startDecl == lex->index() ) + nextToken(); // skip at least one token + skipUntilDeclaration(); + } + node->addDeclaration( def ); + } + + UPDATE_POS( node, start, lex->index() ); + + // force (0,0) as start position + node->setStartPosition( 0, 0 ); + + return m_problems == 0; +} + +bool Parser::parseDeclaration( DeclarationAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseDeclaration()" << endl; + + int start = lex->index(); + + switch( lex->lookAhead(0) ){ + + case ';': + nextToken(); + return true; + + case Token_extern: + return parseLinkageSpecification( node ); + + case Token_namespace: + return parseNamespace( node ); + + case Token_using: + return parseUsing( node ); + + case Token_typedef: + return parseTypedef( node ); + + case Token_asm: + return parseAsmDefinition( node ); + + case Token_template: + case Token_export: + return parseTemplateDeclaration( node ); + + default: + { + // lex->setIndex( start ); + + if( objcp && parseObjcDef(node) ) + return true; + + lex->setIndex( start ); + + GroupAST::Node storageSpec; + parseStorageClassSpecifier( storageSpec ); + + GroupAST::Node cv; + parseCvQualify( cv ); + + TypeSpecifierAST::Node spec; + AST::Node declarator; + if( parseEnumSpecifier(spec) || parseClassSpecifier(spec) ) { + int line, c; + spec->getEndPosition( &line, &c ); + spec->setCvQualify( cv ); + + GroupAST::Node cv2; + parseCvQualify( cv2 ); + spec->setCv2Qualify( cv2 ); + + InitDeclaratorListAST::Node declarators; + parseInitDeclaratorList(declarators); + + SimpleDeclarationAST::Node ast = CreateNode<SimpleDeclarationAST>(); + + ADVANCE( ';', ";" ); + + preparseLineComments( line ); + + ast->setComment( m_commentStore.getCommentInRange( line ) ); + + ast->setStorageSpecifier( storageSpec ); + ast->setTypeSpec( spec ); + ast->setInitDeclaratorList( declarators ); + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; + } + + lex->setIndex( start ); + return parseDeclarationInternal( node ); + } + + } // end switch +} + +bool Parser::parseLinkageSpecification( DeclarationAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseLinkageSpecification()" << endl; + + int start = lex->index(); + + if( lex->lookAhead(0) != Token_extern ){ + return false; + } + nextToken(); + + LinkageSpecificationAST::Node ast = CreateNode<LinkageSpecificationAST>(); + + int startExternType = lex->index(); + if( lex->lookAhead(0) == Token_string_literal ){ + nextToken(); + AST::Node externType = CreateNode<AST>(); + UPDATE_POS( externType, startExternType, lex->index() ); + + ast->setExternType( externType ); + } + + if( lex->lookAhead(0) == '{' ){ + LinkageBodyAST::Node linkageBody; + parseLinkageBody( linkageBody ); + ast->setLinkageBody( linkageBody ); + } else { + DeclarationAST::Node decl; + if( !parseDeclaration(decl) ){ + reportError( i18n("Declaration syntax error") ); + } + ast->setDeclaration( decl ); + } + + UPDATE_POS( ast, start, lex->index() ); + + node = ast; + + return true; +} + +bool Parser::parseLinkageBody( LinkageBodyAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseLinkageBody()" << endl; + + int start = lex->index(); + + if( lex->lookAhead(0) != '{' ){ + return false; + } + nextToken(); + + LinkageBodyAST::Node lba = CreateNode<LinkageBodyAST>(); + node = lba; + + while( !lex->lookAhead(0).isNull() ){ + int tk = lex->lookAhead( 0 ); + + if( tk == '}' ) + break; + + DeclarationAST::Node def; + int startDecl = lex->index(); + if( parseDeclaration(def) ){ + node->addDeclaration( def ); + } else { + // error recovery + if( startDecl == lex->index() ) + nextToken(); // skip at least one token + skipUntilDeclaration(); + } + } + + clearComment(); + + if( lex->lookAhead(0) != '}' ){ + reportError( i18n("} expected") ); + } else + nextToken(); + + UPDATE_POS( node, start, lex->index() ); + return true; +} + +bool Parser::parseNamespace( DeclarationAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseNamespace()" << endl; + + int start = lex->index(); + + if( lex->lookAhead(0) != Token_namespace ){ + return false; + } + nextToken(); + + int startNamespaceName = lex->index(); + if( lex->lookAhead(0) == Token_identifier ){ + nextToken(); + } + AST::Node namespaceName = CreateNode<AST>(); + UPDATE_POS( namespaceName, startNamespaceName, lex->index() ); + + if ( lex->lookAhead(0) == '=' ) { + // namespace alias + nextToken(); + + NameAST::Node name; + if( parseName(name) ){ + ADVANCE( ';', ";" ); + + NamespaceAliasAST::Node ast = CreateNode<NamespaceAliasAST>(); + ast->setNamespaceName( namespaceName ); + ast->setAliasName( name ); + UPDATE_POS( ast, start, lex->index() ); + node = ast; + return true; + } else { + reportError( i18n("namespace expected") ); + return false; + } + } else if( lex->lookAhead(0) != '{' ){ + reportError( i18n("{ expected") ); + return false; + } + + NamespaceAST::Node ast = CreateNode<NamespaceAST>(); + ast->setNamespaceName( namespaceName ); + + LinkageBodyAST::Node linkageBody; + parseLinkageBody( linkageBody ); + + ast->setLinkageBody( linkageBody ); + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; +} + +bool Parser::parseUsing( DeclarationAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseUsing()" << endl; + + int start = lex->index(); + + if( lex->lookAhead(0) != Token_using ){ + return false; + } + nextToken(); + + if( lex->lookAhead(0) == Token_namespace ){ + if( !parseUsingDirective(node) ){ + return false; + } + UPDATE_POS( node, start, lex->index() ); + return true; + } + + UsingAST::Node ast = CreateNode<UsingAST>(); + + int startTypeName = lex->index(); + if( lex->lookAhead(0) == Token_typename ){ + nextToken(); + AST::Node tn = CreateNode<AST>(); + UPDATE_POS( tn, startTypeName, lex->index() ); + ast->setTypeName( tn ); + } + + NameAST::Node name; + if( !parseName(name) ) + return false; + + ast->setName( name ); + + ADVANCE( ';', ";" ); + + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; +} + +bool Parser::parseUsingDirective( DeclarationAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseUsingDirective()" << endl; + + int start = lex->index(); + + if( lex->lookAhead(0) != Token_namespace ){ + return false; + } + nextToken(); + + NameAST::Node name; + if( !parseName(name) ){ + reportError( i18n("Namespace name expected") ); + return false; + } + + ADVANCE( ';', ";" ); + + UsingDirectiveAST::Node ast = CreateNode<UsingDirectiveAST>(); + ast->setName( name ); + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; +} + + +bool Parser::parseOperatorFunctionId( AST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseOperatorFunctionId()" << endl; + + int start = lex->index(); + + if( lex->lookAhead(0) != Token_operator ){ + return false; + } + nextToken(); + + AST::Node op; + if( parseOperator(op) ){ + AST::Node asn = CreateNode<AST>(); + node = asn; + UPDATE_POS( node, start, lex->index() ); + return true; + } else { + // parse cast operator + GroupAST::Node cv; + parseCvQualify(cv); + + TypeSpecifierAST::Node spec; + if( !parseSimpleTypeSpecifier(spec) ){ + syntaxError(); + return false; + } + spec->setCvQualify( cv ); + + GroupAST::Node cv2; + parseCvQualify(cv2); + spec->setCv2Qualify( cv2 ); + + AST::Node ptrOp; + while( parsePtrOperator(ptrOp) ) + ; + + AST::Node asn = CreateNode<AST>(); + node = asn; + UPDATE_POS( node, start, lex->index() ); + return true; + } +} + +bool Parser::parseTemplateArgumentList( TemplateArgumentListAST::Node& node, bool reportError ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTemplateArgumentList()" << endl; + + int start = lex->index(); + + TemplateArgumentListAST::Node ast = CreateNode<TemplateArgumentListAST>(); + + AST::Node templArg; + if( !parseTemplateArgument(templArg) ) + return false; + ast->addArgument( templArg ); + + while( lex->lookAhead(0) == ',' ){ + nextToken(); + + if( !parseTemplateArgument(templArg) ){ + if( reportError ){ + syntaxError(); + break; + } else + return false; + } + ast->addArgument( templArg ); + } + + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; +} + +bool Parser::parseTypedef( DeclarationAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTypedef()" << endl; + + int start = lex->index(); + + if( lex->lookAhead(0) != Token_typedef ){ + return false; + } + nextToken(); + + TypeSpecifierAST::Node spec; + if( !parseTypeSpecifierOrClassSpec(spec) ){ + reportError( i18n("Need a type specifier to declare") ); + return false; + } + + InitDeclaratorListAST::Node declarators; + if( !parseInitDeclaratorList(declarators) ){ + //reportError( i18n("Need an identifier to declare") ); + //return false; + } + + TypedefAST::Node ast = CreateNode<TypedefAST>(); + + + if( comment() ) { + ast->setComment( comment() ); + clearComment(); + + preparseLineComments( currentLine() ); + + if( comment() ) { + ast->addComment( comment() ); + clearComment(); + } + } + + ADVANCE( ';', ";" ); + + ast->setTypeSpec( spec ); + ast->setInitDeclaratorList( declarators ); + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; +} + +bool Parser::parseAsmDefinition( DeclarationAST::Node& /*node*/ ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseAsmDefinition()" << endl; + + ADVANCE( Token_asm, "asm" ); + + GroupAST::Node cv; + parseCvQualify( cv ); + + skip( '(', ')' ); + ADVANCE( ')', ")" ); + ADVANCE( ';', ';' ); + + return true; +} + +bool Parser::parseTemplateDeclaration( DeclarationAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTemplateDeclaration()" << endl; + + int start = lex->index(); + + AST::Node exp; + + int startExport = lex->index(); + if( lex->lookAhead(0) == Token_export ){ + nextToken(); + AST::Node n = CreateNode<AST>(); + UPDATE_POS( n, startExport, lex->index() ); + exp = n; + } + + if( lex->lookAhead(0) != Token_template ){ + return false; + } + nextToken(); + + TemplateParameterListAST::Node params; + if( lex->lookAhead(0) == '<' ){ + nextToken(); + parseTemplateParameterList( params ); + + ADVANCE( '>', ">" ); + } + + DeclarationAST::Node def; + if( !parseDeclaration(def) ){ + reportError( i18n("expected a declaration") ); + } + + TemplateDeclarationAST::Node ast = CreateNode<TemplateDeclarationAST>(); + ast->setExported( exp ); + ast->setTemplateParameterList( params ); + ast->setDeclaration( def ); + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; +} + +bool Parser::parseOperator( AST::Node& /*node*/ ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseOperator()" << endl; + QString text = lex->lookAhead(0).text(); + + switch( lex->lookAhead(0) ){ + case Token_new: + case Token_delete: + nextToken(); + if( lex->lookAhead(0) == '[' && lex->lookAhead(1) == ']' ){ + nextToken(); + nextToken(); + text += "[]"; + } + return true; + + case '+': + case '-': + case '*': + case '/': + case '%': + case '^': + case '&': + case '|': + case '~': + case '!': + case '=': + case '<': + case '>': + case ',': + case Token_assign: + case Token_shift: + case Token_eq: + case Token_not_eq: + case Token_leq: + case Token_geq: + case Token_and: + case Token_or: + case Token_incr: + case Token_decr: + case Token_ptrmem: + case Token_arrow: + nextToken(); + return true; + + default: + if( lex->lookAhead(0) == '(' && lex->lookAhead(1) == ')' ){ + nextToken(); + nextToken(); + return true; + } else if( lex->lookAhead(0) == '[' && lex->lookAhead(1) == ']' ){ + nextToken(); + nextToken(); + return true; + } + } + + return false; +} + +bool Parser::parseCvQualify( GroupAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseCvQualify()" << endl; + + int start = lex->index(); + + GroupAST::Node ast = CreateNode<GroupAST>(); + + int n = 0; + while( !lex->lookAhead(0).isNull() ){ + int tk = lex->lookAhead( 0 ); + if( tk == Token_const || tk == Token_volatile ){ + ++n; + int startWord = lex->index(); + nextToken(); + AST::Node word = CreateNode<AST>(); + UPDATE_POS( word, startWord, lex->index() ); + ast->addNode( word ); + } else + break; + } + + if( n == 0 ) + return false; + + + ////kdDebug(9007)<< "-----------------> token = " << lex->lookAhead(0).text() << endl; + UPDATE_POS( ast, start, lex->index() ); + + node = ast; + return true; +} + +bool Parser::parseSimpleTypeSpecifier( TypeSpecifierAST::Node& node ) +{ + int start = lex->index(); + bool isIntegral = false; + bool done = false; + + while( !done ){ + + switch( lex->lookAhead(0) ){ + 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; + nextToken(); + break; + + default: + done = true; + } + } + + TypeSpecifierAST::Node ast = CreateNode<TypeSpecifierAST>(); + if( isIntegral ){ + ClassOrNamespaceNameAST::Node cl = CreateNode<ClassOrNamespaceNameAST>(); + + AST::Node n = CreateNode<AST>(); + UPDATE_POS( n, start, lex->index() ); + cl->setName( n ); + UPDATE_POS( cl, start, lex->index() ); + + NameAST::Node name = CreateNode<NameAST>(); + name->setUnqualifiedName( cl ); + UPDATE_POS( name, start, lex->index() ); + ast->setName( name ); + + } else { + NameAST::Node name; + if( !parseName(name) ){ + lex->setIndex( start ); + return false; + } + ast->setName( name ); + } + + UPDATE_POS( ast, start, lex->index() ); + node = ast; + return true; +} + +bool Parser::parsePtrOperator( AST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parsePtrOperator()" << endl; + + int start = lex->index(); + + if( lex->lookAhead(0) == '&' ){ + nextToken(); + } else if( lex->lookAhead(0) == '*' ){ + nextToken(); + } else { + int index = lex->index(); + AST::Node memPtr; + if( !parsePtrToMember(memPtr) ){ + lex->setIndex( index ); + return false; + } + } + + GroupAST::Node cv; + parseCvQualify( cv ); + + AST::Node ast = CreateNode<AST>(); + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; +} + + +bool Parser::parseTemplateArgument( AST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTemplateArgument()" << endl; + + int start = lex->index(); + if( parseTypeId(node) ){ + if( lex->lookAhead(0) == ',' || lex->lookAhead(0) == '>' ) + return true; + } + + lex->setIndex( start ); + if( !parseLogicalOrExpression(node, true) ){ + return false; + } + + return true; +} + +bool Parser::parseTypeSpecifier( TypeSpecifierAST::Node& spec ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTypeSpecifier()" << endl; + + GroupAST::Node cv; + parseCvQualify( cv ); + + if( parseElaboratedTypeSpecifier(spec) || parseSimpleTypeSpecifier(spec) ){ + spec->setCvQualify( cv ); + + GroupAST::Node cv2; + parseCvQualify( cv2 ); + spec->setCv2Qualify( cv2 ); + + return true; + } + + return false; +} + +bool Parser::parseDeclarator( DeclaratorAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseDeclarator()" << endl; + + int start = lex->index(); + + DeclaratorAST::Node ast = CreateNode<DeclaratorAST>(); + + DeclaratorAST::Node decl; + NameAST::Node declId; + + AST::Node ptrOp; + while( parsePtrOperator(ptrOp) ){ + ast->addPtrOp( ptrOp ); + } + + if( lex->lookAhead(0) == '(' ){ + nextToken(); + + if( !parseDeclarator(decl) ){ + return false; + } + ast->setSubDeclarator( decl ); + + if( lex->lookAhead(0) != ')'){ + return false; + } + nextToken(); + } else { + + if( lex->lookAhead(0) == ':' ){ + // unnamed bitfield + } else if( parseDeclaratorId(declId) ){ + ast->setDeclaratorId( declId ); + } else { + lex->setIndex( start ); + return false; + } + + if( lex->lookAhead(0) == ':' ){ + nextToken(); + AST::Node expr; + if( !parseConstantExpression(expr) ){ + reportError( i18n("Constant expression expected") ); + } + goto update_pos; + } + } + + { + bool isVector = true; + + while( lex->lookAhead(0) == '[' ){ + int startArray = lex->index(); + nextToken(); + AST::Node expr; + parseCommaExpression( expr ); + + ADVANCE( ']', "]" ); + AST::Node array = CreateNode<AST>(); + UPDATE_POS( array, startArray, lex->index() ); + ast->addArrayDimension( array ); + isVector = true; + } + + bool skipParen = false; + if( lex->lookAhead(0) == Token_identifier && lex->lookAhead(1) == '(' && lex->lookAhead(2) == '(' ){ + nextToken(); + nextToken(); + skipParen = true; + } + + if( ast->subDeclarator() && (!isVector || lex->lookAhead(0) != '(') ){ + lex->setIndex( start ); + return false; + } + + int index = lex->index(); + if( lex->lookAhead(0) == '(' ){ + nextToken(); + + ParameterDeclarationClauseAST::Node params; + if( !parseParameterDeclarationClause(params) ){ + ////kdDebug(9007)<< "----------------------> not a parameter declaration, maybe an initializer!?" << endl; + lex->setIndex( index ); + goto update_pos; + } + ast->setParameterDeclarationClause( params ); + + if( lex->lookAhead(0) != ')' ){ + lex->setIndex( index ); + goto update_pos; + } + + nextToken(); // skip ')' + + int startConstant = lex->index(); + if( lex->lookAhead(0) == Token_const ){ + nextToken(); + AST::Node constant = CreateNode<AST>(); + UPDATE_POS( constant, startConstant, lex->index() ); + ast->setConstant( constant ); + } + + GroupAST::Node except; + if( parseExceptionSpecification(except) ){ + ast->setExceptionSpecification( except ); + } + } + + if( skipParen ){ + if( lex->lookAhead(0) != ')' ){ + reportError( i18n("')' expected") ); + } else + nextToken(); + } + + } + +update_pos: + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; +} + +bool Parser::parseAbstractDeclarator( DeclaratorAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseDeclarator()" << endl; + int start = lex->index(); + + DeclaratorAST::Node ast = CreateNode<DeclaratorAST>(); + + DeclaratorAST::Node decl; + NameAST::Node declId; + + AST::Node ptrOp; + while( parsePtrOperator(ptrOp) ){ + ast->addPtrOp( ptrOp ); + } + + if( lex->lookAhead(0) == '(' ){ + nextToken(); + + if( !parseAbstractDeclarator(decl) ){ + return false; + } + ast->setSubDeclarator( decl ); + + if( lex->lookAhead(0) != ')'){ + return false; + } + nextToken(); + } + + { + + while( lex->lookAhead(0) == '[' ){ + int startArray = lex->index(); + nextToken(); + AST::Node expr; + skipCommaExpression( expr ); + + ADVANCE( ']', "]" ); + AST::Node array = CreateNode<AST>(); + UPDATE_POS( array, startArray, lex->index() ); + ast->addArrayDimension( array ); + } + + bool skipParen = false; + if( lex->lookAhead(0) == Token_identifier && lex->lookAhead(1) == '(' && lex->lookAhead(2) == '(' ){ + nextToken(); + nextToken(); + skipParen = true; + } + + int index = lex->index(); + if( lex->lookAhead(0) == '(' ){ + nextToken(); + + ParameterDeclarationClauseAST::Node params; + if( !parseParameterDeclarationClause(params) ){ + lex->setIndex( index ); + goto UPDATE_POS; + } + ast->setParameterDeclarationClause( params ); + + if( lex->lookAhead(0) != ')' ){ + lex->setIndex( index ); + goto UPDATE_POS; + } else + nextToken(); + + int startConstant = lex->index(); + if( lex->lookAhead(0) == Token_const ){ + nextToken(); + AST::Node constant = CreateNode<AST>(); + UPDATE_POS( constant, startConstant, lex->index() ); + ast->setConstant( constant ); + } + + GroupAST::Node except; + if( parseExceptionSpecification(except) ){ + ast->setExceptionSpecification( except ); + } + } + + if( skipParen ){ + if( lex->lookAhead(0) != ')' ){ + reportError( i18n("')' expected") ); + } else + nextToken(); + } + + } + +UPDATE_POS: + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; +} + + +bool Parser::parseEnumSpecifier( TypeSpecifierAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseEnumSpecifier()" << endl; + + int start = lex->index(); + + if( lex->lookAhead(0) != Token_enum ){ + return false; + } + + nextToken(); + + Comment c = comment(); + clearComment(); + NameAST::Node name; + parseName( name ); + + if( lex->lookAhead(0) != '{' ){ + lex->setIndex( start ); + return false; + } + nextToken(); + + EnumSpecifierAST::Node ast = CreateNode<EnumSpecifierAST>(); + ast->setName( name ); + + ast->setComment( c ); + + EnumeratorAST::Node enumerator; + if( parseEnumerator(enumerator) ){ + ast->addEnumerator( enumerator ); + + while( lex->lookAhead(0) == ',' ){ + nextToken(); + + if( !parseEnumerator(enumerator) ){ + //reportError( i18n("Enumerator expected") ); + break; + } + + ast->addEnumerator( enumerator ); + } + } + + clearComment( ); + + if( lex->lookAhead(0) != '}' ) + reportError( i18n("} missing") ); + else + nextToken(); + + + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; +} + +bool Parser::parseTemplateParameterList( TemplateParameterListAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTemplateParameterList()" << endl; + + int start = lex->index(); + + TemplateParameterListAST::Node ast = CreateNode<TemplateParameterListAST>(); + + TemplateParameterAST::Node param; + if( !parseTemplateParameter(param) ){ + return false; + } + ast->addTemplateParameter( param ); + + while( lex->lookAhead(0) == ',' ){ + nextToken(); + + if( !parseTemplateParameter(param) ){ + syntaxError(); + break; + } else { + ast->addTemplateParameter( param ); + } + } + + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; +} + +bool Parser::parseTemplateParameter( TemplateParameterAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTemplateParameter()" << endl; + + int start = lex->index(); + TemplateParameterAST::Node ast = CreateNode<TemplateParameterAST>(); + + TypeParameterAST::Node typeParameter; + ParameterDeclarationAST::Node param; + + int tk = lex->lookAhead( 0 ); + + 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, lex->index() ); + node = ast; + + return true; +} + +bool Parser::parseTypeParameter( TypeParameterAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTypeParameter()" << endl; + + int start = lex->index(); + TypeParameterAST::Node ast = CreateNode<TypeParameterAST>(); + + AST_FROM_TOKEN( kind, lex->index() ); + ast->setKind( kind ); + + switch( lex->lookAhead(0) ){ + + case Token_class: + case Token_typename: + { + nextToken(); // skip class + + // parse optional name + NameAST::Node name; + if( parseName(name) ){ + ast->setName( name ); + if( lex->lookAhead(0) == '=' ){ + nextToken(); + + AST::Node typeId; + if( !parseTypeId(typeId) ){ + syntaxError(); + return false; + } + ast->setTypeId( typeId ); + } + } + } + break; + + case Token_template: + { + nextToken(); // skip template + ADVANCE( '<', '<' ); + + TemplateParameterListAST::Node params; + if( !parseTemplateParameterList(params) ){ + return false; + } + ast->setTemplateParameterList( params ); + + ADVANCE( '>', ">" ); + + if( lex->lookAhead(0) == Token_class ) + nextToken(); + + // parse optional name + NameAST::Node name; + if( parseName(name) ){ + ast->setName( name ); + if( lex->lookAhead(0) == '=' ){ + nextToken(); + + AST::Node typeId; + if( !parseTypeId(typeId) ){ + syntaxError(); + return false; + } + ast->setTypeId( typeId ); + } + } + + if( lex->lookAhead(0) == '=' ){ + nextToken(); + + NameAST::Node templ_name; + parseName( templ_name ); + } + } + break; + + default: + return false; + + } // end switch + + + UPDATE_POS( ast, start, lex->index() ); + node = ast; + return true; +} + +bool Parser::parseStorageClassSpecifier( GroupAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseStorageClassSpecifier()" << endl; + + int start = lex->index(); + GroupAST::Node ast = CreateNode<GroupAST>(); + + while( !lex->lookAhead(0).isNull() ){ + int tk = lex->lookAhead( 0 ); + if( tk == Token_friend || tk == Token_auto || tk == Token_register || tk == Token_static || + tk == Token_extern || tk == Token_mutable ){ + int startNode = lex->index(); + nextToken(); + + AST::Node n = CreateNode<AST>(); + UPDATE_POS( n, startNode, lex->index() ); + ast->addNode( n ); + } else + break; + } + + if( ast->nodeList().count() == 0 ) + return false; + + UPDATE_POS( ast, start, lex->index() ); + node = ast; + return true; +} + +bool Parser::parseFunctionSpecifier( GroupAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseFunctionSpecifier()" << endl; + + int start = lex->index(); + GroupAST::Node ast = CreateNode<GroupAST>(); + + while( !lex->lookAhead(0).isNull() ){ + int tk = lex->lookAhead( 0 ); + if( tk == Token_inline || tk == Token_virtual || tk == Token_explicit ){ + int startNode = lex->index(); + nextToken(); + + AST::Node n = CreateNode<AST>(); + UPDATE_POS( n, startNode, lex->index() ); + ast->addNode( n ); + } else { + break; + } + } + + if( ast->nodeList().count() == 0 ) + return false; + + UPDATE_POS( ast, start, lex->index() ); + node = ast; + return true; +} + +bool Parser::parseTypeId( AST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTypeId()" << endl; + + /// @todo implement the AST for typeId + int start = lex->index(); + AST::Node ast = CreateNode<AST>(); + + TypeSpecifierAST::Node spec; + if( !parseTypeSpecifier(spec) ){ + return false; + } + + DeclaratorAST::Node decl; + parseAbstractDeclarator( decl ); + + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; +} + +bool Parser::parseInitDeclaratorList( InitDeclaratorListAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseInitDeclaratorList()" << endl; + + int start = lex->index(); + + InitDeclaratorListAST::Node ast = CreateNode<InitDeclaratorListAST>(); + InitDeclaratorAST::Node decl; + + if( !parseInitDeclarator(decl) ){ + return false; + } + ast->addInitDeclarator( decl ); + + while( lex->lookAhead(0) == ',' ){ + nextToken(); + + if( !parseInitDeclarator(decl) ){ + syntaxError(); + break; + } + ast->addInitDeclarator( decl ); + } + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseInitDeclaratorList() -- end" << endl; + + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; +} + +bool Parser::parseParameterDeclarationClause( ParameterDeclarationClauseAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseParameterDeclarationClause()" << endl; + + int start = lex->index(); + + ParameterDeclarationClauseAST::Node ast = CreateNode<ParameterDeclarationClauseAST>(); + + ParameterDeclarationListAST::Node params; + if( !parseParameterDeclarationList(params) ){ + + if ( lex->lookAhead(0) == ')' ) + goto good; + + if( lex->lookAhead(0) == Token_ellipsis && lex->lookAhead(1) == ')' ){ + AST_FROM_TOKEN( ellipsis, lex->index() ); + ast->setEllipsis( ellipsis ); + nextToken(); + goto good; + } + return false; + } + + if( lex->lookAhead(0) == Token_ellipsis ){ + AST_FROM_TOKEN( ellipsis, lex->index() ); + ast->setEllipsis( ellipsis ); + nextToken(); + } + +good: + ast->setParameterDeclarationList( params ); + + /// @todo add ellipsis + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; +} + + +void Parser::nextToken( bool skipComm ) { + lex->nextToken(); + if( skipComm ) { + if( lex->lookAhead(0) == Token_comment ) { + processComment(); + nextToken(); + } + } +} + + +Comment Parser::comment() { + return m_commentStore.latestComment(); +} + + +void Parser::preparseLineComments( int l ) { + for( int a = 0; a < 40; a++ ) { + if( lex->lookAhead(a).isNull() ) break; + int line, col; + lex->lookAhead( a ).getStartPosition( &line, &col ); + if( line < l ) { + continue; + } else if( line == l ) { + if( lex->lookAhead( a ) == Token_comment ) { + processComment( a ); + } + } else { + break; + } + } +} + + +void Parser::processComment( int offset ) { + int line, col; + lex->lookAhead( offset ).getStartPosition( &line, &col ); + m_commentStore.addComment( Comment( lex->lookAhead(offset).text(), line ) ); +} + +template<class Type> +void Parser::eventuallyTakeComment( int startLn, int endLn, Type& ast ) { + if( comment().line() >= startLn && comment().line() <= endLn ) { + if( &(*ast) ) { + if( comment() ) { + ast->setComment( comment() ); + } + } + + clearComment(); + } +} + +template<class Type> +void Parser::eventuallyTakeComment( Type& ast ) { + if( &(*ast) && comment() ) { + ast->setComment( comment() ); + } + + clearComment(); +} + +void Parser::clearComment( ) { + + m_commentStore.clear(); + +} + +int Parser::currentLine() { + int ln, col; + lex->lookAhead( 0 ).getStartPosition( &ln, &col ); + return ln; +} + +bool Parser::parseParameterDeclarationList( ParameterDeclarationListAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseParameterDeclarationList()" << endl; + + int start = lex->index(); + + ParameterDeclarationListAST::Node ast = CreateNode<ParameterDeclarationListAST>(); + + ParameterDeclarationAST::Node param; + if( !parseParameterDeclaration(param) ){ + lex->setIndex( start ); + return false; + } + ast->addParameter( param ); + + while( lex->lookAhead(0) == ',' ){ + nextToken(); + + if( lex->lookAhead(0) == Token_ellipsis ) + break; + + if( !parseParameterDeclaration(param) ){ + lex->setIndex( start ); + return false; + } + ast->addParameter( param ); + } + + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; +} + +bool Parser::parseParameterDeclaration( ParameterDeclarationAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseParameterDeclaration()" << endl; + + int start = lex->index(); + + // parse decl spec + TypeSpecifierAST::Node spec; + if( !parseTypeSpecifier(spec) ){ + lex->setIndex( start ); + return false; + } + + int index = lex->index(); + + DeclaratorAST::Node decl; + if( !parseDeclarator(decl) ){ + lex->setIndex( index ); + + // try with abstract declarator + if( !parseAbstractDeclarator(decl) ) + return false; + } + + AST::Node expr; + if( lex->lookAhead(0) == '=' ){ + nextToken(); + if( !parseLogicalOrExpression(expr,true) ){ + //reportError( i18n("Expression expected") ); + } + } + + ParameterDeclarationAST::Node ast = CreateNode<ParameterDeclarationAST>(); + ast->setTypeSpec( spec ); + ast->setDeclarator( decl ); + ast->setExpression( expr ); + + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; +} + + +bool Parser::parseClassSpecifier( TypeSpecifierAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseClassSpecifier()" << endl; + + int start = lex->index(); + + AST::Node classKey; + int classKeyStart = lex->index(); + + int kind = lex->lookAhead( 0 ); + if( kind == Token_class || kind == Token_struct || kind == Token_union ){ + AST::Node asn = CreateNode<AST>(); + classKey = asn; + nextToken(); + UPDATE_POS( classKey, classKeyStart, lex->index() ); + } else { + return false; + } + + GroupAST::Node winDeclSpec; + parseWinDeclSpec( winDeclSpec ); + + while( lex->lookAhead(0) == Token_identifier && lex->lookAhead(1) == Token_identifier ) + nextToken(); + + NameAST::Node name; + parseName( name ); + + BaseClauseAST::Node bases; + if( lex->lookAhead(0) == ':' ){ + if( !parseBaseClause(bases) ){ + skipUntil( '{' ); + } + } + + if( lex->lookAhead(0) != '{' ){ + lex->setIndex( start ); + return false; + } + + ClassSpecifierAST::Node ast = CreateNode<ClassSpecifierAST>(); + + eventuallyTakeComment( ast ); + + ADVANCE( '{', '{' ); + + + ast->setWinDeclSpec( winDeclSpec ); + ast->setClassKey( classKey ); + ast->setName( name ); + ast->setBaseClause( bases ); + + + while( !lex->lookAhead(0).isNull() ){ + if( lex->lookAhead(0) == '}' ) + break; + + DeclarationAST::Node memSpec; + int startDecl = lex->index(); + if( !parseMemberSpecification(memSpec) ){ + if( startDecl == lex->index() ) + nextToken(); // skip at least one token + skipUntilDeclaration(); + } else + ast->addDeclaration( memSpec ); + } + + clearComment(); + + if( lex->lookAhead(0) != '}' ){ + reportError( i18n("} missing") ); + } else + nextToken(); + + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; +} + +bool Parser::parseAccessSpecifier( AST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseAccessSpecifier()" << endl; + + int start = lex->index(); + + switch( lex->lookAhead(0) ){ + case Token_public: + case Token_protected: + case Token_private: { + AST::Node asn = CreateNode<AST>(); + node = asn; + nextToken(); + UPDATE_POS( node, start, lex->index() ); + return true; + } + } + + return false; +} + +bool Parser::parseMemberSpecification( DeclarationAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseMemberSpecification()" << endl; + + int start = lex->index(); + + AST::Node access; + + if( lex->lookAhead(0) == ';' ){ + nextToken(); + return true; + } else if( lex->lookAhead(0) == Token_Q_OBJECT || lex->lookAhead(0) == Token_K_DCOP ){ + nextToken(); + return true; + } else if( lex->lookAhead(0) == Token_signals || lex->lookAhead(0) == Token_k_dcop || lex->lookAhead(0) == Token_k_dcop_signals ){ + AccessDeclarationAST::Node ast = CreateNode<AccessDeclarationAST>(); + nextToken(); + AST::Node n = CreateNode<AST>(); + UPDATE_POS( n, start, lex->index() ); + ast->addAccess( n ); + ADVANCE( ':', ":" ); + UPDATE_POS( ast, start, lex->index() ); + 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::Node ast = CreateNode<AccessDeclarationAST>(); + ast->addAccess( access ); + + int startSlot = lex->index(); + if( lex->lookAhead(0) == Token_slots ){ + nextToken(); + AST::Node sl = CreateNode<AST>(); + UPDATE_POS( sl, startSlot, lex->index() ); + ast->addAccess( sl ); + } + ADVANCE( ':', ":" ); + UPDATE_POS( ast, start, lex->index() ); + node = ast; + return true; + } + + lex->setIndex( start ); + + GroupAST::Node storageSpec; + parseStorageClassSpecifier( storageSpec ); + + GroupAST::Node cv; + parseCvQualify( cv ); + + TypeSpecifierAST::Node spec; + if( parseEnumSpecifier(spec) || parseClassSpecifier(spec) ){ + spec->setCvQualify( cv ); + + GroupAST::Node cv2; + parseCvQualify( cv2 ); + spec->setCv2Qualify( cv2 ); + + InitDeclaratorListAST::Node declarators; + parseInitDeclaratorList( declarators ); + ADVANCE( ';', ";" ); + + SimpleDeclarationAST::Node ast = CreateNode<SimpleDeclarationAST>(); + ast->setTypeSpec( spec ); + ast->setInitDeclaratorList( declarators ); + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; + } + + lex->setIndex( start ); + return parseDeclarationInternal( node ); +} + +bool Parser::parseCtorInitializer( AST::Node& /*node*/ ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseCtorInitializer()" << endl; + + if( lex->lookAhead(0) != ':' ){ + return false; + } + nextToken(); + + AST::Node inits; + if( !parseMemInitializerList(inits) ){ + reportError( i18n("Member initializers expected") ); + } + + return true; +} + +bool Parser::parseElaboratedTypeSpecifier( TypeSpecifierAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseElaboratedTypeSpecifier()" << endl; + + int start = lex->index(); + + int tk = lex->lookAhead( 0 ); + if( tk == Token_class || + tk == Token_struct || + tk == Token_union || + tk == Token_enum || + tk == Token_typename ) + { + AST::Node kind = CreateNode<AST>(); + nextToken(); + UPDATE_POS( kind, start, lex->index() ); + + NameAST::Node name; + + if( parseName(name) ){ + ElaboratedTypeSpecifierAST::Node ast = CreateNode<ElaboratedTypeSpecifierAST>(); + ast->setKind( kind ); + ast->setName( name ); + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; + } + } + + lex->setIndex( start ); + return false; +} + +bool Parser::parseDeclaratorId( NameAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseDeclaratorId()" << endl; + return parseName( node ); +} + +bool Parser::parseExceptionSpecification( GroupAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseExceptionSpecification()" << endl; + + if( lex->lookAhead(0) != Token_throw ){ + return false; + } + nextToken(); + + ADVANCE( '(', "(" ); + if( lex->lookAhead(0) == Token_ellipsis ){ + // extension found in MSVC++ 7.x headers + int start = lex->index(); + GroupAST::Node ast = CreateNode<GroupAST>(); + AST_FROM_TOKEN( ellipsis, lex->index() ); + ast->addNode( ellipsis ); + nextToken(); + UPDATE_POS( ast, start, lex->index() ); + node = ast; + } else if( lex->lookAhead(0) == ')' ) { + node = CreateNode<GroupAST>(); + } else { + parseTypeIdList( node ); + } + ADVANCE( ')', ")" ); + + return true; +} + +bool Parser::parseEnumerator( EnumeratorAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseEnumerator()" << endl; + + int start = lex->index(); + + if( lex->lookAhead(0) != Token_identifier ){ + return false; + } + + nextToken(); + + + EnumeratorAST::Node ena = CreateNode<EnumeratorAST>(); + node = ena; + + AST::Node id = CreateNode<AST>(); + UPDATE_POS( id, start, lex->index() ); + node->setId( id ); + int line = currentLine(); + + if( lex->lookAhead(0) == '=' ){ + nextToken(); + + AST::Node expr; + line = currentLine(); + if( !parseConstantExpression(expr) ){ + reportError( i18n("Constant expression expected") ); + } + node->setExpr( expr ); + } + + UPDATE_POS( node, start, lex->index() ); + + preparseLineComments( line ); + + node->setComment( m_commentStore.getCommentInRange( line ) ); + + return true; +} + +bool Parser::parseInitDeclarator( InitDeclaratorAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseInitDeclarator()" << endl; + + int start = lex->index(); + + DeclaratorAST::Node decl; + AST::Node init; + if( !parseDeclarator(decl) ){ + return false; + } + + parseInitializer( init ); + + InitDeclaratorAST::Node ast = CreateNode<InitDeclaratorAST>(); + ast->setDeclarator( decl ); + ast->setInitializer( init ); + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; +} + + + +bool Parser::parseBaseClause( BaseClauseAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseBaseClause()" << endl; + + int start = lex->index(); + if( lex->lookAhead(0) != ':' ){ + return false; + } + nextToken(); + + BaseClauseAST::Node bca = CreateNode<BaseClauseAST>(); + + BaseSpecifierAST::Node baseSpec; + if( parseBaseSpecifier(baseSpec) ){ + bca->addBaseSpecifier( baseSpec ); + + while( lex->lookAhead(0) == ',' ){ + nextToken(); + + if( !parseBaseSpecifier(baseSpec) ){ + reportError( i18n("Base class specifier expected") ); + return false; + } + bca->addBaseSpecifier( baseSpec ); + } + } else + return false; + + UPDATE_POS( bca, start, lex->index() ); + node = bca; + + return true; +} + +bool Parser::parseInitializer( AST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseInitializer()" << endl; + + if( lex->lookAhead(0) == '=' ){ + nextToken(); + + AST::Node init; + if( !parseInitializerClause(node) ){ + reportError( i18n("Initializer clause expected") ); + return false; + } + } else if( lex->lookAhead(0) == '(' ){ + nextToken(); + AST::Node expr; + skipCommaExpression( expr ); + + ADVANCE( ')', ")" ); + } + + return false; +} + +bool Parser::parseMemInitializerList( AST::Node& /*node*/ ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseMemInitializerList()" << endl; + + AST::Node init; + if( !parseMemInitializer(init) ){ + return false; + } + + while( lex->lookAhead(0) == ',' ){ + nextToken(); + + if( parseMemInitializer(init) ){ + } else { + break; + } + } + + return true; +} + +bool Parser::parseMemInitializer( AST::Node& /*node*/ ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseMemInitializer()" << endl; + + NameAST::Node initId; + if( !parseMemInitializerId(initId) ){ + reportError( i18n("Identifier expected") ); + return false; + } + ADVANCE( '(', '(' ); + AST::Node expr; + skipCommaExpression( expr ); + ADVANCE( ')', ')' ); + + return true; +} + +bool Parser::parseTypeIdList( GroupAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTypeIdList()" << endl; + + int start = lex->index(); + + AST::Node typeId; + if( !parseTypeId(typeId) ){ + return false; + } + + GroupAST::Node ast = CreateNode<GroupAST>(); + ast->addNode( typeId ); + + while( lex->lookAhead(0) == ',' ){ + nextToken(); + if( parseTypeId(typeId) ){ + ast->addNode( typeId ); + } else { + reportError( i18n("Type id expected") ); + break; + } + } + + UPDATE_POS( ast, start, lex->index() ); + node = ast; + return true; +} + +bool Parser::parseBaseSpecifier( BaseSpecifierAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseBaseSpecifier()" << endl; + + int start = lex->index(); + BaseSpecifierAST::Node ast = CreateNode<BaseSpecifierAST>(); + + AST::Node access; + if( lex->lookAhead(0) == Token_virtual ){ + AST_FROM_TOKEN( virt, lex->index() ); + ast->setIsVirtual( virt ); + + nextToken(); + + parseAccessSpecifier( access ); + } else { + parseAccessSpecifier( access ); + + if( lex->lookAhead(0) == Token_virtual ){ + AST_FROM_TOKEN( virt, lex->index() ); + ast->setIsVirtual( virt ); + nextToken(); + } + } + + NameAST::Node name; + if( !parseName(name) ){ + reportError( i18n("Class name expected") ); + } + + ast->setAccess( access ); + ast->setName( name ); + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; +} + + +bool Parser::parseInitializerClause( AST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseInitializerClause()" << endl; + + if( lex->lookAhead(0) == '{' ){ + if( !skip('{','}') ){ + reportError( i18n("} missing") ); + } else { + clearComment(); + nextToken(); + } + } else { + if( !parseAssignmentExpression(node) ){ + //reportError( i18n("Expression expected") ); + } + } + + return true; +} + +bool Parser::parseMemInitializerId( NameAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseMemInitializerId()" << endl; + + return parseName( node ); +} + +bool Parser::parsePtrToMember( AST::Node& /*node*/ ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parsePtrToMember()" << endl; + + if( lex->lookAhead(0) == Token_scope ){ + nextToken(); + } + + while( lex->lookAhead(0) == Token_identifier ){ + nextToken(); + + if( lex->lookAhead(0) == Token_scope && lex->lookAhead(1) == '*' ){ + nextToken(); // skip :: + nextToken(); // skip * + return true; + } else + break; + } + + return false; +} + +bool Parser::parseUnqualifiedName( ClassOrNamespaceNameAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseUnqualifiedName()" << endl; + + int start = lex->index(); + bool isDestructor = false; + + ClassOrNamespaceNameAST::Node ast = CreateNode<ClassOrNamespaceNameAST>(); + + if( lex->lookAhead(0) == Token_identifier ){ + int startName = lex->index(); + AST::Node n = CreateNode<AST>(); + nextToken(); + UPDATE_POS( n, startName, lex->index() ); + ast->setName( n ); + } else if( lex->lookAhead(0) == '~' && lex->lookAhead(1) == Token_identifier ){ + int startName = lex->index(); + AST::Node n = CreateNode<AST>(); + nextToken(); // skip ~ + nextToken(); // skip classname + UPDATE_POS( n, startName, lex->index() ); + ast->setName( n ); + isDestructor = true; + } else if( lex->lookAhead(0) == Token_operator ){ + AST::Node n; + if( !parseOperatorFunctionId(n) ) + return false; + ast->setName( n ); + } else { + return false; + } + + if( !isDestructor ){ + + int index = lex->index(); + + if( lex->lookAhead(0) == '<' ){ + nextToken(); + + // optional template arguments + TemplateArgumentListAST::Node args; + parseTemplateArgumentList( args ); + + if( lex->lookAhead(0) != '>' ){ + lex->setIndex( index ); + } else { + nextToken(); + ast->setTemplateArgumentList( args ); + } + } + } + + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; +} + +bool Parser::parseStringLiteral( AST::Node& /*node*/ ) +{ + while( !lex->lookAhead(0).isNull() ) { + if( lex->lookAhead(0) == Token_identifier && + lex->lookAhead(0).text() == "L" && lex->lookAhead(1) == Token_string_literal ) { + + nextToken(); + nextToken(); + } else if( lex->lookAhead(0) == Token_string_literal ) { + nextToken(); + } else + return false; + } + return true; +} + +bool Parser::skipExpressionStatement( StatementAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::skipExpressionStatement()" << endl; + + int start = lex->index(); + + AST::Node expr; + skipCommaExpression( expr ); + + ADVANCE( ';', ";" ); + + ExpressionStatementAST::Node ast = CreateNode<ExpressionStatementAST>(); + ast->setExpression( expr ); + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; +} + +bool Parser::parseStatement( StatementAST::Node& node ) // thanks to fiore@8080.it ;) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseStatement()" << endl; + switch( lex->lookAhead(0) ){ + + case Token_while: + return parseWhileStatement( node ); + + case Token_do: + return parseDoStatement( node ); + + case Token_for: + return parseForStatement( node ); + + case Token_foreach: + return parseForEachStatement( 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: + nextToken(); + ADVANCE( ';', ";" ); + return true; + + case Token_goto: + nextToken(); + ADVANCE( Token_identifier, "identifier" ); + ADVANCE( ';', ";" ); + return true; + + case Token_return: + { + nextToken(); + AST::Node expr; + skipCommaExpression( expr ); + ADVANCE( ';', ";" ); + } + return true; + + case '{': + return parseCompoundStatement( node ); + + case Token_identifier: + if( parseLabeledStatement(node) ) + return true; + break; + } + + ////kdDebug(9007)<< "------------> try with declaration statement" << endl; + if ( parseDeclarationStatement(node) ) + return true; + + return skipExpressionStatement( node ); +} + +bool Parser::parseCondition( ConditionAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseCondition()" << endl; + + int start = lex->index(); + + ConditionAST::Node ast = CreateNode<ConditionAST>(); + + TypeSpecifierAST::Node spec; + if( parseTypeSpecifier(spec) ){ + DeclaratorAST::Node decl; + if( parseDeclarator(decl) ) { + if( lex->lookAhead(0) == '=' ) { + nextToken(); + + AST::Node expr; + if( skipExpression(expr) ){ + ast->setTypeSpec( spec ); + ast->setDeclarator( decl ); + ast->setExpression( expr ); + + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; + } + } else { + ast->setTypeSpec( spec ); + ast->setDeclarator( decl ); + + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; + } + } + } + + lex->setIndex( start ); + + AST::Node expr; + if( !skipCommaExpression(expr) ) + return false; + + ast->setExpression( expr ); + UPDATE_POS( ast, start, lex->index() ); + node = ast; + return true; +} + + +bool Parser::parseWhileStatement( StatementAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseWhileStatement()" << endl; + int start = lex->index(); + + ADVANCE( Token_while, "while" ); + ADVANCE( '(' , "(" ); + + ConditionAST::Node cond; + if( !parseCondition(cond) ){ + reportError( i18n("condition expected") ); + return false; + } + ADVANCE( ')', ")" ); + + StatementAST::Node body; + if( !parseStatement(body) ){ + reportError( i18n("statement expected") ); + } + + WhileStatementAST::Node ast = CreateNode<WhileStatementAST>(); + ast->setCondition( cond ); + ast->setStatement( body ); + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; +} + +bool Parser::parseDoStatement( StatementAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseDoStatement()" << endl; + int start = lex->index(); + + ADVANCE( Token_do, "do" ); + + StatementAST::Node body; + if( !parseStatement(body) ){ + reportError( i18n("statement expected") ); + //return false; + } + + ADVANCE_NR( Token_while, "while" ); + ADVANCE_NR( '(' , "(" ); + + AST::Node expr; + if( !skipCommaExpression(expr) ){ + reportError( i18n("expression expected") ); + //return false; + } + + ADVANCE_NR( ')', ")" ); + ADVANCE_NR( ';', ";" ); + + DoStatementAST::Node ast = CreateNode<DoStatementAST>(); + ast->setStatement( body ); + //ast->setCondition( condition ); + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; +} + +bool Parser::parseForStatement( StatementAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseForStatement()" << endl; + int start = lex->index(); + + ADVANCE( Token_for, "for" ); + ADVANCE( '(', "(" ); + + StatementAST::Node init; + if( !parseForInitStatement(init) ){ + reportError( i18n("for initialization expected") ); + return false; + } + + ConditionAST::Node cond; + parseCondition( cond ); + ADVANCE( ';', ";" ); + + AST::Node expr; + skipCommaExpression( expr ); + ADVANCE( ')', ")" ); + + StatementAST::Node body; + parseStatement(body); + + ForStatementAST::Node ast = CreateNode<ForStatementAST>(); + ast->setInitStatement( init ); + ast->setCondition( cond ); + // ast->setExpression( expression ); + ast->setStatement( body ); + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; +} + +// qt4 [erbsland] +///@todo add the right parsing for the foreach statement +bool Parser::parseForEachStatement( StatementAST::Node& node ) +{ + int start = lex->index(); + + ADVANCE( Token_foreach, "foreach" ); + ADVANCE( '(', "(" ); + + AST::Node expr; + // replace with the right parsing + skipCommaExpression( expr ); + ADVANCE( ')', ")" ); + + StatementAST::Node body; + parseStatement(body); + + ForEachStatementAST::Node ast = CreateNode<ForEachStatementAST>(); + // add here the parser results + ast->setStatement( body ); + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; +} + +bool Parser::parseForInitStatement( StatementAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseForInitStatement()" << endl; + + if ( parseDeclarationStatement(node) ) + return true; + + return skipExpressionStatement( node ); +} + +bool Parser::parseCompoundStatement( StatementAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseCompoundStatement()" << endl; + int start = lex->index(); + + if( lex->lookAhead(0) != '{' ){ + return false; + } + nextToken(); + + StatementListAST::Node ast = CreateNode<StatementListAST>(); + + while( !lex->lookAhead(0).isNull() ){ + if( lex->lookAhead(0) == '}' ) + break; + + StatementAST::Node stmt; + int startStmt = lex->index(); + if( !parseStatement(stmt) ){ + if( startStmt == lex->index() ) + nextToken(); + skipUntilStatement(); + } else { + ast->addStatement( stmt ); + } + } + + clearComment(); + + if( lex->lookAhead(0) != '}' ){ + reportError( i18n("} expected") ); + } else { + nextToken(); + } + + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; +} + +bool Parser::parseIfStatement( StatementAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseIfStatement()" << endl; + + int start = lex->index(); + + ADVANCE( Token_if, "if" ); + + ADVANCE( '(' , "(" ); + + IfStatementAST::Node ast = CreateNode<IfStatementAST>(); + + ConditionAST::Node cond; + if( !parseCondition(cond) ){ + reportError( i18n("condition expected") ); + return false; + } + ADVANCE( ')', ")" ); + + StatementAST::Node stmt; + if( !parseStatement(stmt) ){ + reportError( i18n("statement expected") ); + } + + ast->setCondition( cond ); + ast->setStatement( stmt ); + + if( lex->lookAhead(0) == Token_else ){ + nextToken(); + StatementAST::Node elseStmt; + if( !parseStatement(elseStmt) ) { + reportError( i18n("statement expected") ); + } + ast->setElseStatement( elseStmt ); + } + + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; +} + +bool Parser::parseSwitchStatement( StatementAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseSwitchStatement()" << endl; + int start = lex->index(); + ADVANCE( Token_switch, "switch" ); + + ADVANCE( '(' , "(" ); + + ConditionAST::Node cond; + if( !parseCondition(cond) ){ + reportError( i18n("condition expected") ); + return false; + } + ADVANCE( ')', ")" ); + + StatementAST::Node stmt; + if( !parseCompoundStatement(stmt) ){ + syntaxError(); + return false; + } + + SwitchStatementAST::Node ast = CreateNode<SwitchStatementAST>(); + ast->setCondition( cond ); + ast->setStatement( stmt ); + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; +} + +bool Parser::parseLabeledStatement( StatementAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseLabeledStatement()" << endl; + switch( lex->lookAhead(0) ){ + case Token_identifier: + case Token_default: + if( lex->lookAhead(1) == ':' ){ + nextToken(); + nextToken(); + + StatementAST::Node stmt; + if( parseStatement(stmt) ){ + node = stmt; + return true; + } + } + break; + + case Token_case: + { + nextToken(); + AST::Node expr; + if( !parseConstantExpression(expr) ){ + reportError( i18n("expression expected") ); + } else if( lex->lookAhead(0) == Token_ellipsis ){ + nextToken(); + + AST::Node expr2; + if( !parseConstantExpression(expr2) ){ + reportError( i18n("expression expected") ); + } + } + ADVANCE( ':', ":" ); + + StatementAST::Node stmt; + if( parseStatement(stmt) ){ + node = stmt; + return true; + } + } + break; + + } + + return false; +} + +bool Parser::parseBlockDeclaration( DeclarationAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseBlockDeclaration()" << endl; + switch( lex->lookAhead(0) ) { + 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 = lex->index(); + + GroupAST::Node storageSpec; + parseStorageClassSpecifier( storageSpec ); + + GroupAST::Node cv; + parseCvQualify( cv ); + + TypeSpecifierAST::Node spec; + if ( !parseTypeSpecifierOrClassSpec(spec) ) { // replace with simpleTypeSpecifier?!?! + lex->setIndex( start ); + return false; + } + spec->setCvQualify( cv ); + + GroupAST::Node cv2; + parseCvQualify( cv2 ); + spec->setCv2Qualify( cv2 ); + + InitDeclaratorListAST::Node declarators; + parseInitDeclaratorList( declarators ); + + if( lex->lookAhead(0) != ';' ){ + lex->setIndex( start ); + return false; + } + nextToken(); + + SimpleDeclarationAST::Node ast = CreateNode<SimpleDeclarationAST>(); + ast->setTypeSpec( spec ); + ast->setInitDeclaratorList( declarators ); + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; +} + +bool Parser::parseNamespaceAliasDefinition( DeclarationAST::Node& /*node*/ ) +{ + if ( lex->lookAhead(0) != Token_namespace ) { + return false; + } + nextToken(); + + ADVANCE( Token_identifier, "identifier" ); + ADVANCE( '=', "=" ); + + NameAST::Node name; + if( !parseName(name) ){ + reportError( i18n("Namespace name expected") ); + } + + ADVANCE( ';', ";" ); + + return true; + +} + +bool Parser::parseDeclarationStatement( StatementAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseDeclarationStatement()" << endl; + + int start = lex->index(); + + DeclarationAST::Node decl; + if ( !parseBlockDeclaration(decl) ){ + return false; + } + + DeclarationStatementAST::Node ast = CreateNode<DeclarationStatementAST>(); + ast->setDeclaration( decl ); + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + ////kdDebug(9007)<< "---------------------> found a block declaration" << endl; + return true; +} + +bool Parser::parseDeclarationInternal( DeclarationAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseDeclarationInternal()" << endl; + + int start = lex->index(); + + // that is for the case '__declspec(dllexport) int ...' or + // '__declspec(dllexport) inline int ...', etc. + GroupAST::Node winDeclSpec; + parseWinDeclSpec( winDeclSpec ); + + GroupAST::Node funSpec; + bool hasFunSpec = parseFunctionSpecifier( funSpec ); + + GroupAST::Node storageSpec; + bool hasStorageSpec = parseStorageClassSpecifier( storageSpec ); + + if( hasStorageSpec && !hasFunSpec ) + hasFunSpec = parseFunctionSpecifier( funSpec ); + + // that is for the case 'friend __declspec(dllexport) ....' + GroupAST::Node winDeclSpec2; + parseWinDeclSpec( winDeclSpec2 ); + + GroupAST::Node cv; + parseCvQualify( cv ); + + int index = lex->index(); + NameAST::Node name; + if( parseName(name) && lex->lookAhead(0) == '(' ){ + // no type specifier, maybe a constructor or a cast operator?? + + lex->setIndex( index ); + + InitDeclaratorAST::Node declarator; + if( parseInitDeclarator(declarator) ){ + int endSignature = lex->index(); + + switch( lex->lookAhead(0) ){ + case ';': + { + nextToken(); + + InitDeclaratorListAST::Node declarators = CreateNode<InitDeclaratorListAST>(); + + // update declarators position + int startLine, startColumn, endLine, endColumn; + if( declarator.get() ){ + declarator->getStartPosition( &startLine, &startColumn ); + declarator->getEndPosition( &endLine, &endColumn ); + declarators->setStartPosition( startLine, startColumn ); + declarators->setEndPosition( endLine, endColumn ); + } + declarators->addInitDeclarator( declarator ); + + SimpleDeclarationAST::Node ast = CreateNode<SimpleDeclarationAST>(); + ast->setInitDeclaratorList( declarators ); + ast->setText( toString(start, endSignature) ); + node = ast; + UPDATE_POS( node, start, lex->index() ); + return true; + + } + break; + + case ':': + { + AST::Node ctorInit; + StatementListAST::Node funBody; + if( parseCtorInitializer(ctorInit) && parseFunctionBody(funBody) ){ + FunctionDefinitionAST::Node ast = CreateNode<FunctionDefinitionAST>(); + ast->setStorageSpecifier( storageSpec ); + ast->setFunctionSpecifier( funSpec ); + ast->setInitDeclarator( declarator ); + ast->setFunctionBody( funBody ); + ast->setText( toString(start, endSignature) ); + node = ast; + UPDATE_POS( node, start, lex->index() ); + return true; + } + } + break; + + case '{': + { + StatementListAST::Node funBody; + if( parseFunctionBody(funBody) ){ + FunctionDefinitionAST::Node ast = CreateNode<FunctionDefinitionAST>(); + ast->setStorageSpecifier( storageSpec ); + ast->setFunctionSpecifier( funSpec ); + ast->setInitDeclarator( declarator ); + ast->setText( toString(start, endSignature) ); + ast->setFunctionBody( funBody ); + node = ast; + UPDATE_POS( node, start, lex->index() ); + return true; + } + } + break; + + case '(': + case '[': + // ops!! it seems a declarator + goto start_decl; + break; + } + + } + + syntaxError(); + return false; + } + +start_decl: + lex->setIndex( index ); + + if( lex->lookAhead(0) == Token_const && lex->lookAhead(1) == Token_identifier && lex->lookAhead(2) == '=' ){ + // constant definition + nextToken(); + InitDeclaratorListAST::Node declarators; + if( parseInitDeclaratorList(declarators) ){ + ADVANCE( ';', ";" ); + DeclarationAST::Node ast = CreateNode<DeclarationAST>(); + node = ast; + UPDATE_POS( node, start, lex->index() ); + return true; + } + syntaxError(); + return false; + } + + Comment mcomment = comment(); + clearComment(); + + TypeSpecifierAST::Node spec; + if( parseTypeSpecifier(spec) ){ + if ( !hasFunSpec ) + parseFunctionSpecifier( funSpec ); // e.g. "void inline" + spec->setCvQualify( cv ); + + InitDeclaratorListAST::Node declarators; + + InitDeclaratorAST::Node decl; + int startDeclarator = lex->index(); + bool maybeFunctionDefinition = false; + + if( lex->lookAhead(0) != ';' ){ + if( parseInitDeclarator(decl) && lex->lookAhead(0) == '{' ){ + // function definition + maybeFunctionDefinition = true; + } else { + lex->setIndex( startDeclarator ); + if( !parseInitDeclaratorList(declarators) ){ + syntaxError(); + return false; + } + } + } + + int endSignature = lex->index(); + switch( lex->lookAhead(0) ){ + case ';': + { + nextToken(); + SimpleDeclarationAST::Node ast = CreateNode<SimpleDeclarationAST>(); + int line, col; + ast->setComment( mcomment ); + if( &(*decl) ) { + decl->getEndPosition( &line, &col ); + + preparseLineComments( line ); + Comment c = m_commentStore.getCommentInRange( line ); + if( c ) { + ast->addComment( c ); + } + } + + ast->setStorageSpecifier( storageSpec ); + ast->setFunctionSpecifier( funSpec ); + ast->setText( toString(start, endSignature) ); + ast->setTypeSpec( spec ); + ast->setWinDeclSpec( winDeclSpec ); + ast->setInitDeclaratorList( declarators ); + + node = ast; + UPDATE_POS( node, start, lex->index() ); + } + return true; + + case '{': + { + if( !maybeFunctionDefinition ){ + syntaxError(); + return false; + } + StatementListAST::Node funBody; + if ( parseFunctionBody(funBody) ) { + FunctionDefinitionAST::Node ast = CreateNode<FunctionDefinitionAST>(); + + ast->setComment( mcomment ); + + ast->setWinDeclSpec( winDeclSpec ); + ast->setStorageSpecifier( storageSpec ); + ast->setFunctionSpecifier( funSpec ); + ast->setText( toString(start, endSignature) ); + ast->setTypeSpec( spec ); + ast->setFunctionBody( funBody ); + ast->setInitDeclarator( decl ); + node = ast; + UPDATE_POS( node, start, lex->index() ); + return true; + } + } + break; + + } + } + + syntaxError(); + return false; +} + +bool Parser::parseFunctionBody( StatementListAST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseFunctionBody()" << endl; + + int start = lex->index(); + if( lex->lookAhead(0) != '{' ){ + return false; + } + nextToken(); + + StatementListAST::Node ast = CreateNode<StatementListAST>(); + + while( !lex->lookAhead(0).isNull() ){ + if( lex->lookAhead(0) == '}' ) + break; + + StatementAST::Node stmt; + int startStmt = lex->index(); + if( !parseStatement(stmt) ){ + if( startStmt == lex->index() ) + nextToken(); + skipUntilStatement(); + } else + ast->addStatement( stmt ); + } + + clearComment(); + + if( lex->lookAhead(0) != '}' ){ + reportError( i18n("} expected") ); + } else + nextToken(); + + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; +} + +QString Parser::toString( int start, int end, const QString& sep ) const +{ + QStringList l; + + for( int i=start; i<end; ++i ){ + const Token& t = lex->tokenAt(i); + if( t != Token_comment ) + l << t.text(); + } + + return l.join( sep ).stripWhiteSpace(); +} + +bool Parser::parseTypeSpecifierOrClassSpec( TypeSpecifierAST::Node& 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& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTryBlockStatement()" << endl; + + int start = lex->index(); + if( lex->lookAhead(0) != Token_try ){ + return false; + } + nextToken(); + + StatementAST::Node stmt; + if( !parseCompoundStatement(stmt) ){ + syntaxError(); + } + + if( lex->lookAhead(0) != Token_catch ){ + reportError( i18n("catch expected") ); + } + + CatchStatementListAST::Node list = CreateNode<CatchStatementListAST>(); + + while( lex->lookAhead(0) == Token_catch ){ + + nextToken(); + ADVANCE( '(', "(" ); + ConditionAST::Node cond; + if( !parseCondition(cond) ){ + reportError( i18n("condition expected") ); + return false; + } + ADVANCE( ')', ")" ); + + StatementAST::Node body; + if( !parseCompoundStatement(body) ){ + syntaxError(); + } + + CatchStatementAST::Node cstmt = CreateNode<CatchStatementAST>(); + cstmt->setCondition( cond ); + cstmt->setStatement( body ); + int l=0, c=0; + if( cond.get() ) + cond->getStartPosition( &l, &c ); + else if( body.get() ) + body->getStartPosition( &l, &c ); + + cstmt->setStartPosition( l, c ); + if( body.get() ) + body->getEndPosition( &l, &c ); + + cstmt->setEndPosition( l, c ); + list->addStatement( cstmt ); + } + + TryBlockStatementAST::Node ast = CreateNode<TryBlockStatementAST>(); + ast->setStatement( stmt ); + ast->setCatchStatementList( list ); + UPDATE_POS( ast, start, lex->index() ); + node = ast; + + return true; +} + +bool Parser::parsePrimaryExpression( AST::Node& /*node*/ ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parsePrimarExpression()" << endl; + + + switch( lex->lookAhead(0) ){ + case Token_string_literal: + { + AST::Node lit; + parseStringLiteral( lit ); + } + return true; + + case Token_number_literal: + case Token_char_literal: + case Token_true: + case Token_false: + nextToken(); + return true; + + case Token_this: + nextToken(); + return true; + + case Token_dynamic_cast: + case Token_static_cast: + case Token_reinterpret_cast: + case Token_const_cast: + { + nextToken(); + + CHECK( '<', "<" ); + AST::Node typeId; + parseTypeId( typeId ); + CHECK( '>', ">" ); + + CHECK( '(', "(" ); + AST::Node expr; + parseCommaExpression( expr ); + CHECK( ')', ")" ); + } + return true; + + case Token_typeid: + { + nextToken(); + CHECK( '(', "(" ); + AST::Node expr; + parseCommaExpression( expr ); + CHECK( ')', ")" ); + } + return true; + + case '(': + { + nextToken(); + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "token = " << lex->lookAhead(0).text() << endl; + AST::Node expr; + if( !parseExpression(expr) ){ + return false; + } + CHECK( ')', ")" ); + } + return true; + + default: + { + int start = lex->index(); + TypeSpecifierAST::Node typeSpec; + if( parseSimpleTypeSpecifier(typeSpec) && lex->lookAhead(0) == '(' ){ + nextToken(); + AST::Node expr; + parseCommaExpression( expr ); + CHECK( ')', ")" ); + return true; + } + + lex->setIndex( start ); + NameAST::Node name; + if( parseName(name) ) + return true; + } + } + + return false; +} + +bool Parser::parsePostfixExpression( AST::Node& /*node*/ ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parsePostfixExpression()" << endl; + + AST::Node expr; + if( !parsePrimaryExpression(expr) ) + return false; + + while( true ){ + switch(lex->lookAhead(0)) + { + case '[': + { + nextToken(); + AST::Node e; + parseCommaExpression( e ); + CHECK( ']', "]" ); + } + break; + + case '(': + { + nextToken(); + AST::Node funArgs; + parseCommaExpression( funArgs ); + CHECK( ')', ")" ); + } + break; + + case Token_incr: + case Token_decr: + nextToken(); + break; + + case '.': + case Token_arrow: + { + nextToken(); + if( lex->lookAhead(0) == Token_template ) + nextToken(); + + NameAST::Node name; + if( !parseName(name) ){ + return false; + } + } + break; + + case Token_typename: + { + nextToken(); + + NameAST::Node name; + if( !parseName(name) ){ + return false; + } + + CHECK( '(', "(" ); + AST::Node expr; + parseCommaExpression(expr); + CHECK( ')', ")" ); + } + return true; + + default: + return true; + + } // end switch + + } // end while + + return true; +} + +bool Parser::parseUnaryExpression( AST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseUnaryExpression()" << endl; + + switch( lex->lookAhead(0) ){ + case Token_incr: + case Token_decr: + case '*': + case '&': + case '+': + case '-': + case '!': + case '~': + { + nextToken(); + AST::Node expr; + return parseCastExpression( expr ); + } + + case Token_sizeof: + { + nextToken(); + int index = lex->index(); + if( lex->lookAhead(0) == '(' ){ + nextToken(); + AST::Node typeId; + if( parseTypeId(typeId) && lex->lookAhead(0) == ')' ){ + nextToken(); + return true; + } + lex->setIndex( index ); + } + AST::Node expr; + return parseUnaryExpression( expr ); + } + + case Token_new: + return parseNewExpression( node ); + + case Token_delete: + return parseDeleteExpression( node ); + } + + return parsePostfixExpression( node ); +} + +bool Parser::parseNewExpression( AST::Node& /*node*/ ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseNewExpression()" << endl; + if( lex->lookAhead(0) == Token_scope && lex->lookAhead(1) == Token_new ) + nextToken(); + + CHECK( Token_new, "new"); + + if( lex->lookAhead(0) == '(' ){ + nextToken(); + AST::Node expr; + parseCommaExpression( expr ); + CHECK( ')', ")" ); + } + + if( lex->lookAhead(0) == '(' ){ + nextToken(); + AST::Node typeId; + parseTypeId( typeId ); + CHECK( ')', ")" ); + } else { + AST::Node typeId; + parseNewTypeId( typeId ); + } + + AST::Node init; + parseNewInitializer( init ); + return true; +} + +bool Parser::parseNewTypeId( AST::Node& /*node*/ ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseNewTypeId()" << endl; + TypeSpecifierAST::Node typeSpec; + if( parseTypeSpecifier(typeSpec) ){ + AST::Node declarator; + parseNewDeclarator( declarator ); + return true; + } + + return false; +} + +bool Parser::parseNewDeclarator( AST::Node& /*node*/ ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseNewDeclarator()" << endl; + AST::Node ptrOp; + if( parsePtrOperator(ptrOp) ){ + AST::Node declarator; + parseNewDeclarator( declarator ); + return true; + } + + if( lex->lookAhead(0) == '[' ){ + while( lex->lookAhead(0) == '[' ){ + nextToken(); + AST::Node expr; + parseExpression( expr ); + ADVANCE( ']', "]" ); + } + return true; + } + + return false; +} + +bool Parser::parseNewInitializer( AST::Node& /*node*/ ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseNewInitializer()" << endl; + if( lex->lookAhead(0) != '(' ) + return false; + + nextToken(); + AST::Node expr; + parseCommaExpression( expr ); + CHECK( ')', ")" ); + + return true; +} + +bool Parser::parseDeleteExpression( AST::Node& /*node*/ ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseDeleteExpression()" << endl; + if( lex->lookAhead(0) == Token_scope && lex->lookAhead(1) == Token_delete ) + nextToken(); + + CHECK( Token_delete, "delete" ); + + if( lex->lookAhead(0) == '[' ){ + nextToken(); + CHECK( ']', "]" ); + } + + AST::Node expr; + return parseCastExpression( expr ); +} + +bool Parser::parseCastExpression( AST::Node& /*node*/ ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseCastExpression()" << endl; + + int index = lex->index(); + + if( lex->lookAhead(0) == '(' ){ + nextToken(); + AST::Node typeId; + if ( parseTypeId(typeId) ) { + if ( lex->lookAhead(0) == ')' ) { + nextToken(); + AST::Node expr; + if( parseCastExpression(expr) ) + return true; + } + } + } + + lex->setIndex( index ); + + AST::Node expr; + return parseUnaryExpression( expr ); +} + +bool Parser::parsePmExpression( AST::Node& /*node*/ ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser:parsePmExpression()" << endl; + AST::Node expr; + if( !parseCastExpression(expr) ) + return false; + + while( lex->lookAhead(0) == Token_ptrmem ){ + nextToken(); + + if( !parseCastExpression(expr) ) + return false; + } + + return true; +} + +bool Parser::parseMultiplicativeExpression( AST::Node& /*node*/ ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseMultiplicativeExpression()" << endl; + AST::Node expr; + if( !parsePmExpression(expr) ) + return false; + + while( lex->lookAhead(0) == '*' || lex->lookAhead(0) == '/' || lex->lookAhead(0) == '%' ){ + nextToken(); + + if( !parsePmExpression(expr) ) + return false; + } + + return true; +} + + +bool Parser::parseAdditiveExpression( AST::Node& /*node*/ ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseAdditiveExpression()" << endl; + AST::Node expr; + if( !parseMultiplicativeExpression(expr) ) + return false; + + while( lex->lookAhead(0) == '+' || lex->lookAhead(0) == '-' ){ + nextToken(); + + if( !parseMultiplicativeExpression(expr) ) + return false; + } + + return true; +} + +bool Parser::parseShiftExpression( AST::Node& /*node*/ ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseShiftExpression()" << endl; + AST::Node expr; + if( !parseAdditiveExpression(expr) ) + return false; + + while( lex->lookAhead(0) == Token_shift ){ + nextToken(); + + if( !parseAdditiveExpression(expr) ) + return false; + } + + return true; +} + +bool Parser::parseRelationalExpression( AST::Node& /*node*/, bool templArgs ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseRelationalExpression()" << endl; + AST::Node expr; + if( !parseShiftExpression(expr) ) + return false; + + while( lex->lookAhead(0) == '<' || (lex->lookAhead(0) == '>' && !templArgs) || + lex->lookAhead(0) == Token_leq || lex->lookAhead(0) == Token_geq ){ + nextToken(); + + if( !parseShiftExpression(expr) ) + return false; + } + + return true; +} + +bool Parser::parseEqualityExpression( AST::Node& /*node*/, bool templArgs ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseEqualityExpression()" << endl; + AST::Node expr; + if( !parseRelationalExpression(expr, templArgs) ) + return false; + + while( lex->lookAhead(0) == Token_eq || lex->lookAhead(0) == Token_not_eq ){ + nextToken(); + + if( !parseRelationalExpression(expr, templArgs) ) + return false; + } + + return true; +} + +bool Parser::parseAndExpression( AST::Node& /*node*/, bool templArgs ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseAndExpression()" << endl; + AST::Node expr; + if( !parseEqualityExpression(expr, templArgs) ) + return false; + + while( lex->lookAhead(0) == '&' ){ + nextToken(); + + if( !parseEqualityExpression(expr, templArgs) ) + return false; + } + + return true; +} + +bool Parser::parseExclusiveOrExpression( AST::Node& /*node*/, bool templArgs ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseExclusiveOrExpression()" << endl; + AST::Node expr; + if( !parseAndExpression(expr, templArgs) ) + return false; + + while( lex->lookAhead(0) == '^' ){ + nextToken(); + + if( !parseAndExpression(expr, templArgs) ) + return false; + } + + return true; +} + +bool Parser::parseInclusiveOrExpression( AST::Node& /*node*/, bool templArgs ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseInclusiveOrExpression()" << endl; + AST::Node expr; + if( !parseExclusiveOrExpression(expr, templArgs) ) + return false; + + while( lex->lookAhead(0) == '|' ){ + nextToken(); + + if( !parseExclusiveOrExpression(expr, templArgs) ) + return false; + } + + return true; +} + +bool Parser::parseLogicalAndExpression( AST::Node& /*node*/, bool templArgs ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseLogicalAndExpression()" << endl; + + AST::Node expr; + if( !parseInclusiveOrExpression(expr, templArgs) ) + return false; + + while( lex->lookAhead(0) == Token_and ){ + nextToken(); + + if( !parseInclusiveOrExpression(expr, templArgs) ) + return false; + } + + return true; +} + +bool Parser::parseLogicalOrExpression( AST::Node& node, bool templArgs ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseLogicalOrExpression()" << endl; + + int start = lex->index(); + + AST::Node expr; + if( !parseLogicalAndExpression(expr, templArgs) ) + return false; + + while( lex->lookAhead(0) == Token_or ){ + nextToken(); + + if( !parseLogicalAndExpression(expr, templArgs) ) + return false; + } + + AST::Node ast = CreateNode<AST>(); + UPDATE_POS( ast, start, lex->index() ); + node = ast; + return true; +} + +bool Parser::parseConditionalExpression( AST::Node& /*node*/ ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseConditionalExpression()" << endl; + AST::Node expr; + if( !parseLogicalOrExpression(expr) ) + return false; + + if( lex->lookAhead(0) == '?' ){ + nextToken(); + + if( !parseExpression(expr) ) + return false; + + CHECK( ':', ":" ); + + if( !parseAssignmentExpression(expr) ) + return false; + } + + return true; +} + +bool Parser::parseAssignmentExpression( AST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseAssignmentExpression()" << endl; + int start = lex->index(); + AST::Node expr; + if( lex->lookAhead(0) == Token_throw && !parseThrowExpression(expr) ) + return false; + else if( !parseConditionalExpression(expr) ) + return false; + + while( lex->lookAhead(0) == Token_assign || lex->lookAhead(0) == '=' ){ + nextToken(); + + if( !parseConditionalExpression(expr) ) + return false; + } + + AST::Node ast = CreateNode<AST>(); + UPDATE_POS( ast, start, lex->index() ); + node = ast; + return true; +} + +bool Parser::parseConstantExpression( AST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseConstantExpression()" << endl; + int start = lex->index(); + if( parseConditionalExpression(node) ){ + AST::Node ast = CreateNode<AST>(); + UPDATE_POS( ast, start, lex->index() ); + node = ast; + return true; + } + return false; +} + +bool Parser::parseExpression( AST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseExpression()" << endl; + + int start = lex->index(); + + if( !parseCommaExpression(node) ) + return false; + + AST::Node ast = CreateNode<AST>(); + UPDATE_POS( ast, start, lex->index() ); + node = ast; + return true; +} + +bool Parser::parseCommaExpression( AST::Node& node ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseCommaExpression()" << endl; + int start = lex->index(); + + AST::Node expr; + if( !parseAssignmentExpression(expr) ) + return false; + + while( lex->lookAhead(0) == ',' ){ + nextToken(); + + if( !parseAssignmentExpression(expr) ) + return false; + } + + AST::Node ast = CreateNode<AST>(); + UPDATE_POS( ast, start, lex->index() ); + node = ast; + return true; +} + +bool Parser::parseThrowExpression( AST::Node& /*node*/ ) +{ + ////kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseThrowExpression()" << endl; + if( lex->lookAhead(0) != Token_throw ) + return false; + + CHECK( Token_throw, "throw" ); + AST::Node expr; + if( !parseAssignmentExpression(expr) ) + return false; + + return true; +} + +bool Parser::parseIvarDeclList( AST::Node & node ) +{ + Q_UNUSED( node ); + return false; +} + +bool Parser::parseIvarDecls( AST::Node & node ) +{ + Q_UNUSED( node ); + return false; +} + +bool Parser::parseIvarDecl( AST::Node & node ) +{ + Q_UNUSED( node ); + return false; +} + +bool Parser::parseIvars( AST::Node & node ) +{ + Q_UNUSED( node ); + return false; +} + +bool Parser::parseIvarDeclarator( AST::Node & node ) +{ + Q_UNUSED( node ); + return false; +} + +bool Parser::parseMethodDecl( AST::Node & node ) +{ + Q_UNUSED( node ); + return false; +} + +bool Parser::parseUnarySelector( AST::Node & node ) +{ + Q_UNUSED( node ); + return false; +} + +bool Parser::parseKeywordSelector( AST::Node & node ) +{ + Q_UNUSED( node ); + return false; +} + +bool Parser::parseSelector( AST::Node & node ) +{ + Q_UNUSED( node ); + return false; +} + +bool Parser::parseKeywordDecl( AST::Node & node ) +{ + Q_UNUSED( node ); + return false; +} + +bool Parser::parseReceiver( AST::Node & node ) +{ + Q_UNUSED( node ); + return false; +} + +bool Parser::parseObjcMessageExpr( AST::Node & node ) +{ + Q_UNUSED( node ); + return false; +} + +bool Parser::parseMessageArgs( AST::Node & node ) +{ + Q_UNUSED( node ); + return false; +} + +bool Parser::parseKeywordExpr( AST::Node & node ) +{ + Q_UNUSED( node ); + return false; +} + +bool Parser::parseKeywordArgList( AST::Node & node ) +{ + Q_UNUSED( node ); + return false; +} + +bool Parser::parseKeywordArg( AST::Node & node ) +{ + Q_UNUSED( node ); + return false; +} + +bool Parser::parseReservedWord( AST::Node & node ) +{ + Q_UNUSED( node ); + return false; +} + +bool Parser::parseMyParms( AST::Node & node ) +{ + Q_UNUSED( node ); + return false; +} + +bool Parser::parseMyParm( AST::Node & node ) +{ + Q_UNUSED( node ); + return false; +} + +bool Parser::parseOptParmList( AST::Node & node ) +{ + Q_UNUSED( node ); + return false; +} + +bool Parser::parseObjcSelectorExpr( AST::Node & node ) +{ + Q_UNUSED( node ); + return false; +} + +bool Parser::parseSelectorArg( AST::Node & node ) +{ + Q_UNUSED( node ); + return false; +} + +bool Parser::parseKeywordNameList( AST::Node & node ) +{ + Q_UNUSED( node ); + return false; +} + +bool Parser::parseKeywordName( AST::Node & node ) +{ + Q_UNUSED( node ); + return false; +} + +bool Parser::parseObjcEncodeExpr( AST::Node & node ) +{ + Q_UNUSED( node ); + return false; +} + +bool Parser::parseObjcString( AST::Node & node ) +{ + Q_UNUSED( node ); + return false; +} + +bool Parser::parseProtocolRefs( AST::Node & node ) +{ + Q_UNUSED( node ); + return false; +} + +bool Parser::parseIdentifierList( GroupAST::Node & node ) +{ + int start = lex->index(); + + if( lex->lookAhead(0) != Token_identifier ) + return false; + + GroupAST::Node ast = CreateNode<GroupAST>(); + + AST_FROM_TOKEN( tk, lex->index() ); + ast->addNode( tk ); + nextToken(); + + while( lex->lookAhead(0) == ',' ){ + nextToken(); + if( lex->lookAhead(0) == Token_identifier ){ + AST_FROM_TOKEN( tk, lex->index() ); + ast->addNode( tk ); +// nextToken(); + } + ADVANCE( Token_identifier, "identifier" ); + } + + node = ast; + UPDATE_POS( node, start, lex->index() ); + return true; +} + +bool Parser::parseIdentifierColon( AST::Node & node ) +{ + Q_UNUSED( node ); + + if( lex->lookAhead(0) == Token_identifier && lex->lookAhead(1) == ':' ){ + nextToken(); + nextToken(); + return true; + } // ### else if PTYPENAME -> return true ; + + return false; +} + +bool Parser::parseObjcProtocolExpr( AST::Node & node ) +{ + Q_UNUSED( node ); + return false; +} + +bool Parser::parseObjcOpenBracketExpr( AST::Node & node ) +{ + Q_UNUSED( node ); + return false; +} + +bool Parser::parseObjcCloseBracket( AST::Node & node ) +{ + Q_UNUSED( node ); + return false; +} + +bool Parser::parseObjcDef( DeclarationAST::Node & node ) +{ + Q_UNUSED( node ); + return false; +} + +bool Parser::parseObjcClassDef( DeclarationAST::Node & node ) +{ + Q_UNUSED( node ); + return false; +} + +bool Parser::parseObjcClassDecl( DeclarationAST::Node & node ) +{ + Q_UNUSED( node ); + + ADVANCE( OBJC_CLASS, "@class" ); + + GroupAST::Node idList; + if ( !parseIdentifierList( idList ) ) + return false; + + ADVANCE( ';', ";" ); + + return true; +} + +bool Parser::parseObjcProtocolDecl( DeclarationAST::Node & node ) +{ + Q_UNUSED( node ); + + ADVANCE( OBJC_PROTOCOL, "@protocol" ); + + GroupAST::Node idList; + if ( !parseIdentifierList( idList ) ) + return false; + + ADVANCE( ';', ";" ); + + return true; +} + +bool Parser::parseObjcAliasDecl( DeclarationAST::Node & node ) +{ + Q_UNUSED( node ); + + ADVANCE( OBJC_ALIAS, "@alias" ); + + GroupAST::Node idList; + if ( !parseIdentifierList( idList ) ) + return false; + + ADVANCE( ';', ";" ); + + return true; +} + +bool Parser::parseObjcProtocolDef( DeclarationAST::Node & node ) +{ + Q_UNUSED( node ); + return false; +} + +bool Parser::parseObjcMethodDef( DeclarationAST::Node & node ) +{ + Q_UNUSED( node ); + return false; +} + +bool Parser::parseWinDeclSpec( GroupAST::Node & node ) +{ + if( lex->lookAhead(0) == Token_identifier && lex->lookAhead(0).text() == "__declspec" && lex->lookAhead(1) == '(' && lex->lookAhead(2) != ')'){ + int start = lex->index(); + nextToken(); + nextToken(); // skip '(' + + if ( !parseIdentifierList( node ) ) + return false; + + ADVANCE( ')', ")" ); + + UPDATE_POS( node, start, lex->index() ); + return true; + } + + return false; +} + |