#include "gamebuilder.h" #include #include "game.h" #include "astbranch.h" #include "astleaf.h" #include "astleafliteral.h" #include "astfunction.h" #include "command.h" #include "situation.h" #include "parser.tab.h" using namespace Bu; GameBuilder::GameBuilder() : pGame( NULL ), bGlobal( false ), pCurNode( NULL ), pCurRoot( NULL ), pCurCmd( NULL ), pCurFnc( NULL ), pCurSit( NULL ), iStackHeight( 0 ) { pGame = new Game(); } GameBuilder::~GameBuilder() { } typedef void *yyscan_t; void yylex_init( yyscan_t * ); void yylex_destroy( yyscan_t ); void yyparse( yyscan_t, GameBuilder &bld ); void yyset_in( FILE *, yyscan_t ); void GameBuilder::parse( const Bu::String &sFile ) { yyscan_t scanner; yylex_init( &scanner ); FILE *in = fopen( sFile.getStr(), "rb" ); yyset_in( in, scanner ); yyparse( scanner, *this ); yylex_destroy( scanner ); fclose( in ); } void GameBuilder::endCmpltExpr() { while( iStackHeight > 0 ) { addNode( AstNode::tPop ); } iStackHeight = 0; } void GameBuilder::setLiteral( const Variable &v ) { vLiteral = v; } void GameBuilder::setGameParam( const Bu::String &sName ) { pGame->hGlobalParam.insert( sName, vLiteral ); } void GameBuilder::beginFunction( const Bu::String &sName ) { pCurNode = pCurRoot = new AstBranch( AstNode::tScope ); pCurFnc = new AstFunction( sName ); //sio << "New function: " << sName << sio.nl; } void GameBuilder::addFunctionParam( const Bu::String &sName ) { pCurFnc->addParam( sName ); //sio << " - Param added '" << sName << "'" << sio.nl; } void GameBuilder::endFunctionParams() { Bu::StringList lRev; for( Bu::StringList::const_iterator i = pCurFnc->getParamList().begin(); i; i++ ) { lRev.prepend( *i ); } for( Bu::StringList::iterator i = lRev.begin(); i; i++ ) { addVarRef( *i, sidLocal ); addNode( AstNode::tStoreRev ); } } void GameBuilder::endFunction() { //sio << "Function ended: " << *pCurRoot << sio.nl; pCurNode->addNode( new AstLeafLiteral( Variable::tNull ) ); pCurFnc->setAst( pCurRoot ); pCurRoot = pCurNode = NULL; pGame->hFunction.insert( pCurFnc->getName(), pCurFnc ); iStackHeight = 0; } void GameBuilder::beginSituation( const Bu::String &sName, Situation::InputType tInput ) { pCurSit = new Situation( sName, tInput ); //sio << "New situation: " << sName << sio.nl; } void GameBuilder::beginSituationMode( Situation::Mode m ) { pCurNode = pCurRoot = new AstBranch( AstNode::tScope ); eCurSitMode = m; } void GameBuilder::closeSituationMode() { // sio << "Set situation <<" << pCurSit->getName() << ">> mode " << eCurSitMode << " to " << *pCurRoot << sio.nl; pCurSit->setAst( pCurRoot, eCurSitMode ); pCurRoot = pCurNode = NULL; } void GameBuilder::endSituation() { pGame->hSituation.insert( pCurSit->getName(), pCurSit ); //sio << "Situation ended." << sio.nl; } void GameBuilder::addNode( AstNode::Type iType ) { stackMod( iType ); switch( iType&AstNode::tTypeMask ) { case AstNode::tBranch: pCurNode = (AstBranch *)pCurNode->addNode( new AstBranch( iType ) ); break; case AstNode::tLeaf: pCurNode->addNode( new AstLeaf( iType ) ); break; } } void GameBuilder::closeNode() { pCurNode = pCurNode->getParent(); } void GameBuilder::addLiteral( const Variable &v ) { setLiteral( v ); if( pCurNode ) { stackMod( AstNode::tLeafLiteral ); pCurNode->addNode( new AstLeafLiteral( v ) ); } } void GameBuilder::addVarRef( const Bu::String &sName, ScopeId sid ) { if( pCurNode ) { stackMod( AstNode::tVarName ); pCurNode->addNode( new AstLeafLiteral( AstNode::tVarName, Variable::newVariableName( sName, sid ) ) ); } } void GameBuilder::addFuncCall( const Bu::String &sName ) { if( pCurNode ) { stackMod( AstNode::tFuncCall ); pCurNode->addNode( new AstLeafLiteral( AstNode::tFuncCall, sName ) ); } } void GameBuilder::stackMod( AstNode::Type iType ) { switch( iType ) { case AstNode::tNot: case AstNode::tNegate: case AstNode::tSwap: case AstNode::tDeref: case AstNode::tExists: case AstNode::tDelete: break; case AstNode::tComp: case AstNode::tCompGt: case AstNode::tCompLt: case AstNode::tCompGtEq: case AstNode::tCompLtEq: case AstNode::tStore: case AstNode::tAnd: case AstNode::tOr: case AstNode::tPlus: case AstNode::tMinus: case AstNode::tDivide: case AstNode::tMultiply: case AstNode::tPlusStore: case AstNode::tMinusStore: case AstNode::tDivideStore: case AstNode::tMultiplyStore: case AstNode::tIn: case AstNode::tGoto: case AstNode::tStoreRev: case AstNode::tReturn: // return doesn't pop anything, but it counts as it. case AstNode::tAppend: case AstNode::tPop: case AstNode::tIndex: iStackHeight--; break; case AstNode::tInsert: iStackHeight -= 2; break; case AstNode::tLeafLiteral: case AstNode::tVarName: case AstNode::tLiteral: case AstNode::tFuncCall: iStackHeight++; break; case AstNode::tBranch: break; case AstNode::tScope: break; case AstNode::tIf: iStackHeight--; break; case AstNode::tForEach: iStackHeight -= 2; break; case AstNode::tWhile: iStackHeight -= 1; break; } } void GameBuilder::beginGlobal() { bGlobal = true; } void GameBuilder::closeGlobal() { bGlobal = false; } void GameBuilder::beginCommand( const Bu::String &sValue ) { if( !bGlobal && pCurSit->getInputType() != Situation::inputCommand ) throw Bu::ExceptionBase("Command in non-command situation."); pCurNode = pCurRoot = new AstBranch( AstNode::tScope ); pCurCmd = new Command(); pCurCmd->addLiteral( sValue ); } void GameBuilder::addCommandLiteral( const Bu::String &sValue ) { pCurCmd->addLiteral( sValue ); } void GameBuilder::addCommandParam( const Bu::String &sValue ) { pCurCmd->addParam( sValue ); } void GameBuilder::endCommandParams() { Bu::StringList lParams = pCurCmd->getParamList(); for( Bu::StringList::iterator i = lParams.begin(); i; i++ ) { addVarRef( *i, sidLocal ); addNode( AstNode::tStoreRev ); } } void GameBuilder::closeCommand() { pCurCmd->setAst( pCurRoot ); pCurRoot = pCurNode = NULL; //pCurCmd->print(); if( bGlobal ) { pGame->csGlobal.addCommand( pCurCmd ); } else { pCurSit->csLocal.addCommand( pCurCmd ); } pCurCmd = NULL; iStackHeight = 0; } void GameBuilder::beginOption( const Bu::String &sValue ) { if( pCurSit->getInputType() != Situation::inputOption ) throw Bu::ExceptionBase("Option in non-option situation."); pCurNode = pCurRoot = new AstBranch( AstNode::tScope ); pCurCmd = new Command(); pCurCmd->addLiteral( sValue ); } void GameBuilder::closeOption() { pCurCmd->setAst( pCurRoot ); pCurRoot = pCurNode = NULL; //pCurCmd->print(); pCurSit->csLocal.addCommand( pCurCmd ); pCurCmd = NULL; iStackHeight = 0; }