📄 programgraphparser.cpp
字号:
/*************************************************************************** tag: Peter Soetens Mon May 10 19:10:37 CEST 2004 ProgramGraphParser.cxx ProgramGraphParser.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 "ProgramGraphParser.hpp"#include "ArgumentsParser.hpp"#include "CommandNOP.hpp"#include "CommandDataSource.hpp"#include "ConditionTrue.hpp"#include "Logger.hpp"#include "DataSourceCondition.hpp"#include "ConditionComposite.hpp"#include "CommandComposite.hpp"#include "CommandBinary.hpp"#include "TryCommand.hpp"#include "FunctionFactory.hpp"#include <iostream>#include <boost/bind.hpp>#include <boost/lambda/lambda.hpp>namespace RTT{ using namespace boost; using namespace detail; namespace { assertion<std::string> expect_opencurly("Open curly brace '{' expected."); assertion<std::string> expect_closecurly("Closing curly brace '}' expected ( or could not find out what this line means )."); assertion<std::string> expect_open("Open brace '(' expected."); assertion<std::string> expect_close("Closing brace ')' expected."); assertion<std::string> expect_comma("Expected a comma separator."); assertion<std::string> expect_ident("Expected a valid identifier."); assertion<std::string> expect_semicolon("Semicolon ';' expected after statement."); assertion<std::string> expect_condition("Expected a boolean expression ( a condition )."); assertion<std::string> expect_expression("Expected an expression."); assertion<std::string> expect_command("Expected a command after 'do'."); assertion<std::string> expect_nl("Expected a newline after statement."); assertion<std::string> expect_eof("Invalid input in file."); assertion<std::string> expect_term("No valid termination claues found in do ... until { } block."); } ProgramGraphParser::ProgramGraphParser( iter_t& positer, TaskContext* t) : rootc( t ),context( 0 ), fcontext(0), mpositer( positer ), mcallfunc(), implcond(0), mcondition(0), try_cond(0), conditionparser( rootc ), commandparser( rootc, true ), // as_action == true valuechangeparser( rootc ), expressionparser( rootc ), argsparser(0), peerparser(rootc), program_builder( new FunctionGraphBuilder() ), for_init_command(0), for_incr_command(0), exportf(false), ln_offset(0) { // putting the code in setup() works around a GCC 4.1 bug. this->setup(); this->setup2(); } void ProgramGraphParser::setup() { BOOST_SPIRIT_DEBUG_RULE( newline ); BOOST_SPIRIT_DEBUG_RULE( openbrace ); BOOST_SPIRIT_DEBUG_RULE( closebrace ); BOOST_SPIRIT_DEBUG_RULE( opencurly ); BOOST_SPIRIT_DEBUG_RULE( closecurly ); BOOST_SPIRIT_DEBUG_RULE( semicolon ); BOOST_SPIRIT_DEBUG_RULE( condition ); BOOST_SPIRIT_DEBUG_RULE( terminationclause ); BOOST_SPIRIT_DEBUG_RULE( jumpdestination ); BOOST_SPIRIT_DEBUG_RULE( terminationpart ); BOOST_SPIRIT_DEBUG_RULE( dostatement ); BOOST_SPIRIT_DEBUG_RULE( trystatement ); BOOST_SPIRIT_DEBUG_RULE( catchpart ); BOOST_SPIRIT_DEBUG_RULE( statement ); BOOST_SPIRIT_DEBUG_RULE( line ); BOOST_SPIRIT_DEBUG_RULE( content ); BOOST_SPIRIT_DEBUG_RULE( program ); BOOST_SPIRIT_DEBUG_RULE( production ); BOOST_SPIRIT_DEBUG_RULE( valuechange ); BOOST_SPIRIT_DEBUG_RULE( function ); BOOST_SPIRIT_DEBUG_RULE( functions ); BOOST_SPIRIT_DEBUG_RULE( arguments ); BOOST_SPIRIT_DEBUG_RULE( returnstatement ); BOOST_SPIRIT_DEBUG_RULE( funcstatement ); BOOST_SPIRIT_DEBUG_RULE( continuepart ); BOOST_SPIRIT_DEBUG_RULE( callpart ); BOOST_SPIRIT_DEBUG_RULE( returnpart ); BOOST_SPIRIT_DEBUG_RULE( ifstatement ); BOOST_SPIRIT_DEBUG_RULE( whilestatement ); BOOST_SPIRIT_DEBUG_RULE( forstatement ); BOOST_SPIRIT_DEBUG_RULE( breakstatement ); BOOST_SPIRIT_DEBUG_RULE( ifblock ); BOOST_SPIRIT_DEBUG_RULE( funcargs ); //newline = ch_p( '\n' ); openbrace = expect_open( ch_p('(') ); closebrace = expect_close( ch_p(')') ); opencurly = expect_opencurly( ch_p('{') ); closecurly = expect_closecurly( ch_p('}') ); semicolon = expect_semicolon( ch_p(';') ); condition = expect_condition( conditionparser.parser()[ bind(&ProgramGraphParser::seencondition, this) ] ); // program is the production rule of this grammar. The // production rule is the rule that the entire input should be // matched by... This line basically means that we're finished // ;) // Zero or n functions can precede the program. production = (functions >> *program)[bind(&ProgramGraphParser::programtext,this, _1, _2)] >> expect_eof(end_p) ; functions = *function; // a function is very similar to a program, but it also has a name function = ( !str_p( "export" )[bind(&ProgramGraphParser::exportdef, this)] >> str_p( "function" ) >> expect_ident( commonparser.identifier[ bind( &ProgramGraphParser::functiondef, this, _1, _2 ) ] ) >> !funcargs >> opencurly >> content >> closecurly[ bind( &ProgramGraphParser::seenfunctionend, this ) ] ); // the function's definition args : funcargs = ch_p('(') >> ( ch_p(')') || ( !( valuechangeparser.bareDefinitionParser()[bind(&ProgramGraphParser::seenfunctionarg, this)] >> *(ch_p(',')>> valuechangeparser.bareDefinitionParser()[bind(&ProgramGraphParser::seenfunctionarg, this)]) ) >> closebrace )); // a program looks like "program { content }". program = str_p( "program" ) >> expect_ident( commonparser.identifier[ bind( &ProgramGraphParser::programdef, this, _1, _2 ) ] ) >> opencurly >> content >> closecurly[ bind( &ProgramGraphParser::seenprogramend, this ) ]; // the content of a program can be any number of lines content = *line; // a line can be empty or contain a statement. Empty is // necessary, because comment's are skipped, but newline's // aren't. So a line like "/* very interesting comment // */\n" will reach us as simply "\n".. //line = !( statement ) >> eol_p; line = statement[bind(&ProgramGraphParser::noskip_eol, this )] >> commonparser.eos[bind(&ProgramGraphParser::skip_eol, this )]; statement = valuechange | dostatement | trystatement | funcstatement | returnstatement | ifstatement | whilestatement | forstatement | breakstatement; valuechange_parsers = valuechangeparser.constantDefinitionParser() | valuechangeparser.variableDefinitionParser() | valuechangeparser.aliasDefinitionParser() | valuechangeparser.variableAssignmentParser(); valuechange = valuechange_parsers[ bind( &ProgramGraphParser::seenvaluechange, this ) ]; // a do statement: "do xxx <and y> <and...> until { terminationclauses }" dostatement = (str_p( "do" ) [ bind( &ProgramGraphParser::startofnewstatement, this, "do" ) ] >> (expect_command ( commandparser.parser()[ bind( &ProgramGraphParser::seencommandcall, this ) ] ) >> *andpart)[bind( &ProgramGraphParser::seencommands, this )] >> !terminationpart ) [ bind( &ProgramGraphParser::seendostatement, this ) ]; // a try statement: "try xxx <and y> <and...> until { terminationclauses } catch { stuff to do once on any error} " trystatement = (str_p("try") [ bind(&ProgramGraphParser::startofnewstatement, this, "try")] >> (expect_command ( commandparser.parser()[ bind( &ProgramGraphParser::seencommandcall, this ) ] ) >> *andpart)[bind( &ProgramGraphParser::seencommands, this )] >> !terminationpart ) [ bind( &ProgramGraphParser::seendostatement, this ) ] >> !catchpart; } void ProgramGraphParser::initBodyParser(const std::string& name, OperationInterface* stck, int offset) { ln_offset = offset; assert(program_builder != 0 ); program_builder->startFunction(name); this->setStack( stck ); } rule_t& ProgramGraphParser::bodyParser() { // content is the bodyparser of a program or function return content; } ProgramInterfacePtr ProgramGraphParser::bodyParserResult() { // store the variables in the program's taskcontext object. valuechangeparser.store( context ); valuechangeparser.reset(); // 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); return program_builder->endFunction( mpositer.get_position().line - ln_offset ); } void ProgramGraphParser::setStack(OperationInterface* st) { context = st; } void ProgramGraphParser::seencommands() { // Chain all implicit termination conditions into 'done' : std::vector<ConditionInterface*>::iterator it = implcond_v.begin(); implcond = *it; while ( ++it != implcond_v.end() ) { implcond = new ConditionBinaryCompositeAND( implcond, *it ) ; } implcond_v.clear(); rootc->attributes() ->setValue( new Alias<bool>("done", new DataSourceCondition( implcond->clone() ) ) ); } void ProgramGraphParser::seendostatement() { // assert(implcond); // Called after a whole command statement is parsed. // a CommandNode should have at least one edge // If it doesn't, then we add a default one, // which just moves on to the next node.. if ( program_builder->buildEdges() == 0 ) { program_builder->proceedToNext( implcond->clone(), mpositer.get_position().line - ln_offset ); } else { program_builder->proceedToNext( mpositer.get_position().line - ln_offset ); } delete implcond; implcond = 0; // the done condition is no longer valid.. rootc->attributes()->removeValue( "done" ); } void ProgramGraphParser::startofprogram() { } void ProgramGraphParser::programdef( iter_t begin, iter_t end ) { // Now that we got the name, set everything up: std::string def(begin, end); if ( rootc->getObject( def ) != 0 ) throw parse_exception_semantic_error("Object with name '" + def + "' already present in task '"+rootc->getName()+"'."); FunctionGraphPtr pi(program_builder->startFunction( def )); // ptsk becomes the owner of pi.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -