Browse Source
Added ternary operator. Parsing standard PRISM models into the PRISM classes now works. Included tests for parsing stuff. ToDo: add remaining semantic checks for parsing/PRISM classes and fix explicit model adapter.
Added ternary operator. Parsing standard PRISM models into the PRISM classes now works. Included tests for parsing stuff. ToDo: add remaining semantic checks for parsing/PRISM classes and fix explicit model adapter.
Former-commit-id: cb37c98f1f
main
31 changed files with 1223 additions and 909 deletions
-
636src/parser/PrismParser.cpp
-
320src/parser/PrismParser.h
-
373src/parser/prismparser/PrismGrammar.cpp
-
282src/parser/prismparser/PrismGrammar.h
-
70src/parser/prismparser/PrismParser.cpp
-
36src/parser/prismparser/PrismParser.h
-
5src/storage/expressions/BaseExpression.cpp
-
2src/storage/expressions/BaseExpression.h
-
7src/storage/expressions/Expression.cpp
-
1src/storage/expressions/Expression.h
-
2src/storage/expressions/ExpressionVisitor.h
-
23src/storage/expressions/IdentifierSubstitutionVisitor.cpp
-
1src/storage/expressions/IdentifierSubstitutionVisitor.h
-
96src/storage/expressions/IfThenElseExpression.cpp
-
74src/storage/expressions/IfThenElseExpression.h
-
23src/storage/expressions/SubstitutionVisitor.cpp
-
1src/storage/expressions/SubstitutionVisitor.h
-
7src/storage/prism/Assignment.cpp
-
12src/storage/prism/Assignment.h
-
4src/storage/prism/BooleanVariable.cpp
-
12src/storage/prism/BooleanVariable.h
-
15src/storage/prism/Command.cpp
-
12src/storage/prism/Command.h
-
4src/storage/prism/IntegerVariable.cpp
-
11src/storage/prism/IntegerVariable.h
-
29src/storage/prism/Module.cpp
-
14src/storage/prism/Module.h
-
15src/storage/prism/Update.cpp
-
11src/storage/prism/Update.h
-
21test/functional/parser/PrismParserTest.cpp
-
13test/functional/storage/ExpressionTest.cpp
@ -0,0 +1,636 @@ |
|||
#include "src/parser/PrismParser.h"
|
|||
#include "src/exceptions/InvalidArgumentException.h"
|
|||
#include "src/exceptions/WrongFormatException.h"
|
|||
|
|||
namespace storm { |
|||
namespace parser { |
|||
storm::prism::Program PrismParser::parse(std::string const& filename, bool typeCheck) { |
|||
// Open file and initialize result.
|
|||
std::ifstream inputFileStream(filename, std::ios::in); |
|||
LOG_THROW(inputFileStream.good(), storm::exceptions::WrongFormatException, "Unable to read from file " << filename << "."); |
|||
|
|||
storm::prism::Program result; |
|||
|
|||
// Now try to parse the contents of the file.
|
|||
try { |
|||
std::string fileContent((std::istreambuf_iterator<char>(inputFileStream)), (std::istreambuf_iterator<char>())); |
|||
result = parseFromString(fileContent, filename, typeCheck); |
|||
} catch(std::exception& e) { |
|||
// In case of an exception properly close the file before passing exception.
|
|||
inputFileStream.close(); |
|||
throw e; |
|||
} |
|||
|
|||
// Close the stream in case everything went smoothly and return result.
|
|||
inputFileStream.close(); |
|||
return result; |
|||
} |
|||
|
|||
storm::prism::Program PrismParser::parseFromString(std::string const& input, std::string const& filename, bool typeCheck) { |
|||
PositionIteratorType first(input.begin()); |
|||
PositionIteratorType iter = first; |
|||
PositionIteratorType last(input.end()); |
|||
|
|||
// Create empty result;
|
|||
storm::prism::Program result; |
|||
|
|||
// Create grammar.
|
|||
storm::parser::PrismParser grammar(filename, first); |
|||
try { |
|||
// Now parse the content using phrase_parse in order to be able to supply a skipping parser.
|
|||
bool succeeded = qi::phrase_parse(iter, last, grammar, boost::spirit::ascii::space | qi::lit("//") >> *(qi::char_ - qi::eol) >> qi::eol, result); |
|||
LOG_THROW(succeeded, storm::exceptions::WrongFormatException, "Parsing failed in first pass."); |
|||
if (typeCheck) { |
|||
first = PositionIteratorType(input.begin()); |
|||
iter = first; |
|||
last = PositionIteratorType(input.end()); |
|||
grammar.moveToSecondRun(); |
|||
succeeded = qi::phrase_parse(iter, last, grammar, boost::spirit::ascii::space | qi::lit("//") >> *(qi::char_ - qi::eol) >> qi::eol, result); |
|||
LOG_THROW(succeeded, storm::exceptions::WrongFormatException, "Parsing failed in second pass."); |
|||
} |
|||
} catch (qi::expectation_failure<PositionIteratorType> const& e) { |
|||
// If the parser expected content different than the one provided, display information about the location of the error.
|
|||
std::size_t lineNumber = boost::spirit::get_line(e.first); |
|||
|
|||
// Now propagate exception.
|
|||
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << lineNumber << " of file " << filename << "."); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
PrismParser::PrismParser(std::string const& filename, Iterator first) : PrismParser::base_type(start), secondRun(false), allowDoubleLiteralsFlag(true), filename(filename), annotate(first) { |
|||
// Parse simple identifier.
|
|||
identifier %= qi::as_string[qi::raw[qi::lexeme[((qi::alpha | qi::char_('_')) >> *(qi::alnum | qi::char_('_')))]]][qi::_pass = phoenix::bind(&PrismParser::isValidIdentifier, phoenix::ref(*this), qi::_1)]; |
|||
identifier.name("identifier"); |
|||
|
|||
floorCeilExpression = ((qi::lit("floor")[qi::_a = true] | qi::lit("ceil")[qi::_a = false]) >> qi::lit("(") >> plusExpression >> qi::lit(")"))[phoenix::if_(qi::_a) [qi::_val = phoenix::bind(&PrismParser::createFloorExpression, phoenix::ref(*this), qi::_1)] .else_ [qi::_val = phoenix::bind(&PrismParser::createCeilExpression, phoenix::ref(*this), qi::_1)]]; |
|||
floorCeilExpression.name("floor/ceil expression"); |
|||
|
|||
minMaxExpression = ((qi::lit("min")[qi::_a = true] | qi::lit("max")[qi::_a = false]) >> qi::lit("(") >> plusExpression >> qi::lit(",") >> plusExpression >> qi::lit(")"))[phoenix::if_(qi::_a) [qi::_val = phoenix::bind(&PrismParser::createMinimumExpression, phoenix::ref(*this), qi::_1, qi::_2)] .else_ [qi::_val = phoenix::bind(&PrismParser::createMaximumExpression, phoenix::ref(*this), qi::_1, qi::_2)]]; |
|||
minMaxExpression.name("min/max expression"); |
|||
|
|||
identifierExpression = identifier[qi::_val = phoenix::bind(&PrismParser::getIdentifierExpression, phoenix::ref(*this), qi::_1)]; |
|||
identifierExpression.name("identifier expression"); |
|||
|
|||
literalExpression = qi::lit("true")[qi::_val = phoenix::bind(&PrismParser::createTrueExpression, phoenix::ref(*this))] | qi::lit("false")[qi::_val = phoenix::bind(&PrismParser::createFalseExpression, phoenix::ref(*this))] | strict_double[qi::_val = phoenix::bind(&PrismParser::createDoubleLiteralExpression, phoenix::ref(*this), qi::_1, qi::_pass)] | qi::int_[qi::_val = phoenix::bind(&PrismParser::createIntegerLiteralExpression, phoenix::ref(*this), qi::_1)]; |
|||
literalExpression.name("literal expression"); |
|||
|
|||
atomicExpression = minMaxExpression | floorCeilExpression | qi::lit("(") >> expression >> qi::lit(")") | literalExpression | identifierExpression; |
|||
atomicExpression.name("atomic expression"); |
|||
|
|||
unaryExpression = atomicExpression[qi::_val = qi::_1] | (qi::lit("!") >> atomicExpression)[qi::_val = phoenix::bind(&PrismParser::createNotExpression, phoenix::ref(*this), qi::_1)] | (qi::lit("-") >> atomicExpression)[qi::_val = phoenix::bind(&PrismParser::createMinusExpression, phoenix::ref(*this), qi::_1)]; |
|||
unaryExpression.name("unary expression"); |
|||
|
|||
multiplicationExpression = unaryExpression[qi::_val = qi::_1] >> *((qi::lit("*")[qi::_a = true] | qi::lit("/")[qi::_a = false]) >> unaryExpression[phoenix::if_(qi::_a) [qi::_val = phoenix::bind(&PrismParser::createMultExpression, phoenix::ref(*this), qi::_val, qi::_1)] .else_ [qi::_val = phoenix::bind(&PrismParser::createDivExpression, phoenix::ref(*this), qi::_val, qi::_1)]]); |
|||
multiplicationExpression.name("multiplication expression"); |
|||
|
|||
plusExpression = multiplicationExpression[qi::_val = qi::_1] >> *((qi::lit("+")[qi::_a = true] | qi::lit("-")[qi::_a = false]) >> multiplicationExpression)[phoenix::if_(qi::_a) [qi::_val = phoenix::bind(&PrismParser::createPlusExpression, phoenix::ref(*this), qi::_val, qi::_1)] .else_ [qi::_val = phoenix::bind(&PrismParser::createMinusExpression, phoenix::ref(*this), qi::_val, qi::_1)]]; |
|||
plusExpression.name("plus expression"); |
|||
|
|||
relativeExpression = (plusExpression >> qi::lit(">=") >> plusExpression)[qi::_val = phoenix::bind(&PrismParser::createGreaterOrEqualExpression, phoenix::ref(*this), qi::_1, qi::_2)] | (plusExpression >> qi::lit(">") >> plusExpression)[qi::_val = phoenix::bind(&PrismParser::createGreaterExpression, phoenix::ref(*this), qi::_1, qi::_2)] | (plusExpression >> qi::lit("<=") >> plusExpression)[qi::_val = phoenix::bind(&PrismParser::createLessOrEqualExpression, phoenix::ref(*this), qi::_1, qi::_2)] | (plusExpression >> qi::lit("<") >> plusExpression)[qi::_val = phoenix::bind(&PrismParser::createLessExpression, phoenix::ref(*this), qi::_1, qi::_2)] | (plusExpression >> qi::lit("=") >> plusExpression)[qi::_val = phoenix::bind(&PrismParser::createEqualsExpression, phoenix::ref(*this), qi::_1, qi::_2)] | (plusExpression >> qi::lit("!=") >> plusExpression)[qi::_val = phoenix::bind(&PrismParser::createNotEqualsExpression, phoenix::ref(*this), qi::_1, qi::_2)] | plusExpression[qi::_val = qi::_1]; |
|||
relativeExpression.name("relative expression"); |
|||
|
|||
andExpression = relativeExpression[qi::_val = qi::_1] >> *(qi::lit("&") >> relativeExpression)[qi::_val = phoenix::bind(&PrismParser::createAndExpression, phoenix::ref(*this), qi::_val, qi::_1)]; |
|||
andExpression.name("and expression"); |
|||
|
|||
orExpression = andExpression[qi::_val = qi::_1] >> *(qi::lit("|") >> andExpression)[qi::_val = phoenix::bind(&PrismParser::createOrExpression, phoenix::ref(*this), qi::_val, qi::_1)]; |
|||
orExpression.name("or expression"); |
|||
|
|||
iteExpression = orExpression[qi::_val = qi::_1] >> -(qi::lit("?") > orExpression > qi::lit(":") > orExpression)[qi::_val = phoenix::bind(&PrismParser::createIteExpression, phoenix::ref(*this), qi::_val, qi::_1, qi::_2)]; |
|||
iteExpression.name("if-then-else expression"); |
|||
|
|||
expression %= iteExpression; |
|||
expression.name("expression"); |
|||
|
|||
modelTypeDefinition %= modelType_; |
|||
modelTypeDefinition.name("model type"); |
|||
|
|||
undefinedBooleanConstantDefinition = ((qi::lit("const") >> qi::lit("bool")) > identifier > qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createUndefinedBooleanConstant, phoenix::ref(*this), qi::_1)]; |
|||
undefinedBooleanConstantDefinition.name("undefined boolean constant declaration"); |
|||
|
|||
undefinedIntegerConstantDefinition = ((qi::lit("const") >> qi::lit("int")) > identifier > qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createUndefinedIntegerConstant, phoenix::ref(*this), qi::_1)]; |
|||
undefinedIntegerConstantDefinition.name("undefined integer constant declaration"); |
|||
|
|||
undefinedDoubleConstantDefinition = ((qi::lit("const") >> qi::lit("double")) > identifier > qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createUndefinedDoubleConstant, phoenix::ref(*this), qi::_1)]; |
|||
undefinedDoubleConstantDefinition.name("undefined double constant definition"); |
|||
|
|||
undefinedConstantDefinition = (undefinedBooleanConstantDefinition | undefinedIntegerConstantDefinition | undefinedDoubleConstantDefinition); |
|||
undefinedConstantDefinition.name("undefined constant definition"); |
|||
|
|||
definedBooleanConstantDefinition = ((qi::lit("const") >> qi::lit("bool") >> identifier >> qi::lit("=")) > expression > qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createDefinedBooleanConstant, phoenix::ref(*this), qi::_1, qi::_2)]; |
|||
definedBooleanConstantDefinition.name("defined boolean constant declaration"); |
|||
|
|||
definedIntegerConstantDefinition = ((qi::lit("const") >> qi::lit("int") >> identifier >> qi::lit("=")) > expression >> qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createDefinedIntegerConstant, phoenix::ref(*this), qi::_1, qi::_2)]; |
|||
definedIntegerConstantDefinition.name("defined integer constant declaration"); |
|||
|
|||
definedDoubleConstantDefinition = ((qi::lit("const") >> qi::lit("double") >> identifier >> qi::lit("=")) > expression > qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createDefinedDoubleConstant, phoenix::ref(*this), qi::_1, qi::_2)]; |
|||
definedDoubleConstantDefinition.name("defined double constant declaration"); |
|||
|
|||
definedConstantDefinition %= (definedBooleanConstantDefinition | definedIntegerConstantDefinition | definedDoubleConstantDefinition); |
|||
definedConstantDefinition.name("defined constant definition"); |
|||
|
|||
formulaDefinition = (qi::lit("formula") > identifier > qi::lit("=") > expression > qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createFormula, phoenix::ref(*this), qi::_1, qi::_2)]; |
|||
formulaDefinition.name("formula definition"); |
|||
|
|||
booleanVariableDefinition = ((identifier >> qi::lit(":") >> qi::lit("bool")) > ((qi::lit("init") > expression) | qi::attr(storm::expressions::Expression::createFalse())) > qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createBooleanVariable, phoenix::ref(*this), qi::_1, qi::_2)]; |
|||
booleanVariableDefinition.name("boolean variable definition"); |
|||
|
|||
integerVariableDefinition = ((identifier >> qi::lit(":") >> qi::lit("[")[phoenix::bind(&PrismParser::allowDoubleLiterals, phoenix::ref(*this), false)]) > expression[qi::_a = qi::_1] > qi::lit("..") > expression > qi::lit("]")[phoenix::bind(&PrismParser::allowDoubleLiterals, phoenix::ref(*this), true)] > -(qi::lit("init") > expression[qi::_a = qi::_1]) > qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createIntegerVariable, phoenix::ref(*this), qi::_1, qi::_2, qi::_3, qi::_a)]; |
|||
integerVariableDefinition.name("integer variable definition"); |
|||
|
|||
variableDefinition = (booleanVariableDefinition[phoenix::push_back(qi::_r1, qi::_1)] | integerVariableDefinition[phoenix::push_back(qi::_r2, qi::_1)]); |
|||
variableDefinition.name("variable declaration"); |
|||
|
|||
globalVariableDefinition = (qi::lit("global") > (booleanVariableDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::globalBooleanVariables, qi::_r1), qi::_1)] | integerVariableDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::globalIntegerVariables, qi::_r1), qi::_1)])); |
|||
globalVariableDefinition.name("global variable declaration list"); |
|||
|
|||
programHeader = modelTypeDefinition[phoenix::bind(&GlobalProgramInformation::modelType, qi::_r1) = qi::_1] |
|||
> *(definedConstantDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::constants, qi::_r1), qi::_1)] | undefinedConstantDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::constants, qi::_r1), qi::_1)]) |
|||
> *(formulaDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::formulas, qi::_r1), qi::_1)]) |
|||
> *(globalVariableDefinition(qi::_r1)); |
|||
programHeader.name("program header"); |
|||
|
|||
stateRewardDefinition = (expression > qi::lit(":") > plusExpression >> qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createStateReward, phoenix::ref(*this), qi::_1, qi::_2)]; |
|||
stateRewardDefinition.name("state reward definition"); |
|||
|
|||
transitionRewardDefinition = (qi::lit("[") > -(identifier[qi::_a = qi::_1]) > qi::lit("]") > expression > qi::lit(":") > plusExpression > qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createTransitionReward, phoenix::ref(*this), qi::_a, qi::_2, qi::_3)]; |
|||
transitionRewardDefinition.name("transition reward definition"); |
|||
|
|||
rewardModelDefinition = (qi::lit("rewards") > qi::lit("\"") > identifier > qi::lit("\"") |
|||
> +( stateRewardDefinition[phoenix::push_back(qi::_a, qi::_1)] |
|||
| transitionRewardDefinition[phoenix::push_back(qi::_b, qi::_1)] |
|||
) |
|||
>> qi::lit("endrewards"))[qi::_val = phoenix::bind(&PrismParser::createRewardModel, phoenix::ref(*this), qi::_1, qi::_a, qi::_b)]; |
|||
rewardModelDefinition.name("reward model definition"); |
|||
|
|||
initialStatesConstruct = (qi::lit("init") > expression > qi::lit("endinit"))[qi::_pass = phoenix::bind(&PrismParser::addInitialStatesExpression, phoenix::ref(*this), qi::_1, qi::_r1)]; |
|||
initialStatesConstruct.name("initial construct"); |
|||
|
|||
labelDefinition = (qi::lit("label") > -qi::lit("\"") > identifier > -qi::lit("\"") > qi::lit("=") > expression >> qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createLabel, phoenix::ref(*this), qi::_1, qi::_2)]; |
|||
labelDefinition.name("label definition"); |
|||
|
|||
assignmentDefinition = (qi::lit("(") > identifier > qi::lit("'") > qi::lit("=") > expression > qi::lit(")"))[qi::_val = phoenix::bind(&PrismParser::createAssignment, phoenix::ref(*this), qi::_1, qi::_2)]; |
|||
assignmentDefinition.name("assignment"); |
|||
|
|||
assignmentDefinitionList %= +assignmentDefinition % "&"; |
|||
assignmentDefinitionList.name("assignment list"); |
|||
|
|||
updateDefinition = (((plusExpression > qi::lit(":")) | qi::attr(storm::expressions::Expression::createDoubleLiteral(1))) >> assignmentDefinitionList)[qi::_val = phoenix::bind(&PrismParser::createUpdate, phoenix::ref(*this), qi::_1, qi::_2, qi::_r1)]; |
|||
updateDefinition.name("update"); |
|||
|
|||
updateListDefinition %= +updateDefinition(qi::_r1) % "+"; |
|||
updateListDefinition.name("update list"); |
|||
|
|||
commandDefinition = (qi::lit("[") > -(identifier[qi::_a = qi::_1]) > qi::lit("]") > expression > qi::lit("->") > updateListDefinition(qi::_r1) > qi::lit(";"))[qi::_val = phoenix::bind(&PrismParser::createCommand, phoenix::ref(*this), qi::_a, qi::_2, qi::_3, qi::_r1)]; |
|||
commandDefinition.name("command definition"); |
|||
|
|||
moduleDefinition = ((qi::lit("module") >> identifier >> *(variableDefinition(qi::_a, qi::_b))) > +commandDefinition(qi::_r1) > qi::lit("endmodule"))[qi::_val = phoenix::bind(&PrismParser::createModule, phoenix::ref(*this), qi::_1, qi::_a, qi::_b, qi::_2, qi::_r1)]; |
|||
moduleDefinition.name("module definition"); |
|||
|
|||
moduleRenaming = ((qi::lit("module") >> identifier >> qi::lit("=")) > identifier > qi::lit("[") |
|||
> ((identifier > qi::lit("=") > identifier)[phoenix::insert(qi::_a, phoenix::construct<std::pair<std::string,std::string>>(qi::_1, qi::_2))] % ",") > qi::lit("]") |
|||
> qi::lit("endmodule"))[qi::_val = phoenix::bind(&PrismParser::createRenamedModule, phoenix::ref(*this), qi::_1, qi::_2, qi::_a, qi::_r1)]; |
|||
moduleRenaming.name("module definition via renaming"); |
|||
|
|||
moduleDefinitionList %= +(moduleRenaming(qi::_r1) | moduleDefinition(qi::_r1))[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::modules, qi::_r1), qi::_1)]; |
|||
moduleDefinitionList.name("module list"); |
|||
|
|||
start = (qi::eps > programHeader(qi::_a) > moduleDefinitionList(qi::_a) > *(initialStatesConstruct(qi::_a) | rewardModelDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::rewardModels, qi::_a), qi::_1)] | labelDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::labels, qi::_a), qi::_1)] | formulaDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::formulas, qi::_a), qi::_1)]) > qi::eoi)[qi::_val = phoenix::bind(&PrismParser::createProgram, phoenix::ref(*this), qi::_a)]; |
|||
start.name("probabilistic program"); |
|||
|
|||
// Enable error reporting.
|
|||
qi::on_error<qi::fail>(expression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); |
|||
qi::on_error<qi::fail>(iteExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); |
|||
qi::on_error<qi::fail>(orExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); |
|||
qi::on_error<qi::fail>(andExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); |
|||
qi::on_error<qi::fail>(relativeExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); |
|||
qi::on_error<qi::fail>(plusExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); |
|||
qi::on_error<qi::fail>(multiplicationExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); |
|||
qi::on_error<qi::fail>(unaryExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); |
|||
qi::on_error<qi::fail>(atomicExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); |
|||
qi::on_error<qi::fail>(literalExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); |
|||
qi::on_error<qi::fail>(identifierExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); |
|||
qi::on_error<qi::fail>(minMaxExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); |
|||
qi::on_error<qi::fail>(floorCeilExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); |
|||
|
|||
// Enable location tracking for important entities.
|
|||
auto setLocationInfoFunction = this->annotate(qi::_val, qi::_1, qi::_3); |
|||
qi::on_success(undefinedBooleanConstantDefinition, setLocationInfoFunction); |
|||
qi::on_success(undefinedIntegerConstantDefinition, setLocationInfoFunction); |
|||
qi::on_success(undefinedDoubleConstantDefinition, setLocationInfoFunction); |
|||
qi::on_success(definedBooleanConstantDefinition, setLocationInfoFunction); |
|||
qi::on_success(definedIntegerConstantDefinition, setLocationInfoFunction); |
|||
qi::on_success(definedDoubleConstantDefinition, setLocationInfoFunction); |
|||
qi::on_success(booleanVariableDefinition, setLocationInfoFunction); |
|||
qi::on_success(integerVariableDefinition, setLocationInfoFunction); |
|||
qi::on_success(moduleDefinition, setLocationInfoFunction); |
|||
qi::on_success(moduleRenaming, setLocationInfoFunction); |
|||
qi::on_success(formulaDefinition, setLocationInfoFunction); |
|||
qi::on_success(rewardModelDefinition, setLocationInfoFunction); |
|||
qi::on_success(labelDefinition, setLocationInfoFunction); |
|||
qi::on_success(commandDefinition, setLocationInfoFunction); |
|||
qi::on_success(updateDefinition, setLocationInfoFunction); |
|||
qi::on_success(assignmentDefinition, setLocationInfoFunction); |
|||
} |
|||
|
|||
void PrismParser::moveToSecondRun() { |
|||
this->secondRun = true; |
|||
} |
|||
|
|||
void PrismParser::allowDoubleLiterals(bool flag) { |
|||
this->allowDoubleLiteralsFlag = flag; |
|||
} |
|||
|
|||
std::string const& PrismParser::getFilename() const { |
|||
return this->filename; |
|||
} |
|||
|
|||
bool PrismParser::isValidIdentifier(std::string const& identifier) { |
|||
if (this->keywords_.find(identifier) != nullptr) { |
|||
return false; |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
bool PrismParser::addInitialStatesExpression(storm::expressions::Expression initialStatesExpression, GlobalProgramInformation& globalProgramInformation) { |
|||
LOG_THROW(!globalProgramInformation.hasInitialStatesExpression, storm::exceptions::InvalidArgumentException, "Program must not define two initial constructs."); |
|||
if (globalProgramInformation.hasInitialStatesExpression) { |
|||
return false; |
|||
} |
|||
globalProgramInformation.hasInitialStatesExpression = true; |
|||
globalProgramInformation.initialStatesExpression = initialStatesExpression; |
|||
return true; |
|||
} |
|||
|
|||
storm::expressions::Expression PrismParser::createIteExpression(storm::expressions::Expression e1, storm::expressions::Expression e2, storm::expressions::Expression e3) const { |
|||
if (!this->secondRun) { |
|||
return storm::expressions::Expression::createFalse(); |
|||
} else { |
|||
return e1.ite(e2, e3); |
|||
} |
|||
} |
|||
|
|||
storm::expressions::Expression PrismParser::createOrExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const { |
|||
if (!this->secondRun) { |
|||
return storm::expressions::Expression::createFalse(); |
|||
} else { |
|||
return e1 || e2; |
|||
} |
|||
} |
|||
|
|||
storm::expressions::Expression PrismParser::createAndExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const { |
|||
if (!this->secondRun) { |
|||
return storm::expressions::Expression::createFalse(); |
|||
} else { |
|||
return e1 && e2; |
|||
} |
|||
} |
|||
|
|||
storm::expressions::Expression PrismParser::createGreaterExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const { |
|||
if (!this->secondRun) { |
|||
return storm::expressions::Expression::createFalse(); |
|||
} else { |
|||
return e1 > e2; |
|||
} |
|||
} |
|||
|
|||
storm::expressions::Expression PrismParser::createGreaterOrEqualExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const { |
|||
if (!this->secondRun) { |
|||
return storm::expressions::Expression::createFalse(); |
|||
} else { |
|||
return e1 >= e2; |
|||
} |
|||
} |
|||
|
|||
storm::expressions::Expression PrismParser::createLessExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const { |
|||
if (!this->secondRun) { |
|||
return storm::expressions::Expression::createFalse(); |
|||
} else { |
|||
return e1 < e2; |
|||
} |
|||
} |
|||
|
|||
storm::expressions::Expression PrismParser::createLessOrEqualExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const { |
|||
if (!this->secondRun) { |
|||
return storm::expressions::Expression::createFalse(); |
|||
} else { |
|||
return e1 <= e2; |
|||
} |
|||
} |
|||
|
|||
storm::expressions::Expression PrismParser::createEqualsExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const { |
|||
if (!this->secondRun) { |
|||
return storm::expressions::Expression::createFalse(); |
|||
} else { |
|||
return e1 == e2; |
|||
} |
|||
} |
|||
|
|||
storm::expressions::Expression PrismParser::createNotEqualsExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const { |
|||
if (!this->secondRun) { |
|||
return storm::expressions::Expression::createFalse(); |
|||
} else { |
|||
return e1 != e2; |
|||
} |
|||
} |
|||
|
|||
storm::expressions::Expression PrismParser::createPlusExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const { |
|||
if (!this->secondRun) { |
|||
return storm::expressions::Expression::createFalse(); |
|||
} else { |
|||
return e1 + e2; |
|||
} |
|||
} |
|||
|
|||
storm::expressions::Expression PrismParser::createMinusExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const { |
|||
if (!this->secondRun) { |
|||
return storm::expressions::Expression::createFalse(); |
|||
} else { |
|||
return e1 - e2; |
|||
} |
|||
} |
|||
|
|||
storm::expressions::Expression PrismParser::createMultExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const { |
|||
if (!this->secondRun) { |
|||
return storm::expressions::Expression::createFalse(); |
|||
} else { |
|||
return e1 * e2; |
|||
} |
|||
} |
|||
|
|||
storm::expressions::Expression PrismParser::createDivExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const { |
|||
if (!this->secondRun) { |
|||
return storm::expressions::Expression::createFalse(); |
|||
} else { |
|||
return e1 / e2; |
|||
} |
|||
} |
|||
|
|||
storm::expressions::Expression PrismParser::createNotExpression(storm::expressions::Expression e1) const { |
|||
if (!this->secondRun) { |
|||
return storm::expressions::Expression::createFalse(); |
|||
} else { |
|||
return !e1; |
|||
} |
|||
} |
|||
|
|||
storm::expressions::Expression PrismParser::createMinusExpression(storm::expressions::Expression e1) const { |
|||
if (!this->secondRun) { |
|||
return storm::expressions::Expression::createFalse(); |
|||
} else { |
|||
return -e1; |
|||
} |
|||
} |
|||
|
|||
storm::expressions::Expression PrismParser::createTrueExpression() const { |
|||
if (!this->secondRun) { |
|||
return storm::expressions::Expression::createFalse(); |
|||
} else { |
|||
return storm::expressions::Expression::createTrue(); |
|||
} |
|||
} |
|||
|
|||
storm::expressions::Expression PrismParser::createFalseExpression() const { |
|||
if (!this->secondRun) { |
|||
return storm::expressions::Expression::createFalse(); |
|||
} else { |
|||
return storm::expressions::Expression::createFalse(); |
|||
} |
|||
} |
|||
|
|||
storm::expressions::Expression PrismParser::createDoubleLiteralExpression(double value, bool& pass) const { |
|||
// If we are not supposed to accept double expressions, we reject it by setting pass to false.
|
|||
if (!this->allowDoubleLiteralsFlag) { |
|||
pass = false; |
|||
} |
|||
|
|||
if (!this->secondRun) { |
|||
return storm::expressions::Expression::createFalse(); |
|||
} else { |
|||
return storm::expressions::Expression::createDoubleLiteral(value); |
|||
} |
|||
} |
|||
|
|||
storm::expressions::Expression PrismParser::createIntegerLiteralExpression(int value) const { |
|||
if (!this->secondRun) { |
|||
return storm::expressions::Expression::createFalse(); |
|||
} else { |
|||
return storm::expressions::Expression::createIntegerLiteral(static_cast<int_fast64_t>(value)); |
|||
} |
|||
} |
|||
|
|||
storm::expressions::Expression PrismParser::createMinimumExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const { |
|||
if (!this->secondRun) { |
|||
return storm::expressions::Expression::createFalse(); |
|||
} else { |
|||
return storm::expressions::Expression::minimum(e1, e2); |
|||
} |
|||
} |
|||
|
|||
storm::expressions::Expression PrismParser::createMaximumExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const { |
|||
if (!this->secondRun) { |
|||
return storm::expressions::Expression::createFalse(); |
|||
} else { |
|||
return storm::expressions::Expression::maximum(e1, e2); |
|||
} |
|||
} |
|||
|
|||
storm::expressions::Expression PrismParser::createFloorExpression(storm::expressions::Expression e1) const { |
|||
if (!this->secondRun) { |
|||
return storm::expressions::Expression::createFalse(); |
|||
} else { |
|||
return e1.floor(); |
|||
} |
|||
} |
|||
|
|||
storm::expressions::Expression PrismParser::createCeilExpression(storm::expressions::Expression e1) const { |
|||
if (!this->secondRun) { |
|||
return storm::expressions::Expression::createFalse(); |
|||
} else { |
|||
return e1.ceil(); |
|||
} |
|||
} |
|||
|
|||
storm::expressions::Expression PrismParser::getIdentifierExpression(std::string const& identifier) const { |
|||
if (!this->secondRun) { |
|||
return storm::expressions::Expression::createFalse(); |
|||
} else { |
|||
storm::expressions::Expression const* expression = this->identifiers_.find(identifier); |
|||
LOG_THROW(expression != nullptr, storm::exceptions::WrongFormatException, "Undeclared identifier '" << identifier << "'."); |
|||
return *expression; |
|||
} |
|||
} |
|||
|
|||
storm::prism::Constant PrismParser::createUndefinedBooleanConstant(std::string const& newConstant) const { |
|||
this->identifiers_.add(newConstant, storm::expressions::Expression::createBooleanConstant(newConstant)); |
|||
return storm::prism::Constant(storm::prism::Constant::ConstantType::Bool, newConstant, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::Constant PrismParser::createUndefinedIntegerConstant(std::string const& newConstant) const { |
|||
this->identifiers_.add(newConstant, storm::expressions::Expression::createIntegerConstant(newConstant)); |
|||
return storm::prism::Constant(storm::prism::Constant::ConstantType::Integer, newConstant, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::Constant PrismParser::createUndefinedDoubleConstant(std::string const& newConstant) const { |
|||
this->identifiers_.add(newConstant, storm::expressions::Expression::createDoubleConstant(newConstant)); |
|||
return storm::prism::Constant(storm::prism::Constant::ConstantType::Double, newConstant, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::Constant PrismParser::createDefinedBooleanConstant(std::string const& newConstant, storm::expressions::Expression expression) const { |
|||
this->identifiers_.add(newConstant, storm::expressions::Expression::createBooleanConstant(newConstant)); |
|||
return storm::prism::Constant(storm::prism::Constant::ConstantType::Bool, newConstant, expression, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::Constant PrismParser::createDefinedIntegerConstant(std::string const& newConstant, storm::expressions::Expression expression) const { |
|||
this->identifiers_.add(newConstant, storm::expressions::Expression::createIntegerConstant(newConstant)); |
|||
return storm::prism::Constant(storm::prism::Constant::ConstantType::Integer, newConstant, expression, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::Constant PrismParser::createDefinedDoubleConstant(std::string const& newConstant, storm::expressions::Expression expression) const { |
|||
this->identifiers_.add(newConstant, storm::expressions::Expression::createDoubleConstant(newConstant)); |
|||
return storm::prism::Constant(storm::prism::Constant::ConstantType::Double, newConstant, expression, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::Formula PrismParser::createFormula(std::string const& formulaName, storm::expressions::Expression expression) const { |
|||
if (this->secondRun) { |
|||
this->identifiers_.add(formulaName, expression); |
|||
} |
|||
return storm::prism::Formula(formulaName, expression, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::Label PrismParser::createLabel(std::string const& labelName, storm::expressions::Expression expression) const { |
|||
return storm::prism::Label(labelName, expression, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::RewardModel PrismParser::createRewardModel(std::string const& rewardModelName, std::vector<storm::prism::StateReward> const& stateRewards, std::vector<storm::prism::TransitionReward> const& transitionRewards) const { |
|||
return storm::prism::RewardModel(rewardModelName, stateRewards, transitionRewards, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::StateReward PrismParser::createStateReward(storm::expressions::Expression statePredicateExpression, storm::expressions::Expression rewardValueExpression) const { |
|||
return storm::prism::StateReward(statePredicateExpression, rewardValueExpression, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::TransitionReward PrismParser::createTransitionReward(std::string const& actionName, storm::expressions::Expression statePredicateExpression, storm::expressions::Expression rewardValueExpression) const { |
|||
return storm::prism::TransitionReward(actionName, statePredicateExpression, rewardValueExpression, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::Assignment PrismParser::createAssignment(std::string const& variableName, storm::expressions::Expression assignedExpression) const { |
|||
return storm::prism::Assignment(variableName, assignedExpression, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::Update PrismParser::createUpdate(storm::expressions::Expression likelihoodExpression, std::vector<storm::prism::Assignment> const& assignments, GlobalProgramInformation& globalProgramInformation) const { |
|||
++globalProgramInformation.currentUpdateIndex; |
|||
return storm::prism::Update(globalProgramInformation.currentUpdateIndex - 1, likelihoodExpression, assignments, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::Command PrismParser::createCommand(std::string const& actionName, storm::expressions::Expression guardExpression, std::vector<storm::prism::Update> const& updates, GlobalProgramInformation& globalProgramInformation) const { |
|||
++globalProgramInformation.currentCommandIndex; |
|||
return storm::prism::Command(globalProgramInformation.currentCommandIndex - 1, actionName, guardExpression, updates, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::BooleanVariable PrismParser::createBooleanVariable(std::string const& variableName, storm::expressions::Expression initialValueExpression) const { |
|||
this->identifiers_.add(variableName, storm::expressions::Expression::createBooleanVariable(variableName)); |
|||
return storm::prism::BooleanVariable(variableName, initialValueExpression, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::IntegerVariable PrismParser::createIntegerVariable(std::string const& variableName, storm::expressions::Expression lowerBoundExpression, storm::expressions::Expression upperBoundExpression, storm::expressions::Expression initialValueExpression) const { |
|||
this->identifiers_.add(variableName, storm::expressions::Expression::createIntegerVariable(variableName)); |
|||
return storm::prism::IntegerVariable(variableName, lowerBoundExpression, upperBoundExpression, initialValueExpression, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::Module PrismParser::createModule(std::string const& moduleName, std::vector<storm::prism::BooleanVariable> const& booleanVariables, std::vector<storm::prism::IntegerVariable> const& integerVariables, std::vector<storm::prism::Command> const& commands, GlobalProgramInformation& globalProgramInformation) const { |
|||
globalProgramInformation.moduleToIndexMap[moduleName] = globalProgramInformation.modules.size(); |
|||
return storm::prism::Module(moduleName, booleanVariables, integerVariables, commands, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::Module PrismParser::createRenamedModule(std::string const& newModuleName, std::string const& oldModuleName, std::map<std::string, std::string> const& renaming, GlobalProgramInformation& globalProgramInformation) const { |
|||
// Check whether the module to rename actually exists.
|
|||
auto const& moduleIndexPair = globalProgramInformation.moduleToIndexMap.find(oldModuleName); |
|||
LOG_THROW(moduleIndexPair != globalProgramInformation.moduleToIndexMap.end(), storm::exceptions::WrongFormatException, "No module named '" << oldModuleName << "' to rename."); |
|||
storm::prism::Module const& moduleToRename = globalProgramInformation.modules[moduleIndexPair->second]; |
|||
|
|||
if (!this->secondRun) { |
|||
// Register all (renamed) variables for later use.
|
|||
for (auto const& variable : moduleToRename.getBooleanVariables()) { |
|||
auto const& renamingPair = renaming.find(variable.getName()); |
|||
LOG_THROW(renamingPair != renaming.end(), storm::exceptions::WrongFormatException, "Boolean variable '" << variable.getName() << " was not renamed."); |
|||
this->identifiers_.add(renamingPair->second, storm::expressions::Expression::createBooleanVariable(renamingPair->second)); |
|||
} |
|||
for (auto const& variable : moduleToRename.getIntegerVariables()) { |
|||
auto const& renamingPair = renaming.find(variable.getName()); |
|||
LOG_THROW(renamingPair != renaming.end(), storm::exceptions::WrongFormatException, "Integer variable '" << variable.getName() << " was not renamed."); |
|||
this->identifiers_.add(renamingPair->second, storm::expressions::Expression::createIntegerVariable(renamingPair->second)); |
|||
} |
|||
|
|||
// Return a dummy module in the first pass.
|
|||
return storm::prism::Module(); |
|||
} else { |
|||
// Add a mapping from the new module name to its (future) index.
|
|||
globalProgramInformation.moduleToIndexMap[newModuleName] = globalProgramInformation.modules.size(); |
|||
|
|||
// Create a mapping from identifiers to the expressions they need to be replaced with.
|
|||
std::map<std::string, storm::expressions::Expression> expressionRenaming; |
|||
for (auto const& namePair : renaming) { |
|||
storm::expressions::Expression const* substitutedExpression = this->identifiers_.find(namePair.second); |
|||
// If the mapped-to-value is an expression, we need to replace it.
|
|||
if (substitutedExpression != nullptr) { |
|||
expressionRenaming.emplace(namePair.first, *substitutedExpression); |
|||
} |
|||
} |
|||
|
|||
// Rename the boolean variables.
|
|||
std::vector<storm::prism::BooleanVariable> booleanVariables; |
|||
for (auto const& variable : moduleToRename.getBooleanVariables()) { |
|||
auto const& renamingPair = renaming.find(variable.getName()); |
|||
LOG_THROW(renamingPair != renaming.end(), storm::exceptions::WrongFormatException, "Boolean variable '" << variable.getName() << " was not renamed."); |
|||
|
|||
booleanVariables.push_back(storm::prism::BooleanVariable(renamingPair->second, variable.getInitialValueExpression().substitute<std::map>(expressionRenaming), this->getFilename(), get_line(qi::_1))); |
|||
} |
|||
|
|||
// Rename the integer variables.
|
|||
std::vector<storm::prism::IntegerVariable> integerVariables; |
|||
for (auto const& variable : moduleToRename.getIntegerVariables()) { |
|||
auto const& renamingPair = renaming.find(variable.getName()); |
|||
LOG_THROW(renamingPair != renaming.end(), storm::exceptions::WrongFormatException, "Integer variable '" << variable.getName() << " was not renamed."); |
|||
|
|||
integerVariables.push_back(storm::prism::IntegerVariable(renamingPair->second, variable.getLowerBoundExpression().substitute<std::map>(expressionRenaming), variable.getUpperBoundExpression().substitute<std::map>(expressionRenaming), variable.getInitialValueExpression().substitute<std::map>(expressionRenaming), this->getFilename(), get_line(qi::_1))); |
|||
} |
|||
|
|||
// Rename commands.
|
|||
std::vector<storm::prism::Command> commands; |
|||
for (auto const& command : moduleToRename.getCommands()) { |
|||
std::vector<storm::prism::Update> updates; |
|||
for (auto const& update : command.getUpdates()) { |
|||
std::vector<storm::prism::Assignment> assignments; |
|||
for (auto const& assignment : update.getAssignments()) { |
|||
auto const& renamingPair = renaming.find(assignment.getVariableName()); |
|||
if (renamingPair != renaming.end()) { |
|||
assignments.emplace_back(renamingPair->second, assignment.getExpression().substitute<std::map>(expressionRenaming), this->getFilename(), get_line(qi::_1)); |
|||
} else { |
|||
assignments.emplace_back(assignment.getVariableName(), assignment.getExpression().substitute<std::map>(expressionRenaming), this->getFilename(), get_line(qi::_1)); |
|||
} |
|||
} |
|||
updates.emplace_back(globalProgramInformation.currentUpdateIndex, update.getLikelihoodExpression().substitute<std::map>(expressionRenaming), assignments, this->getFilename(), get_line(qi::_1)); |
|||
++globalProgramInformation.currentUpdateIndex; |
|||
} |
|||
|
|||
std::string newActionName = command.getActionName(); |
|||
auto const& renamingPair = renaming.find(command.getActionName()); |
|||
if (renamingPair != renaming.end()) { |
|||
newActionName = renamingPair->second; |
|||
} |
|||
|
|||
commands.emplace_back(globalProgramInformation.currentCommandIndex, newActionName, command.getGuardExpression().substitute<std::map>(expressionRenaming), updates, this->getFilename(), get_line(qi::_1)); |
|||
++globalProgramInformation.currentCommandIndex; |
|||
} |
|||
|
|||
return storm::prism::Module(newModuleName, booleanVariables, integerVariables, commands, this->getFilename()); |
|||
} |
|||
} |
|||
|
|||
storm::prism::Program PrismParser::createProgram(GlobalProgramInformation const& globalProgramInformation) const { |
|||
return storm::prism::Program(globalProgramInformation.modelType, globalProgramInformation.constants, globalProgramInformation.globalBooleanVariables, globalProgramInformation.globalIntegerVariables, globalProgramInformation.formulas, globalProgramInformation.modules, globalProgramInformation.rewardModels, globalProgramInformation.hasInitialStatesExpression, globalProgramInformation.initialStatesExpression, globalProgramInformation.labels, this->getFilename()); |
|||
} |
|||
} // namespace parser
|
|||
} // namespace storm
|
@ -0,0 +1,320 @@ |
|||
#ifndef STORM_PARSER_PRISMPARSER_H_ |
|||
#define STORM_PARSER_PRISMPARSER_H_ |
|||
|
|||
// Include files for file input. |
|||
#include <fstream> |
|||
#include <memory> |
|||
#include <iomanip> |
|||
|
|||
// Include boost spirit. |
|||
#define BOOST_SPIRIT_USE_PHOENIX_V3 |
|||
#include <boost/typeof/typeof.hpp> |
|||
#include <boost/spirit/include/qi.hpp> |
|||
#include <boost/spirit/include/phoenix.hpp> |
|||
#include <boost/spirit/include/support_line_pos_iterator.hpp> |
|||
#include <boost/spirit/home/classic/iterator/position_iterator.hpp> |
|||
|
|||
namespace qi = boost::spirit::qi; |
|||
namespace phoenix = boost::phoenix; |
|||
|
|||
typedef std::string::const_iterator BaseIteratorType; |
|||
typedef boost::spirit::line_pos_iterator<BaseIteratorType> PositionIteratorType; |
|||
typedef PositionIteratorType Iterator; |
|||
typedef BOOST_TYPEOF(boost::spirit::ascii::space | qi::lit("//") >> *(qi::char_ - qi::eol) >> qi::eol) Skipper; |
|||
typedef BOOST_TYPEOF(qi::lit("//") >> *(qi::char_ - qi::eol) >> qi::eol | boost::spirit::ascii::space) Skipper2; |
|||
|
|||
#include "src/storage/prism/Program.h" |
|||
#include "src/storage/expressions/Expression.h" |
|||
#include "src/exceptions/ExceptionMacros.h" |
|||
|
|||
namespace storm { |
|||
namespace parser { |
|||
class GlobalProgramInformation { |
|||
public: |
|||
// Default construct the header information. |
|||
GlobalProgramInformation() = default; |
|||
|
|||
// Members for all essential information that needs to be collected. |
|||
storm::prism::Program::ModelType modelType; |
|||
std::vector<storm::prism::Constant> constants; |
|||
std::vector<storm::prism::Formula> formulas; |
|||
std::vector<storm::prism::BooleanVariable> globalBooleanVariables; |
|||
std::vector<storm::prism::IntegerVariable> globalIntegerVariables; |
|||
std::map<std::string, uint_fast64_t> moduleToIndexMap; |
|||
std::vector<storm::prism::Module> modules; |
|||
std::vector<storm::prism::RewardModel> rewardModels; |
|||
std::vector<storm::prism::Label> labels; |
|||
storm::expressions::Expression initialStatesExpression; |
|||
bool hasInitialStatesExpression; |
|||
|
|||
// Counters to provide unique indexing for commands and updates. |
|||
uint_fast64_t currentCommandIndex; |
|||
uint_fast64_t currentUpdateIndex; |
|||
}; |
|||
|
|||
class PrismParser : public qi::grammar<Iterator, storm::prism::Program(), qi::locals<GlobalProgramInformation>, Skipper> { |
|||
public: |
|||
/*! |
|||
* Parses the given file into the PRISM storage classes assuming it complies with the PRISM syntax. |
|||
* |
|||
* @param filename the name of the file to parse. |
|||
* @param typeCheck Sets whether the expressions are generated and therefore typechecked. |
|||
* @return The resulting PRISM program. |
|||
*/ |
|||
static storm::prism::Program parse(std::string const& filename, bool typeCheck = true); |
|||
|
|||
/*! |
|||
* Parses the given input stream into the PRISM storage classes assuming it complies with the PRISM syntax. |
|||
* |
|||
* @param input The input string to parse. |
|||
* @param filename The name of the file from which the input was read. |
|||
* @param typeCheck Sets whether the expressions are generated and therefore typechecked. |
|||
* @return The resulting PRISM program. |
|||
*/ |
|||
static storm::prism::Program parseFromString(std::string const& input, std::string const& filename, bool typeCheck = true); |
|||
|
|||
private: |
|||
struct modelTypeStruct : qi::symbols<char, storm::prism::Program::ModelType> { |
|||
modelTypeStruct() { |
|||
add |
|||
("dtmc", storm::prism::Program::ModelType::DTMC) |
|||
("ctmc", storm::prism::Program::ModelType::CTMC) |
|||
("mdp", storm::prism::Program::ModelType::MDP) |
|||
("ctmdp", storm::prism::Program::ModelType::CTMDP) |
|||
("ma", storm::prism::Program::ModelType::MA); |
|||
} |
|||
}; |
|||
|
|||
struct keywordsStruct : qi::symbols<char, bool> { |
|||
keywordsStruct() { |
|||
add |
|||
("dtmc", 1) |
|||
("ctmc", 2) |
|||
("mdp", 3) |
|||
("ctmdp", 4) |
|||
("ma", 5) |
|||
("const", 6) |
|||
("int", 7) |
|||
("bool", 8) |
|||
("module", 9) |
|||
("endmodule", 10) |
|||
("rewards", 11) |
|||
("endrewards", 12) |
|||
("true", 13) |
|||
("min", 14) |
|||
("max", 15) |
|||
("floor", 16) |
|||
("ceil", 17) |
|||
("init", 18) |
|||
("endinit", 19); |
|||
} |
|||
}; |
|||
|
|||
// Functor used for displaying error information. |
|||
struct ErrorHandler { |
|||
typedef qi::error_handler_result result_type; |
|||
|
|||
template<typename T1, typename T2, typename T3, typename T4> |
|||
qi::error_handler_result operator()(T1 b, T2 e, T3 where, T4 const& what) const { |
|||
// LOG4CPLUS_ERROR(logger, "Error: expecting " << what << " in line " << get_line(where) << " at column " << get_column(b, where, 4) << "."); |
|||
std::cerr << "Error: expecting " << what << " in line " << get_line(where) << "." << std::endl; |
|||
T3 end(where); |
|||
while (end != e && *end != '\r' && *end != '\n') { |
|||
++end; |
|||
} |
|||
std::cerr << "Error: expecting " << what << " in line " << get_line(where) << ": \n" << std::string(get_line_start(b, where), end) << " ... \n" << std::setw(std::distance(b, where)) << '^' << "---- here\n"; |
|||
return qi::fail; |
|||
} |
|||
}; |
|||
|
|||
// 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; |
|||
}; |
|||
|
|||
/*! |
|||
* Creates a grammar for the given filename and the iterator to the first input to parse. |
|||
* |
|||
* @param filename The filename that is to be read. This is used for proper error reporting. |
|||
* @param first The iterator to the beginning of the input. |
|||
*/ |
|||
PrismParser(std::string const& filename, Iterator first); |
|||
|
|||
/*! |
|||
* Sets an internal flag that indicates the second run is now taking place. |
|||
*/ |
|||
void moveToSecondRun(); |
|||
|
|||
// A flag that stores whether the grammar is currently doing the second run. |
|||
bool secondRun; |
|||
|
|||
/*! |
|||
* Sets whether doubles literals are allowed in the parsed expression. |
|||
* |
|||
* @param flag Indicates whether to allow or forbid double literals in the parsed expression. |
|||
*/ |
|||
void allowDoubleLiterals(bool flag); |
|||
|
|||
// A flag that stores wether to allow or forbid double literals in parsed expressions. |
|||
bool allowDoubleLiteralsFlag; |
|||
|
|||
// The name of the file being parsed. |
|||
std::string filename; |
|||
|
|||
/*! |
|||
* Retrieves the name of the file currently being parsed. |
|||
* |
|||
* @return The name of the file currently being parsed. |
|||
*/ |
|||
std::string const& getFilename() const; |
|||
|
|||
// A function used for annotating the entities with their position. |
|||
phoenix::function<ErrorHandler> handler; |
|||
phoenix::function<PositionAnnotation> annotate; |
|||
|
|||
// The starting point of the grammar. |
|||
qi::rule<Iterator, storm::prism::Program(), qi::locals<GlobalProgramInformation>, Skipper> start; |
|||
|
|||
// Rules for model type. |
|||
qi::rule<Iterator, storm::prism::Program::ModelType(), Skipper> modelTypeDefinition; |
|||
|
|||
// Rules for parsing the program header. |
|||
qi::rule<Iterator, qi::unused_type(GlobalProgramInformation&), Skipper> programHeader; |
|||
qi::rule<Iterator, storm::prism::Constant(), Skipper> undefinedConstantDefinition; |
|||
qi::rule<Iterator, storm::prism::Constant(), Skipper> undefinedBooleanConstantDefinition; |
|||
qi::rule<Iterator, storm::prism::Constant(), Skipper> undefinedIntegerConstantDefinition; |
|||
qi::rule<Iterator, storm::prism::Constant(), Skipper> undefinedDoubleConstantDefinition; |
|||
qi::rule<Iterator, storm::prism::Constant(), Skipper> definedConstantDefinition; |
|||
qi::rule<Iterator, storm::prism::Constant(), Skipper> definedBooleanConstantDefinition; |
|||
qi::rule<Iterator, storm::prism::Constant(), Skipper> definedIntegerConstantDefinition; |
|||
qi::rule<Iterator, storm::prism::Constant(), Skipper> definedDoubleConstantDefinition; |
|||
|
|||
// Rules for global variable definitions. |
|||
qi::rule<Iterator, qi::unused_type(GlobalProgramInformation&), Skipper> globalVariableDefinition; |
|||
qi::rule<Iterator, qi::unused_type(GlobalProgramInformation&), Skipper> globalBooleanVariableDefinition; |
|||
qi::rule<Iterator, qi::unused_type(GlobalProgramInformation&), Skipper> globalIntegerVariableDefinition; |
|||
|
|||
// Rules for modules definition. |
|||
qi::rule<Iterator, std::vector<storm::prism::Module>(GlobalProgramInformation&), Skipper> moduleDefinitionList; |
|||
qi::rule<Iterator, storm::prism::Module(GlobalProgramInformation&), qi::locals<std::vector<storm::prism::BooleanVariable>, std::vector<storm::prism::IntegerVariable>>, Skipper> moduleDefinition; |
|||
qi::rule<Iterator, storm::prism::Module(GlobalProgramInformation&), qi::locals<std::map<std::string, std::string>>, Skipper> moduleRenaming; |
|||
|
|||
// Rules for variable definitions. |
|||
qi::rule<Iterator, qi::unused_type(std::vector<storm::prism::BooleanVariable>&, std::vector<storm::prism::IntegerVariable>&), Skipper> variableDefinition; |
|||
qi::rule<Iterator, storm::prism::BooleanVariable(), Skipper> booleanVariableDefinition; |
|||
qi::rule<Iterator, storm::prism::IntegerVariable(), qi::locals<storm::expressions::Expression>, Skipper> integerVariableDefinition; |
|||
|
|||
// Rules for command definitions. |
|||
qi::rule<Iterator, storm::prism::Command(GlobalProgramInformation&), qi::locals<std::string>, Skipper> commandDefinition; |
|||
qi::rule<Iterator, std::vector<storm::prism::Update>(GlobalProgramInformation&), Skipper> updateListDefinition; |
|||
qi::rule<Iterator, storm::prism::Update(GlobalProgramInformation&), Skipper> updateDefinition; |
|||
qi::rule<Iterator, std::vector<storm::prism::Assignment>(), Skipper> assignmentDefinitionList; |
|||
qi::rule<Iterator, storm::prism::Assignment(), Skipper> assignmentDefinition; |
|||
|
|||
// Rules for reward definitions. |
|||
qi::rule<Iterator, storm::prism::RewardModel(), qi::locals<std::vector<storm::prism::StateReward>, std::vector<storm::prism::TransitionReward>>, Skipper> rewardModelDefinition; |
|||
qi::rule<Iterator, storm::prism::StateReward(), Skipper> stateRewardDefinition; |
|||
qi::rule<Iterator, storm::prism::TransitionReward(), qi::locals<std::string>, Skipper> transitionRewardDefinition; |
|||
|
|||
// Rules for initial states expression. |
|||
qi::rule<Iterator, qi::unused_type(GlobalProgramInformation&), Skipper> initialStatesConstruct; |
|||
|
|||
// Rules for label definitions. |
|||
qi::rule<Iterator, storm::prism::Label(), Skipper> labelDefinition; |
|||
|
|||
// Rules for formula definitions. |
|||
qi::rule<Iterator, storm::prism::Formula(), Skipper> formulaDefinition; |
|||
|
|||
// Rules for identifier parsing. |
|||
qi::rule<Iterator, std::string(), Skipper> identifier; |
|||
|
|||
// Rules for parsing a composed expression. |
|||
qi::rule<Iterator, storm::expressions::Expression(), Skipper> expression; |
|||
qi::rule<Iterator, storm::expressions::Expression(), Skipper> iteExpression; |
|||
qi::rule<Iterator, storm::expressions::Expression(), Skipper> orExpression; |
|||
qi::rule<Iterator, storm::expressions::Expression(), Skipper> andExpression; |
|||
qi::rule<Iterator, storm::expressions::Expression(), Skipper> relativeExpression; |
|||
qi::rule<Iterator, storm::expressions::Expression(), qi::locals<bool>, Skipper> plusExpression; |
|||
qi::rule<Iterator, storm::expressions::Expression(), qi::locals<bool>, Skipper> multiplicationExpression; |
|||
qi::rule<Iterator, storm::expressions::Expression(), Skipper> unaryExpression; |
|||
qi::rule<Iterator, storm::expressions::Expression(), Skipper> atomicExpression; |
|||
qi::rule<Iterator, storm::expressions::Expression(), Skipper> literalExpression; |
|||
qi::rule<Iterator, storm::expressions::Expression(), Skipper> identifierExpression; |
|||
qi::rule<Iterator, storm::expressions::Expression(), qi::locals<bool>, Skipper> minMaxExpression; |
|||
qi::rule<Iterator, storm::expressions::Expression(), qi::locals<bool>, Skipper> floorCeilExpression; |
|||
|
|||
// Parser that is used to recognize doubles only (as opposed to Spirit's double_ parser). |
|||
boost::spirit::qi::real_parser<double, boost::spirit::qi::strict_real_policies<double>> strict_double; |
|||
|
|||
// Parsers that recognize special keywords and model types. |
|||
storm::parser::PrismParser::keywordsStruct keywords_; |
|||
storm::parser::PrismParser::modelTypeStruct modelType_; |
|||
qi::symbols<char, storm::expressions::Expression> identifiers_; |
|||
|
|||
// Helper methods used in the grammar. |
|||
bool isValidIdentifier(std::string const& identifier); |
|||
bool addInitialStatesExpression(storm::expressions::Expression initialStatesExpression, GlobalProgramInformation& globalProgramInformation); |
|||
|
|||
storm::expressions::Expression createIteExpression(storm::expressions::Expression e1, storm::expressions::Expression e2, storm::expressions::Expression e3) const; |
|||
storm::expressions::Expression createOrExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const; |
|||
storm::expressions::Expression createAndExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const; |
|||
storm::expressions::Expression createGreaterExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const; |
|||
storm::expressions::Expression createGreaterOrEqualExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const; |
|||
storm::expressions::Expression createLessExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const; |
|||
storm::expressions::Expression createLessOrEqualExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const; |
|||
storm::expressions::Expression createEqualsExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const; |
|||
storm::expressions::Expression createNotEqualsExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const; |
|||
storm::expressions::Expression createPlusExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const; |
|||
storm::expressions::Expression createMinusExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const; |
|||
storm::expressions::Expression createMultExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const; |
|||
storm::expressions::Expression createDivExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const; |
|||
storm::expressions::Expression createNotExpression(storm::expressions::Expression e1) const; |
|||
storm::expressions::Expression createMinusExpression(storm::expressions::Expression e1) const; |
|||
storm::expressions::Expression createTrueExpression() const; |
|||
storm::expressions::Expression createFalseExpression() const; |
|||
storm::expressions::Expression createDoubleLiteralExpression(double value, bool& pass) const; |
|||
storm::expressions::Expression createIntegerLiteralExpression(int value) const; |
|||
storm::expressions::Expression createMinimumExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const; |
|||
storm::expressions::Expression createMaximumExpression(storm::expressions::Expression e1, storm::expressions::Expression e2) const; |
|||
storm::expressions::Expression createFloorExpression(storm::expressions::Expression e1) const; |
|||
storm::expressions::Expression createCeilExpression(storm::expressions::Expression e1) const; |
|||
storm::expressions::Expression getIdentifierExpression(std::string const& identifier) const; |
|||
|
|||
storm::prism::Constant createUndefinedBooleanConstant(std::string const& newConstant) const; |
|||
storm::prism::Constant createUndefinedIntegerConstant(std::string const& newConstant) const; |
|||
storm::prism::Constant createUndefinedDoubleConstant(std::string const& newConstant) const; |
|||
storm::prism::Constant createDefinedBooleanConstant(std::string const& newConstant, storm::expressions::Expression expression) const; |
|||
storm::prism::Constant createDefinedIntegerConstant(std::string const& newConstant, storm::expressions::Expression expression) const; |
|||
storm::prism::Constant createDefinedDoubleConstant(std::string const& newConstant, storm::expressions::Expression expression) const; |
|||
storm::prism::Formula createFormula(std::string const& formulaName, storm::expressions::Expression expression) const; |
|||
storm::prism::Label createLabel(std::string const& labelName, storm::expressions::Expression expression) const; |
|||
storm::prism::RewardModel createRewardModel(std::string const& rewardModelName, std::vector<storm::prism::StateReward> const& stateRewards, std::vector<storm::prism::TransitionReward> const& transitionRewards) const; |
|||
storm::prism::StateReward createStateReward(storm::expressions::Expression statePredicateExpression, storm::expressions::Expression rewardValueExpression) const; |
|||
storm::prism::TransitionReward createTransitionReward(std::string const& actionName, storm::expressions::Expression statePredicateExpression, storm::expressions::Expression rewardValueExpression) const; |
|||
storm::prism::Assignment createAssignment(std::string const& variableName, storm::expressions::Expression assignedExpression) const; |
|||
storm::prism::Update createUpdate(storm::expressions::Expression likelihoodExpression, std::vector<storm::prism::Assignment> const& assignments, GlobalProgramInformation& globalProgramInformation) const; |
|||
storm::prism::Command createCommand(std::string const& actionName, storm::expressions::Expression guardExpression, std::vector<storm::prism::Update> const& updates, GlobalProgramInformation& globalProgramInformation) const; |
|||
storm::prism::BooleanVariable createBooleanVariable(std::string const& variableName, storm::expressions::Expression initialValueExpression) const; |
|||
storm::prism::IntegerVariable createIntegerVariable(std::string const& variableName, storm::expressions::Expression lowerBoundExpression, storm::expressions::Expression upperBoundExpression, storm::expressions::Expression initialValueExpression) const; |
|||
storm::prism::Module createModule(std::string const& moduleName, std::vector<storm::prism::BooleanVariable> const& booleanVariables, std::vector<storm::prism::IntegerVariable> const& integerVariables, std::vector<storm::prism::Command> const& commands, GlobalProgramInformation& globalProgramInformation) const; |
|||
storm::prism::Module createRenamedModule(std::string const& newModuleName, std::string const& oldModuleName, std::map<std::string, std::string> const& renaming, GlobalProgramInformation& globalProgramInformation) const; |
|||
storm::prism::Program createProgram(GlobalProgramInformation const& globalProgramInformation) const; |
|||
}; |
|||
} // namespace parser |
|||
} // namespace storm |
|||
|
|||
#endif /* STORM_PARSER_PRISMPARSER_H_ */ |
|||
|
@ -1,373 +0,0 @@ |
|||
// #define BOOST_SPIRIT_DEBUG
|
|||
#include "src/parser/prismparser/PrismGrammar.h"
|
|||
#include "src/exceptions/InvalidArgumentException.h"
|
|||
#include "src/exceptions/WrongFormatException.h"
|
|||
|
|||
namespace storm { |
|||
namespace parser { |
|||
namespace prism { |
|||
PrismGrammar::PrismGrammar(std::string const& filename, Iterator first) : PrismGrammar::base_type(start), doExpressionGeneration(false), filename(filename), annotate(first) { |
|||
// Parse simple identifier.
|
|||
identifier %= qi::as_string[qi::raw[qi::lexeme[((qi::alpha | qi::char_('_')) >> *(qi::alnum | qi::char_('_')))]]][qi::_pass = phoenix::bind(&PrismGrammar::isValidIdentifier, phoenix::ref(*this), qi::_1)]; |
|||
identifier.name("identifier"); |
|||
|
|||
setExpressionGeneration(doExpressionGeneration); |
|||
|
|||
modelTypeDefinition %= modelType_; |
|||
modelTypeDefinition.name("model type"); |
|||
|
|||
undefinedBooleanConstantDefinition = ((qi::lit("const") >> qi::lit("bool")) > identifier > qi::lit(";"))[qi::_val = phoenix::bind(&PrismGrammar::createUndefinedBooleanConstant, phoenix::ref(*this), qi::_1)]; |
|||
undefinedBooleanConstantDefinition.name("undefined boolean constant declaration"); |
|||
|
|||
undefinedIntegerConstantDefinition = ((qi::lit("const") >> qi::lit("int")) > identifier > qi::lit(";"))[qi::_val = phoenix::bind(&PrismGrammar::createUndefinedIntegerConstant, phoenix::ref(*this), qi::_1)]; |
|||
undefinedIntegerConstantDefinition.name("undefined integer constant declaration"); |
|||
|
|||
undefinedDoubleConstantDefinition = ((qi::lit("const") >> qi::lit("double")) > identifier > qi::lit(";"))[qi::_val = phoenix::bind(&PrismGrammar::createUndefinedDoubleConstant, phoenix::ref(*this), qi::_1)]; |
|||
undefinedDoubleConstantDefinition.name("undefined double constant definition"); |
|||
|
|||
undefinedConstantDefinition = (undefinedBooleanConstantDefinition | undefinedIntegerConstantDefinition | undefinedDoubleConstantDefinition); |
|||
undefinedConstantDefinition.name("undefined constant definition"); |
|||
|
|||
definedBooleanConstantDefinition = ((qi::lit("const") >> qi::lit("bool") >> identifier >> qi::lit("=")) > expression > qi::lit(";"))[qi::_val = phoenix::bind(&PrismGrammar::createDefinedBooleanConstant, phoenix::ref(*this), qi::_1, qi::_2)]; |
|||
definedBooleanConstantDefinition.name("defined boolean constant declaration"); |
|||
|
|||
definedIntegerConstantDefinition = ((qi::lit("const") >> qi::lit("int") >> identifier >> qi::lit("=")) > expression >> qi::lit(";"))[qi::_val = phoenix::bind(&PrismGrammar::createDefinedIntegerConstant, phoenix::ref(*this), qi::_1, qi::_2)]; |
|||
definedIntegerConstantDefinition.name("defined integer constant declaration"); |
|||
|
|||
definedDoubleConstantDefinition = ((qi::lit("const") >> qi::lit("double") >> identifier >> qi::lit("=")) > expression > qi::lit(";"))[qi::_val = phoenix::bind(&PrismGrammar::createDefinedDoubleConstant, phoenix::ref(*this), qi::_1, qi::_2)]; |
|||
definedDoubleConstantDefinition.name("defined double constant declaration"); |
|||
|
|||
definedConstantDefinition %= (definedBooleanConstantDefinition | definedIntegerConstantDefinition | definedDoubleConstantDefinition); |
|||
definedConstantDefinition.name("defined constant definition"); |
|||
|
|||
formulaDefinition = (qi::lit("formula") > identifier > qi::lit("=") > expression > qi::lit(";"))[qi::_val = phoenix::bind(&PrismGrammar::createFormula, phoenix::ref(*this), qi::_1, qi::_2)]; |
|||
formulaDefinition.name("formula definition"); |
|||
|
|||
booleanVariableDefinition = ((identifier >> qi::lit(":") >> qi::lit("bool")) > ((qi::lit("init") > expression) | qi::attr(storm::expressions::Expression::createFalse())) > qi::lit(";"))[qi::_val = phoenix::bind(&PrismGrammar::createBooleanVariable, phoenix::ref(*this), qi::_1, qi::_2)]; |
|||
booleanVariableDefinition.name("boolean variable definition"); |
|||
|
|||
integerVariableDefinition = ((identifier >> qi::lit(":") >> qi::lit("[")[phoenix::bind(&PrismGrammar::allowDoubleLiterals, phoenix::ref(*this), false)]) > expression[qi::_a = qi::_1] > qi::lit("..") > expression > qi::lit("]")[phoenix::bind(&PrismGrammar::allowDoubleLiterals, phoenix::ref(*this), true)] > -(qi::lit("init") > expression[qi::_a = qi::_1]) > qi::lit(";"))[qi::_val = phoenix::bind(&PrismGrammar::createIntegerVariable, phoenix::ref(*this), qi::_1, qi::_2, qi::_3, qi::_a)]; |
|||
integerVariableDefinition.name("integer variable definition"); |
|||
|
|||
variableDefinition = (booleanVariableDefinition[phoenix::push_back(qi::_r1, qi::_1)] | integerVariableDefinition[phoenix::push_back(qi::_r2, qi::_1)]); |
|||
variableDefinition.name("variable declaration"); |
|||
|
|||
globalVariableDefinition = (qi::lit("global") > (booleanVariableDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::globalBooleanVariables, qi::_r1), qi::_1)] | integerVariableDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::globalIntegerVariables, qi::_r1), qi::_1)])); |
|||
globalVariableDefinition.name("global variable declaration list"); |
|||
|
|||
programHeader = modelTypeDefinition[phoenix::bind(&GlobalProgramInformation::modelType, qi::_r1) = qi::_1] |
|||
> *(definedConstantDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::constants, qi::_r1), qi::_1)] | undefinedConstantDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::constants, qi::_r1), qi::_1)]) |
|||
> *(formulaDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::formulas, qi::_r1), qi::_1)]) |
|||
> *(globalVariableDefinition(qi::_r1)); |
|||
programHeader.name("program header"); |
|||
|
|||
stateRewardDefinition = (expression > qi::lit(":") > plusExpression >> qi::lit(";"))[qi::_val = phoenix::bind(&PrismGrammar::createStateReward, phoenix::ref(*this), qi::_1, qi::_2)]; |
|||
stateRewardDefinition.name("state reward definition"); |
|||
|
|||
transitionRewardDefinition = (qi::lit("[") > -(identifier[qi::_a = qi::_1]) > qi::lit("]") > expression > qi::lit(":") > plusExpression > qi::lit(";"))[qi::_val = phoenix::bind(&PrismGrammar::createTransitionReward, phoenix::ref(*this), qi::_a, qi::_2, qi::_3)]; |
|||
transitionRewardDefinition.name("transition reward definition"); |
|||
|
|||
rewardModelDefinition = (qi::lit("rewards") > qi::lit("\"") > identifier > qi::lit("\"") |
|||
> +( stateRewardDefinition[phoenix::push_back(qi::_a, qi::_1)] |
|||
| transitionRewardDefinition[phoenix::push_back(qi::_b, qi::_1)] |
|||
) |
|||
>> qi::lit("endrewards"))[qi::_val = phoenix::bind(&PrismGrammar::createRewardModel, phoenix::ref(*this), qi::_1, qi::_a, qi::_b)]; |
|||
rewardModelDefinition.name("reward model definition"); |
|||
|
|||
initialStatesConstruct = (qi::lit("init") > expression > qi::lit("endinit"))[qi::_pass = phoenix::bind(&PrismGrammar::addInitialStatesExpression, phoenix::ref(*this), qi::_1, qi::_r1)]; |
|||
initialStatesConstruct.name("initial construct"); |
|||
|
|||
labelDefinition = (qi::lit("label") > -qi::lit("\"") > identifier > -qi::lit("\"") > qi::lit("=") > expression >> qi::lit(";"))[qi::_val = phoenix::bind(&PrismGrammar::createLabel, phoenix::ref(*this), qi::_1, qi::_2)]; |
|||
labelDefinition.name("label definition"); |
|||
|
|||
assignmentDefinition = (qi::lit("(") > identifier > qi::lit("'") > qi::lit("=") > expression > qi::lit(")"))[qi::_val = phoenix::bind(&PrismGrammar::createAssignment, phoenix::ref(*this), qi::_1, qi::_2)]; |
|||
assignmentDefinition.name("assignment"); |
|||
|
|||
assignmentDefinitionList %= +assignmentDefinition % "&"; |
|||
assignmentDefinitionList.name("assignment list"); |
|||
|
|||
updateDefinition = (((plusExpression > qi::lit(":")) | qi::attr(storm::expressions::Expression::createDoubleLiteral(1))) >> assignmentDefinitionList)[qi::_val = phoenix::bind(&PrismGrammar::createUpdate, phoenix::ref(*this), qi::_1, qi::_2, qi::_r1)]; |
|||
updateDefinition.name("update"); |
|||
|
|||
updateListDefinition %= +updateDefinition(qi::_r1) % "+"; |
|||
updateListDefinition.name("update list"); |
|||
|
|||
commandDefinition = (qi::lit("[") > -(identifier[qi::_a = qi::_1]) > qi::lit("]") > expression > qi::lit("->") > updateListDefinition(qi::_r1) > qi::lit(";"))[qi::_val = phoenix::bind(&PrismGrammar::createCommand, phoenix::ref(*this), qi::_a, qi::_2, qi::_3, qi::_r1)]; |
|||
commandDefinition.name("command definition"); |
|||
|
|||
moduleDefinition = ((qi::lit("module") >> identifier >> *(variableDefinition(qi::_a, qi::_b))) > +commandDefinition(qi::_r1) > qi::lit("endmodule"))[qi::_val = phoenix::bind(&PrismGrammar::createModule, phoenix::ref(*this), qi::_1, qi::_a, qi::_b, qi::_2, qi::_r1)]; |
|||
moduleDefinition.name("module definition"); |
|||
|
|||
moduleRenaming = ((qi::lit("module") >> identifier >> qi::lit("=")) > identifier > qi::lit("[") |
|||
> ((identifier > qi::lit("=") > identifier)[phoenix::insert(qi::_a, phoenix::construct<std::pair<std::string,std::string>>(qi::_1, qi::_2))] % ",") > qi::lit("]") |
|||
> qi::lit("endmodule"))[qi::_val = phoenix::bind(&PrismGrammar::createRenamedModule, phoenix::ref(*this), qi::_1, qi::_2, qi::_a, qi::_r1)]; |
|||
moduleRenaming.name("module definition via renaming"); |
|||
|
|||
moduleDefinitionList %= +(moduleRenaming(qi::_r1) | moduleDefinition(qi::_r1))[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::modules, qi::_r1), qi::_1)]; |
|||
moduleDefinitionList.name("module list"); |
|||
|
|||
start = (qi::eps > programHeader(qi::_a) > moduleDefinitionList(qi::_a) > *(initialStatesConstruct(qi::_a) | rewardModelDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::rewardModels, qi::_a), qi::_1)] | labelDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::labels, qi::_a), qi::_1)]) > qi::eoi)[qi::_val = phoenix::bind(&PrismGrammar::createProgram, phoenix::ref(*this), qi::_a)]; |
|||
start.name("probabilistic program"); |
|||
|
|||
// Enable location tracking for important entities.
|
|||
auto setLocationInfoFunction = this->annotate(qi::_val, qi::_1, qi::_3); |
|||
qi::on_success(undefinedBooleanConstantDefinition, setLocationInfoFunction); |
|||
qi::on_success(undefinedIntegerConstantDefinition, setLocationInfoFunction); |
|||
qi::on_success(undefinedDoubleConstantDefinition, setLocationInfoFunction); |
|||
qi::on_success(definedBooleanConstantDefinition, setLocationInfoFunction); |
|||
qi::on_success(definedIntegerConstantDefinition, setLocationInfoFunction); |
|||
qi::on_success(definedDoubleConstantDefinition, setLocationInfoFunction); |
|||
qi::on_success(booleanVariableDefinition, setLocationInfoFunction); |
|||
qi::on_success(integerVariableDefinition, setLocationInfoFunction); |
|||
qi::on_success(moduleDefinition, setLocationInfoFunction); |
|||
qi::on_success(moduleRenaming, setLocationInfoFunction); |
|||
qi::on_success(formulaDefinition, setLocationInfoFunction); |
|||
qi::on_success(rewardModelDefinition, setLocationInfoFunction); |
|||
qi::on_success(labelDefinition, setLocationInfoFunction); |
|||
qi::on_success(commandDefinition, setLocationInfoFunction); |
|||
qi::on_success(updateDefinition, setLocationInfoFunction); |
|||
qi::on_success(assignmentDefinition, setLocationInfoFunction); |
|||
} |
|||
|
|||
void PrismGrammar::setExpressionGeneration(bool doExpressionGeneration) { |
|||
if (doExpressionGeneration) { |
|||
floorCeilExpression = ((qi::lit("floor")[qi::_a = true] | qi::lit("ceil")[qi::_a = false]) >> qi::lit("(") >> plusExpression >> qi::lit(")"))[phoenix::if_(qi::_a) [qi::_val = phoenix::bind(&storm::expressions::Expression::floor, qi::_1)] .else_ [qi::_val = phoenix::bind(&storm::expressions::Expression::ceil, qi::_1)]]; |
|||
floorCeilExpression.name("floor/ceil expression"); |
|||
|
|||
minMaxExpression = ((qi::lit("min")[qi::_a = true] | qi::lit("max")[qi::_a = false]) >> qi::lit("(") >> plusExpression >> qi::lit(",") >> plusExpression >> qi::lit(")"))[phoenix::if_(qi::_a) [qi::_val = phoenix::bind(&storm::expressions::Expression::minimum, qi::_1, qi::_2)] .else_ [qi::_val = phoenix::bind(&storm::expressions::Expression::maximum, qi::_1, qi::_2)]]; |
|||
minMaxExpression.name("min/max expression"); |
|||
|
|||
identifierExpression = identifier[qi::_val = phoenix::bind(&PrismGrammar::getIdentifierExpression, phoenix::ref(*this), qi::_1)]; |
|||
identifierExpression.name("identifier expression"); |
|||
|
|||
literalExpression = qi::lit("true")[qi::_val = phoenix::bind(&storm::expressions::Expression::createTrue)] | qi::lit("false")[qi::_val = phoenix::bind(&storm::expressions::Expression::createFalse)] | strict_double[qi::_val = phoenix::bind(&storm::expressions::Expression::createDoubleLiteral, qi::_1)] | qi::int_[qi::_val = phoenix::bind(&storm::expressions::Expression::createIntegerLiteral, qi::_1)]; |
|||
literalExpression.name("literal expression"); |
|||
|
|||
atomicExpression = minMaxExpression | floorCeilExpression | qi::lit("(") >> expression >> qi::lit(")") | literalExpression | identifierExpression; |
|||
atomicExpression.name("atomic expression"); |
|||
|
|||
unaryExpression = atomicExpression[qi::_val = qi::_1] | (qi::lit("!") >> atomicExpression)[qi::_val = !qi::_1] | (qi::lit("-") >> atomicExpression)[qi::_val = -qi::_1]; |
|||
unaryExpression.name("unary expression"); |
|||
|
|||
multiplicationExpression = unaryExpression[qi::_val = qi::_1] >> *((qi::lit("*")[qi::_a = true] | qi::lit("/")[qi::_a = false]) >> unaryExpression[phoenix::if_(qi::_a) [qi::_val = qi::_val * qi::_1] .else_ [qi::_val = qi::_val / qi::_1]]); |
|||
multiplicationExpression.name("multiplication expression"); |
|||
|
|||
plusExpression = multiplicationExpression[qi::_val = qi::_1] >> *((qi::lit("+")[qi::_a = true] | qi::lit("-")[qi::_a = false]) >> multiplicationExpression)[phoenix::if_(qi::_a) [qi::_val = qi::_val + qi::_1] .else_ [qi::_val = qi::_val - qi::_1]]; |
|||
plusExpression.name("plus expression"); |
|||
|
|||
relativeExpression = (plusExpression >> qi::lit(">=") >> plusExpression)[qi::_val = qi::_1 >= qi::_1] | (plusExpression >> qi::lit(">") >> plusExpression)[qi::_val = qi::_1 > qi::_2] | (plusExpression >> qi::lit("<=") >> plusExpression)[qi::_val = qi::_1 <= qi::_2] | (plusExpression >> qi::lit("<") >> plusExpression)[qi::_val = qi::_1 < qi::_2] | (plusExpression >> qi::lit("=") >> plusExpression)[qi::_val = qi::_1 == qi::_2] | (plusExpression >> qi::lit("!=") >> plusExpression)[qi::_val = qi::_1 != qi::_2] | plusExpression[qi::_val = qi::_1]; |
|||
relativeExpression.name("relative expression"); |
|||
|
|||
andExpression = relativeExpression[qi::_val = qi::_1] >> *(qi::lit("&") >> relativeExpression)[qi::_val = qi::_val && qi::_1]; |
|||
andExpression.name("and expression"); |
|||
|
|||
orExpression = andExpression[qi::_val = qi::_1] >> *(qi::lit("|") >> andExpression)[qi::_val = qi::_val || qi::_1]; |
|||
orExpression.name("or expression"); |
|||
|
|||
expression %= orExpression; |
|||
expression.name("expression"); |
|||
} else { |
|||
floorCeilExpression = ((qi::lit("floor") | qi::lit("ceil")) >> qi::lit("(") >> plusExpression >> qi::lit(")"))[qi::_val = phoenix::bind(&storm::expressions::Expression::createFalse)]; |
|||
floorCeilExpression.name("floor/ceil expression"); |
|||
|
|||
minMaxExpression = ((qi::lit("min") | qi::lit("max")) >> qi::lit("(") >> plusExpression >> qi::lit(",") >> plusExpression >> qi::lit(")"))[qi::_val = phoenix::bind(&storm::expressions::Expression::createFalse)]; |
|||
minMaxExpression.name("min/max expression"); |
|||
|
|||
identifierExpression = identifier[qi::_val = phoenix::construct<storm::expressions::Expression>(), qi::_pass = phoenix::bind(&PrismGrammar::isValidIdentifier, phoenix::ref(*this), qi::_1)]; |
|||
identifierExpression.name("identifier expression"); |
|||
|
|||
literalExpression = (qi::lit("true") | qi::lit("false") | strict_double | qi::int_)[qi::_val = phoenix::bind(&storm::expressions::Expression::createFalse)]; |
|||
literalExpression.name("literal expression"); |
|||
|
|||
atomicExpression = (minMaxExpression | floorCeilExpression | qi::lit("(") >> expression >> qi::lit(")") | literalExpression | identifierExpression)[qi::_val = phoenix::bind(&storm::expressions::Expression::createFalse)]; |
|||
atomicExpression.name("atomic expression"); |
|||
|
|||
unaryExpression = (atomicExpression | (qi::lit("!") >> atomicExpression) | (qi::lit("-") >> atomicExpression))[qi::_val = phoenix::bind(&storm::expressions::Expression::createFalse)]; |
|||
unaryExpression.name("unary expression"); |
|||
|
|||
multiplicationExpression = (unaryExpression >> *((qi::lit("*") | qi::lit("/")) >> unaryExpression))[qi::_val = phoenix::bind(&storm::expressions::Expression::createFalse)]; |
|||
multiplicationExpression.name("multiplication expression"); |
|||
|
|||
plusExpression = (multiplicationExpression >> *((qi::lit("+") | qi::lit("-")) >> multiplicationExpression))[qi::_val = phoenix::bind(&storm::expressions::Expression::createFalse)]; |
|||
plusExpression.name("plus expression"); |
|||
|
|||
relativeExpression = ((plusExpression >> qi::lit(">=") >> plusExpression) | (plusExpression >> qi::lit(">") >> plusExpression) | (plusExpression >> qi::lit("<=") >> plusExpression) | (plusExpression >> qi::lit("<") >> plusExpression) | (plusExpression >> qi::lit("=") >> plusExpression) | (plusExpression >> qi::lit("!=") >> plusExpression) | plusExpression)[qi::_val = phoenix::bind(&storm::expressions::Expression::createFalse)]; |
|||
relativeExpression.name("relative expression"); |
|||
|
|||
andExpression = (relativeExpression >> *(qi::lit("&") >> relativeExpression))[qi::_val = phoenix::bind(&storm::expressions::Expression::createFalse)]; |
|||
andExpression.name("and expression"); |
|||
|
|||
orExpression = (andExpression >> *(qi::lit("|") >> andExpression))[qi::_val = phoenix::bind(&storm::expressions::Expression::createFalse)]; |
|||
orExpression.name("or expression"); |
|||
|
|||
expression %= orExpression; |
|||
expression.name("expression"); |
|||
} |
|||
|
|||
// Enable error reporting.
|
|||
qi::on_error<qi::fail>(expression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); |
|||
qi::on_error<qi::fail>(orExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); |
|||
qi::on_error<qi::fail>(andExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); |
|||
qi::on_error<qi::fail>(relativeExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); |
|||
qi::on_error<qi::fail>(plusExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); |
|||
qi::on_error<qi::fail>(multiplicationExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); |
|||
qi::on_error<qi::fail>(unaryExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); |
|||
qi::on_error<qi::fail>(atomicExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); |
|||
qi::on_error<qi::fail>(literalExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); |
|||
qi::on_error<qi::fail>(identifierExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); |
|||
qi::on_error<qi::fail>(minMaxExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); |
|||
qi::on_error<qi::fail>(floorCeilExpression, handler(qi::_1, qi::_2, qi::_3, qi::_4)); |
|||
|
|||
// Finally toggle the internal flag.
|
|||
this->doExpressionGeneration = doExpressionGeneration; |
|||
} |
|||
|
|||
void PrismGrammar::toggleExpressionGeneration() { |
|||
setExpressionGeneration(!doExpressionGeneration); |
|||
} |
|||
|
|||
void PrismGrammar::allowDoubleLiterals(bool flag) { |
|||
if (flag) { |
|||
if (this->doExpressionGeneration) { |
|||
literalExpression = qi::lit("true")[qi::_val = phoenix::bind(&storm::expressions::Expression::createTrue)] | qi::lit("false")[qi::_val = phoenix::bind(&storm::expressions::Expression::createFalse)] | strict_double[qi::_val = phoenix::bind(&storm::expressions::Expression::createDoubleLiteral, qi::_1)] | qi::int_[qi::_val = phoenix::bind(&storm::expressions::Expression::createIntegerLiteral, qi::_1)]; |
|||
literalExpression.name("literal expression"); |
|||
} else { |
|||
literalExpression = (qi::lit("true") | qi::lit("false") | strict_double | qi::int_)[qi::_val = phoenix::bind(&storm::expressions::Expression::createFalse)]; |
|||
literalExpression.name("literal expression"); |
|||
} |
|||
} else { |
|||
if (this->doExpressionGeneration) { |
|||
literalExpression = qi::lit("true")[qi::_val = phoenix::bind(&storm::expressions::Expression::createTrue)] | qi::lit("false")[qi::_val = phoenix::bind(&storm::expressions::Expression::createFalse)] | qi::int_[qi::_val = phoenix::bind(&storm::expressions::Expression::createIntegerLiteral, qi::_1)]; |
|||
literalExpression.name("literal expression"); |
|||
} else { |
|||
literalExpression = (qi::lit("true") | qi::lit("false") | qi::int_)[qi::_val = phoenix::bind(&storm::expressions::Expression::createFalse)]; |
|||
literalExpression.name("literal expression"); |
|||
} |
|||
} |
|||
} |
|||
|
|||
std::string const& PrismGrammar::getFilename() const { |
|||
return this->filename; |
|||
} |
|||
|
|||
bool PrismGrammar::isValidIdentifier(std::string const& identifier) { |
|||
if (this->keywords_.find(identifier) != nullptr) { |
|||
return false; |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
bool PrismGrammar::addInitialStatesExpression(storm::expressions::Expression initialStatesExpression, GlobalProgramInformation& globalProgramInformation) { |
|||
LOG_THROW(!globalProgramInformation.hasInitialStatesExpression, storm::exceptions::InvalidArgumentException, "Program must not define two initial constructs."); |
|||
if (globalProgramInformation.hasInitialStatesExpression) { |
|||
return false; |
|||
} |
|||
globalProgramInformation.hasInitialStatesExpression = true; |
|||
globalProgramInformation.initialStatesExpression = initialStatesExpression; |
|||
return true; |
|||
} |
|||
|
|||
storm::expressions::Expression PrismGrammar::getIdentifierExpression(std::string const& identifier) const { |
|||
storm::expressions::Expression const* expression = this->identifiers_.find(identifier); |
|||
LOG_THROW(expression != nullptr, storm::exceptions::WrongFormatException, "Undeclared identifier '" << identifier << "'."); |
|||
return *expression; |
|||
} |
|||
|
|||
storm::prism::Constant PrismGrammar::createUndefinedBooleanConstant(std::string const& newConstant) const { |
|||
this->identifiers_.add(newConstant, storm::expressions::Expression::createBooleanConstant(newConstant)); |
|||
return storm::prism::Constant(storm::prism::Constant::ConstantType::Bool, newConstant, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::Constant PrismGrammar::createUndefinedIntegerConstant(std::string const& newConstant) const { |
|||
this->identifiers_.add(newConstant, storm::expressions::Expression::createIntegerConstant(newConstant)); |
|||
return storm::prism::Constant(storm::prism::Constant::ConstantType::Integer, newConstant, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::Constant PrismGrammar::createUndefinedDoubleConstant(std::string const& newConstant) const { |
|||
this->identifiers_.add(newConstant, storm::expressions::Expression::createDoubleConstant(newConstant)); |
|||
return storm::prism::Constant(storm::prism::Constant::ConstantType::Double, newConstant, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::Constant PrismGrammar::createDefinedBooleanConstant(std::string const& newConstant, storm::expressions::Expression expression) const { |
|||
this->identifiers_.add(newConstant, storm::expressions::Expression::createBooleanConstant(newConstant)); |
|||
return storm::prism::Constant(storm::prism::Constant::ConstantType::Bool, newConstant, expression, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::Constant PrismGrammar::createDefinedIntegerConstant(std::string const& newConstant, storm::expressions::Expression expression) const { |
|||
this->identifiers_.add(newConstant, storm::expressions::Expression::createIntegerConstant(newConstant)); |
|||
return storm::prism::Constant(storm::prism::Constant::ConstantType::Integer, newConstant, expression, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::Constant PrismGrammar::createDefinedDoubleConstant(std::string const& newConstant, storm::expressions::Expression expression) const { |
|||
this->identifiers_.add(newConstant, storm::expressions::Expression::createDoubleConstant(newConstant)); |
|||
return storm::prism::Constant(storm::prism::Constant::ConstantType::Double, newConstant, expression, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::Formula PrismGrammar::createFormula(std::string const& formulaName, storm::expressions::Expression expression) const { |
|||
this->identifiers_.add(formulaName, expression); |
|||
return storm::prism::Formula(formulaName, expression, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::Label PrismGrammar::createLabel(std::string const& labelName, storm::expressions::Expression expression) const { |
|||
return storm::prism::Label(labelName, expression, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::RewardModel PrismGrammar::createRewardModel(std::string const& rewardModelName, std::vector<storm::prism::StateReward> const& stateRewards, std::vector<storm::prism::TransitionReward> const& transitionRewards) const { |
|||
return storm::prism::RewardModel(rewardModelName, stateRewards, transitionRewards, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::StateReward PrismGrammar::createStateReward(storm::expressions::Expression statePredicateExpression, storm::expressions::Expression rewardValueExpression) const { |
|||
return storm::prism::StateReward(statePredicateExpression, rewardValueExpression, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::TransitionReward PrismGrammar::createTransitionReward(std::string const& actionName, storm::expressions::Expression statePredicateExpression, storm::expressions::Expression rewardValueExpression) const { |
|||
return storm::prism::TransitionReward(actionName, statePredicateExpression, rewardValueExpression, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::Assignment PrismGrammar::createAssignment(std::string const& variableName, storm::expressions::Expression assignedExpression) const { |
|||
return storm::prism::Assignment(variableName, assignedExpression, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::Update PrismGrammar::createUpdate(storm::expressions::Expression likelihoodExpression, std::vector<storm::prism::Assignment> const& assignments, GlobalProgramInformation& globalProgramInformation) const { |
|||
++globalProgramInformation.currentUpdateIndex; |
|||
return storm::prism::Update(globalProgramInformation.currentUpdateIndex - 1, likelihoodExpression, assignments, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::Command PrismGrammar::createCommand(std::string const& actionName, storm::expressions::Expression guardExpression, std::vector<storm::prism::Update> const& updates, GlobalProgramInformation& globalProgramInformation) const { |
|||
++globalProgramInformation.currentCommandIndex; |
|||
return storm::prism::Command(globalProgramInformation.currentCommandIndex - 1, actionName, guardExpression, updates, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::BooleanVariable PrismGrammar::createBooleanVariable(std::string const& variableName, storm::expressions::Expression initialValueExpression) const { |
|||
this->identifiers_.add(variableName, storm::expressions::Expression::createBooleanVariable(variableName)); |
|||
return storm::prism::BooleanVariable(variableName, initialValueExpression, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::IntegerVariable PrismGrammar::createIntegerVariable(std::string const& variableName, storm::expressions::Expression lowerBoundExpression, storm::expressions::Expression upperBoundExpression, storm::expressions::Expression initialValueExpression) const { |
|||
this->identifiers_.add(variableName, storm::expressions::Expression::createIntegerVariable(variableName)); |
|||
return storm::prism::IntegerVariable(variableName, lowerBoundExpression, upperBoundExpression, initialValueExpression, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::Module PrismGrammar::createModule(std::string const& moduleName, std::vector<storm::prism::BooleanVariable> const& booleanVariables, std::vector<storm::prism::IntegerVariable> const& integerVariables, std::vector<storm::prism::Command> const& commands, GlobalProgramInformation& globalProgramInformation) const { |
|||
globalProgramInformation.moduleToIndexMap[moduleName] = globalProgramInformation.modules.size(); |
|||
return storm::prism::Module(moduleName, booleanVariables, integerVariables, commands, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::Module PrismGrammar::createRenamedModule(std::string const& newModuleName, std::string const& oldModuleName, std::map<std::string, std::string> const& renaming, GlobalProgramInformation& globalProgramInformation) const { |
|||
auto const& moduleIndexPair = globalProgramInformation.moduleToIndexMap.find(oldModuleName); |
|||
LOG_THROW(moduleIndexPair != globalProgramInformation.moduleToIndexMap.end(), storm::exceptions::WrongFormatException, "No module named '" << oldModuleName << "' to rename."); |
|||
globalProgramInformation.moduleToIndexMap[newModuleName] = globalProgramInformation.modules.size(); |
|||
uint_fast64_t commandBaseIndex = globalProgramInformation.currentCommandIndex; |
|||
uint_fast64_t updateBaseIndex = globalProgramInformation.currentUpdateIndex; |
|||
storm::prism::Module const& moduleToClone = globalProgramInformation.modules[moduleIndexPair->second]; |
|||
globalProgramInformation.currentCommandIndex += moduleToClone.getNumberOfCommands(); |
|||
globalProgramInformation.currentUpdateIndex += moduleToClone.getNumberOfUpdates(); |
|||
return storm::prism::Module(moduleToClone, newModuleName, commandBaseIndex, updateBaseIndex, renaming, this->getFilename()); |
|||
} |
|||
|
|||
storm::prism::Program PrismGrammar::createProgram(GlobalProgramInformation const& globalProgramInformation) const { |
|||
return storm::prism::Program(globalProgramInformation.modelType, globalProgramInformation.constants, globalProgramInformation.globalBooleanVariables, globalProgramInformation.globalIntegerVariables, globalProgramInformation.formulas, globalProgramInformation.modules, globalProgramInformation.rewardModels, globalProgramInformation.hasInitialStatesExpression, globalProgramInformation.initialStatesExpression, globalProgramInformation.labels, this->getFilename()); |
|||
} |
|||
} // namespace prism
|
|||
} // namespace parser
|
|||
} // namespace storm
|
@ -1,282 +0,0 @@ |
|||
#ifndef STORM_PARSER_PRISMPARSER_PRISMGRAMMAR_H_ |
|||
#define STORM_PARSER_PRISMPARSER_PRISMGRAMMAR_H_ |
|||
|
|||
// Include files for file input. |
|||
#include <istream> |
|||
#include <memory> |
|||
#include <iomanip> |
|||
|
|||
// Include boost spirit. |
|||
#define BOOST_SPIRIT_USE_PHOENIX_V3 |
|||
#include <boost/typeof/typeof.hpp> |
|||
#include <boost/spirit/include/qi.hpp> |
|||
#include <boost/spirit/include/phoenix.hpp> |
|||
#include <boost/spirit/include/support_line_pos_iterator.hpp> |
|||
#include <boost/spirit/home/classic/iterator/position_iterator.hpp> |
|||
|
|||
namespace qi = boost::spirit::qi; |
|||
namespace phoenix = boost::phoenix; |
|||
|
|||
typedef std::string::const_iterator BaseIteratorType; |
|||
typedef boost::spirit::line_pos_iterator<BaseIteratorType> PositionIteratorType; |
|||
typedef PositionIteratorType Iterator; |
|||
typedef BOOST_TYPEOF(boost::spirit::ascii::space | qi::lit("//") >> *(qi::char_ - qi::eol) >> qi::eol) Skipper; |
|||
typedef BOOST_TYPEOF(qi::lit("//") >> *(qi::char_ - qi::eol) >> qi::eol | boost::spirit::ascii::space) Skipper2; |
|||
|
|||
#include "src/storage/prism/Program.h" |
|||
#include "src/storage/expressions/Expression.h" |
|||
#include "src/exceptions/ExceptionMacros.h" |
|||
|
|||
namespace storm { |
|||
namespace parser { |
|||
namespace prism { |
|||
struct modelTypeStruct : qi::symbols<char, storm::prism::Program::ModelType> { |
|||
modelTypeStruct() { |
|||
add |
|||
("dtmc", storm::prism::Program::ModelType::DTMC) |
|||
("ctmc", storm::prism::Program::ModelType::CTMC) |
|||
("mdp", storm::prism::Program::ModelType::MDP) |
|||
("ctmdp", storm::prism::Program::ModelType::CTMDP) |
|||
("ma", storm::prism::Program::ModelType::MA); |
|||
} |
|||
}; |
|||
|
|||
struct keywordsStruct : qi::symbols<char, bool> { |
|||
keywordsStruct() { |
|||
add |
|||
("dtmc", 1) |
|||
("ctmc", 2) |
|||
("mdp", 3) |
|||
("ctmdp", 4) |
|||
("ma", 5) |
|||
("const", 6) |
|||
("int", 7) |
|||
("bool", 8) |
|||
("module", 9) |
|||
("endmodule", 10) |
|||
("rewards", 11) |
|||
("endrewards", 12) |
|||
("true", 13) |
|||
("min", 14) |
|||
("max", 15) |
|||
("floor", 16) |
|||
("ceil", 17) |
|||
("init", 18) |
|||
("endinit", 19); |
|||
} |
|||
}; |
|||
|
|||
class GlobalProgramInformation { |
|||
public: |
|||
// Default construct the header information. |
|||
GlobalProgramInformation() = default; |
|||
|
|||
// Members for all essential information that needs to be collected. |
|||
storm::prism::Program::ModelType modelType; |
|||
std::vector<storm::prism::Constant> constants; |
|||
std::vector<storm::prism::Formula> formulas; |
|||
std::vector<storm::prism::BooleanVariable> globalBooleanVariables; |
|||
std::vector<storm::prism::IntegerVariable> globalIntegerVariables; |
|||
std::map<std::string, uint_fast64_t> moduleToIndexMap; |
|||
std::vector<storm::prism::Module> modules; |
|||
std::vector<storm::prism::RewardModel> rewardModels; |
|||
std::vector<storm::prism::Label> labels; |
|||
storm::expressions::Expression initialStatesExpression; |
|||
bool hasInitialStatesExpression; |
|||
|
|||
// Counters to provide unique indexing for commands and updates. |
|||
uint_fast64_t currentCommandIndex; |
|||
uint_fast64_t currentUpdateIndex; |
|||
}; |
|||
|
|||
// Functor used for displaying error information. |
|||
struct ErrorHandler { |
|||
typedef qi::error_handler_result result_type; |
|||
|
|||
template<typename T1, typename T2, typename T3, typename T4> |
|||
qi::error_handler_result operator()(T1 b, T2 e, T3 where, T4 const& what) const { |
|||
// LOG4CPLUS_ERROR(logger, "Error: expecting " << what << " in line " << get_line(where) << " at column " << get_column(b, where, 4) << "."); |
|||
std::cerr << "Error: expecting " << what << " in line " << get_line(where) << "." << std::endl; |
|||
T3 end(where); |
|||
while (end != e && *end != '\r' && *end != '\n') { |
|||
++end; |
|||
} |
|||
std::cerr << "Error: expecting " << what << " in line " << get_line(where) << ": \n" << std::string(get_line_start(b, where), end) << " ... \n" << std::setw(std::distance(b, where)) << '^' << "---- here\n"; |
|||
return qi::fail; |
|||
} |
|||
}; |
|||
|
|||
// 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; |
|||
}; |
|||
|
|||
class PrismGrammar : public qi::grammar<Iterator, storm::prism::Program(), qi::locals<GlobalProgramInformation>, Skipper> { |
|||
public: |
|||
/*! |
|||
* Creates a grammar for the given filename and the iterator to the first input to parse. |
|||
* |
|||
* @param filename The filename that is to be read. This is used for proper error reporting. |
|||
* @param first The iterator to the beginning of the input. |
|||
*/ |
|||
PrismGrammar(std::string const& filename, Iterator first); |
|||
|
|||
/*! |
|||
* Toggles whether or not expressions are generated. |
|||
*/ |
|||
void toggleExpressionGeneration(); |
|||
|
|||
private: |
|||
// A flag that stores whether the grammar currently generates expressions or not. |
|||
bool doExpressionGeneration; |
|||
|
|||
/*! |
|||
* Sets the expression generation to the desired value. |
|||
* |
|||
* @param doExpressionGeneration A flag that sets whether or not expressions are generated. |
|||
*/ |
|||
void setExpressionGeneration(bool doExpressionGeneration); |
|||
|
|||
/*! |
|||
* Sets whether doubles literals are allowed in the parsed expression. |
|||
* |
|||
* @param flag Indicates whether to allow or forbid double literals in the parsed expression. |
|||
*/ |
|||
void allowDoubleLiterals(bool flag); |
|||
|
|||
// The name of the file being parsed. |
|||
std::string filename; |
|||
|
|||
/*! |
|||
* Retrieves the name of the file currently being parsed. |
|||
* |
|||
* @return The name of the file currently being parsed. |
|||
*/ |
|||
std::string const& getFilename() const; |
|||
|
|||
// A function used for annotating the entities with their position. |
|||
phoenix::function<ErrorHandler> handler; |
|||
phoenix::function<PositionAnnotation> annotate; |
|||
|
|||
// The starting point of the grammar. |
|||
qi::rule<Iterator, storm::prism::Program(), qi::locals<GlobalProgramInformation>, Skipper> start; |
|||
|
|||
// Rules for model type. |
|||
qi::rule<Iterator, storm::prism::Program::ModelType(), Skipper> modelTypeDefinition; |
|||
|
|||
// Rules for parsing the program header. |
|||
qi::rule<Iterator, qi::unused_type(GlobalProgramInformation&), Skipper> programHeader; |
|||
qi::rule<Iterator, storm::prism::Constant(), Skipper> undefinedConstantDefinition; |
|||
qi::rule<Iterator, storm::prism::Constant(), Skipper> undefinedBooleanConstantDefinition; |
|||
qi::rule<Iterator, storm::prism::Constant(), Skipper> undefinedIntegerConstantDefinition; |
|||
qi::rule<Iterator, storm::prism::Constant(), Skipper> undefinedDoubleConstantDefinition; |
|||
qi::rule<Iterator, storm::prism::Constant(), Skipper> definedConstantDefinition; |
|||
qi::rule<Iterator, storm::prism::Constant(), Skipper> definedBooleanConstantDefinition; |
|||
qi::rule<Iterator, storm::prism::Constant(), Skipper> definedIntegerConstantDefinition; |
|||
qi::rule<Iterator, storm::prism::Constant(), Skipper> definedDoubleConstantDefinition; |
|||
|
|||
// Rules for global variable definitions. |
|||
qi::rule<Iterator, qi::unused_type(GlobalProgramInformation&), Skipper> globalVariableDefinition; |
|||
qi::rule<Iterator, qi::unused_type(GlobalProgramInformation&), Skipper> globalBooleanVariableDefinition; |
|||
qi::rule<Iterator, qi::unused_type(GlobalProgramInformation&), Skipper> globalIntegerVariableDefinition; |
|||
|
|||
// Rules for modules definition. |
|||
qi::rule<Iterator, std::vector<storm::prism::Module>(GlobalProgramInformation&), Skipper> moduleDefinitionList; |
|||
qi::rule<Iterator, storm::prism::Module(GlobalProgramInformation&), qi::locals<std::vector<storm::prism::BooleanVariable>, std::vector<storm::prism::IntegerVariable>>, Skipper> moduleDefinition; |
|||
qi::rule<Iterator, storm::prism::Module(GlobalProgramInformation&), qi::locals<std::map<std::string, std::string>>, Skipper> moduleRenaming; |
|||
|
|||
// Rules for variable definitions. |
|||
qi::rule<Iterator, qi::unused_type(std::vector<storm::prism::BooleanVariable>&, std::vector<storm::prism::IntegerVariable>&), Skipper> variableDefinition; |
|||
qi::rule<Iterator, storm::prism::BooleanVariable(), Skipper> booleanVariableDefinition; |
|||
qi::rule<Iterator, storm::prism::IntegerVariable(), qi::locals<storm::expressions::Expression>, Skipper> integerVariableDefinition; |
|||
|
|||
// Rules for command definitions. |
|||
qi::rule<Iterator, storm::prism::Command(GlobalProgramInformation&), qi::locals<std::string>, Skipper> commandDefinition; |
|||
qi::rule<Iterator, std::vector<storm::prism::Update>(GlobalProgramInformation&), Skipper> updateListDefinition; |
|||
qi::rule<Iterator, storm::prism::Update(GlobalProgramInformation&), Skipper> updateDefinition; |
|||
qi::rule<Iterator, std::vector<storm::prism::Assignment>(), Skipper> assignmentDefinitionList; |
|||
qi::rule<Iterator, storm::prism::Assignment(), Skipper> assignmentDefinition; |
|||
|
|||
// Rules for reward definitions. |
|||
qi::rule<Iterator, storm::prism::RewardModel(), qi::locals<std::vector<storm::prism::StateReward>, std::vector<storm::prism::TransitionReward>>, Skipper> rewardModelDefinition; |
|||
qi::rule<Iterator, storm::prism::StateReward(), Skipper> stateRewardDefinition; |
|||
qi::rule<Iterator, storm::prism::TransitionReward(), qi::locals<std::string>, Skipper> transitionRewardDefinition; |
|||
|
|||
// Rules for initial states expression. |
|||
qi::rule<Iterator, qi::unused_type(GlobalProgramInformation&), Skipper> initialStatesConstruct; |
|||
|
|||
// Rules for label definitions. |
|||
qi::rule<Iterator, storm::prism::Label(), Skipper> labelDefinition; |
|||
|
|||
// Rules for formula definitions. |
|||
qi::rule<Iterator, storm::prism::Formula(), Skipper> formulaDefinition; |
|||
|
|||
// Rules for identifier parsing. |
|||
qi::rule<Iterator, std::string(), Skipper> identifier; |
|||
|
|||
// Rules for parsing a composed expression. |
|||
qi::rule<Iterator, storm::expressions::Expression(), Skipper> expression; |
|||
qi::rule<Iterator, storm::expressions::Expression(), Skipper> orExpression; |
|||
qi::rule<Iterator, storm::expressions::Expression(), Skipper> andExpression; |
|||
qi::rule<Iterator, storm::expressions::Expression(), Skipper> relativeExpression; |
|||
qi::rule<Iterator, storm::expressions::Expression(), qi::locals<bool>, Skipper> plusExpression; |
|||
qi::rule<Iterator, storm::expressions::Expression(), qi::locals<bool>, Skipper> multiplicationExpression; |
|||
qi::rule<Iterator, storm::expressions::Expression(), Skipper> unaryExpression; |
|||
qi::rule<Iterator, storm::expressions::Expression(), Skipper> atomicExpression; |
|||
qi::rule<Iterator, storm::expressions::Expression(), Skipper> literalExpression; |
|||
qi::rule<Iterator, storm::expressions::Expression(), Skipper> identifierExpression; |
|||
qi::rule<Iterator, storm::expressions::Expression(), qi::locals<bool>, Skipper> minMaxExpression; |
|||
qi::rule<Iterator, storm::expressions::Expression(), qi::locals<bool>, Skipper> floorCeilExpression; |
|||
|
|||
// Parser that is used to recognize doubles only (as opposed to Spirit's double_ parser). |
|||
boost::spirit::qi::real_parser<double, boost::spirit::qi::strict_real_policies<double>> strict_double; |
|||
|
|||
// Parsers that recognize special keywords and model types. |
|||
storm::parser::prism::keywordsStruct keywords_; |
|||
storm::parser::prism::modelTypeStruct modelType_; |
|||
qi::symbols<char, storm::expressions::Expression> identifiers_; |
|||
|
|||
// Helper methods used in the grammar. |
|||
bool isValidIdentifier(std::string const& identifier); |
|||
bool addInitialStatesExpression(storm::expressions::Expression initialStatesExpression, GlobalProgramInformation& globalProgramInformation); |
|||
storm::expressions::Expression getIdentifierExpression(std::string const& identifier) const; |
|||
storm::prism::Constant createUndefinedBooleanConstant(std::string const& newConstant) const; |
|||
storm::prism::Constant createUndefinedIntegerConstant(std::string const& newConstant) const; |
|||
storm::prism::Constant createUndefinedDoubleConstant(std::string const& newConstant) const; |
|||
storm::prism::Constant createDefinedBooleanConstant(std::string const& newConstant, storm::expressions::Expression expression) const; |
|||
storm::prism::Constant createDefinedIntegerConstant(std::string const& newConstant, storm::expressions::Expression expression) const; |
|||
storm::prism::Constant createDefinedDoubleConstant(std::string const& newConstant, storm::expressions::Expression expression) const; |
|||
storm::prism::Formula createFormula(std::string const& formulaName, storm::expressions::Expression expression) const; |
|||
storm::prism::Label createLabel(std::string const& labelName, storm::expressions::Expression expression) const; |
|||
storm::prism::RewardModel createRewardModel(std::string const& rewardModelName, std::vector<storm::prism::StateReward> const& stateRewards, std::vector<storm::prism::TransitionReward> const& transitionRewards) const; |
|||
storm::prism::StateReward createStateReward(storm::expressions::Expression statePredicateExpression, storm::expressions::Expression rewardValueExpression) const; |
|||
storm::prism::TransitionReward createTransitionReward(std::string const& actionName, storm::expressions::Expression statePredicateExpression, storm::expressions::Expression rewardValueExpression) const; |
|||
storm::prism::Assignment createAssignment(std::string const& variableName, storm::expressions::Expression assignedExpression) const; |
|||
storm::prism::Update createUpdate(storm::expressions::Expression likelihoodExpression, std::vector<storm::prism::Assignment> const& assignments, GlobalProgramInformation& globalProgramInformation) const; |
|||
storm::prism::Command createCommand(std::string const& actionName, storm::expressions::Expression guardExpression, std::vector<storm::prism::Update> const& updates, GlobalProgramInformation& globalProgramInformation) const; |
|||
storm::prism::BooleanVariable createBooleanVariable(std::string const& variableName, storm::expressions::Expression initialValueExpression) const; |
|||
storm::prism::IntegerVariable createIntegerVariable(std::string const& variableName, storm::expressions::Expression lowerBoundExpression, storm::expressions::Expression upperBoundExpression, storm::expressions::Expression initialValueExpression) const; |
|||
storm::prism::Module createModule(std::string const& moduleName, std::vector<storm::prism::BooleanVariable> const& booleanVariables, std::vector<storm::prism::IntegerVariable> const& integerVariables, std::vector<storm::prism::Command> const& commands, GlobalProgramInformation& globalProgramInformation) const; |
|||
storm::prism::Module createRenamedModule(std::string const& newModuleName, std::string const& oldModuleName, std::map<std::string, std::string> const& renaming, GlobalProgramInformation& globalProgramInformation) const; |
|||
storm::prism::Program createProgram(GlobalProgramInformation const& globalProgramInformation) const; |
|||
}; |
|||
} // namespace prism |
|||
} // namespace parser |
|||
} // namespace storm |
|||
|
|||
|
|||
#endif /* STORM_PARSER_PRISMPARSER_PRISMGRAMMAR_H_ */ |
|||
|
@ -1,70 +0,0 @@ |
|||
#include "src/parser/prismparser/PrismParser.h"
|
|||
#include "src/parser/prismparser/PrismGrammar.h"
|
|||
|
|||
// If the parser fails due to ill-formed data, this exception is thrown.
|
|||
#include "src/exceptions/ExceptionMacros.h"
|
|||
#include "src/exceptions/WrongFormatException.h"
|
|||
|
|||
// Needed for file IO.
|
|||
#include <fstream>
|
|||
#include <iomanip>
|
|||
#include <limits>
|
|||
|
|||
namespace storm { |
|||
namespace parser { |
|||
storm::prism::Program PrismParser::parse(std::string const& filename, bool typeCheck) { |
|||
// Open file and initialize result.
|
|||
std::ifstream inputFileStream(filename, std::ios::in); |
|||
LOG_THROW(inputFileStream.good(), storm::exceptions::WrongFormatException, "Unable to read from file " << filename << "."); |
|||
|
|||
storm::prism::Program result; |
|||
|
|||
// Now try to parse the contents of the file.
|
|||
try { |
|||
std::string fileContent((std::istreambuf_iterator<char>(inputFileStream)), (std::istreambuf_iterator<char>())); |
|||
result = parseFromString(fileContent, filename, typeCheck); |
|||
} catch(std::exception& e) { |
|||
// In case of an exception properly close the file before passing exception.
|
|||
inputFileStream.close(); |
|||
throw e; |
|||
} |
|||
|
|||
// Close the stream in case everything went smoothly and return result.
|
|||
inputFileStream.close(); |
|||
return result; |
|||
} |
|||
|
|||
storm::prism::Program PrismParser::parseFromString(std::string const& input, std::string const& filename, bool typeCheck) { |
|||
PositionIteratorType first(input.begin()); |
|||
PositionIteratorType iter = first; |
|||
PositionIteratorType last(input.end()); |
|||
|
|||
// Create empty result;
|
|||
storm::prism::Program result; |
|||
|
|||
// Create grammar.
|
|||
storm::parser::prism::PrismGrammar grammar(filename, first); |
|||
try { |
|||
// Now parse the content using phrase_parse in order to be able to supply a skipping parser.
|
|||
bool succeeded = qi::phrase_parse(iter, last, grammar, boost::spirit::ascii::space | qi::lit("//") >> *(qi::char_ - qi::eol) >> qi::eol, result); |
|||
LOG_THROW(succeeded, storm::exceptions::WrongFormatException, "Parsing failed in first pass."); |
|||
if (typeCheck) { |
|||
first = PositionIteratorType(input.begin()); |
|||
iter = first; |
|||
last = PositionIteratorType(input.end()); |
|||
grammar.toggleExpressionGeneration(); |
|||
succeeded = qi::phrase_parse(iter, last, grammar, boost::spirit::ascii::space | qi::lit("//") >> *(qi::char_ - qi::eol) >> qi::eol, result); |
|||
LOG_THROW(succeeded, storm::exceptions::WrongFormatException, "Parsing failed in second pass."); |
|||
} |
|||
} catch (qi::expectation_failure<PositionIteratorType> const& e) { |
|||
// If the parser expected content different than the one provided, display information about the location of the error.
|
|||
std::size_t lineNumber = boost::spirit::get_line(e.first); |
|||
|
|||
// Now propagate exception.
|
|||
LOG_THROW(false, storm::exceptions::WrongFormatException, "Parsing error in line " << lineNumber << " of file " << filename << "."); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
} // namespace parser
|
|||
} // namespace storm
|
@ -1,36 +0,0 @@ |
|||
#ifndef STORM_PARSER_PRISMPARSER_H_ |
|||
#define STORM_PARSER_PRISMPARSER_H_ |
|||
|
|||
// All classes of the intermediate representation are used. |
|||
#include "src/storage/prism/Program.h" |
|||
|
|||
// Used for file input. |
|||
#include <istream> |
|||
|
|||
namespace storm { |
|||
namespace parser { |
|||
class PrismParser { |
|||
public: |
|||
/*! |
|||
* Parses the given file into the PRISM storage classes assuming it complies with the PRISM syntax. |
|||
* |
|||
* @param filename the name of the file to parse. |
|||
* @param typeCheck Sets whether the expressions are generated and therefore typechecked. |
|||
* @return The resulting PRISM program. |
|||
*/ |
|||
static storm::prism::Program parse(std::string const& filename, bool typeCheck = true); |
|||
|
|||
/*! |
|||
* Parses the given input stream into the PRISM storage classes assuming it complies with the PRISM syntax. |
|||
* |
|||
* @param input The input string to parse. |
|||
* @param filename The name of the file from which the input was read. |
|||
* @param typeCheck Sets whether the expressions are generated and therefore typechecked. |
|||
* @return The resulting PRISM program. |
|||
*/ |
|||
static storm::prism::Program parseFromString(std::string const& input, std::string const& filename, bool typeCheck = true); |
|||
}; |
|||
} // namespace parser |
|||
} // namespace storm |
|||
|
|||
#endif /* STORM_PARSER_PRISMPARSER_H_ */ |
@ -0,0 +1,96 @@ |
|||
#include "src/storage/expressions/IfThenElseExpression.h"
|
|||
|
|||
namespace storm { |
|||
namespace expressions { |
|||
IfThenElseExpression::IfThenElseExpression(ExpressionReturnType returnType, std::shared_ptr<BaseExpression const> const& condition, std::shared_ptr<BaseExpression const> const& thenExpression, std::shared_ptr<BaseExpression const> const& elseExpression) : BaseExpression(returnType), condition(condition), thenExpression(thenExpression), elseExpression(elseExpression) { |
|||
// Intentionally left empty.
|
|||
} |
|||
|
|||
bool IfThenElseExpression::evaluateAsBool(Valuation const& valuation) const { |
|||
bool conditionValue = this->condition->evaluateAsBool(valuation); |
|||
if (conditionValue) { |
|||
return this->thenExpression->evaluateAsBool(valuation); |
|||
} else { |
|||
return this->elseExpression->evaluateAsBool(valuation); |
|||
} |
|||
} |
|||
|
|||
int_fast64_t IfThenElseExpression::evaluateAsInt(Valuation const& valuation) const { |
|||
bool conditionValue = this->condition->evaluateAsBool(valuation); |
|||
if (conditionValue) { |
|||
return this->thenExpression->evaluateAsInt(valuation); |
|||
} else { |
|||
return this->elseExpression->evaluateAsInt(valuation); |
|||
} |
|||
} |
|||
|
|||
double IfThenElseExpression::evaluateAsDouble(Valuation const& valuation) const { |
|||
bool conditionValue = this->condition->evaluateAsBool(valuation); |
|||
if (conditionValue) { |
|||
return this->thenExpression->evaluateAsDouble(valuation); |
|||
} else { |
|||
return this->elseExpression->evaluateAsDouble(valuation); |
|||
} |
|||
} |
|||
|
|||
bool IfThenElseExpression::isConstant() const { |
|||
return this->condition->isConstant() && this->thenExpression->isConstant() && this->elseExpression->isConstant(); |
|||
} |
|||
|
|||
std::set<std::string> IfThenElseExpression::getVariables() const { |
|||
std::set<std::string> result = this->condition->getVariables(); |
|||
std::set<std::string> tmp = this->thenExpression->getVariables(); |
|||
result.insert(tmp.begin(), tmp.end()); |
|||
tmp = this->elseExpression->getVariables(); |
|||
result.insert(tmp.begin(), tmp.end()); |
|||
return result; |
|||
} |
|||
|
|||
std::set<std::string> IfThenElseExpression::getConstants() const { |
|||
std::set<std::string> result = this->condition->getConstants(); |
|||
std::set<std::string> tmp = this->thenExpression->getConstants(); |
|||
result.insert(tmp.begin(), tmp.end()); |
|||
tmp = this->elseExpression->getConstants(); |
|||
result.insert(tmp.begin(), tmp.end()); |
|||
return result; |
|||
} |
|||
|
|||
std::shared_ptr<BaseExpression const> IfThenElseExpression::simplify() const { |
|||
std::shared_ptr<BaseExpression const> conditionSimplified; |
|||
if (conditionSimplified->isTrue()) { |
|||
return this->thenExpression->simplify(); |
|||
} else if (conditionSimplified->isFalse()) { |
|||
return this->elseExpression->simplify(); |
|||
} else { |
|||
std::shared_ptr<BaseExpression const> thenExpressionSimplified = this->thenExpression->simplify(); |
|||
std::shared_ptr<BaseExpression const> elseExpressionSimplified = this->elseExpression->simplify(); |
|||
|
|||
if (conditionSimplified.get() == this->condition.get() && thenExpressionSimplified.get() == this->thenExpression.get() && elseExpressionSimplified.get() == this->elseExpression.get()) { |
|||
return this->shared_from_this(); |
|||
} else { |
|||
return std::shared_ptr<BaseExpression>(new IfThenElseExpression(this->getReturnType(), conditionSimplified, thenExpressionSimplified, elseExpressionSimplified)); |
|||
} |
|||
} |
|||
} |
|||
|
|||
void IfThenElseExpression::accept(ExpressionVisitor* visitor) const { |
|||
visitor->visit(this); |
|||
} |
|||
|
|||
std::shared_ptr<BaseExpression const> IfThenElseExpression::getCondition() const { |
|||
return this->condition; |
|||
} |
|||
|
|||
std::shared_ptr<BaseExpression const> IfThenElseExpression::getThenExpression() const { |
|||
return this->thenExpression; |
|||
} |
|||
|
|||
std::shared_ptr<BaseExpression const> IfThenElseExpression::getElseExpression() const { |
|||
return this->elseExpression; |
|||
} |
|||
|
|||
void IfThenElseExpression::printToStream(std::ostream& stream) const { |
|||
stream << "(" << *this->condition << " ? " << *this->thenExpression << " : " << *this->elseExpression << ")"; |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,74 @@ |
|||
#ifndef STORM_STORAGE_EXPRESSIONS_IFTHENELSEEXPRESSION_H_ |
|||
#define STORM_STORAGE_EXPRESSIONS_IFTHENELSEEXPRESSION_H_ |
|||
|
|||
#include "src/storage/expressions/BaseExpression.h" |
|||
|
|||
namespace storm { |
|||
namespace expressions { |
|||
class IfThenElseExpression : public BaseExpression { |
|||
public: |
|||
/*! |
|||
* Creates an if-then-else expression with the given return type, condition and operands. |
|||
* |
|||
* @param returnType The return type of the expression. |
|||
* @param thenExpression The expression evaluated if the condition evaluates true. |
|||
* @param elseExpression The expression evaluated if the condition evaluates false. |
|||
*/ |
|||
IfThenElseExpression(ExpressionReturnType returnType, std::shared_ptr<BaseExpression const> const& condition, std::shared_ptr<BaseExpression const> const& thenExpression, std::shared_ptr<BaseExpression const> const& elseExpression); |
|||
|
|||
// Instantiate constructors and assignments with their default implementations. |
|||
IfThenElseExpression(IfThenElseExpression const& other) = default; |
|||
IfThenElseExpression& operator=(IfThenElseExpression const& other) = default; |
|||
IfThenElseExpression(IfThenElseExpression&&) = default; |
|||
IfThenElseExpression& operator=(IfThenElseExpression&&) = default; |
|||
virtual ~IfThenElseExpression() = default; |
|||
|
|||
// Override base class methods. |
|||
virtual bool evaluateAsBool(Valuation const& valuation) const override; |
|||
virtual int_fast64_t evaluateAsInt(Valuation const& valuation) const override; |
|||
virtual double evaluateAsDouble(Valuation const& valuation) const override; |
|||
virtual bool isConstant() const override; |
|||
virtual std::set<std::string> getVariables() const override; |
|||
virtual std::set<std::string> getConstants() const override; |
|||
virtual std::shared_ptr<BaseExpression const> simplify() const override; |
|||
virtual void accept(ExpressionVisitor* visitor) const override; |
|||
|
|||
/*! |
|||
* Retrieves the condition expression of the if-then-else expression. |
|||
* |
|||
* @return The condition expression of the if-then-else expression. |
|||
*/ |
|||
std::shared_ptr<BaseExpression const> getCondition() const; |
|||
|
|||
/*! |
|||
* Retrieves the then expression of the if-then-else expression. |
|||
* |
|||
* @return The then expression of the if-then-else expression. |
|||
*/ |
|||
std::shared_ptr<BaseExpression const> getThenExpression() const; |
|||
|
|||
/*! |
|||
* Retrieves the else expression of the if-then-else expression. |
|||
* |
|||
* @return The else expression of the if-then-else expression. |
|||
*/ |
|||
std::shared_ptr<BaseExpression const> getElseExpression() const; |
|||
|
|||
protected: |
|||
// Override base class method. |
|||
virtual void printToStream(std::ostream& stream) const override; |
|||
|
|||
private: |
|||
// The condition of the if-then-else. |
|||
std::shared_ptr<BaseExpression const> condition; |
|||
|
|||
// The return expression of the if-part. |
|||
std::shared_ptr<BaseExpression const> thenExpression; |
|||
|
|||
// The return expression of the else-part. |
|||
std::shared_ptr<BaseExpression const> elseExpression; |
|||
}; |
|||
} |
|||
} |
|||
|
|||
#endif /* STORM_STORAGE_EXPRESSIONS_IFTHENELSEEXPRESSION_H_ */ |
Write
Preview
Loading…
Cancel
Save
Reference in new issue