/* * File: PgclParser.h * Author: Lukas Westhofen * * Created on 1. April 2015, 19:12 */ #ifndef PGCLPARSER_H #define PGCLPARSER_H // Includes files for file input. #include #include #include // Includes files for building and parsing the PGCL program #include "src/parser/SpiritParserDefinitions.h" #include "src/parser/ExpressionParser.h" #include "src/storage/expressions/ExpressionManager.h" #include "src/storage/expressions/Expression.h" #include "src/storage/pgcl/PgclProgram.h" #include "src/storage/pgcl/AssignmentStatement.h" #include "src/storage/pgcl/BooleanExpression.h" #include "src/storage/pgcl/UniformExpression.h" #include "src/storage/pgcl/IfStatement.h" #include "src/storage/pgcl/LoopStatement.h" #include "src/storage/pgcl/NondeterministicBranch.h" #include "src/storage/pgcl/ObserveStatement.h" #include "src/storage/pgcl/ProbabilisticBranch.h" #include "src/storage/pgcl/Statement.h" namespace storm { namespace parser { class PgclParser : public qi::grammar { public: /*! * Parses the given file into the PGCL storage classes in case it * complies with the PGCL syntax. * * @param filename the name of the file to parse. * @return The resulting PGCL program. */ static storm::pgcl::PgclProgram parse(std::string const& filename); /*! * Parses the given input stream into the PGCL storage classes in * case it complies with the PGCL syntax. * * @param input The input string to parse. * @param filename Name of the file from which the input was read. * @return The resulting PGCL program. */ static storm::pgcl::PgclProgram parseFromString(std::string const& input, std::string const& filename); private: // Internal constructor used by the parseFromString function. PgclParser(std::string const& filename, Iterator first); // Nonterminals (and their semantic types) of the PGCL grammar. qi::rule program; qi::rule >(), Skipper> sequenceOfStatements; qi::rule(), Skipper> statement; qi::rule(), Skipper> simpleStatement; qi::rule(), Skipper> compoundStatement; qi::rule(), Skipper> ifElseStatement; qi::rule(), Skipper> branchStatement; qi::rule(), Skipper> loopStatement; qi::rule(), Skipper> nondeterministicBranch; qi::rule(), Skipper> probabilisticBranch; qi::rule(), Skipper> assignmentStatement; qi::rule declaration; qi::rule doubleDeclaration; qi::rule(), Skipper> integerDeclarationStatement; qi::rule(), Skipper> observeStatement; qi::rule expression; qi::rule booleanCondition; qi::rule uniformExpression; qi::rule variableName; qi::rule programName; /// Denotes the invalid identifiers, which are later passed to the expression parser. struct keywordsStruct : qi::symbols { keywordsStruct() { add ("while", 1) ("if", 2) ("observe", 3) ("int", 4) ("function", 5); } }; /// Initializes the invalid identifier struct. keywordsStruct invalidIdentifiers; /// Is used to store the identifiers of the PGCL program that are found while parsing. qi::symbols identifiers_; /// Functor used for annotating entities with line number information. class PositionAnnotation { public: typedef void result_type; PositionAnnotation(Iterator first) : first(first) { // Intentionally left empty. } template result_type operator()(Entity& entity, First f, Last l) const { entity.setLineNumber(get_line(f)); } private: std::string filename; Iterator const first; }; /// A function used for annotating the entities with their position. phoenix::function annotate; /// Manages the expressions and their parsing externally. std::shared_ptr expressionManager; storm::parser::ExpressionParser expressionParser; /// Stores a mapping from location numbers to statements. std::vector > locationToStatement; /// Saves whether a loop statements was created. bool loopCreated = false; /// Saves whether a nondet statements was created. bool nondetCreated = false; /// Saves whether a observe statement was created. bool observeCreated = false; /// Stores the unique identifier of the currently parsed statement, starting at 1. std::size_t currentLocationNumber = 1; /// Sets the expression parser to a mode where it actually generates valid expressions. void enableExpressions(); // Constructors for the single program parts. They just wrap the statement constructors and throw exceptions in case something unexpected was parsed. storm::pgcl::PgclProgram createProgram(std::string const& programName, boost::optional > parameters, std::vector > statements); storm::expressions::Variable declareDoubleVariable(std::string const& variableName); std::shared_ptr createAssignmentStatement(std::string const& variableName, boost::variant const& assignedExpression); std::shared_ptr createIntegerDeclarationStatement(std::string const& variableName, storm::expressions::Expression const& assignedExpression); std::shared_ptr createObserveStatement(storm::pgcl::BooleanExpression const& condition); std::shared_ptr createIfElseStatement(storm::pgcl::BooleanExpression const& condition, std::vector > const& if_body, boost::optional > > const& else_body); std::shared_ptr createLoopStatement(storm::pgcl::BooleanExpression const& condition, std::vector > const& body); std::shared_ptr createNondeterministicBranch(std::vector > const& left, std::vector > const& right); std::shared_ptr createProbabilisticBranch(storm::expressions::Expression const& probability, std::vector > const& left, std::vector > const& right); storm::pgcl::BooleanExpression createBooleanExpression(storm::expressions::Expression const& expression); storm::pgcl::UniformExpression createUniformExpression(int const& begin, int const& end); }; } // namespace parser } // namespace storm #endif /* PGCLPARSER_H */