📄 programgraphparser.cpp
字号:
ProgramTask* ptsk(new ProgramTask( pi, rootc->engine() )); pi->setProgramTask(ptsk); context = ptsk; rootc->addObject( ptsk ); } void ProgramGraphParser::programtext( iter_t begin, iter_t end ) { //program_text = std::string(begin, end); } void ProgramGraphParser::exportdef() { exportf = true; } void ProgramGraphParser::functiondef( iter_t begin, iter_t end ) { // store the function in our map for later // referencing. std::string funcdef(begin, end); // store the function in the TaskContext current.__functions// TaskContext* __f = rootc->getPeer("__functions");// if ( __f == 0 ) {// // install the __functions if not yet present.// __f = new TaskContext("__functions", rootc->engine() );// rootc->connectPeers( __f );// }// if ( __f->hasPeer( funcdef ) ) if ( mfuncs.count( funcdef ) ) throw parse_exception_semantic_error("function " + funcdef + " redefined."); if ( exportf && rootc->commands()->hasMember( funcdef )) throw parse_exception_semantic_error("exported function " + funcdef + " is already defined in "+ rootc->getName()+".");; mfuncs[funcdef] = program_builder->startFunction( funcdef ); // Connect the new function to the relevant contexts. // 'fun' acts as a stack for storing variables. context = fcontext = new TaskContext(funcdef, rootc->engine() ); } void ProgramGraphParser::seenfunctionarg() { // the ValueChangeParser stores each variable in the // current stack's repository, but we need to inform the // FunctionGraph itself about its arguments. program_builder->getFunction()->addArgument( valuechangeparser.lastDefinedValue()->clone() ); valuechangeparser.clear(); } void ProgramGraphParser::seenfunctionend() { // Fake a 'return' statement at the last line. program_builder->returnFunction( new ConditionTrue, mpositer.get_position().line - ln_offset ); program_builder->proceedToNext( mpositer.get_position().line - ln_offset ); shared_ptr<ProgramInterface> mfunc = program_builder->endFunction( mpositer.get_position().line - ln_offset ); // export the function in the context's interface. if (exportf) { std::map<const DataSourceBase*, DataSourceBase*> dummy; FunctionFactory* cfi = new FunctionFactory(ProgramInterfacePtr(mfunc->copy(dummy)), rootc->engine() ); // execute in the processor which has the command. rootc->commands()->add(mfunc->getName(), cfi ); Logger::log() << Logger::Info << "Exported Function '" << mfunc->getName() << "' added to task '"<< rootc->getName() << "'" <<Logger::endl; } delete fcontext; context = fcontext = 0; // reset exportf = false; valuechangeparser.reset(); } void ProgramGraphParser::seencondition() { mcondition = conditionparser.getParseResult(); assert( mcondition ); // leaves the condition in the parser, if we want to use // getParseResultAsCommand(); // mcondition is only used with seen*label statements, // when the command and condition are associated, // not in the branching where the evaluation of the // condition is the command. } void ProgramGraphParser::seenreturnstatement() { // return statement can happen in program and in a function program_builder->returnFunction( new ConditionTrue, mpositer.get_position().line - ln_offset ); program_builder->proceedToNext( mpositer.get_position().line - ln_offset ); } void ProgramGraphParser::seenbreakstatement() { if ( program_builder->inLoop() ) { program_builder->breakLoop(); program_builder->proceedToNext( mpositer.get_position().line - ln_offset ); } else throw parse_exception_syntactic_error("Illegal use of 'break'. Can only be used within for and while loops."); } void ProgramGraphParser::seenreturnlabel() { // return label can happen in program and in a function assert(mcondition); program_builder->returnFunction( mcondition->clone(), mpositer.get_position().line - ln_offset ); delete mcondition; mcondition = 0; } void ProgramGraphParser::seenfuncidentifier( iter_t begin, iter_t end ) { // store the part after 'call' std::string fname(begin, end); if ( mfuncs.count(fname) == 0 ) throw parse_exception_semantic_error("calling function " + fname + " but it is not defined ( use 'do' for calling exported functions )."); if ( fname == program_builder->getFunction()->getName() ) throw parse_exception_semantic_error("calling function " + fname + " recursively is not allowed."); mcallfunc = mfuncs[ fname ]; // Parse the function's args in the programs context. argsparser = new ArgumentsParser( expressionparser, rootc, rootc, "this", fname ); arguments = argsparser->parser(); } void ProgramGraphParser::seencallfuncargs() { callfnargs = argsparser->result(); } void ProgramGraphParser::seencallfuncstatement() { // This function is called if the 'call func' is outside // a termination clause. // add it to the main program line of execution. assert( mcallfunc ); try { program_builder->setFunction( mcallfunc, callfnargs ); // only delete parser, when the args are used. delete argsparser; argsparser = 0; callfnargs.clear(); } catch( const wrong_number_of_args_exception& e ) { throw parse_exception_wrong_number_of_arguments ( rootc->getName(), mcallfunc->getName(), e.wanted, e.received ); } catch( const wrong_types_of_args_exception& e ) { throw parse_exception_wrong_type_of_argument ( rootc->getName(), mcallfunc->getName(), e.whicharg, e.expected_, e.received_ ); } catch( ... ) { assert( false ); } // The exit node of the function is already connected // to program->nextNode(). program_builder->proceedToNext(mpositer.get_position().line - ln_offset); } void ProgramGraphParser::skip_eol() { eol_skip_functor::skipeol = true; } void ProgramGraphParser::noskip_eol() { eol_skip_functor::skipeol = false; } void ProgramGraphParser::startofnewstatement(const std::string& type) { // cleanup previous left conds (should do this in endofnewstatement func) // try_cond will be zero if used, othewise, delete it delete try_cond; try_cond = 0; // a 'do' fails on the first rejected command, // a 'try' tries all commands. if ( type == "do") try_cmd = false; else if (type == "try") try_cmd = true; else assert(false); } void ProgramGraphParser::startcatchpart() { // we saved the try_cond in the previous try statement, // now process like it said if ( try_cond ) then {...} assert( try_cond ); program_builder->startIfStatement( try_cond, mpositer.get_position().line - ln_offset ); try_cond = 0; } void ProgramGraphParser::seencatchpart() { this->endifblock(); this->endifstatement(); // there is no 'else' part, so close the statement } void ProgramGraphParser::seenifstatement() { assert(mcondition); // transform the evaluation in a command, and pass the result // as a condition std::pair<CommandInterface*, ConditionInterface*> comcon; comcon = conditionparser.getParseResultAsCommand(); program_builder->setCommand( comcon.first ); program_builder->startIfStatement( comcon.second, mpositer.get_position().line - ln_offset ); // we did not need this. delete mcondition; mcondition = 0; } void ProgramGraphParser::endifblock() { program_builder->endIfBlock(mpositer.get_position().line - ln_offset); } void ProgramGraphParser::endifstatement() { program_builder->endElseBlock(mpositer.get_position().line - ln_offset); } void ProgramGraphParser::seenwhilestatement() { // analogous to seenifstatement // the evaluation is a command. assert(mcondition); std::pair<CommandInterface*, ConditionInterface*> comcon; comcon = conditionparser.getParseResultAsCommand(); program_builder->setCommand( comcon.first ); program_builder->startWhileStatement( comcon.second, mpositer.get_position().line - ln_offset ); delete mcondition; mcondition = 0; } void ProgramGraphParser::endwhilestatement() { program_builder->endWhileBlock(mpositer.get_position().line - ln_offset); } void ProgramGraphParser::seenforinit() { // the for loop is different from the while and if branch // structures in that it places an init command before the loop. CommandInterface* ac = 0; std::vector<CommandInterface*> acv = valuechangeparser.assignCommands(); // and not forget to reset().. valuechangeparser.clear(); if ( acv.size() == 1) { ac = acv.front(); } else if (acv.size() > 1) { ac = new CommandComposite( acv ); } for_init_command = ac; } void ProgramGraphParser::seenforincr() { CommandInterface* ac = 0; std::vector<CommandInterface*> acv = valuechangeparser.assignCommands(); if ( acv.size() == 1) { ac = acv.front(); } else if (acv.size() > 1) { ac = new CommandComposite( acv ); } for_incr_command = ac; valuechangeparser.clear(); } void ProgramGraphParser::seenforstatement() { assert( mcondition ); // first insert the initialisation command. if ( for_init_command )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -