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

#pragma once
// Includes files for file input.
#include <fstream>
#include <memory>
#include <iomanip>
// Includes files for building and parsing the PGCL program
#include "storm/parser/SpiritParserDefinitions.h"
#include "storm/parser/SpiritErrorHandler.h"
#include "storm/parser/ExpressionParser.h"
#include "storm/storage/expressions/ExpressionManager.h"
#include "storm/storage/expressions/Expression.h"
#include "storm-pgcl/storage/pgcl/PgclProgram.h"
#include "storm-pgcl/storage/pgcl/AssignmentStatement.h"
#include "storm-pgcl/storage/pgcl/BooleanExpression.h"
#include "storm-pgcl/storage/pgcl/UniformExpression.h"
#include "storm-pgcl/storage/pgcl/IfStatement.h"
#include "storm-pgcl/storage/pgcl/LoopStatement.h"
#include "storm-pgcl/storage/pgcl/NondeterministicBranch.h"
#include "storm-pgcl/storage/pgcl/ObserveStatement.h"
#include "storm-pgcl/storage/pgcl/ProbabilisticBranch.h"
#include "storm-pgcl/storage/pgcl/Statement.h"
namespace storm {
namespace pgcl {
class IfStatement;
}
namespace parser {
class PgclParser : public qi::grammar<Iterator, storm::pgcl::PgclProgram(), Skipper> {
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<Iterator, storm::pgcl::PgclProgram(), Skipper> program;
qi::rule<Iterator, std::vector<std::shared_ptr<storm::pgcl::Statement> >(), Skipper> sequenceOfStatements;
qi::rule<Iterator, std::shared_ptr<storm::pgcl::Statement>(), Skipper> statement;
qi::rule<Iterator, std::shared_ptr<storm::pgcl::Statement>(), Skipper> simpleStatement;
qi::rule<Iterator, std::shared_ptr<storm::pgcl::Statement>(), Skipper> compoundStatement;
qi::rule<Iterator, std::shared_ptr<storm::pgcl::IfStatement>(), Skipper> ifElseStatement;
qi::rule<Iterator, std::shared_ptr<storm::pgcl::BranchStatement>(), Skipper> branchStatement;
qi::rule<Iterator, std::shared_ptr<storm::pgcl::LoopStatement>(), Skipper> loopStatement;
qi::rule<Iterator, std::shared_ptr<storm::pgcl::NondeterministicBranch>(), Skipper> nondeterministicBranch;
qi::rule<Iterator, std::shared_ptr<storm::pgcl::ProbabilisticBranch>(), Skipper> probabilisticBranch;
qi::rule<Iterator, std::shared_ptr<storm::pgcl::AssignmentStatement>(), Skipper> assignmentStatement;
qi::rule<Iterator, storm::expressions::Variable(), Skipper> declaration;
qi::rule<Iterator, std::shared_ptr<storm::pgcl::ObserveStatement>(), Skipper> observeStatement;
qi::rule<Iterator, storm::expressions::Expression(), Skipper> expression;
qi::rule<Iterator, storm::pgcl::BooleanExpression(), Skipper> booleanCondition;
qi::rule<Iterator, storm::pgcl::UniformExpression(), Skipper> uniformExpression;
qi::rule<Iterator, std::string(), Skipper> variableName;
qi::rule<Iterator, std::string(), Skipper> programName;
qi::rule<Iterator, std::vector<std::shared_ptr<storm::pgcl::VariableDeclaration>>(), Skipper> variableDeclarations;
qi::rule<Iterator, std::shared_ptr<storm::pgcl::VariableDeclaration>(), Skipper> integerDeclaration;
qi::rule<Iterator, std::shared_ptr<storm::pgcl::VariableDeclaration>(), Skipper> booleanDeclaration;
qi::rule<Iterator, storm::expressions::Variable(), Skipper> doubleDeclaration;
// An error handler function.
phoenix::function<SpiritErrorHandler> handler;
/// Denotes the invalid identifiers, which are later passed to the expression parser.
struct keywordsStruct : qi::symbols<char, uint_fast64_t> {
keywordsStruct() {
add
("while", 1)
("if", 2)
("observe", 3)
("int", 4)
("bool", 5)
("function", 6);
}
};
/// Initializes the invalid identifier struct.
keywordsStruct invalidIdentifiers;
/// Is used to store the identifiers of the PGCL program that are found while parsing.
qi::symbols<char, storm::expressions::Expression> 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<typename Entity, typename First, typename Last>
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<PositionAnnotation> annotate;
/// Manages the expressions and their parsing externally.
std::shared_ptr<storm::expressions::ExpressionManager> expressionManager;
storm::parser::ExpressionParser expressionParser;
/// Stores a mapping from location numbers to statements.
std::vector<std::shared_ptr<storm::pgcl::Statement> > 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<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);
storm::expressions::Variable declareDoubleVariable(std::string const& variableName);
std::shared_ptr<storm::pgcl::AssignmentStatement> createAssignmentStatement(std::string const& variableName, boost::variant<storm::expressions::Expression, storm::pgcl::UniformExpression> const& assignedExpression);
std::shared_ptr<storm::pgcl::VariableDeclaration> createIntegerDeclarationStatement(std::string const& variableName, storm::expressions::Expression const& assignedExpression);
std::shared_ptr<storm::pgcl::VariableDeclaration> createBooleanDeclarationStatement(std::string const& variableName, storm::expressions::Expression const& assignedExpression);
std::shared_ptr<storm::pgcl::ObserveStatement> createObserveStatement(storm::pgcl::BooleanExpression const& condition);
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);
std::shared_ptr<storm::pgcl::LoopStatement> createLoopStatement(storm::pgcl::BooleanExpression const& condition, std::vector<std::shared_ptr<storm::pgcl::Statement> > const& body);
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);
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);
storm::pgcl::BooleanExpression createBooleanExpression(storm::expressions::Expression const& expression);
storm::pgcl::UniformExpression createUniformExpression(int const& begin, int const& end);
};
} // namespace parser
} // namespace storm