Introduce [->min..max] operator.

* src/ltlast/bunop.hh: Declare bunop::Goto
* src/ltlast/bunop.cc: Handle it.
* src/ltlparse/ltlparse.yy,
src/ltlparse/ltlscan.ll: Add rules for [->min..max].
* src/tgbaalgos/ltl2tgba_fm.cc: Handle bunop::Goto in
the translation.
* src/ltltest/equals.test: Test trivial identities.
* src/tgbatest/ltl2tgba.test: Test two more formulae using [->].
This commit is contained in:
Alexandre Duret-Lutz 2010-10-15 11:41:18 +02:00
parent 2c31e541b5
commit da74b4f180
7 changed files with 138 additions and 11 deletions

View file

@ -113,6 +113,8 @@ namespace spot
return "Equal";
case Star:
return "Star";
case Goto:
return "Goto";
}
// Unreachable code.
assert(0);
@ -124,6 +126,9 @@ namespace spot
{
std::ostringstream out;
unsigned default_min = 0;
unsigned default_max = unbounded;
switch (op_)
{
case Star:
@ -138,10 +143,36 @@ namespace spot
case Equal:
out << "[=";
break;
case Goto:
out << "[->";
default_min = 1;
default_max = 1;
break;
}
if (min_ != 0 || max_ != unbounded)
// Beware that the default parameters of the Goto operator are
// not the same as Star or Equal:
//
// [->] = [->1..1]
// [->..] = [->1..unbounded]
// [*] = [*0..unbounded]
// [*..] = [*0..unbounded]
// [=] = [=0..unbounded]
// [=..] = [=0..unbounded]
//
// Strictly speaking [=] is not specified by PSL, and anyway we
// automatically rewrite Exp[=0..unbounded] as
// Exp[*0..unbounded], so we should never have to print [=]
// here.
//
// Also
// [*..] = [*0..unbounded]
if (min_ != default_min || max_ != default_max)
{
// Always print the min_, even when it is equal to
// default_min, this way we avoid ambiguities (like
// when reading [*..3] near [*->..2])
out << min_;
if (min_ != max_)
{
@ -208,6 +239,38 @@ namespace spot
unop::instance(unop::Not, child));
break;
}
case Goto:
{
// - 0[->min..max] = 0 if min>0
// - 0[->0..max] = [*0]
if (child == constant::false_instance())
{
if (min == 0)
return constant::empty_word_instance();
else
return child;
}
// - 1[->0] = [*0]
// - 1[->min..max] = 1[*min..max]
if (child == constant::true_instance())
{
if (max == 0)
return constant::empty_word_instance();
else
{
op = Star;
break;
}
}
// - Exp[->0] = [*0]
if (max == 0)
{
child->destroy();
return constant::empty_word_instance();
}
break;
}
case Star:
{
// - [*0][*min..max] = [*0]

View file

@ -37,7 +37,7 @@ namespace spot
class bunop : public ref_formula
{
public:
enum type { Star, Equal };
enum type { Star, Equal, Goto };
static const unsigned unbounded = -1U;
@ -57,6 +57,11 @@ namespace spot
/// - 1[=min..max] = 1[*min..max] if max > 0
/// - Exp[=0..] = [*]
/// - Exp[=0] = (!Exp)[*]
/// - 0[->min..max] = 0 if min>0
/// - 0[->0..max] = [*0]
/// - 1[->0] = [*0]
/// - 1[->min..max] = 1[*min..max]
/// - Exp[->0] = [*0]
///
/// These rewriting rules imply that it is not possible to build
/// an LTL formula object that is SYNTACTICALLY equal to one of