📄 stategraphparser.cpp
字号:
/*************************************************************************** tag: Peter Soetens Mon May 10 19:10:37 CEST 2004 StateGraphParser.cxx StateGraphParser.cxx - description ------------------- begin : Mon May 10 2004 copyright : (C) 2004 Peter Soetens email : peter.soetens@mech.kuleuven.ac.be *************************************************************************** * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * * License as published by the Free Software Foundation; either * * version 2.1 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 * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with this library; if not, write to the Free Software * * Foundation, Inc., 59 Temple Place, * * Suite 330, Boston, MA 02111-1307 USA * * * ***************************************************************************/#include "parser-debug.hpp"#include "parse_exception.hpp"#include "StateGraphParser.hpp"#include "CommonParser.hpp"#include "ConditionParser.hpp"#include "CommandParser.hpp"#include "ValueChangeParser.hpp"#include "ProgramGraphParser.hpp"#include "PeerParser.hpp"#include "ArgumentsParser.hpp"#include "StateMachineBuilder.hpp"#include "TaskContext.hpp"#include "StateMachineTask.hpp"#include "CommandComposite.hpp"#include "Exceptions.hpp"#include "AttributeBase.hpp"#include "ConditionTrue.hpp"#include "ConditionInvert.hpp"#include "StateDescription.hpp"#include "ParsedStateMachine.hpp"#include <iostream>#include <functional>#include <algorithm>#include <boost/bind.hpp>#include <boost/lambda/lambda.hpp>#include <boost/call_traits.hpp>#include <iostream>#include <memory>namespace RTT{ using namespace boost; using namespace detail; using boost::bind; using namespace std; namespace { enum GraphSyntaxErrors { state_expected, handle_expected, transition_expected, }; assertion<GraphSyntaxErrors> expect_state(state_expected); assertion<GraphSyntaxErrors> expect_handle(handle_expected); assertion<GraphSyntaxErrors> expect_transition(transition_expected); assertion<std::string> expect_end("Ending '}' expected ( or could not find out what this line means )."); assertion<std::string> expect_end_of_state("Exptected ending '}' at end of state ( or could not find out what this line means )."); assertion<std::string> expect_if("Wrongly formatted \"if ... then select\" clause."); assertion<std::string> expect_select("'select' statement required after emty transition program."); assertion<std::string> expect_comma("Expected a comma separator."); assertion<std::string> expect_ident("Expected a valid identifier."); assertion<std::string> expect_open("Open brace expected."); assertion<std::string> expect_eof("Invalid input in file."); assertion<std::string> expect_eol("Newline expected at end of statement."); assertion<std::string> expect_semicolon("Semi colon expected after statement."); assertion<std::string> expect_open_parenth( "Open parenthesis expected." ); assertion<std::string> expect_close_parenth( "Open parenthesis expected." ); assertion<std::string> expect_eventselect("'select' statement required after event or transition program."); assertion<std::string> expect_eventargs("Could not parse arguments after event."); } StateGraphParser::StateGraphParser( iter_t& positer, TaskContext* tc ) : context( tc ), curobject( 0 ), mpositer( positer ), ln_offset(0), curtemplate(), curinstantiatedmachine(), curmachinebuilder( 0 ), curinitialstateflag( false ), curfinalstateflag( false ), curstate( 0 ), curnonprecstate( 0 ), progParser( 0 ), elsestate(0), curcondition( 0 ), isroot(false), selectln(0), evname(""), conditionparser( new ConditionParser( context ) ), commonparser( new CommonParser ), valuechangeparser( new ValueChangeParser(context) ), expressionparser( new ExpressionParser(context) ), argsparser(0), peerparser( new PeerParser(context, true) ) // full-path peer parser for events. { BOOST_SPIRIT_DEBUG_RULE( production ); BOOST_SPIRIT_DEBUG_RULE( rootmachineinstantiation ); BOOST_SPIRIT_DEBUG_RULE( statemachine ); BOOST_SPIRIT_DEBUG_RULE( machineinstantiation ); BOOST_SPIRIT_DEBUG_RULE( statemachinecontent ); BOOST_SPIRIT_DEBUG_RULE( varline ); BOOST_SPIRIT_DEBUG_RULE( state ); BOOST_SPIRIT_DEBUG_RULE( vardec ); BOOST_SPIRIT_DEBUG_RULE( subMachinedecl ); BOOST_SPIRIT_DEBUG_RULE( statecontent ); BOOST_SPIRIT_DEBUG_RULE( statecontentline ); BOOST_SPIRIT_DEBUG_RULE( entry ); BOOST_SPIRIT_DEBUG_RULE( preconditions ); BOOST_SPIRIT_DEBUG_RULE( precondition ); BOOST_SPIRIT_DEBUG_RULE( handle ); BOOST_SPIRIT_DEBUG_RULE( transitions ); BOOST_SPIRIT_DEBUG_RULE( transition ); BOOST_SPIRIT_DEBUG_RULE( exit ); BOOST_SPIRIT_DEBUG_RULE( transline ); BOOST_SPIRIT_DEBUG_RULE( selectcommand ); BOOST_SPIRIT_DEBUG_RULE( brancher ); BOOST_SPIRIT_DEBUG_RULE( selector ); BOOST_SPIRIT_DEBUG_RULE( machineinstarguments ); BOOST_SPIRIT_DEBUG_RULE( machineinstargument ); BOOST_SPIRIT_DEBUG_RULE( machinememvar ); BOOST_SPIRIT_DEBUG_RULE( machinevariable ); BOOST_SPIRIT_DEBUG_RULE( machineparam ); BOOST_SPIRIT_DEBUG_RULE( machineconstant ); BOOST_SPIRIT_DEBUG_RULE( machinealias ); BOOST_SPIRIT_DEBUG_RULE( subMachinevarchange ); production = *( (statemachine[ bind( &StateGraphParser::seenstatemachineend, this ) ] >> *( rootmachineinstantiation ))[bind( &StateGraphParser::saveText, this, _1, _2)]) >> expect_eof(end_p); rootmachineinstantiation = str_p("RootMachine")[bind (&StateGraphParser::startrootmachineinstantiation, this) ] >> machineinstantiation[ bind( &StateGraphParser::seenrootmachineinstantiation, this ) ]; statemachine = str_p("StateMachine") //[bind( &StateGraphParser::storeOffset, this)] >> expect_ident( commonparser->identifier[ bind( &StateGraphParser::seenstatemachinename, this, _1, _2 )] ) >> expect_open( ch_p( '{' ) ) >> statemachinecontent >> expect_end( ch_p( '}' ) ); // Zero or more declarations and Zero or more states statemachinecontent = *( varline | state ); varline = vardec[lambda::var(eol_skip_functor::skipeol) = false] >> commonparser->eos[lambda::var(eol_skip_functor::skipeol) = true]; vardec = subMachinedecl | machinememvar | machineparam; machinememvar = ( machineconstant | machinevariable | machinealias )[bind( &StateGraphParser::seenmachinevariable, this )]; machineconstant = valuechangeparser->constantDefinitionParser(); machinevariable = valuechangeparser->variableDefinitionParser(); machinealias = valuechangeparser->aliasDefinitionParser(); machineparam = valuechangeparser->paramDefinitionParser()[bind( &StateGraphParser::seenmachineparam, this )]; subMachinedecl = str_p("SubMachine") >> machineinstantiation[bind( &StateGraphParser::seensubMachineinstantiation, this )]; machineinstantiation = expect_ident( commonparser->identifier[ bind( &StateGraphParser::seenmachinetypename, this, _1, _2 )] ) >> expect_ident( commonparser->identifier[ bind( &StateGraphParser::seeninstmachinename, this, _1, _2 )] ) >> ( ! ( ch_p( '(' ) >> !machineinstarguments >> expect_close_parenth( ch_p( ')' ) ) ) )[ bind( &StateGraphParser::seenmachineinstantiation, this )]; machineinstarguments = machineinstargument >> *( ',' >> machineinstargument ); machineinstargument = commonparser->identifier[ bind( &StateGraphParser::seenmachineinstargumentname, this, _1, _2 )] >> '=' >> expressionparser->parser()[ bind( &StateGraphParser::seenmachineinstargumentvalue, this )]; state = !( str_p( "initial" )[bind( &StateGraphParser::seeninitialstate,this )] | str_p( "final" )[bind( &StateGraphParser::seenfinalstate,this )] ) >> str_p( "state" ) >> expect_ident(commonparser->identifier[ bind( &StateGraphParser::statedef, this, _1, _2 ) ]) >> expect_open(ch_p( '{' )) >> statecontent >> expect_end_of_state(ch_p( '}' ))[ bind( &StateGraphParser::seenstateend, this ) ]; // the content of a program can be any number of lines // a line is not strictly defined in the sense of text-line. statecontent = *statecontentline; // a state can contain various programs and variable definitions statecontentline = entry | preconditions | run | handle | transitions | exit | machinememvar[lambda::var(eol_skip_functor::skipeol) = false] >> commonparser->eos[lambda::var(eol_skip_functor::skipeol) = true]; precondition = str_p( "precondition") >> conditionparser->parser()[ bind( &StateGraphParser::seenprecondition, this)] ; preconditions = (str_p( "preconditions" )[ bind( &StateGraphParser::inpreconditions, this )] >> expect_open( ch_p( '{' )) >> *transline >> expect_end( ch_p( '}' ) )[ bind( &StateGraphParser::seenpreconditions, this )]) | precondition; entry = str_p( "entry" )[ bind( &StateGraphParser::inprogram, this, "entry" )] >> expect_open(ch_p('{'))>> programBody >> expect_end(ch_p('}'))[ bind( &StateGraphParser::seenentry, this )]; run = str_p( "run" )[ bind( &StateGraphParser::inprogram, this, "run" )] >> expect_open(ch_p('{'))>> programBody >> expect_end(ch_p('}'))[ bind( &StateGraphParser::seenrun, this )]; exit = str_p( "exit" )[ bind( &StateGraphParser::inprogram, this, "exit" )] >> expect_open(ch_p('{')) >> programBody >> expect_end(ch_p('}'))[ bind( &StateGraphParser::seenexit, this )]; handle = str_p( "handle" )[ bind( &StateGraphParser::inprogram, this, "handle" )] >> expect_open(ch_p('{'))>> programBody >> expect_end(ch_p('}'))[ bind( &StateGraphParser::seenhandle, this )]; // event based transition transition = str_p("transition") >> !peerparser->parser() >> expect_ident(commonparser->identifier[ bind( &StateGraphParser::seeneventname, this,_1,_2)]) >> expect_eventargs(argslist[ bind( &StateGraphParser::seeneventargs, this)]) >> expect_eventselect(selectcommand[ bind( &StateGraphParser::seeneventtrans, this)]); // condition based transition. // the order of rule "transition" vs "transitions" is important transitions = ( str_p( "transitions" ) >> expect_open(ch_p('{'))>> *transline >> expect_end(ch_p('}')) ) | transition; transline = selectcommand; // You are only allowed to select a new state in transitions : selectcommand = (brancher | selector)[bind(&StateGraphParser::seenendcondition,this)]; brancher = str_p( "if") >> conditionparser->parser()[ bind( &StateGraphParser::seencondition, this)] >> expect_if(str_p( "then" )) >> !transprog >> !selector >> !(str_p("else")[bind( &StateGraphParser::seenelse, this )] >> expect_select( (elseprog >> !selector) | selector)); transprog = ch_p('{')[ bind( &StateGraphParser::inprogram, this, "transition" )] >> programBody >> expect_end(ch_p('}'))[bind( &StateGraphParser::seentransprog, this )]; elseprog = ch_p('{')[ bind( &StateGraphParser::inprogram, this, "elsetransition" )] >> programBody >> expect_end(ch_p('}'))[bind( &StateGraphParser::seenelseprog, this )]; selector = str_p( "select" ) >> ( commonparser->identifier[ bind( &StateGraphParser::seenselect, this, _1, _2) ] >> *("or" >> commonparser->identifier[ bind( &StateGraphParser::seenselect, this, _1, _2) ]) )[lambda::var(eol_skip_functor::skipeol) = false] >> commonparser->eos[lambda::var(eol_skip_functor::skipeol) = true]; // if eos fails skipeol stays false !, see cleanup() ! } void StateGraphParser::seeninitialstate() { curinitialstateflag = true; } void StateGraphParser::seenfinalstate() { curfinalstateflag = true; } void StateGraphParser::statedef( iter_t s, iter_t f) { assert( !curstate ); std::string def(s, f); if ( curtemplate->getState( def ) != 0 ) { assert( dynamic_cast<StateDescription*>( curtemplate->getState( def ) ) ); StateDescription* existingstate = static_cast<StateDescription*>( curtemplate->getState( def ) ); if ( existingstate->isDefined() ) ORO_THROW(parse_exception_semantic_error("state " + def + " redefined.") ); else curstate = existingstate; curstate->setEntryPoint( mpositer.get_position().line - ln_offset ); } else { curstate = new StateDescription(def, curtemplate->getTaskObject()->engine()->programs(), mpositer.get_position().line - ln_offset ); // create an empty state curtemplate->addState( curstate ); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -