You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdevelop/lib/cppparser/parser.cpp

4331 lines
98 KiB

/* This file is part of KDevelop
Copyright (C) 2002,2003 Roberto Raggi <roberto@tdevelop.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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
// c++ support
#include "driver.h"
#include "lexer.h"
#include "parser.h"
#include "errors.h"
// qt
#include <tqstring.h>
#include <tqstringlist.h>
#include <tqasciidict.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 );
TQString 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 TQString& 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: // TQt
case Token_slots: // TQt
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;
TQString 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_TQ_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;
}
TQString Parser::toString( int start, int end, const TQString& sep ) const
{
TQStringList 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;
}