Add support for PSL's non-length-matching And.
* src/ltlast/multop.cc, src/ltlast/multop.hh: Declare AndNML
operator.
* src/ltlparse/ltlscan.ll: Distinguish "&" and "&&".
* src/ltlparse/ltlparse.yy: Handle them both as "And" for LTL
formula, use AndNML or And for rational expressions.
* src/ltlvisit/tostring.cc: Adjust to distinguish "&" and "&&" in
rational expressions. Also use {braces} to group rational
expressions.
* src/tgbaalgos/ltl2tgba_fm.cc
(ratexp_trad_visitor::ratexp_trad_visitor): Remove the possibility
to select the empty_word should act like true, and fix the rules
for Closure and NegClosure to rely on constant_term instead.
(ratexp_trad_visitor::visit) Adjust the And translation to also
support AndNML.
(ratexp_trad_visitor::recurse_and_concat): Introduce this new
method to simplify some calls to recurse(f, to_concat_).
* src/tgbatest/ltl2tgba.test: Add more test cases.
* src/ltlvisit/basicreduce.cc, src/ltlvisit/consterm.cc,
src/ltlvisit/contain.cc, src/ltlvisit/mark.cc,
src/ltlvisit/nenoform.cc, src/ltlvisit/syntimpl.cc,
src/tgba/formula2bdd.cc, src/tgbaalgos/eltl2tgba_lacim.cc,
src/tgbaalgos/ltl2taa.cc, src/tgbaalgos/ltl2tgba_lacim.cc: Add
missing cases in switches.
This commit is contained in:
parent
1ecc6984d3
commit
bbb645e1fc
17 changed files with 238 additions and 100 deletions
|
|
@ -109,6 +109,8 @@ namespace spot
|
||||||
{
|
{
|
||||||
case And:
|
case And:
|
||||||
return "And";
|
return "And";
|
||||||
|
case AndNLM:
|
||||||
|
return "AndNLM";
|
||||||
case Or:
|
case Or:
|
||||||
return "Or";
|
return "Or";
|
||||||
case Concat:
|
case Concat:
|
||||||
|
|
@ -171,6 +173,7 @@ namespace spot
|
||||||
std::sort(v->begin(), v->end(), formula_ptr_less_than());
|
std::sort(v->begin(), v->end(), formula_ptr_less_than());
|
||||||
|
|
||||||
formula* neutral;
|
formula* neutral;
|
||||||
|
formula* neutral2;
|
||||||
formula* abs;
|
formula* abs;
|
||||||
formula* abs2;
|
formula* abs2;
|
||||||
formula* weak_abs;
|
formula* weak_abs;
|
||||||
|
|
@ -178,24 +181,35 @@ namespace spot
|
||||||
{
|
{
|
||||||
case And:
|
case And:
|
||||||
neutral = constant::true_instance();
|
neutral = constant::true_instance();
|
||||||
|
neutral2 = 0;
|
||||||
abs = constant::false_instance();
|
abs = constant::false_instance();
|
||||||
abs2 = 0;
|
abs2 = 0;
|
||||||
weak_abs = constant::empty_word_instance();
|
weak_abs = constant::empty_word_instance();
|
||||||
break;
|
break;
|
||||||
|
case AndNLM:
|
||||||
|
neutral = constant::true_instance();
|
||||||
|
neutral2 = constant::empty_word_instance();
|
||||||
|
abs = constant::false_instance();
|
||||||
|
abs2 = 0;
|
||||||
|
weak_abs = 0;
|
||||||
|
break;
|
||||||
case Or:
|
case Or:
|
||||||
neutral = constant::false_instance();
|
neutral = constant::false_instance();
|
||||||
|
neutral2 = 0;
|
||||||
abs = constant::true_instance();
|
abs = constant::true_instance();
|
||||||
abs2 = 0;
|
abs2 = 0;
|
||||||
weak_abs = 0;
|
weak_abs = 0;
|
||||||
break;
|
break;
|
||||||
case Concat:
|
case Concat:
|
||||||
neutral = constant::empty_word_instance();
|
neutral = constant::empty_word_instance();
|
||||||
|
neutral2 = 0;
|
||||||
abs = constant::false_instance();
|
abs = constant::false_instance();
|
||||||
abs2 = 0;
|
abs2 = 0;
|
||||||
weak_abs = 0;
|
weak_abs = 0;
|
||||||
break;
|
break;
|
||||||
case Fusion:
|
case Fusion:
|
||||||
neutral = constant::true_instance();
|
neutral = constant::true_instance();
|
||||||
|
neutral2 = 0;
|
||||||
abs = constant::false_instance();
|
abs = constant::false_instance();
|
||||||
abs2 = constant::empty_word_instance();
|
abs2 = constant::empty_word_instance();
|
||||||
weak_abs = 0;
|
weak_abs = 0;
|
||||||
|
|
@ -203,6 +217,7 @@ namespace spot
|
||||||
|
|
||||||
default:
|
default:
|
||||||
neutral = 0;
|
neutral = 0;
|
||||||
|
neutral2 = 0;
|
||||||
abs = 0;
|
abs = 0;
|
||||||
abs2 = 0;
|
abs2 = 0;
|
||||||
weak_abs = 0;
|
weak_abs = 0;
|
||||||
|
|
@ -218,7 +233,7 @@ namespace spot
|
||||||
bool weak_abs_seen = false;
|
bool weak_abs_seen = false;
|
||||||
while (i != v->end())
|
while (i != v->end())
|
||||||
{
|
{
|
||||||
if ((*i == neutral) || (*i == last))
|
if ((*i == neutral) || (*i == neutral2) || (*i == last))
|
||||||
{
|
{
|
||||||
(*i)->destroy();
|
(*i)->destroy();
|
||||||
i = v->erase(i);
|
i = v->erase(i);
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ namespace spot
|
||||||
class multop : public ref_formula
|
class multop : public ref_formula
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum type { Or, And, Concat, Fusion };
|
enum type { Or, And, AndNLM, Concat, Fusion };
|
||||||
|
|
||||||
/// List of formulae.
|
/// List of formulae.
|
||||||
typedef std::vector<formula*> vec;
|
typedef std::vector<formula*> vec;
|
||||||
|
|
@ -80,15 +80,24 @@ namespace spot
|
||||||
/// are also taken care of. The following rewriting are performed
|
/// are also taken care of. The following rewriting are performed
|
||||||
/// (the left patterns are rewritten as shown on the right):
|
/// (the left patterns are rewritten as shown on the right):
|
||||||
///
|
///
|
||||||
/// - Concat(Exps1...,[*0],Exps2...) = Concat(Exps1...,Exps2...)
|
|
||||||
/// - Concat(Exps1...,0,Exps2...) = 0
|
|
||||||
/// - Concat(Exp) = Exp
|
|
||||||
/// - And(Exps1...,1,Exps2...) = And(Exps1...,Exps2...)
|
/// - And(Exps1...,1,Exps2...) = And(Exps1...,Exps2...)
|
||||||
/// - And(Exps1...,0,Exps2...) = 0
|
/// - And(Exps1...,0,Exps2...) = 0
|
||||||
|
/// - And(Exps1...,[*0],Exps2...) = [*0] if no Expi is 0.
|
||||||
/// - And(Exp) = Exp
|
/// - And(Exp) = Exp
|
||||||
|
/// - AndNLM(Exps1...,1,Exps2...) = AndNLM(Exps1...,Exps2...)
|
||||||
|
/// - AndNLM(Exps1...,0,Exps2...) = 0
|
||||||
|
/// - AndNLM(Exps1...,[*0],Exps2...) = AndNLM(Exps1...,Exps2...)
|
||||||
|
/// - AndNLM(Exp) = Exp
|
||||||
/// - Or(Exps1...,1,Exps2...) = 1
|
/// - Or(Exps1...,1,Exps2...) = 1
|
||||||
/// - Or(Exps1...,0,Exps2...) = And(Exps1...,Exps2...)
|
/// - Or(Exps1...,0,Exps2...) = And(Exps1...,Exps2...)
|
||||||
/// - Or(Exp) = Exp
|
/// - Or(Exp) = Exp
|
||||||
|
/// - Concat(Exps1...,[*0],Exps2...) = Concat(Exps1...,Exps2...)
|
||||||
|
/// - Concat(Exps1...,0,Exps2...) = 0
|
||||||
|
/// - Concat(Exp) = Exp
|
||||||
|
/// - Fusion(Exps1...,1,Exps2...) = Concat(Exps1...,Exps2...)
|
||||||
|
/// - Fusion(Exps1...,0,Exps2...) = 0
|
||||||
|
/// - Fusion(Exps1...,[*0],Exps2...) = 0
|
||||||
|
/// - Fusion(Exp) = Exp
|
||||||
static formula* instance(type op, vec* v);
|
static formula* instance(type op, vec* v);
|
||||||
|
|
||||||
virtual void accept(visitor& v);
|
virtual void accept(visitor& v);
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,8 @@ using namespace spot::ltl;
|
||||||
%token START_RATEXP "RATEXP start marker"
|
%token START_RATEXP "RATEXP start marker"
|
||||||
%token PAR_OPEN "opening parenthesis" PAR_CLOSE "closing parenthesis"
|
%token PAR_OPEN "opening parenthesis" PAR_CLOSE "closing parenthesis"
|
||||||
%token BRACE_OPEN "opening brace" BRACE_CLOSE "closing brace"
|
%token BRACE_OPEN "opening brace" BRACE_CLOSE "closing brace"
|
||||||
%token OP_OR "or operator" OP_XOR "xor operator" OP_AND "and operator"
|
%token OP_OR "or operator" OP_XOR "xor operator"
|
||||||
|
%token OP_AND "and operator" OP_SHORT_AND "short and operator"
|
||||||
%token OP_IMPLIES "implication operator" OP_EQUIV "equivalent operator"
|
%token OP_IMPLIES "implication operator" OP_EQUIV "equivalent operator"
|
||||||
%token OP_U "until operator" OP_R "release operator"
|
%token OP_U "until operator" OP_R "release operator"
|
||||||
%token OP_W "weak until operator" OP_M "strong release operator"
|
%token OP_W "weak until operator" OP_M "strong release operator"
|
||||||
|
|
@ -103,7 +104,7 @@ using namespace spot::ltl;
|
||||||
%left OP_IMPLIES OP_EQUIV
|
%left OP_IMPLIES OP_EQUIV
|
||||||
%left OP_OR
|
%left OP_OR
|
||||||
%left OP_XOR
|
%left OP_XOR
|
||||||
%left OP_AND
|
%left OP_AND OP_SHORT_AND
|
||||||
|
|
||||||
/* LTL operators. */
|
/* LTL operators. */
|
||||||
%left OP_U OP_R OP_M OP_W
|
%left OP_U OP_R OP_M OP_W
|
||||||
|
|
@ -257,7 +258,13 @@ rationalexp: booleanatom
|
||||||
| rationalexp OP_AND rationalexp
|
| rationalexp OP_AND rationalexp
|
||||||
{ $$ = multop::instance(multop::And, $1, $3); }
|
{ $$ = multop::instance(multop::And, $1, $3); }
|
||||||
| rationalexp OP_AND error
|
| rationalexp OP_AND error
|
||||||
{ missing_right_binop($$, $1, @2, "and operator"); }
|
{ missing_right_binop($$, $1, @2,
|
||||||
|
"length-matching and operator"); }
|
||||||
|
| rationalexp OP_SHORT_AND rationalexp
|
||||||
|
{ $$ = multop::instance(multop::AndNLM, $1, $3); }
|
||||||
|
| rationalexp OP_SHORT_AND error
|
||||||
|
{ missing_right_binop($$, $1, @2,
|
||||||
|
"non-length-matching and operator"); }
|
||||||
| rationalexp OP_OR rationalexp
|
| rationalexp OP_OR rationalexp
|
||||||
{ $$ = multop::instance(multop::Or, $1, $3); }
|
{ $$ = multop::instance(multop::Or, $1, $3); }
|
||||||
| rationalexp OP_OR error
|
| rationalexp OP_OR error
|
||||||
|
|
@ -318,6 +325,10 @@ subformula: booleanatom
|
||||||
{ $$ = multop::instance(multop::And, $1, $3); }
|
{ $$ = multop::instance(multop::And, $1, $3); }
|
||||||
| subformula OP_AND error
|
| subformula OP_AND error
|
||||||
{ missing_right_binop($$, $1, @2, "and operator"); }
|
{ missing_right_binop($$, $1, @2, "and operator"); }
|
||||||
|
| subformula OP_SHORT_AND subformula
|
||||||
|
{ $$ = multop::instance(multop::And, $1, $3); }
|
||||||
|
| subformula OP_SHORT_AND error
|
||||||
|
{ missing_right_binop($$, $1, @2, "and operator"); }
|
||||||
| subformula OP_OR subformula
|
| subformula OP_OR subformula
|
||||||
{ $$ = multop::instance(multop::Or, $1, $3); }
|
{ $$ = multop::instance(multop::Or, $1, $3); }
|
||||||
| subformula OP_OR error
|
| subformula OP_OR error
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,8 @@ flex_set_buffer(const char* buf, int start_tok)
|
||||||
/\, \/, and xor are from LBTT.
|
/\, \/, and xor are from LBTT.
|
||||||
--> and <--> come from Goal. */
|
--> and <--> come from Goal. */
|
||||||
"||"|"|"|"+"|"\\/" BEGIN(0); return token::OP_OR;
|
"||"|"|"|"+"|"\\/" BEGIN(0); return token::OP_OR;
|
||||||
"&&"|"&"|"/\\" BEGIN(0); return token::OP_AND;
|
"&&"|"/\\" BEGIN(0); return token::OP_AND;
|
||||||
|
"&" BEGIN(0); return token::OP_SHORT_AND;
|
||||||
"^"|"xor" BEGIN(0); return token::OP_XOR;
|
"^"|"xor" BEGIN(0); return token::OP_XOR;
|
||||||
"=>"|"->"|"-->" BEGIN(0); return token::OP_IMPLIES;
|
"=>"|"->"|"-->" BEGIN(0); return token::OP_IMPLIES;
|
||||||
"<=>"|"<->"|"<-->" BEGIN(0); return token::OP_EQUIV;
|
"<=>"|"<->"|"<-->" BEGIN(0); return token::OP_EQUIV;
|
||||||
|
|
|
||||||
|
|
@ -786,6 +786,7 @@ namespace spot
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case multop::Concat:
|
case multop::Concat:
|
||||||
|
case multop::AndNLM:
|
||||||
case multop::Fusion:
|
case multop::Fusion:
|
||||||
std::copy(res->begin(), res->end(), tmpOther->end());
|
std::copy(res->begin(), res->end(), tmpOther->end());
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -122,6 +122,7 @@ namespace spot
|
||||||
return;
|
return;
|
||||||
break;
|
break;
|
||||||
case multop::And:
|
case multop::And:
|
||||||
|
case multop::AndNLM:
|
||||||
case multop::Concat:
|
case multop::Concat:
|
||||||
result_ &= r;
|
result_ &= r;
|
||||||
if (!result_)
|
if (!result_)
|
||||||
|
|
|
||||||
|
|
@ -357,6 +357,7 @@ namespace spot
|
||||||
break;
|
break;
|
||||||
case multop::Concat:
|
case multop::Concat:
|
||||||
case multop::Fusion:
|
case multop::Fusion:
|
||||||
|
case multop::AndNLM:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (changed)
|
if (changed)
|
||||||
|
|
|
||||||
|
|
@ -203,6 +203,7 @@ namespace spot
|
||||||
res->push_back(recurse(mo->nth(i)));
|
res->push_back(recurse(mo->nth(i)));
|
||||||
break;
|
break;
|
||||||
case multop::And:
|
case multop::And:
|
||||||
|
case multop::AndNLM:
|
||||||
{
|
{
|
||||||
typedef std::set<std::pair<formula*, formula*> > pset;
|
typedef std::set<std::pair<formula*, formula*> > pset;
|
||||||
pset Epairs, EMpairs;
|
pset Epairs, EMpairs;
|
||||||
|
|
|
||||||
|
|
@ -233,6 +233,7 @@ namespace spot
|
||||||
break;
|
break;
|
||||||
case multop::Concat:
|
case multop::Concat:
|
||||||
case multop::Fusion:
|
case multop::Fusion:
|
||||||
|
case multop::AndNLM:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
multop::vec* res = new multop::vec;
|
multop::vec* res = new multop::vec;
|
||||||
|
|
@ -249,12 +250,12 @@ namespace spot
|
||||||
}
|
}
|
||||||
case multop::Concat:
|
case multop::Concat:
|
||||||
case multop::Fusion:
|
case multop::Fusion:
|
||||||
|
case multop::AndNLM:
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < mos; ++i)
|
for (unsigned i = 0; i < mos; ++i)
|
||||||
res->push_back(recurse_(mo->nth(i), false));
|
res->push_back(recurse_(mo->nth(i), false));
|
||||||
result_ = multop::instance(op, res);
|
result_ = multop::instance(op, res);
|
||||||
if (negated_)
|
assert(!negated_);
|
||||||
result_ = unop::instance(unop::Not, result_);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -205,6 +205,7 @@ namespace spot
|
||||||
break;
|
break;
|
||||||
case multop::Concat:
|
case multop::Concat:
|
||||||
case multop::Fusion:
|
case multop::Fusion:
|
||||||
|
case multop::AndNLM:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -462,6 +463,7 @@ namespace spot
|
||||||
break;
|
break;
|
||||||
case multop::Concat:
|
case multop::Concat:
|
||||||
case multop::Fusion:
|
case multop::Fusion:
|
||||||
|
case multop::AndNLM:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,8 @@ namespace spot
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
to_string_visitor(std::ostream& os, bool full_parent = false)
|
to_string_visitor(std::ostream& os, bool full_parent = false)
|
||||||
: os_(os), top_level_(true), full_parent_(full_parent)
|
: os_(os), top_level_(true),
|
||||||
|
full_parent_(full_parent), in_ratexp_(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -71,6 +72,18 @@ namespace spot
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
openp() const
|
||||||
|
{
|
||||||
|
os_ << (in_ratexp_ ? "{" : "(");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
closep() const
|
||||||
|
{
|
||||||
|
os_ << (in_ratexp_ ? "}" : ")");
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
visit(const atomic_prop* ap)
|
visit(const atomic_prop* ap)
|
||||||
{
|
{
|
||||||
|
|
@ -93,31 +106,30 @@ namespace spot
|
||||||
visit(const constant* c)
|
visit(const constant* c)
|
||||||
{
|
{
|
||||||
if (full_parent_)
|
if (full_parent_)
|
||||||
os_ << "(";
|
openp();
|
||||||
os_ << c->val_name();
|
os_ << c->val_name();
|
||||||
if (full_parent_)
|
if (full_parent_)
|
||||||
os_ << ")";
|
closep();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
visit(const binop* bo)
|
visit(const binop* bo)
|
||||||
{
|
{
|
||||||
bool top_level = top_level_;
|
bool top_level = top_level_;
|
||||||
|
top_level_ = false;
|
||||||
if (!top_level)
|
if (!top_level)
|
||||||
os_ << "(";
|
openp();
|
||||||
|
|
||||||
switch (bo->op())
|
switch (bo->op())
|
||||||
{
|
{
|
||||||
case binop::UConcat:
|
case binop::UConcat:
|
||||||
case binop::EConcat:
|
case binop::EConcat:
|
||||||
case binop::EConcatMarked:
|
case binop::EConcatMarked:
|
||||||
os_ << "{ ";
|
os_ << "{";
|
||||||
|
in_ratexp_ = true;
|
||||||
top_level_ = true;
|
top_level_ = true;
|
||||||
bo->first()->accept(*this);
|
// fall through
|
||||||
top_level_ = false;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
top_level_ = false;
|
|
||||||
bo->first()->accept(*this);
|
bo->first()->accept(*this);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -146,19 +158,25 @@ namespace spot
|
||||||
os_ << " M ";
|
os_ << " M ";
|
||||||
break;
|
break;
|
||||||
case binop::UConcat:
|
case binop::UConcat:
|
||||||
os_ << " }[]-> ";
|
os_ << "} []-> ";
|
||||||
|
in_ratexp_ = false;
|
||||||
|
top_level_ = top_level;
|
||||||
break;
|
break;
|
||||||
case binop::EConcat:
|
case binop::EConcat:
|
||||||
os_ << " }<>-> ";
|
os_ << "} <>-> ";
|
||||||
|
in_ratexp_ = false;
|
||||||
|
top_level_ = false;
|
||||||
break;
|
break;
|
||||||
case binop::EConcatMarked:
|
case binop::EConcatMarked:
|
||||||
os_ << " }<>+> ";
|
os_ << "} <>+> ";
|
||||||
|
in_ratexp_ = false;
|
||||||
|
top_level_ = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
bo->second()->accept(*this);
|
bo->second()->accept(*this);
|
||||||
if (!top_level)
|
if (!top_level)
|
||||||
os_ << ")";
|
closep();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -175,7 +193,7 @@ namespace spot
|
||||||
need_parent = false; // These will be printed by each subformula
|
need_parent = false; // These will be printed by each subformula
|
||||||
|
|
||||||
if (!top_level)
|
if (!top_level)
|
||||||
os_ << "(";
|
openp();
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (uo->op())
|
switch (uo->op())
|
||||||
|
|
@ -199,13 +217,16 @@ namespace spot
|
||||||
break;
|
break;
|
||||||
case unop::Closure:
|
case unop::Closure:
|
||||||
os_ << "{";
|
os_ << "{";
|
||||||
|
in_ratexp_ = true;
|
||||||
top_level_ = true;
|
top_level_ = true;
|
||||||
break;
|
break;
|
||||||
case unop::NegClosure:
|
case unop::NegClosure:
|
||||||
os_ << "!{";
|
os_ << "!{";
|
||||||
|
in_ratexp_ = true;
|
||||||
|
top_level_ = true;
|
||||||
break;
|
break;
|
||||||
case unop::Star:
|
case unop::Star:
|
||||||
// 1* is OK, no need to print (1)*.
|
// 1* is OK, no need to print {1}*.
|
||||||
need_parent = false;
|
need_parent = false;
|
||||||
// Do not output anything yet, star is a postfix operator.
|
// Do not output anything yet, star is a postfix operator.
|
||||||
break;
|
break;
|
||||||
|
|
@ -213,10 +234,10 @@ namespace spot
|
||||||
|
|
||||||
top_level_ = false;
|
top_level_ = false;
|
||||||
if (need_parent || full_parent_)
|
if (need_parent || full_parent_)
|
||||||
os_ << "(";
|
openp();
|
||||||
uo->child()->accept(*this);
|
uo->child()->accept(*this);
|
||||||
if (need_parent)
|
if (need_parent || full_parent_)
|
||||||
os_ << ")";
|
closep();
|
||||||
|
|
||||||
switch (uo->op())
|
switch (uo->op())
|
||||||
{
|
{
|
||||||
|
|
@ -226,6 +247,7 @@ namespace spot
|
||||||
case unop::Closure:
|
case unop::Closure:
|
||||||
case unop::NegClosure:
|
case unop::NegClosure:
|
||||||
os_ << "}";
|
os_ << "}";
|
||||||
|
in_ratexp_ = false;
|
||||||
top_level_ = false;
|
top_level_ = false;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -233,7 +255,7 @@ namespace spot
|
||||||
}
|
}
|
||||||
|
|
||||||
if (full_parent_ && !top_level)
|
if (full_parent_ && !top_level)
|
||||||
os_ << ")";
|
closep();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -264,7 +286,7 @@ namespace spot
|
||||||
bool top_level = top_level_;
|
bool top_level = top_level_;
|
||||||
top_level_ = false;
|
top_level_ = false;
|
||||||
if (!top_level)
|
if (!top_level)
|
||||||
os_ << "(";
|
openp();
|
||||||
unsigned max = mo->size();
|
unsigned max = mo->size();
|
||||||
mo->nth(0)->accept(*this);
|
mo->nth(0)->accept(*this);
|
||||||
const char* ch = " ";
|
const char* ch = " ";
|
||||||
|
|
@ -274,6 +296,9 @@ namespace spot
|
||||||
ch = " | ";
|
ch = " | ";
|
||||||
break;
|
break;
|
||||||
case multop::And:
|
case multop::And:
|
||||||
|
ch = in_ratexp_ ? " && " : " & ";
|
||||||
|
break;
|
||||||
|
case multop::AndNLM:
|
||||||
ch = " & ";
|
ch = " & ";
|
||||||
break;
|
break;
|
||||||
case multop::Concat:
|
case multop::Concat:
|
||||||
|
|
@ -290,12 +315,13 @@ namespace spot
|
||||||
mo->nth(n)->accept(*this);
|
mo->nth(n)->accept(*this);
|
||||||
}
|
}
|
||||||
if (!top_level)
|
if (!top_level)
|
||||||
os_ << ")";
|
closep();
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
std::ostream& os_;
|
std::ostream& os_;
|
||||||
bool top_level_;
|
bool top_level_;
|
||||||
bool full_parent_;
|
bool full_parent_;
|
||||||
|
bool in_ratexp_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class to_spin_string_visitor : public to_string_visitor
|
class to_spin_string_visitor : public to_string_visitor
|
||||||
|
|
@ -317,7 +343,7 @@ namespace spot
|
||||||
bool top_level = top_level_;
|
bool top_level = top_level_;
|
||||||
top_level_ = false;
|
top_level_ = false;
|
||||||
if (!top_level)
|
if (!top_level)
|
||||||
os_ << "(";
|
openp();
|
||||||
|
|
||||||
switch (bo->op())
|
switch (bo->op())
|
||||||
{
|
{
|
||||||
|
|
@ -361,17 +387,26 @@ namespace spot
|
||||||
break;
|
break;
|
||||||
case binop::UConcat:
|
case binop::UConcat:
|
||||||
bo->first()->accept(*this);
|
bo->first()->accept(*this);
|
||||||
os_ << " []-> ";
|
os_ << "} []-> ";
|
||||||
|
top_level_ = false;
|
||||||
bo->second()->accept(*this);
|
bo->second()->accept(*this);
|
||||||
break;
|
break;
|
||||||
case binop::EConcat:
|
case binop::EConcat:
|
||||||
|
in_ratexp_ = true;
|
||||||
|
top_level_ = true;
|
||||||
|
os_ << "{";
|
||||||
bo->first()->accept(*this);
|
bo->first()->accept(*this);
|
||||||
os_ << " <>-> ";
|
os_ << "} <>-> ";
|
||||||
|
top_level_ = false;
|
||||||
bo->second()->accept(*this);
|
bo->second()->accept(*this);
|
||||||
break;
|
break;
|
||||||
case binop::EConcatMarked:
|
case binop::EConcatMarked:
|
||||||
|
in_ratexp_ = true;
|
||||||
|
top_level_ = true;
|
||||||
|
os_ << "{";
|
||||||
bo->first()->accept(*this);
|
bo->first()->accept(*this);
|
||||||
os_ << " <>+> ";
|
os_ << "} <>+> ";
|
||||||
|
top_level_ = false;
|
||||||
bo->second()->accept(*this);
|
bo->second()->accept(*this);
|
||||||
break;
|
break;
|
||||||
/* W and M are not supported by Spin */
|
/* W and M are not supported by Spin */
|
||||||
|
|
@ -388,7 +423,7 @@ namespace spot
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!top_level)
|
if (!top_level)
|
||||||
os_ << ")";
|
closep();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -396,7 +431,7 @@ namespace spot
|
||||||
{
|
{
|
||||||
bool top_level = top_level_;
|
bool top_level = top_level_;
|
||||||
if (full_parent_ && !top_level)
|
if (full_parent_ && !top_level)
|
||||||
os_ << "(";
|
openp();
|
||||||
|
|
||||||
bool need_parent = false;
|
bool need_parent = false;
|
||||||
top_level_ = false;
|
top_level_ = false;
|
||||||
|
|
@ -426,23 +461,24 @@ namespace spot
|
||||||
case unop::Closure:
|
case unop::Closure:
|
||||||
os_ << "{";
|
os_ << "{";
|
||||||
top_level_ = true;
|
top_level_ = true;
|
||||||
|
in_ratexp_ = true;
|
||||||
break;
|
break;
|
||||||
case unop::NegClosure:
|
case unop::NegClosure:
|
||||||
os_ << "!{";
|
os_ << "!{";
|
||||||
top_level_ = true;
|
top_level_ = true;
|
||||||
|
in_ratexp_ = true;
|
||||||
break;
|
break;
|
||||||
case unop::Star:
|
case unop::Star:
|
||||||
// Do not output anything yet, star is a postfix operator.
|
// Do not output anything yet, star is a postfix operator.
|
||||||
|
need_parent = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (need_parent)
|
if (need_parent)
|
||||||
os_ << "(";
|
openp();
|
||||||
uo->child()->accept(*this);
|
uo->child()->accept(*this);
|
||||||
if (need_parent)
|
if (need_parent)
|
||||||
os_ << ")";
|
closep();
|
||||||
if (uo->op() == unop::Star)
|
|
||||||
os_ << "*";
|
|
||||||
|
|
||||||
switch (uo->op())
|
switch (uo->op())
|
||||||
{
|
{
|
||||||
|
|
@ -452,6 +488,7 @@ namespace spot
|
||||||
case unop::Closure:
|
case unop::Closure:
|
||||||
case unop::NegClosure:
|
case unop::NegClosure:
|
||||||
os_ << "}";
|
os_ << "}";
|
||||||
|
in_ratexp_ = false;
|
||||||
top_level_ = false;
|
top_level_ = false;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -459,29 +496,7 @@ namespace spot
|
||||||
}
|
}
|
||||||
|
|
||||||
if (full_parent_ && !top_level)
|
if (full_parent_ && !top_level)
|
||||||
os_ << ")";
|
closep();
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
visit(const automatop* ao)
|
|
||||||
{
|
|
||||||
// Warning: this string isn't parsable because the automaton
|
|
||||||
// operators used may not be defined.
|
|
||||||
bool top_level = top_level_;
|
|
||||||
top_level_ = false;
|
|
||||||
if (!top_level)
|
|
||||||
os_ << "(";
|
|
||||||
os_ << ao->get_nfa()->get_name() << "(";
|
|
||||||
unsigned max = ao->size();
|
|
||||||
ao->nth(0)->accept(*this);
|
|
||||||
for (unsigned n = 1; n < max; ++n)
|
|
||||||
{
|
|
||||||
os_ << ",";
|
|
||||||
ao->nth(n)->accept(*this);
|
|
||||||
}
|
|
||||||
os_ << ")";
|
|
||||||
if (!top_level)
|
|
||||||
os_ << ")";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -490,7 +505,7 @@ namespace spot
|
||||||
bool top_level = top_level_;
|
bool top_level = top_level_;
|
||||||
top_level_ = false;
|
top_level_ = false;
|
||||||
if (!top_level)
|
if (!top_level)
|
||||||
os_ << "(";
|
openp();
|
||||||
unsigned max = mo->size();
|
unsigned max = mo->size();
|
||||||
mo->nth(0)->accept(*this);
|
mo->nth(0)->accept(*this);
|
||||||
const char* ch = " ";
|
const char* ch = " ";
|
||||||
|
|
@ -502,6 +517,9 @@ namespace spot
|
||||||
case multop::And:
|
case multop::And:
|
||||||
ch = " && ";
|
ch = " && ";
|
||||||
break;
|
break;
|
||||||
|
case multop::AndNLM:
|
||||||
|
ch = " & ";
|
||||||
|
break;
|
||||||
case multop::Concat:
|
case multop::Concat:
|
||||||
ch = ";";
|
ch = ";";
|
||||||
break;
|
break;
|
||||||
|
|
@ -516,7 +534,7 @@ namespace spot
|
||||||
mo->nth(n)->accept(*this);
|
mo->nth(n)->accept(*this);
|
||||||
}
|
}
|
||||||
if (!top_level)
|
if (!top_level)
|
||||||
os_ << ")";
|
closep();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -145,6 +145,7 @@ namespace spot
|
||||||
break;
|
break;
|
||||||
case multop::Concat:
|
case multop::Concat:
|
||||||
case multop::Fusion:
|
case multop::Fusion:
|
||||||
|
case multop::AndNLM:
|
||||||
assert(!"unsupported operator");
|
assert(!"unsupported operator");
|
||||||
}
|
}
|
||||||
assert(op != -1);
|
assert(op != -1);
|
||||||
|
|
|
||||||
|
|
@ -162,6 +162,7 @@ namespace spot
|
||||||
break;
|
break;
|
||||||
case multop::Concat:
|
case multop::Concat:
|
||||||
case multop::Fusion:
|
case multop::Fusion:
|
||||||
|
case multop::AndNLM:
|
||||||
assert(!"unsupported operator");
|
assert(!"unsupported operator");
|
||||||
}
|
}
|
||||||
assert(op != -1);
|
assert(op != -1);
|
||||||
|
|
|
||||||
|
|
@ -326,6 +326,7 @@ namespace spot
|
||||||
return;
|
return;
|
||||||
case multop::Concat:
|
case multop::Concat:
|
||||||
case multop::Fusion:
|
case multop::Fusion:
|
||||||
|
case multop::AndNLM:
|
||||||
assert(!"unsupported operator");
|
assert(!"unsupported operator");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -158,7 +158,7 @@ namespace spot
|
||||||
}
|
}
|
||||||
|
|
||||||
formula*
|
formula*
|
||||||
conj_bdd_to_formula(bdd b) const
|
conj_bdd_to_formula(bdd b, multop::type op = multop::And) const
|
||||||
{
|
{
|
||||||
if (b == bddfalse)
|
if (b == bddfalse)
|
||||||
return constant::false_instance();
|
return constant::false_instance();
|
||||||
|
|
@ -181,7 +181,7 @@ namespace spot
|
||||||
assert(b != bddfalse);
|
assert(b != bddfalse);
|
||||||
v->push_back(res);
|
v->push_back(res);
|
||||||
}
|
}
|
||||||
return multop::instance(multop::And, v);
|
return multop::instance(op, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
formula*
|
formula*
|
||||||
|
|
@ -297,12 +297,8 @@ namespace spot
|
||||||
class ratexp_trad_visitor: public const_visitor
|
class ratexp_trad_visitor: public const_visitor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ratexp_trad_visitor(translate_dict& dict,
|
ratexp_trad_visitor(translate_dict& dict, formula* to_concat = 0)
|
||||||
bool empty_word_is_true,
|
: dict_(dict), to_concat_(to_concat)
|
||||||
formula* to_concat = 0)
|
|
||||||
: dict_(dict),
|
|
||||||
empty_word_is_true_(empty_word_is_true),
|
|
||||||
to_concat_(to_concat)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -332,7 +328,7 @@ namespace spot
|
||||||
if (to_concat_ && to_concat_ != constant::empty_word_instance())
|
if (to_concat_ && to_concat_ != constant::empty_word_instance())
|
||||||
return recurse(to_concat_);
|
return recurse(to_concat_);
|
||||||
|
|
||||||
return empty_word_is_true_ ? bddtrue : bddfalse;
|
return bddfalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -408,25 +404,82 @@ namespace spot
|
||||||
void
|
void
|
||||||
visit(const multop* node)
|
visit(const multop* node)
|
||||||
{
|
{
|
||||||
switch (node->op())
|
multop::type op = node->op();
|
||||||
|
switch (op)
|
||||||
{
|
{
|
||||||
|
case multop::AndNLM:
|
||||||
case multop::And:
|
case multop::And:
|
||||||
{
|
{
|
||||||
res_ = bddtrue;
|
|
||||||
unsigned s = node->size();
|
unsigned s = node->size();
|
||||||
|
|
||||||
|
if (op == multop::AndNLM)
|
||||||
|
{
|
||||||
|
multop::vec* final = new multop::vec;
|
||||||
|
multop::vec* non_final = new multop::vec;
|
||||||
|
|
||||||
|
for (unsigned n = 0; n < s; ++n)
|
||||||
|
{
|
||||||
|
const formula* f = node->nth(n);
|
||||||
|
if (constant_term_as_bool(f))
|
||||||
|
final->push_back(f->clone());
|
||||||
|
else
|
||||||
|
non_final->push_back(f->clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (non_final->empty())
|
||||||
|
{
|
||||||
|
delete non_final;
|
||||||
|
// (a* & b*);c = (a*|b*);c
|
||||||
|
formula* f = multop::instance(multop::Or, final);
|
||||||
|
res_ = recurse_and_concat(f);
|
||||||
|
f->destroy();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!final->empty())
|
||||||
|
{
|
||||||
|
// let F_i be final formulae
|
||||||
|
// N_i be non final formula
|
||||||
|
// (F_1 & ... & F_n & N_1 & ... & N_m)
|
||||||
|
// = (F_1 | ... | F_n);[*] && (N_1 & ... & N_m)
|
||||||
|
// | (F_1 | ... | F_n) && (N_1 & ... & N_m);[*]
|
||||||
|
formula* f = multop::instance(multop::Or, final);
|
||||||
|
formula* n = multop::instance(multop::AndNLM, non_final);
|
||||||
|
formula* t = unop::instance(unop::Star,
|
||||||
|
constant::true_instance());
|
||||||
|
formula* ft = multop::instance(multop::Concat,
|
||||||
|
f->clone(), t->clone());
|
||||||
|
formula* nt = multop::instance(multop::Concat,
|
||||||
|
n->clone(), t);
|
||||||
|
formula* ftn = multop::instance(multop::And, ft, n);
|
||||||
|
formula* fnt = multop::instance(multop::And, f, nt);
|
||||||
|
formula* all = multop::instance(multop::Or, ftn, fnt);
|
||||||
|
res_ = recurse_and_concat(all);
|
||||||
|
all->destroy();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// No final formula.
|
||||||
|
// Apply same rule as &&, until we reach a point where
|
||||||
|
// we have final formulae.
|
||||||
|
delete final;
|
||||||
|
for (unsigned n = 0; n < s; ++n)
|
||||||
|
(*non_final)[n]->destroy();
|
||||||
|
delete non_final;
|
||||||
|
}
|
||||||
|
|
||||||
|
res_ = bddtrue;
|
||||||
for (unsigned n = 0; n < s; ++n)
|
for (unsigned n = 0; n < s; ++n)
|
||||||
{
|
{
|
||||||
bdd res = recurse(node->nth(n));
|
bdd res = recurse(node->nth(n));
|
||||||
// trace_ltl_bdd(dict_, res);
|
// trace_ltl_bdd(dict_, res);
|
||||||
res_ &= res;
|
res_ &= res;
|
||||||
}
|
}
|
||||||
|
|
||||||
//std::cerr << "Pre-Concat:" << std::endl;
|
//std::cerr << "Pre-Concat:" << std::endl;
|
||||||
//trace_ltl_bdd(dict_, res_);
|
//trace_ltl_bdd(dict_, res_);
|
||||||
|
|
||||||
if (to_concat_)
|
if (to_concat_)
|
||||||
{
|
{
|
||||||
// If we have translated (a* & b*) in (a* & b*);c, we
|
// If we have translated (a* && b*) in (a* && b*);c, we
|
||||||
// have to append ";c" to all destinations.
|
// have to append ";c" to all destinations.
|
||||||
|
|
||||||
minato_isop isop(res_);
|
minato_isop isop(res_);
|
||||||
|
|
@ -436,7 +489,8 @@ namespace spot
|
||||||
{
|
{
|
||||||
bdd label = bdd_exist(cube, dict_.next_set);
|
bdd label = bdd_exist(cube, dict_.next_set);
|
||||||
bdd dest_bdd = bdd_existcomp(cube, dict_.next_set);
|
bdd dest_bdd = bdd_existcomp(cube, dict_.next_set);
|
||||||
formula* dest = dict_.conj_bdd_to_formula(dest_bdd);
|
formula* dest =
|
||||||
|
dict_.conj_bdd_to_formula(dest_bdd, op);
|
||||||
formula* dest2;
|
formula* dest2;
|
||||||
int x;
|
int x;
|
||||||
if (dest == constant::empty_word_instance())
|
if (dest == constant::empty_word_instance())
|
||||||
|
|
@ -458,6 +512,8 @@ namespace spot
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (constant_term_as_bool(node))
|
||||||
|
res_ |= now_to_concat();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -465,12 +521,8 @@ namespace spot
|
||||||
{
|
{
|
||||||
res_ = bddfalse;
|
res_ = bddfalse;
|
||||||
unsigned s = node->size();
|
unsigned s = node->size();
|
||||||
if (to_concat_)
|
for (unsigned n = 0; n < s; ++n)
|
||||||
for (unsigned n = 0; n < s; ++n)
|
res_ |= recurse_and_concat(node->nth(n));
|
||||||
res_ |= recurse(node->nth(n), to_concat_->clone());
|
|
||||||
else
|
|
||||||
for (unsigned n = 0; n < s; ++n)
|
|
||||||
res_ |= recurse(node->nth(n));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case multop::Concat:
|
case multop::Concat:
|
||||||
|
|
@ -520,9 +572,7 @@ namespace spot
|
||||||
// can also exit if tail is satisfied.
|
// can also exit if tail is satisfied.
|
||||||
if (!tail_computed)
|
if (!tail_computed)
|
||||||
{
|
{
|
||||||
tail_bdd = recurse(tail,
|
tail_bdd = recurse_and_concat(tail);
|
||||||
to_concat_ ?
|
|
||||||
to_concat_->clone() : 0);
|
|
||||||
tail_computed = true;
|
tail_computed = true;
|
||||||
}
|
}
|
||||||
res_ |= label & tail_bdd;
|
res_ |= label & tail_bdd;
|
||||||
|
|
@ -556,16 +606,20 @@ namespace spot
|
||||||
bdd
|
bdd
|
||||||
recurse(const formula* f, formula* to_concat = 0)
|
recurse(const formula* f, formula* to_concat = 0)
|
||||||
{
|
{
|
||||||
ratexp_trad_visitor v(dict_, empty_word_is_true_, to_concat);
|
ratexp_trad_visitor v(dict_, to_concat);
|
||||||
f->accept(v);
|
f->accept(v);
|
||||||
return v.result();
|
return v.result();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bdd
|
||||||
|
recurse_and_concat(const formula* f)
|
||||||
|
{
|
||||||
|
return recurse(f, to_concat_ ? to_concat_->clone() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
translate_dict& dict_;
|
translate_dict& dict_;
|
||||||
bdd res_;
|
bdd res_;
|
||||||
bool empty_word_is_true_;
|
|
||||||
formula* to_concat_;
|
formula* to_concat_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -697,11 +751,18 @@ namespace spot
|
||||||
case unop::Closure:
|
case unop::Closure:
|
||||||
{
|
{
|
||||||
rat_seen_ = true;
|
rat_seen_ = true;
|
||||||
ratexp_trad_visitor v(dict_, true);
|
if (constant_term_as_bool(node->child()))
|
||||||
|
{
|
||||||
|
res_ = bddtrue;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ratexp_trad_visitor v(dict_);
|
||||||
node->child()->accept(v);
|
node->child()->accept(v);
|
||||||
bdd f1 = v.result();
|
bdd f1 = v.result();
|
||||||
res_ = bddfalse;
|
res_ = bddfalse;
|
||||||
|
|
||||||
|
|
||||||
if (exprop_)
|
if (exprop_)
|
||||||
{
|
{
|
||||||
bdd var_set = bdd_existcomp(bdd_support(f1), dict_.var_set);
|
bdd var_set = bdd_existcomp(bdd_support(f1), dict_.var_set);
|
||||||
|
|
@ -766,7 +827,14 @@ namespace spot
|
||||||
{
|
{
|
||||||
rat_seen_ = true;
|
rat_seen_ = true;
|
||||||
has_marked_ = true;
|
has_marked_ = true;
|
||||||
ratexp_trad_visitor v(dict_, true);
|
|
||||||
|
if (constant_term_as_bool(node->child()))
|
||||||
|
{
|
||||||
|
res_ = bddfalse;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ratexp_trad_visitor v(dict_);
|
||||||
node->child()->accept(v);
|
node->child()->accept(v);
|
||||||
bdd f1 = v.result();
|
bdd f1 = v.result();
|
||||||
|
|
||||||
|
|
@ -893,7 +961,7 @@ namespace spot
|
||||||
// Recognize f2 on transitions going to destinations
|
// Recognize f2 on transitions going to destinations
|
||||||
// that accept the empty word.
|
// that accept the empty word.
|
||||||
bdd f2 = recurse(node->second());
|
bdd f2 = recurse(node->second());
|
||||||
ratexp_trad_visitor v(dict_, false);
|
ratexp_trad_visitor v(dict_);
|
||||||
node->first()->accept(v);
|
node->first()->accept(v);
|
||||||
bdd f1 = v.result();
|
bdd f1 = v.result();
|
||||||
res_ = bddfalse;
|
res_ = bddfalse;
|
||||||
|
|
@ -968,7 +1036,7 @@ namespace spot
|
||||||
// word should recognize f2, and the automaton for f1
|
// word should recognize f2, and the automaton for f1
|
||||||
// should be understood as universal.
|
// should be understood as universal.
|
||||||
bdd f2 = recurse(node->second());
|
bdd f2 = recurse(node->second());
|
||||||
ratexp_trad_visitor v(dict_, false);
|
ratexp_trad_visitor v(dict_);
|
||||||
node->first()->accept(v);
|
node->first()->accept(v);
|
||||||
bdd f1 = v.result();
|
bdd f1 = v.result();
|
||||||
res_ = bddtrue;
|
res_ = bddtrue;
|
||||||
|
|
@ -1067,6 +1135,7 @@ namespace spot
|
||||||
}
|
}
|
||||||
case multop::Concat:
|
case multop::Concat:
|
||||||
case multop::Fusion:
|
case multop::Fusion:
|
||||||
|
case multop::AndNLM:
|
||||||
assert(!"Not an LTL operator");
|
assert(!"Not an LTL operator");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -260,6 +260,7 @@ namespace spot
|
||||||
break;
|
break;
|
||||||
case multop::Concat:
|
case multop::Concat:
|
||||||
case multop::Fusion:
|
case multop::Fusion:
|
||||||
|
case multop::AndNLM:
|
||||||
assert(!"unsupported operator");
|
assert(!"unsupported operator");
|
||||||
}
|
}
|
||||||
assert(op != -1);
|
assert(op != -1);
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,10 @@ check_psl '{a;b}'
|
||||||
check_psl '{(a;b)*}'
|
check_psl '{(a;b)*}'
|
||||||
check_psl 'G{(a;b)*}'
|
check_psl 'G{(a;b)*}'
|
||||||
check_psl '{a*}[]->{b*}'
|
check_psl '{a*}[]->{b*}'
|
||||||
|
check_psl '{a*&b}'
|
||||||
|
check_psl '{a*&b*}'
|
||||||
|
check_psl '{((c;b*) & d);e}'
|
||||||
|
check_psl '{(a* & (c;b*) & d);e}'
|
||||||
# Example from "Beyond Hardware Verification" by Glazberg, Moulin, Orni,
|
# Example from "Beyond Hardware Verification" by Glazberg, Moulin, Orni,
|
||||||
# Ruah, Zarpas (2007).
|
# Ruah, Zarpas (2007).
|
||||||
check_psl '{1[*];req;ack;1}[]->{start;busy[*];done}'
|
check_psl '{1[*];req;ack;1}[]->{start;busy[*];done}'
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue