You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

158 lines
9.5 KiB

  1. #pragma once
  2. // Includes files for file input.
  3. #include <fstream>
  4. #include <memory>
  5. #include <iomanip>
  6. // Includes files for building and parsing the PGCL program
  7. #include "storm/parser/SpiritParserDefinitions.h"
  8. #include "storm/parser/SpiritErrorHandler.h"
  9. #include "storm/parser/ExpressionParser.h"
  10. #include "storm/storage/expressions/ExpressionManager.h"
  11. #include "storm/storage/expressions/Expression.h"
  12. #include "storm-pgcl/storage/pgcl/PgclProgram.h"
  13. #include "storm-pgcl/storage/pgcl/AssignmentStatement.h"
  14. #include "storm-pgcl/storage/pgcl/BooleanExpression.h"
  15. #include "storm-pgcl/storage/pgcl/UniformExpression.h"
  16. #include "storm-pgcl/storage/pgcl/IfStatement.h"
  17. #include "storm-pgcl/storage/pgcl/LoopStatement.h"
  18. #include "storm-pgcl/storage/pgcl/NondeterministicBranch.h"
  19. #include "storm-pgcl/storage/pgcl/ObserveStatement.h"
  20. #include "storm-pgcl/storage/pgcl/ProbabilisticBranch.h"
  21. #include "storm-pgcl/storage/pgcl/Statement.h"
  22. namespace storm {
  23. namespace pgcl {
  24. class IfStatement;
  25. }
  26. namespace parser {
  27. class PgclParser : public qi::grammar<Iterator, storm::pgcl::PgclProgram(), Skipper> {
  28. public:
  29. /*!
  30. * Parses the given file into the PGCL storage classes in case it
  31. * complies with the PGCL syntax.
  32. *
  33. * @param filename the name of the file to parse.
  34. * @return The resulting PGCL program.
  35. */
  36. static storm::pgcl::PgclProgram parse(std::string const& filename);
  37. /*!
  38. * Parses the given input stream into the PGCL storage classes in
  39. * case it complies with the PGCL syntax.
  40. *
  41. * @param input The input string to parse.
  42. * @param filename Name of the file from which the input was read.
  43. * @return The resulting PGCL program.
  44. */
  45. static storm::pgcl::PgclProgram parseFromString(std::string const& input, std::string const& filename);
  46. private:
  47. // Internal constructor used by the parseFromString function.
  48. PgclParser(std::string const& filename, Iterator first);
  49. // Nonterminals (and their semantic types) of the PGCL grammar.
  50. qi::rule<Iterator, storm::pgcl::PgclProgram(), Skipper> program;
  51. qi::rule<Iterator, std::vector<std::shared_ptr<storm::pgcl::Statement> >(), Skipper> sequenceOfStatements;
  52. qi::rule<Iterator, std::shared_ptr<storm::pgcl::Statement>(), Skipper> statement;
  53. qi::rule<Iterator, std::shared_ptr<storm::pgcl::Statement>(), Skipper> simpleStatement;
  54. qi::rule<Iterator, std::shared_ptr<storm::pgcl::Statement>(), Skipper> compoundStatement;
  55. qi::rule<Iterator, std::shared_ptr<storm::pgcl::IfStatement>(), Skipper> ifElseStatement;
  56. qi::rule<Iterator, std::shared_ptr<storm::pgcl::BranchStatement>(), Skipper> branchStatement;
  57. qi::rule<Iterator, std::shared_ptr<storm::pgcl::LoopStatement>(), Skipper> loopStatement;
  58. qi::rule<Iterator, std::shared_ptr<storm::pgcl::NondeterministicBranch>(), Skipper> nondeterministicBranch;
  59. qi::rule<Iterator, std::shared_ptr<storm::pgcl::ProbabilisticBranch>(), Skipper> probabilisticBranch;
  60. qi::rule<Iterator, std::shared_ptr<storm::pgcl::AssignmentStatement>(), Skipper> assignmentStatement;
  61. qi::rule<Iterator, storm::expressions::Variable(), Skipper> declaration;
  62. qi::rule<Iterator, std::shared_ptr<storm::pgcl::ObserveStatement>(), Skipper> observeStatement;
  63. qi::rule<Iterator, storm::expressions::Expression(), Skipper> expression;
  64. qi::rule<Iterator, storm::pgcl::BooleanExpression(), Skipper> booleanCondition;
  65. qi::rule<Iterator, storm::pgcl::UniformExpression(), Skipper> uniformExpression;
  66. qi::rule<Iterator, std::string(), Skipper> variableName;
  67. qi::rule<Iterator, std::string(), Skipper> programName;
  68. qi::rule<Iterator, std::vector<std::shared_ptr<storm::pgcl::VariableDeclaration>>(), Skipper> variableDeclarations;
  69. qi::rule<Iterator, std::shared_ptr<storm::pgcl::VariableDeclaration>(), Skipper> integerDeclaration;
  70. qi::rule<Iterator, std::shared_ptr<storm::pgcl::VariableDeclaration>(), Skipper> booleanDeclaration;
  71. qi::rule<Iterator, storm::expressions::Variable(), Skipper> doubleDeclaration;
  72. // An error handler function.
  73. phoenix::function<SpiritErrorHandler> handler;
  74. /// Denotes the invalid identifiers, which are later passed to the expression parser.
  75. struct keywordsStruct : qi::symbols<char, uint_fast64_t> {
  76. keywordsStruct() {
  77. add
  78. ("while", 1)
  79. ("if", 2)
  80. ("observe", 3)
  81. ("int", 4)
  82. ("bool", 5)
  83. ("function", 6);
  84. }
  85. };
  86. /// Initializes the invalid identifier struct.
  87. keywordsStruct invalidIdentifiers;
  88. /// Is used to store the identifiers of the PGCL program that are found while parsing.
  89. qi::symbols<char, storm::expressions::Expression> identifiers_;
  90. /// Functor used for annotating entities with line number information.
  91. class PositionAnnotation {
  92. public:
  93. typedef void result_type;
  94. PositionAnnotation(Iterator first) : first(first) {
  95. // Intentionally left empty.
  96. }
  97. template<typename Entity, typename First, typename Last>
  98. result_type operator()(Entity& entity, First f, Last l) const {
  99. entity.setLineNumber(get_line(f));
  100. }
  101. private:
  102. std::string filename;
  103. Iterator const first;
  104. };
  105. /// A function used for annotating the entities with their position.
  106. phoenix::function<PositionAnnotation> annotate;
  107. /// Manages the expressions and their parsing externally.
  108. std::shared_ptr<storm::expressions::ExpressionManager> expressionManager;
  109. storm::parser::ExpressionParser expressionParser;
  110. /// Stores a mapping from location numbers to statements.
  111. std::vector<std::shared_ptr<storm::pgcl::Statement> > locationToStatement;
  112. /// Saves whether a loop statements was created.
  113. bool loopCreated = false;
  114. /// Saves whether a nondet statements was created.
  115. bool nondetCreated = false;
  116. /// Saves whether a observe statement was created.
  117. bool observeCreated = false;
  118. /// Stores the unique identifier of the currently parsed statement, starting at 1.
  119. std::size_t currentLocationNumber = 1;
  120. /// Sets the expression parser to a mode where it actually generates valid expressions.
  121. void enableExpressions();
  122. // Constructors for the single program parts. They just wrap the statement constructors and throw exceptions in case something unexpected was parsed.
  123. storm::pgcl::PgclProgram createProgram(std::string const& programName, boost::optional<std::vector<storm::expressions::Variable> > parameters, std::vector<std::shared_ptr<storm::pgcl::VariableDeclaration>> const& variableDeclarations, std::vector<std::shared_ptr<storm::pgcl::Statement> > const& statements);
  124. storm::expressions::Variable declareDoubleVariable(std::string const& variableName);
  125. std::shared_ptr<storm::pgcl::AssignmentStatement> createAssignmentStatement(std::string const& variableName, boost::variant<storm::expressions::Expression, storm::pgcl::UniformExpression> const& assignedExpression);
  126. std::shared_ptr<storm::pgcl::VariableDeclaration> createIntegerDeclarationStatement(std::string const& variableName, storm::expressions::Expression const& assignedExpression);
  127. std::shared_ptr<storm::pgcl::VariableDeclaration> createBooleanDeclarationStatement(std::string const& variableName, storm::expressions::Expression const& assignedExpression);
  128. std::shared_ptr<storm::pgcl::ObserveStatement> createObserveStatement(storm::pgcl::BooleanExpression const& condition);
  129. std::shared_ptr<storm::pgcl::IfStatement> createIfElseStatement(storm::pgcl::BooleanExpression const& condition, std::vector<std::shared_ptr<storm::pgcl::Statement> > const& if_body, boost::optional<std::vector<std::shared_ptr<storm::pgcl::Statement> > > const& else_body);
  130. std::shared_ptr<storm::pgcl::LoopStatement> createLoopStatement(storm::pgcl::BooleanExpression const& condition, std::vector<std::shared_ptr<storm::pgcl::Statement> > const& body);
  131. std::shared_ptr<storm::pgcl::NondeterministicBranch> createNondeterministicBranch(std::vector<std::shared_ptr<storm::pgcl::Statement> > const& left, std::vector<std::shared_ptr<storm::pgcl::Statement> > const& right);
  132. std::shared_ptr<storm::pgcl::ProbabilisticBranch> createProbabilisticBranch(storm::expressions::Expression const& probability, std::vector<std::shared_ptr<storm::pgcl::Statement> > const& left, std::vector<std::shared_ptr<storm::pgcl::Statement> > const& right);
  133. storm::pgcl::BooleanExpression createBooleanExpression(storm::expressions::Expression const& expression);
  134. storm::pgcl::UniformExpression createUniformExpression(int const& begin, int const& end);
  135. };
  136. } // namespace parser
  137. } // namespace storm