/***************************************************************************
* This file is part of KDevelop *
* Copyright 2007 Andreas Pakulat *
* *
* This program 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 program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#include "astbuilder.h"
#include
#include "pythonparser.h"
#include "ast.h"
#include
#include
namespace Python
{
//TODO: Check that created AST nodes are pushed onto the stack _before_ visiting subnodes to make sure their parent is correct
template static T* safeNodeCast( Ast* node )
{
T* ast = dynamic_cast(node);
Q_ASSERT(ast || !node);
return ast;
}
static QList targetAstListFromExpressionAstList( const QList& list )
{
QList l;
foreach( ExpressionAst* ast, list )
{
switch( ast->astType )
{
case Ast::IdentifierAst:
{
IdentifierTargetAst* target = new IdentifierTargetAst( ast->parent );
target->identifier = safeNodeCast( ast );
target->start = ast->start;
target->end = ast->end;
target->startCol = ast->startCol;
target->startLine = ast->startLine;
target->endCol = ast->endCol;
target->endLine = ast->endLine;
l << target;
break;
}
case Ast::SubscriptAst:
{
SubscriptTargetAst* target = new SubscriptTargetAst( ast->parent );
target->subscript = safeNodeCast( ast );
target->start = ast->start;
target->end = ast->end;
target->startCol = ast->startCol;
target->startLine = ast->startLine;
target->endCol = ast->endCol;
target->endLine = ast->endLine;
l << target;
break;
}
case Ast::AttributeReferenceAst:
{
AttributeReferenceTargetAst* target = new AttributeReferenceTargetAst( ast->parent );
target->attribute = safeNodeCast( ast );
target->start = ast->start;
target->end = ast->end;
target->startCol = ast->startCol;
target->startLine = ast->startLine;
target->endCol = ast->endCol;
target->endLine = ast->endLine;
l << target;
break;
}
case Ast::ExtendedSliceAst:
//fall through
case Ast::SimpleSliceAst:
{
SliceTargetAst* target = new SliceTargetAst( ast->parent );
target->slice = safeNodeCast( ast );
target->start = ast->start;
target->end = ast->end;
target->startCol = ast->startCol;
target->startLine = ast->startLine;
target->endCol = ast->endCol;
target->endLine = ast->endLine;
l << target;
break;
}
case Ast::AtomAst:
{
AtomAst* atom = dynamic_cast( ast );
IdentifierTargetAst* target = new IdentifierTargetAst( ast->parent );
target->identifier = atom->identifier;
target->start = atom->start;
target->end = atom->end;
target->startCol = atom->startCol;
target->endCol = atom->endCol;
target->startLine = atom->startLine;
target->endLine = atom->endLine;
l << target;
delete atom;
break;
}
default:
kDebug() << ast->astType;
Q_ASSERT_X( false, "create_targetlist", "Ooops, found an expression that we can't convert to a target ast, check the code! " );
}
}
return l;
}
template static QList generateSpecializedList( const QList& list )
{
QList l;
foreach( Ast* ast, list )
{
T* temp = safeNodeCast( ast );
l << temp;
}
return l;
}
IdentifierAst* AstBuilder::createIdentifier( Ast* parent, qint64 idx )
{
IdentifierAst* ast = new IdentifierAst( parent );
ast->start = parser->tokenStream->token( idx ).begin;
ast->end = parser->tokenStream->token( idx ).end;
parser->tokenStream->startPosition( idx, &ast->startLine, &ast->startCol );
parser->tokenStream->endPosition( idx, &ast->endLine, &ast->endCol );
ast->identifier = tokenText( idx );
return ast;
}
QList AstBuilder::identifierListFromTokenList( Ast* parent, const KDevPG::ListNode* sequence )
{
QList identifiers;
for( int i = 0; i < sequence->count(); i++ )
{
identifiers << createIdentifier( parent, sequence->at(i)->element );
}
return identifiers;
}
void AstBuilder::setStartEnd( Ast* ast, PythonParser::AstNode* node )
{
ast->start = parser->tokenStream->token( node->startToken ).begin;
ast->end = parser->tokenStream->token( node->endToken ).end;
parser->tokenStream->startPosition( node->startToken, &ast->startLine, &ast->startCol );
parser->tokenStream->endPosition( node->endToken, &ast->endLine, &ast->endCol );
}
QString AstBuilder::tokenText( qint64 tokenidx )
{
// -1 means this is not a valid token idx and thus return an empty string;
if( tokenidx == -1 )
return "";
KDevPG::TokenStream::Token token = parser->tokenStream->token( tokenidx );
return parser->tokenText( token.begin, token.end );
}
AstBuilder::AstBuilder(PythonParser::Parser* p)
: parser(p)
{
}
void AstBuilder::visitAndExpr(PythonParser::AndExprAst *node)
{
kDebug() << "visitAndExpr start";
visitNode( node->andExpr );
if( node->anddShifExprSequence && node->anddShifExprSequence->count() > 0 )
{
BinaryExpressionAst* ast = createAst( node );
ast->opType = ArithmeticExpressionAst::BinaryAnd;
ast->lhs = safeNodeCast( mNodeStack.pop() );
int count = node->anddShifExprSequence->count();
BinaryExpressionAst* curast = ast;
for( int i = 0; i < count; i++ )
{
visitNode( node->anddShifExprSequence->at(i)->element );
if( i+1 < count )
{
BinaryExpressionAst* tmp = createAst(
node->anddShifExprSequence->at(i)->element );
curast->opType = ArithmeticExpressionAst::BinaryAnd;
tmp->lhs = safeNodeCast( mNodeStack.pop() );
curast->rhs = tmp;
curast = tmp;
}else
{
curast->rhs = safeNodeCast( mNodeStack.pop() );
}
}
mNodeStack.push( ast );
}
kDebug() << "visitAndExpr end";
}
void AstBuilder::visitAndTest(PythonParser::AndTestAst *node)
{
kDebug() << "visitAndTest start";
visitNode( node->notTestSequence->at(0)->element );
if( node->notTestSequence->count() > 1 )
{
BooleanAndOperationAst* ast = createAst( node );
ast->lhs = safeNodeCast( mNodeStack.pop() );
int count = node->notTestSequence->count();
BooleanAndOperationAst* curast = ast;
for( int i = 1; i < count; i++ )
{
visitNode( node->notTestSequence->at(i)->element );
if( i+1 < count )
{
BooleanAndOperationAst* tmp = createAst(
node->notTestSequence->at(i)->element );
tmp->lhs = safeNodeCast( mNodeStack.pop() );
curast->rhs = tmp;
curast = tmp;
}else
{
curast->rhs = safeNodeCast( mNodeStack.pop() );
}
}
mNodeStack.push( ast );
}
kDebug() << "visitAndTest end";
}
void AstBuilder::visitArglist(PythonParser::ArglistAst *node)
{
kDebug() << "visitArglist start";
QList args;
visitNode( node->argListBegin );
if( dynamic_cast( mNodeStack.top() ) )
{
args << mNodeStack.pop();
mListStack.push( args );
// Early return because a Generator expression was found, thats the only
// thing in this "argumentlist" then
return;
}
if( node->argListBegin )
{
args += mListStack.pop();
}
if( node->arglistStar )
{
ArgumentAst* ast = createAst( node->arglistStar );
ast->argumentType = ArgumentAst::ListArgument;
visitNode( node->arglistStar );
ast->argumentExpression = safeNodeCast( mNodeStack.pop() );
args << ast;
}
if( node->arglistDoublestar )
{
ArgumentAst* ast = createAst( node->arglistDoublestar );
ast->argumentType = ArgumentAst::DictArgument;
visitNode( node->arglistDoublestar );
ast->argumentExpression = safeNodeCast( mNodeStack.pop() );
args << ast;
}
mListStack.push( args );
kDebug() << "visitArglist end";
}
void AstBuilder::visitArgument(PythonParser::ArgumentAst *node)
{
kDebug() << "visitArgument start";
visitNode( node->argumentTest );
if( node->argumentEqualTest )
{
ArgumentAst* ast = createAst( node );
ast->argumentType = ArgumentAst::KeywordArgument;
AtomAst *argumentName = safeNodeCast( mNodeStack.pop() );
ast->keywordName = safeNodeCast( argumentName->identifier );
visitNode( node->argumentEqualTest );
ast->argumentExpression = safeNodeCast( mNodeStack.pop() );
mNodeStack.push( ast );
}else if( node->genFor )
{
GeneratorAst* ast = createAst( node );
ast->generatedValue = safeNodeCast( mNodeStack.pop() );
visitNode( node->genFor );
ast->generator = safeNodeCast( mNodeStack.pop() );
mNodeStack.push( ast );
}else
{
ArgumentAst* ast = createAst( node );
ast->argumentType = ArgumentAst::PositionalArgument;
ast->argumentExpression = safeNodeCast( mNodeStack.pop() );
mNodeStack.push( ast );
}
kDebug() << "visitArgument end";
}
void AstBuilder::visitArithExpr(PythonParser::ArithExprAst *node)
{
kDebug() << "visitArithExpr start";
visitNode( node->arithTerm );
if( node->arithOpListSequence && node->arithOpListSequence->count() > 0 && node->arithTermListSequence->count() > 0 )
{
Q_ASSERT_X( node->arithOpListSequence->count() == node->arithTermListSequence->count(),
"visitArithExpr", "different number of operators and operands" );
BinaryExpressionAst* ast = createAst( node );
Ast *dbg_node = mNodeStack.pop();
ast->lhs = safeNodeCast( dbg_node );
BinaryExpressionAst* cur = ast;
int count = node->arithOpListSequence->count();
for( int i = 0; i < count; i++ )
{
switch( node->arithOpListSequence->at(i)->element->arithOp )
{
case PythonParser::PlusOp:
cur->opType = BinaryExpressionAst::BinaryPlus;
break;
case PythonParser::MinusOp:
cur->opType = BinaryExpressionAst::BinaryMinus;
break;
default:
//Should never reach here, unless somebody changed the grammer and not the builder
Q_ASSERT(false);
}
visitNode( node->arithTermListSequence->at(i)->element );
if( i+1 < count )
{
BinaryExpressionAst* tmp = createAst( node->arithTermListSequence->at(i)->element );
cur->rhs = tmp;
cur = tmp;
cur->lhs = safeNodeCast( mNodeStack.pop() );
}else
{
cur->rhs = safeNodeCast( mNodeStack.pop() );
}
}
mNodeStack.push( ast );
}
kDebug() << "visitArithExpr end";
}
void AstBuilder::visitAssertStmt(PythonParser::AssertStmtAst *node)
{
kDebug() << "visitAssertStmt start";
AssertAst* ast = createAst( node );
visitNode( node->assertNotTest );
ast->assertTest = safeNodeCast(mNodeStack.pop());
if( node->assertRaiseTest )
{
visitNode( node->assertRaiseTest );
ast->exceptionValue = safeNodeCast(mNodeStack.pop());
}
mNodeStack.push(ast);
kDebug() << "visitAssertStmt end";
}
void AstBuilder::visitAtom(PythonParser::AtomAst *node)
{
kDebug() << "visitAtom start";
AtomAst* ast = createAst( node );
if( node->atomIdentifierName >= 0 || node->number || (node->stringliteralSequence && node->stringliteralSequence->count() > 0) )
{
if( node->atomIdentifierName >= 0 )
{
IdentifierAst* id = createIdentifier( ast, node->atomIdentifierName );
ast->identifier = id;
}else if( node->number )
{
visitNode( node->number );
ast->literal = safeNodeCast( mNodeStack.pop() );
}else if ( node->stringliteralSequence )
{
LiteralAst* lit = createAst( node );
lit->parent = ast;
lit->literalType = LiteralAst::String;
for( int i = 0; i < node->stringliteralSequence->count(); i++ )
{
lit->value += tokenText( node->stringliteralSequence->at(i)->element );
}
ast->literal = lit;
}
}else if( node->listmaker )
{
EnclosureAst* enc = createAst( node->listmaker );
enc->parent = ast;
visitNode( node->listmaker );
enc->encType = EnclosureAst::List;
enc->list = safeNodeCast( mNodeStack.pop() );
ast->enclosure = enc;
}else if( node->codeexpr )
{
EnclosureAst* enc = createAst( node->codeexpr );
visitNode( node->codeexpr );
enc->parent = ast;
enc->encType = EnclosureAst::StringConversion;
enc->stringConversion = generateSpecializedList( mListStack.pop() );
ast->enclosure = enc;
}else if( node->dictmaker )
{
EnclosureAst* enc = createAst( node->dictmaker );
enc->parent = ast;
visitNode( node->dictmaker );
enc->encType = EnclosureAst::Dictionary;
enc->dict = safeNodeCast( mNodeStack.pop() );
ast->enclosure = enc;
}else if( node->yield )
{
visitNode( node->yield );
EnclosureAst* enc = createAst( node->yield );
enc->parent = ast;
enc->encType = EnclosureAst::Yield;
enc->yield = safeNodeCast( mNodeStack.pop() );
ast->enclosure = enc;
}else
{
EnclosureAst* enc;
visitNode( node->testlist );
if( node->genFor )
{
enc = createAst( node );
enc->encType = EnclosureAst::Generator;
QList l = generateSpecializedList( mListStack.pop() );
GeneratorAst* gen = createAst( node );
gen->generatedValue = l.first();
visitNode( node->genFor );
gen->generator = safeNodeCast( mNodeStack.pop() );
enc->generator = gen;
enc->parent = ast;
ast->enclosure = enc;
}else
{
enc = createAst( node );
enc->encType = EnclosureAst::ParenthesizedForm;
enc->parent = ast;
QList dbg_node = mListStack.top();
enc->parenthesizedform = generateSpecializedList( mListStack.pop() );
ast->enclosure = enc;
}
}
mNodeStack.push( ast );
kDebug() << "visitAtom end";
}
void AstBuilder::visitBreakStmt(PythonParser::BreakStmtAst *node)
{
kDebug() << "visitBreakStmt start";
StatementAst* ast = createAst( node, Ast::BreakAst );
mNodeStack.push( ast );
kDebug() << "visitBreakStmt end";
}
void AstBuilder::visitClassdef(PythonParser::ClassdefAst *node)
{
kDebug() << "visitClassdef start";
ClassDefinitionAst* ast = createAst( node );
ast->className = createIdentifier( ast, node->className );
if( node->testlist )
{
visitNode( node->testlist );
ast->inheritance = generateSpecializedList( mListStack.pop() );
}
visitNode( node->classSuite );
ast->classBody = generateSpecializedList( mListStack.pop() );
mNodeStack.push(ast);
kDebug() << "visitClassdef end";
}
void AstBuilder::visitComparison(PythonParser::ComparisonAst *node)
{
kDebug() << "visitComparison start";
visitNode( node->compExpr );
if( node->compOpSequence && node->compOpSequence->count() > 0 && node->compOpExprSequence->count() > 0 )
{
ComparisonAst* ast = createAst( node );
ast->firstComparator = safeNodeCast( mNodeStack.pop() );
mNodeStack.push( ast );
Q_ASSERT( node->compOpSequence->count() == node->compOpExprSequence->count() );
int count = node->compOpSequence->count();
for( int i = 0; i < count; i++ )
{
QPair<:comparisonoperator expressionast> pair;
switch( node->compOpSequence->at(i)->element->compOp )
{
case PythonParser::LessOp:
pair.first = ComparisonAst::LessThanOp;
break;
case PythonParser::GreaterOp:
pair.first = ComparisonAst::GreaterThanOp;
break;
case PythonParser::IsEqualOp:
pair.first = ComparisonAst::EqualOp;
break;
case PythonParser::GreaterEqOp:
pair.first = ComparisonAst::GreaterEqualOp;
break;
case PythonParser::LessEqOp:
pair.first = ComparisonAst::LessEqualOp;
break;
case PythonParser::UnEqualOp:
pair.first = ComparisonAst::UnequalOp;
break;
case PythonParser::InOp:
pair.first = ComparisonAst::InOp;
break;
case PythonParser::NotInOp:
pair.first = ComparisonAst::NotInOp;
break;
case PythonParser::IsNotOp:
pair.first = ComparisonAst::IsNotOp;
break;
case PythonParser::IsOp:
pair.first = ComparisonAst::IsOp;
break;
default:
//Should never reach here, unless somebody changed the grammer and not the builder
Q_ASSERT(false);
}
visitNode( node->compOpExprSequence->at(i)->element );
pair.second = safeNodeCast( mNodeStack.pop() );
ast->comparatorList << pair;
}
}
kDebug() << "visitComparison end";
}
void AstBuilder::visitCompoundStmt(PythonParser::CompoundStmtAst *node)
{
kDebug() << "visitCompoundStmt start";
PythonParser::DefaultVisitor::visitCompoundStmt( node );
kDebug() << "visitCompoundStmt end";
}
void AstBuilder::visitContinueStmt(PythonParser::ContinueStmtAst *node)
{
kDebug() << "visitContinueStmt start";
StatementAst* ast = createAst( node, Ast::ContinueAst );
mNodeStack.push( ast );
kDebug() << "visitContinueStmt end";
}
void AstBuilder::visitDottedName(PythonParser::DottedNameAst *node) {
// no idea why this is meant to be a list,
// i've never seen something like "qualified decorators" in python... TODO check this
IdentifierAst *ast = createAst( node );
QList l;
l << ast;
mListStack.push(l);
}
void AstBuilder::visitDecorator(PythonParser::DecoratorAst *node)
{
kDebug() << "visitDecorator start";
DecoratorAst* ast = createAst( node );
visitNode( node->decoratorName );
ast->dottedName = generateSpecializedList( mListStack.pop() );
if( node->arguments )
{
visitNode( node->arguments );
ast->arguments = generateSpecializedList( mListStack.pop() );
}
mNodeStack.push( ast );
kDebug() << "visitDecorator end";
}
void AstBuilder::visitDecorators(PythonParser::DecoratorsAst *node)
{
kDebug() << "visitDecorators start";
QList l;
int count = node->decoratorSequence->count();
for( int i = 0; i < count; i++ )
{
visitNode( node->decoratorSequence->at(i)->element );
l << safeNodeCast( mNodeStack.pop() );
}
mListStack.push( l );
kDebug() << "visitDecorators end";
}
void AstBuilder::visitDefparam(PythonParser::DefparamAst *node)
{
kDebug() << "visitDefparam start";
if( node->paramname != -1 )
{
IdentifierParameterPartAst* ast = createAst( node );
ast->name = createIdentifier( ast, node->paramname );
mNodeStack.push( ast );
}else
{
ListParameterPartAst* ast = createAst( node );
mNodeStack.push( ast );
visitNode( node->fplist );
ast->parameternames = generateSpecializedList( mListStack.pop() );
}
kDebug() << "visitDefparam start";
}
void AstBuilder::visitDelStmt(PythonParser::DelStmtAst *node)
{
kDebug() << "visitDelStmt start";
DelAst* ast = createAst( node );
visitNode( node->delList );
ast->deleteObjects = generateSpecializedList( mListStack.pop() );
mNodeStack.push( ast );
kDebug() << "visitDelStmt end";
}
void AstBuilder::visitDictmaker(PythonParser::DictmakerAst *node)
{
kDebug() << "visitDictmaker start";
DictionaryAst* ast = createAst( node );
mNodeStack.push(ast);
int count = node->keyListSequence ? node->keyListSequence->count() : 0;
Q_ASSERT( count == (node->valueListSequence ? node->valueListSequence->count() : 0) );
for( int i = 0; i < count; i++ )
{
visitNode( node->keyListSequence->at(i)->element );
ExpressionAst* key = safeNodeCast( mNodeStack.pop() );
visitNode( node->valueListSequence->at(i)->element );
ast->dictionary.insert( key, safeNodeCast( mNodeStack.pop() ) );
}
kDebug() << "visitDictmaker end";
}
void AstBuilder::visitExceptClause(PythonParser::ExceptClauseAst *node)
{
kDebug() << "visitExceptClause start";
ExceptAst* ast = createAst( node );
mNodeStack.push( ast );
visitNode( node->exceptTest );
ast->exceptionDeclaration = safeNodeCast( mNodeStack.pop() );
visitNode( node->exceptTargetTest );
ast->exceptionValue = safeNodeCast( mNodeStack.pop() );
kDebug() << "visitExceptClause end";
}
void AstBuilder::visitExecStmt(PythonParser::ExecStmtAst *node)
{
kDebug() << "visitExecStmt start";
ExecAst* ast = createAst( node );
visitNode( node->execCode );
ast->executable = safeNodeCast( mNodeStack.pop() );
if( node->globalDictExec )
{
visitNode( node->globalDictExec );
ast->globalsAndLocals = safeNodeCast( mNodeStack.pop() );
}
if( node->localDictExec )
{
visitNode( node->localDictExec );
ast->localsOnly = safeNodeCast( mNodeStack.pop() );
}
mNodeStack.push( ast );
kDebug() << "visitExecStmt end";
}
void AstBuilder::visitExpr(PythonParser::ExprAst *node)
{
kDebug() << "visitExpr start";
visitNode( node->expr );
if( node->orrExprSequence && node->orrExprSequence->count() > 0 )
{
BinaryExpressionAst* ast = createAst( node );
ast->opType = ArithmeticExpressionAst::BinaryOr;
ast->lhs = safeNodeCast( mNodeStack.pop() );
int count = node->orrExprSequence->count();
BinaryExpressionAst* curast = ast;
for( int i = 0; i < count; i++ )
{
visitNode( node->orrExprSequence->at(i)->element );
if( i+1 < count )
{
BinaryExpressionAst* tmp = createAst(
node->orrExprSequence->at(i)->element );
curast->opType = ArithmeticExpressionAst::BinaryOr;
tmp->lhs = safeNodeCast( mNodeStack.pop() );
curast->rhs = tmp;
curast = tmp;
}else
{
curast->rhs = safeNodeCast( mNodeStack.pop() );
}
}
mNodeStack.push( ast );
}
kDebug() << "visitExpr end";
}
void AstBuilder::visitExprStmt(PythonParser::ExprStmtAst *node)
{
kDebug() << "visitExprStmt start";
visitNode( node->testlist );
if( node->augassign )
{
// Augmented assignments cannot have multiple targets, so the testlist needs to contain only 1 element
Q_ASSERT( mListStack.top().count() == 1 );
AssignmentAst* a = createAst( node );
QList l = targetAstListFromExpressionAstList(
generateSpecializedList( mListStack.pop() ) );
AssignmentAst::OpType op;
switch( node->augassign->assignOp )
{
case PythonParser::PlusEqOp:
op = AssignmentAst::AddEqualOp;
break;
case PythonParser::MinusEqOp:
op = AssignmentAst::SubEqualOp;
break;
case PythonParser::StarEqOp:
op = AssignmentAst::MultiplyEqualOp;
break;
case PythonParser::SlashEqOp:
op = AssignmentAst::DivideEqualOp;
break;
case PythonParser::ModuloEqOp:
op = AssignmentAst::ModuloEqualOp;
break;
case PythonParser::AndEqOp:
op = AssignmentAst::AndEqualOp;
break;
case PythonParser::OrEqOp:
op = AssignmentAst::OrEqualOp;
break;
case PythonParser::HatEqOp:
op = AssignmentAst::XorEqualOp;
break;
case PythonParser::LeftShiftEqOp:
op = AssignmentAst::LeftShiftEqualOp;
break;
case PythonParser::RightShiftEqOp:
op = AssignmentAst::RightShiftEqualOp;
break;
case PythonParser::DoublestarEqOp:
op = AssignmentAst::PowEqualOp;
break;
case PythonParser::DoubleslashEqOp:
op = AssignmentAst::FloorEqualOp;
break;
default:
//Should never reach here, unless somebody changed the grammer and not the builder
Q_ASSERT(false);
}
a->targets.append( qMakePair( l, op ) );
if( node->yield )
{
visitNode( node->yield );
a->yieldValue = safeNodeCast( mNodeStack.pop() );
}else
{
visitNode( node->anugassignTestlist );
a->value = generateSpecializedList( mListStack.pop() );
}
mNodeStack.push( a );
}else if( node->yield || ( node->equalTestlistSequence && node->equalTestlistSequence->count() ) > 0 )
{
AssignmentAst* a = createAst( node );
QList l = targetAstListFromExpressionAstList(
generateSpecializedList( mListStack.pop() ) );
a->targets.append( qMakePair( l, AssignmentAst::AssignmentOp) );
int count = node->equalTestlistSequence->count();
if( count > 0 )
{
for( int i = 0; i < count; i++ )
{
if( !node->yield && i == count-1 )
{
// We have no yield statement, so the last element in the
// list is the actual expression for the assignment
break;
}
visitNode( node->equalTestlistSequence->at(i)->element );
l = targetAstListFromExpressionAstList(
generateSpecializedList( mListStack.pop() ) );
a->targets.append( qMakePair( l, AssignmentAst::AssignmentOp ) );
}
}
if( node->yield )
{
visitNode( node->yield );
a->yieldValue = safeNodeCast( mNodeStack.pop() );
}else
{
visitNode( node->equalTestlistSequence->at( count-1 )->element );
a->value = generateSpecializedList( mListStack.pop() );
}
mNodeStack.push( a );
}else
{
ExpressionStatementAst *ast = createAst( node );
ast->expressions = generateSpecializedList( mListStack.pop() );
mNodeStack.push( ast );
}
kDebug() << "visitExprStmt end";
}
void AstBuilder::visitExprlist(PythonParser::ExprlistAst *node)
{
kDebug() << "visitExprlist start";
QList l;
int count = node->exprSequence->count();
for( int i = 0; i < count; i++ )
{
visitNode( node->exprSequence->at(i)->element );
l << safeNodeCast( mNodeStack.pop() );
}
mListStack.push( l );
kDebug() << "visitExprlist end";
}
void AstBuilder::visitFactor(PythonParser::FactorAst *node)
{
kDebug() << "visitFactor start";
if( node->power )
{
visitNode( node->power );
}else
{
UnaryExpressionAst* ast = createAst( node );
mNodeStack.push( ast );
visitNode( node->factor );
switch( node->factOp->op )
{
case PythonParser::UnaryPlusOp:
ast->opType = ArithmeticExpressionAst::UnaryPlus;
break;
case PythonParser::UnaryTildeOp:
ast->opType = ArithmeticExpressionAst::UnaryTilde;
break;
case PythonParser::UnaryMinusOp:
ast->opType = ArithmeticExpressionAst::UnaryMinus;
break;
default:
//Shouldn't reach this, unless someone changes the grammar and didn't update here
Q_ASSERT(false);
}
ast->operand = safeNodeCast( mNodeStack.pop() );
}
kDebug() << "visitFactor end";
}
void AstBuilder::visitFlowStmt(PythonParser::FlowStmtAst *node)
{
kDebug() << "visitFlowStmt start";
PythonParser::DefaultVisitor::visitFlowStmt( node );
kDebug() << "visitFlowStmt end";
}
void AstBuilder::visitForStmt(PythonParser::ForStmtAst *node)
{
kDebug() << "visitForStmt start";
ForAst* ast = createAst( node );
visitNode( node->forExpr );
ast->assignedTargets = targetAstListFromExpressionAstList( generateSpecializedList( mListStack.pop() ) );
visitNode( node->forTestlist );
ast->iterable = generateSpecializedList( mListStack.pop() );
visitNode( node->forSuite );
ast->forBody = generateSpecializedList( mListStack.pop() );
if( node->forElseSuite )
{
visitNode( node->forElseSuite );
ast->elseBody = generateSpecializedList( mListStack.pop() );
}
mNodeStack.push( ast );
kDebug() << "visitForStmt end";
}
void AstBuilder::visitFpDef(PythonParser::FpDefAst *node)
{
kDebug() << "visitFpDef start";
DefaultParameterAst* ast = createAst( node );
mNodeStack.push( ast );
visitNode( node->defparam );
ast->name = safeNodeCast( mNodeStack.pop() );
if( node->fpDefTest )
{
visitNode( node->fpDefTest );
ast->value = safeNodeCast( mNodeStack.pop() );
}
kDebug() << "visitFpDef end";
}
void AstBuilder::visitFplist(PythonParser::FplistAst *node)
{
kDebug() << "visitFplist start";
int count = node->fplistFpdefSequence->count();
QList l;
for( int i = 0; i < count; i++ )
{
visitNode( node->fplistFpdefSequence->at(i)->element );
l << safeNodeCast( mNodeStack.pop() );
}
mListStack.push( l );
kDebug() << "visitFplist end";
}
void AstBuilder::visitFuncdecl(PythonParser::FuncdeclAst *node)
{
kDebug() << "visitFuncdecl start";
FunctionDefinitionAst* ast = createAst( node );
if( node->decorators )
{
visitNode( node->decorators );
ast->decorators = generateSpecializedList( mListStack.pop() );
}
ast->functionName = createIdentifier( ast, node->funcName );
if( node->funArgs )
{
visitNode( node->funArgs );
ast->parameters = generateSpecializedList( mListStack.pop() );
}
visitNode( node->funSuite );
ast->functionBody = generateSpecializedList( mListStack.pop() );
mNodeStack.push( ast );
kDebug() << "visitFuncdecl end";
}
void AstBuilder::visitFuncDef(PythonParser::FuncDefAst *node)
{
kDebug() << "visitFuncDef start";
QList l;
int count = node->fpDefSequence->count();
for( int i = 0; i < count; i++ )
{
visitNode( node->fpDefSequence->at(i)->element );
l << safeNodeCast( mNodeStack.pop() );
}
mListStack.push( l );
kDebug() << "visitFuncDef end";
}
void AstBuilder::visitGenFor(PythonParser::GenForAst *node)
{
kDebug() << "visitGenFor start";
GeneratorForAst* ast = createAst( node );
mNodeStack.push( ast );
visitNode( node->exprlist );
ast->assignedTargets = generateSpecializedList( mListStack.pop() );
visitNode( node->test );
ast->iterableObject = safeNodeCast( mNodeStack.pop() );
if( node->genIter )
{
visitNode( node->genIter );
if( node->genIter->genFor )
{
ast->nextGenerator = safeNodeCast( mNodeStack.pop() );
}else
{
ast->nextCondition = safeNodeCast( mNodeStack.pop() );
}
}
kDebug() << "visitGenFor end";
}
void AstBuilder::visitGenIf(PythonParser::GenIfAst *node)
{
kDebug() << "visitGenIf start";
GeneratorIfAst* ast = createAst( node );
mNodeStack.push( ast );
visitNode( node->test );
ast->condition = safeNodeCast( mNodeStack.pop() );
if( node->genIter )
{
visitNode( node->genIter );
if( node->genIter->genFor )
{
ast->nextGenerator = safeNodeCast( mNodeStack.pop() );
}else
{
ast->nextCondition = safeNodeCast( mNodeStack.pop() );
}
}
kDebug() << "visitGenIf end";
}
void AstBuilder::visitGenIter(PythonParser::GenIterAst *node)
{
kDebug() << "visitGenIter start";
PythonParser::DefaultVisitor::visitGenIter(node);
kDebug() << "visitGenIter end";
}
void AstBuilder::visitGlobalStmt(PythonParser::GlobalStmtAst *node)
{
kDebug() << "visitGlobalStmt start";
GlobalAst* ast = createAst( node );
ast->identifiers = identifierListFromTokenList( ast, node->globalNameSequence );
mNodeStack.push( ast );
kDebug() << "visitGlobalStmt end";
}
void AstBuilder::visitIfStmt(PythonParser::IfStmtAst *node)
{
kDebug() << "visitIfStmt start";
IfAst* ast = createAst( node );
visitNode( node->ifTest );
ast->ifCondition = safeNodeCast( mNodeStack.pop() );
visitNode( node->ifSuite );
ast->ifBody = generateSpecializedList( mListStack.pop() );
if (node->elifTestSequence && node->elifSuiteSequence) {
Q_ASSERT( node->elifTestSequence->count() == node->elifSuiteSequence->count() );
int count = node->elifTestSequence->count();
for( int i = 0; i < count; i++)
{
visitNode( node->elifTestSequence->at(i)->element );
ExpressionAst* expr = safeNodeCast( mNodeStack.pop() );
visitNode( node->elifSuiteSequence->at(i)->element );
ast->elseIfBodies.append(
qMakePair( expr ,
generateSpecializedList(
mListStack.pop() ) ) );
}
}
if( node->ifElseSuite )
{
visitNode( node->ifElseSuite );
ast->elseBody = generateSpecializedList( mListStack.pop() );
}
mNodeStack.push( ast );
kDebug() << "visitIfStmt end";
}
void AstBuilder::visitImportFrom(PythonParser::ImportFromAst *node)
{
kDebug() << "visitImportFrom start";
if( !node->importAsNames )
{
StarImportAst* ast = createAst( node );
ast->modulePath = identifierListFromTokenList( ast, node->importFromName->dottedNameSequence );
mNodeStack.push( ast );
}else
{
FromImportAst* ast = createAst( node );
ast->modulePath = identifierListFromTokenList( ast, node->importFromName->dottedNameSequence );
const KDevPG::ListNode<:importasnameast>* idNames;
idNames = node->importAsNames->importAsNameSequence;
int count = idNames->count();
for(int i = 0; i < count; i++)
{
PythonParser::ImportAsNameAst* namenode = idNames->at(i)->element;
kDebug() << "Fetching from-as:" << tokenText( namenode->importedName );
ast->identifierAsName.append( qMakePair(
createIdentifier( ast, namenode->importedName ),
createIdentifier( ast, namenode->importedAs ) ) );
}
mNodeStack.push( ast );
}
kDebug() << "visitImportFrom end";
}
void AstBuilder::visitImportName(PythonParser::ImportNameAst *node)
{
kDebug() << "visitImportName start";
PlainImportAst* ast = createAst( node );
const KDevPG::ListNode<:dottedasnameast>* importedmodules;
importedmodules = node->importName->dottedAsNameSequence;
int count = importedmodules->count();
for( int i = 0; i < count ; i++ )
{
PythonParser::DottedAsNameAst* import = importedmodules->at(i)->element;
QList modulepath = identifierListFromTokenList( ast, import->importDottedName->dottedNameSequence );
ast->modulesAsName.append( qMakePair( modulepath, createIdentifier( ast, import->importedAs ) ) );
}
mNodeStack.push( ast );
kDebug() << "visitImportName end";
}
void AstBuilder::visitImportStmt(PythonParser::ImportStmtAst *node)
{
kDebug() << "visitImportStmt start";
PythonParser::DefaultVisitor::visitImportStmt( node );
kDebug() << "visitImportStmt end";
}
void AstBuilder::visitLambdaDef(PythonParser::LambdaDefAst *node)
{
kDebug() << "visitLambdaDef start";
LambdaAst* ast = createAst( node );
if( node->lambdaVarargslist )
{
visitNode( node->lambdaVarargslist );
ast->parameters = generateSpecializedList( mListStack.pop() );
}
visitNode( node->lambdaTest );
ast->expression = safeNodeCast( mNodeStack.pop() );
kDebug() << "visitLambdaDef end";
}
void AstBuilder::visitListFor(PythonParser::ListForAst *node)
{
kDebug() << "visitListFor start";
ListForAst* ast = createAst( node );
mNodeStack.push( ast );
visitNode( node->exprlist );
ast->assignedTargets = generateSpecializedList( mListStack.pop() );
visitNode( node->testlistSafe );
ast->iterableObject = generateSpecializedList( mListStack.pop() );
if( node->listIter )
{
visitNode( node->listIter );
if( node->listIter->listFor )
{
ast->nextGenerator = safeNodeCast( mNodeStack.pop() );
}else
{
ast->nextCondition = safeNodeCast( mNodeStack.pop() );
}
}
kDebug() << "visitListFor end";
}
void AstBuilder::visitListIf(PythonParser::ListIfAst *node)
{
kDebug() << "visitListIf start";
ListIfAst* ast = createAst( node );
mNodeStack.push( ast );
visitNode( node->test );
ast->condition = safeNodeCast( mNodeStack.pop() );
if( node->listIter )
{
visitNode( node->listIter );
if( node->listIter->listFor )
{
ast->nextGenerator = safeNodeCast( mNodeStack.pop() );
}else
{
ast->nextCondition = safeNodeCast( mNodeStack.pop() );
}
}
kDebug() << "visitListIf end";
}
void AstBuilder::visitListIter(PythonParser::ListIterAst *node)
{
kDebug() << "visitListIter start";
PythonParser::DefaultVisitor::visitListIter( node );
kDebug() << "visitListIter end";
}
void AstBuilder::visitListmaker(PythonParser::ListmakerAst *node)
{
kDebug() << "visitListmaker start";
ListAst* ast = createAst( node );
mNodeStack.push( ast );
visitNode( node->listMakerTest );
if ( node->listMakerTest ) {
ast->plainList = generateSpecializedList( mListStack.pop() );
}
if( node->listFor )
{
//We should have only 1 expression in the listMakerTest as we're having a list_comprehension
Q_ASSERT( node->listMakerTest->listTestSequence->count() == 1 );
visitNode( node->listFor );
ast->listGenerator = safeNodeCast( mNodeStack.pop() );
}
kDebug() << "visitListmaker end";
}
void AstBuilder::visitListMakerTest(PythonParser::ListMakerTestAst *node)
{
kDebug() << "visitListMakerTest start";
QList l;
int count = node->listTestSequence->count();
kDebug() << "Elements in list cnt: " << count;
for( int i = 0; i < count; i++ )
{
visitNode( node->listTestSequence->at(i)->element );
l << mNodeStack.pop();
}
mListStack.push( l );
kDebug() << "visitListMakerTest end";
}
void AstBuilder::visitNotTest(PythonParser::NotTestAst *node)
{
kDebug() << "visitNotTest start";
if( node->notTest )
{
BooleanNotOperationAst* ast = createAst( node );
mNodeStack.push( ast );
visitNode( node->notTest );
ast->op = safeNodeCast( mNodeStack.pop() );
}else
{
visitNode( node->comparison );
}
kDebug() << "visitNotTest end";
}
void AstBuilder::visitNumber(PythonParser::NumberAst *node)
{
kDebug() << "visitNumber start";
LiteralAst* ast = createAst( node );
switch( node->numType )
{
case PythonParser::IntegerNumeric:
ast->literalType = LiteralAst::Integer;
break;
case PythonParser::ImaginaryNumeric:
ast->literalType = LiteralAst::ImaginaryNumber;
break;
case PythonParser::FloatNumeric:
ast->literalType = LiteralAst::Float;
break;
}
ast->value = tokenText( node->value );
mNodeStack.push( ast );
kDebug() << "visitNumber end";
}
void AstBuilder::visitPassStmt(PythonParser::PassStmtAst *node)
{
kDebug() << "visitPassStmt start";
StatementAst* ast = createAst( node, Ast::PassAst );
mNodeStack.push( ast );
kDebug() << "visitPassStmt end";
}
void AstBuilder::visitPower(PythonParser::PowerAst *node)
{
kDebug() << "visitPower start";
visitNode( node->atom );
if( node->trailerSequence )
{
int count = node->trailerSequence->count();
if( count > 0 )
{
for( int i = 0; i < count; i++ )
{
visitTrailer( node->trailerSequence->at( i )->element );
PrimaryAst* ast = safeNodeCast( mNodeStack.pop() );
PrimaryAst* prim = safeNodeCast( mNodeStack.pop() );
switch( ast->astType )
{
case Ast::CallAst:
static_cast( ast )->callable = prim;
break;
case Ast::ExtendedSliceAst:
case Ast::SimpleSliceAst:
static_cast( ast )->primary = prim;
break;
case Ast::AttributeReferenceAst:
static_cast( ast )->primary = prim;
break;
case Ast::SubscriptAst:
static_cast( ast )->primary = prim;
break;
default:
Q_ASSERT_X(false, "visitTrailer", "OOOPS visitTrailer returned a PrimaryAst that is not known to have a primary in front of it, like an AtomAst or something new.");
break;
}
mNodeStack.push( ast );
}
}
}
if( node->factor )
{
BinaryExpressionAst* bast = createAst( node );
bast->opType = ArithmeticExpressionAst::Power;
bast->lhs = safeNodeCast( mNodeStack.pop() );
visitNode( node->factor );
bast->rhs = safeNodeCast( mNodeStack.pop() );
mNodeStack.push( bast );
}
kDebug() << "visitPower end";
}
void AstBuilder::visitPlainArgumentsList(PythonParser::PlainArgumentsListAst *node)
{
kDebug() << "visitPlainArgumentsList start";
QList l;
int count = node->argumentsSequence->count();
for( int i = 0; i < count; i++ )
{
visitNode( node->argumentsSequence->at(i)->element );
if( dynamic_cast( mNodeStack.top() ) )
{
l << safeNodeCast( mNodeStack.pop() );
}else if( dynamic_cast( mNodeStack.top() ) )
{
//Early return, we found a generator expression on the stack
return;
}
}
mListStack.push( l );
kDebug() << "visitPlainArgumentsList end";
}
void AstBuilder::visitPrintStmt(PythonParser::PrintStmtAst *node)
{
kDebug() << "visitPrintStmt start";
PrintAst* ast = createAst( node );
if( node->printArgsSequence->count() > 0 )
{
int count = node->printArgsSequence->count();
for( int i = 0; i < count; i++ )
{
visitNode( node->printArgsSequence->at(i)->element );
ast->printables.append( safeNodeCast( mNodeStack.pop() ) );
}
}else
{
visitNode( node->rshiftArgsSequence->at(0)->element );
ast->outfile = safeNodeCast( mNodeStack.pop() );
int count = node->rshiftArgsSequence->count();
for( int i = 1; i < count; i++ )
{
visitNode( node->printArgsSequence->at(i)->element );
ast->printables.append( safeNodeCast( mNodeStack.pop() ) );
}
}
mNodeStack.push( ast );
kDebug() << "visitPrintStmt end";
}
void AstBuilder::visitProject(PythonParser::ProjectAst *node)
{
kDebug() << "visitProject start";
CodeAst* code = new CodeAst();
setStartEnd( code, node );
mNodeStack.push( code );
kDebug() << "Node stack count: " << mNodeStack.count();
if( node->stmtSequence )
{
int count = node->stmtSequence->count();
for( int i = 0; i < count; i++ )
{
visitNode( node->stmtSequence->at(i)->element );
Ast* a = mNodeStack.pop();
if( a )
code->statements << safeNodeCast( a );
kDebug() << "Node stack count: " << mNodeStack.count();
}
}
kDebug() << "Node stack count: " << mNodeStack.count();
kDebug() << "visitProject end";
}
void AstBuilder::visitRaiseStmt(PythonParser::RaiseStmtAst *node)
{
kDebug() << "visitRaiseStmt start";
RaiseAst* ast = createAst( node );
if( node->type )
{
visitNode( node->type );
ast->exceptionType = safeNodeCast( mNodeStack.pop() );
}
if( node->value )
{
visitNode( node->value );
ast->exceptionValue = safeNodeCast( mNodeStack.pop() );
}
if( node->traceback )
{
visitNode( node->traceback );
ast->traceback = safeNodeCast( mNodeStack.pop() );
}
mNodeStack.push( ast );
kDebug() << "visitRaiseStmt end";
}
void AstBuilder::visitReturnStmt(PythonParser::ReturnStmtAst *node)
{
kDebug() << "visitReturnStmt start";
ReturnAst* ast = createAst( node );
visitNode( node->returnExpr );
ast->returnValues = generateSpecializedList( mListStack.pop() );
mNodeStack.push( ast );
kDebug() << "visitReturnStmt end";
}
void AstBuilder::visitShiftExpr(PythonParser::ShiftExprAst *node)
{
kDebug() << "visitShiftExpr start";
visitNode( node->arithExpr );
if( node->shiftOpListSequence )
{
int count = node->shiftOpListSequence->count();
if( count > 0 )
{
Q_ASSERT( count == node->arithExprListSequence->count() );
BinaryExpressionAst* ast = createAst( node );
ast->lhs = safeNodeCast( mNodeStack.pop() );
BinaryExpressionAst* cur = ast;
for( int i = 0; i < count; i++ )
{
switch( node->shiftOpListSequence->at( i )->element->shiftOp )
{
case PythonParser::LeftShiftOp:
cur->opType = ArithmeticExpressionAst::BinaryLeftShift;
break;
case PythonParser::RightShiftOp:
cur->opType = ArithmeticExpressionAst::BinaryRightShift;
break;
default:
Q_ASSERT_X(false, "visitShiftExpr", "OOOPS, shift operator was something other than left or right shifting!");
}
visitNode( node->arithExprListSequence->at( i )->element );
if( i == count - 1 )
{
cur->rhs = safeNodeCast( mNodeStack.pop() );
}else
{
cur->rhs = createAst( node->arithExprListSequence->at( i )->element );
cur = safeNodeCast( cur->rhs );
cur->lhs = safeNodeCast( mNodeStack.pop() );
}
}
mNodeStack.push( ast );
}
}
kDebug() << "visitShiftExpr end";
}
void AstBuilder::visitSimpleStmt(PythonParser::SimpleStmtAst *node)
{
kDebug() << "visitSimpleStmt start";
PythonParser::DefaultVisitor::visitSimpleStmt( node );
kDebug() << "visitSimpleStmt end";
}
void AstBuilder::visitSmallStmt(PythonParser::SmallStmtAst *node)
{
kDebug() << "visitSmallStmt start";
PythonParser::DefaultVisitor::visitSmallStmt( node );
kDebug() << "visitSmallStmt end";
}
void AstBuilder::visitStmt(PythonParser::StmtAst *node)
{
kDebug() << "visitStmt start";
if( node->simpleStmt || node->compoundStmt )
{
PythonParser::DefaultVisitor::visitStmt( node );
}else
{
// Pushing a 0 onto the stack so that visitProject and visitSuite can
// test for this case
mNodeStack.push( 0 );
kDebug() << "Found linebreak";
}
kDebug() << "visitStmt end";
}
void AstBuilder::visitSubscript(PythonParser::SubscriptAst *node)
{
kDebug() << "visitSubscript start";
if( node->isEllipsis || node->hasColon )
{
if( node->isEllipsis )
{
EllipsisSliceItemAst* ast = createAst( node );
mNodeStack.push( ast );
}else
{
ProperSliceItemAst* ast = createAst( node );
mNodeStack.push( ast );
if( node->begin )
{
visitNode( node->begin );
ast->bounds.first = safeNodeCast( mNodeStack.pop() );
}
if( node->end )
{
visitNode( node->end );
ast->bounds.second = safeNodeCast( mNodeStack.pop() );
}
if( node->step )
{
visitNode( node->step );
ast->stride = safeNodeCast( mNodeStack.pop() );
}
}
}else if( node->begin )
{
visitNode( node->begin );
}
kDebug() << "visitSubscript end";
}
void AstBuilder::visitSubscriptlist(PythonParser::SubscriptlistAst *node)
{
kDebug() << "visitSubscriptlist start";
if( node->hasComma )
{
int count = node->subscriptSequence->count();
PrimaryAst* curast = createAst( node );
mNodeStack.push( curast );
for( int i = 0; i < count; i++ )
{
visitNode( node->subscriptSequence->at( i )->element );
if( dynamic_cast( mNodeStack.top() ) == 0
&& curast->astType != Ast::ExtendedSliceAst )
{
SubscriptAst* sast = safeNodeCast( curast );
curast = createAst( node );
ExtendedSliceAst* esast = safeNodeCast( curast );
for( int j = 0; j < sast->subscription.count(); j++ )
{
ExpressionSliceItemAst* esiast = createAst(
node->subscriptSequence->at(j)->element );
esiast->sliceExpression = sast->subscription.at( j );
esast->extendedSliceList << esiast;
}
delete sast;
}
if( curast->astType == Ast::ExtendedSliceAst )
{
if( dynamic_cast( mNodeStack.top() ) != 0 )
{
ExpressionSliceItemAst* itemast = createAst(
node->subscriptSequence->at(i)->element );
itemast->sliceExpression = safeNodeCast( mNodeStack.pop() );
safeNodeCast( curast )->extendedSliceList << itemast;
}else
{
safeNodeCast( curast )->extendedSliceList <<
safeNodeCast( mNodeStack.pop() );
}
}else
{
safeNodeCast( curast )->subscription
<< safeNodeCast( mNodeStack.pop() );
}
}
}else
{
visitNode( node->subscriptSequence->at(0)->element );
if( dynamic_cast( mNodeStack.top() ) )
{
SubscriptAst* ast = createAst( node );
ast->subscription << safeNodeCast( mNodeStack.pop() );
mNodeStack.push( ast );
}else
{
SimpleSliceAst* ast = createAst( node );
ProperSliceItemAst* extslice = safeNodeCast( mNodeStack.pop() );
ast->simpleSliceBounds.first = extslice->bounds.first;
ast->simpleSliceBounds.second = extslice->bounds.second;
delete extslice;
mNodeStack.push( ast );
}
}
kDebug() << "visitSubscriptlist end";
}
void AstBuilder::visitSuite(PythonParser::SuiteAst *node)
{
kDebug() << "visitSuite start";
QList l;
if( node->simpleStmt )
{
visitNode( node->simpleStmt );
l << mNodeStack.pop();
} else
{
int count = node->stmtSequence->count();
for( int i = 0; i < count; i++ )
{
visitNode( node->stmtSequence->at(i)->element );
Ast* a = mNodeStack.pop();
if( a )
l << a;
}
}
mListStack.push( l );
kDebug() << "visitSuite end";
}
void AstBuilder::visitTerm(PythonParser::TermAst *node)
{
kDebug() << "visitTerm start";
visitNode( node->factor );
if( node->factorsSequence )
{
int count = node->factorsSequence->count();
if( count > 0 )
{
Q_ASSERT( count == node->termOpSequence->count() );
BinaryExpressionAst* curast = createAst( node );
curast->lhs = safeNodeCast( mNodeStack.pop() );
// put the binary expression onto the stack now, so its still on the stack
// after the loop finishes
mNodeStack.push( curast );
for( int i = 0; i < count; i++ )
{
//Push current bin-expr on stack to be used as parent
mNodeStack.push( curast );
visitNode( node->factorsSequence->at(i)->element );
if( i == count-1 )
{
curast->rhs = safeNodeCast( mNodeStack.pop() );
}else
{
curast->rhs = createAst( node );
switch( node->termOpSequence->at(i)->element->op )
{
case PythonParser::StarOp:
curast->opType = ArithmeticExpressionAst::BinaryMultiply;
break;
case PythonParser::ModuloOp:
curast->opType = ArithmeticExpressionAst::BinaryModulo;
break;
case PythonParser::SlashOp:
curast->opType = ArithmeticExpressionAst::BinaryDivide;
break;
case PythonParser::DoubleSlashOp:
curast->opType = ArithmeticExpressionAst::BinaryFloor;
break;
default:
Q_ASSERT_X( false, "visitTerm", "OOPS, termop has an unknown value" );
}
curast->lhs = safeNodeCast( mNodeStack.pop() );
curast = safeNodeCast( curast->rhs );
}
//pop parent from stack
mNodeStack.pop();
}
}
}
kDebug() << "visitTerm end";
}
void AstBuilder::visitTest(PythonParser::TestAst *node)
{
kDebug() << "visitTest start";
if( node->lambdaDef )
{
visitNode( node->lambdaDef );
}else
{
visitNode( node->andTestSequence->at(0)->element );
if( node->andTestSequence->count() > 1 )
{
BooleanOrOperationAst* ast = createAst( node );
ast->lhs = safeNodeCast( mNodeStack.pop() );
int count = node->andTestSequence->count();
mNodeStack.push( ast );
for( int i = 1; i < count; i++ )
{
visitNode( node->andTestSequence->at(i)->element );
if( i+1 < count )
{
BooleanOrOperationAst* tmp = createAst(
node->andTestSequence->at(i)->element );
tmp->lhs = safeNodeCast( mNodeStack.pop() );
ast->rhs = tmp;
ast = tmp;
}else
{
ast->rhs = safeNodeCast( mNodeStack.pop() );
}
}
}
}
kDebug() << "visitTest end";
}
void AstBuilder::visitTestlist(PythonParser::TestlistAst *node)
{
kDebug() << "visitTestlist start";
QList expressions;
int count = node->testsSequence->count();
for( int i = 0; i < count; i++ )
{
visitNode( node->testsSequence->at( i )->element );
expressions << safeNodeCast( mNodeStack.pop() );
}
mListStack.push( expressions );
kDebug() << "visitTestlist end";
}
void AstBuilder::visitCodeexpr(PythonParser::CodeexprAst *node)
{
kDebug() << "visitCodeexpr start";
QList l;
int count = node->testSequence->count();
for( int i = 0; i < count; i++ )
{
visitNode( node->testSequence->at(i)->element );
l << safeNodeCast