147 lines
3.7 KiB
147 lines
3.7 KiB
#include "src/parser/PrctlParser.h"
|
|
|
|
#include <iostream>
|
|
#include <map>
|
|
//#include <pair>
|
|
|
|
#include <boost/spirit/include/classic_core.hpp>
|
|
#include <boost/spirit/include/qi_grammar.hpp>
|
|
#include <boost/spirit/include/qi_rule.hpp>
|
|
#include <boost/spirit/include/qi.hpp>
|
|
#include <boost/spirit/include/phoenix_operator.hpp>
|
|
#include <boost/spirit/include/qi_char_class.hpp>
|
|
|
|
#include <boost/bind.hpp>
|
|
|
|
namespace bs = boost::spirit;
|
|
|
|
namespace
|
|
{
|
|
using namespace bs;
|
|
using namespace bs::qi;
|
|
using namespace bs::standard;
|
|
|
|
struct SpiritParser : public grammar< char const* >
|
|
{
|
|
typedef rule< char const* > rule_none;
|
|
typedef rule< char const*, double() > rule_double;
|
|
typedef rule< char const*, std::string() > rule_string;
|
|
|
|
/*!
|
|
* @brief Generic Nonterminals.
|
|
*/
|
|
rule_none ws;
|
|
rule_string variable;
|
|
rule_double value;
|
|
|
|
/*!
|
|
* @brief Nonterminals for file header.
|
|
*/
|
|
rule< char const* > varDef;
|
|
rule_none type;
|
|
|
|
/*!
|
|
* @brief Nonterminals for formula.
|
|
*/
|
|
rule_none formula, opP;
|
|
|
|
/*!
|
|
* @brief Nonterminals for high-level file structure.
|
|
*/
|
|
rule_none file, header;
|
|
|
|
/*!
|
|
* @brief Variable assignments.
|
|
*/
|
|
std::map<std::string, double> variables;
|
|
|
|
/*!
|
|
* @brief Resulting formula.
|
|
*/
|
|
storm::formula::PctlFormula<double>* result;
|
|
|
|
struct dump
|
|
{
|
|
void print(double const& i, std::string& s)
|
|
{
|
|
std::cout << s << " = " << i << std::endl;
|
|
}
|
|
void operator()(double const& a, unused_type, unused_type) const
|
|
{
|
|
std::cout << a << std::endl;
|
|
}
|
|
void operator()(std::string const& a, unused_type, unused_type) const
|
|
{
|
|
std::cout << a << std::endl;
|
|
}
|
|
void operator()(utree const& a, unused_type, unused_type) const
|
|
{
|
|
std::cout << &a << std::endl;
|
|
}
|
|
};
|
|
|
|
SpiritParser() : SpiritParser::base_type(file, "PRCTL parser")
|
|
{
|
|
variable %= alnum;
|
|
ws = *( space );
|
|
value %= ( double_ | int_ ); // double_ must be *before* int_
|
|
type = string("int") | string("double");
|
|
|
|
/*
|
|
* Todo:
|
|
* Use two arguments at one point in the code, e.g. do something like
|
|
* this->variables[ variable ] = value
|
|
*
|
|
* You can have local variables in rules, but somehow does not work.
|
|
* You can also (somehow) let a rule return some arbitrary class and let boost magically collect the arguments for the constructor.
|
|
* No idea how this can possibly work, did not get this to work.
|
|
* You can also generate a syntax tree and do this manually (-> utree)... somehow.
|
|
*
|
|
* Attention: spirit had some major upgrades in the last few releases. 1.48 already lacks some features that might be useful.
|
|
*
|
|
* The rules parse the const definitions of
|
|
* http://www.prismmodelchecker.org/manual/PropertySpecification/PropertiesFiles
|
|
* We actually do not need them, but the problems I described above are fairly generic.
|
|
* We will not be able to parse the formulas if we don't solve them...
|
|
*
|
|
* Example input:
|
|
* const int k = 7;
|
|
* const double T = 9;
|
|
* const double p = 0.01;
|
|
*
|
|
* Parser can be run via ./storm --test-prctl <filename> foo bar
|
|
* foo and bar are necessary, otherwise the option parser fails...
|
|
*/
|
|
|
|
varDef =
|
|
string("const") >> ws >>
|
|
type >> ws >>
|
|
variable >> ws >>
|
|
string("=") >> ws >>
|
|
value >> ws >>
|
|
string(";");
|
|
|
|
header = +( varDef >> ws );
|
|
|
|
file = header;
|
|
}
|
|
|
|
|
|
};
|
|
}
|
|
|
|
storm::parser::PrctlParser::PrctlParser(const char* filename)
|
|
{
|
|
SpiritParser p;
|
|
storm::parser::MappedFile file(filename);
|
|
|
|
char* data = file.data;
|
|
if (bs::qi::parse< char const* >(data, file.dataend, p))
|
|
{
|
|
std::cout << "File was parsed" << std::endl;
|
|
std::string rest(data, file.dataend);
|
|
std::cout << "Rest: " << rest << std::endl;
|
|
this->formula = p.result;
|
|
}
|
|
else this->formula = NULL;
|
|
}
|