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.
4331 lines
98 KiB
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;
|
|
}
|
|
|