tl: extend F[n:m] and G[n:m] to the case of m=$

Suggested by Victor Khomenko.

* spot/tl/formula.cc, spot/tl/formula.hh, spot/parsetl/parsetl.yy:
Implement this.
* NEWS, doc/tl/tl.tex: Document it.
* tests/core/sugar.test, tests/python/ltlparse.py: Add some tests.
This commit is contained in:
Alexandre Duret-Lutz 2019-06-02 14:36:07 +02:00
parent 74786324f4
commit 58389bdb80
7 changed files with 57 additions and 16 deletions

View file

@ -887,6 +887,10 @@ subformula: booleanatom
| OP_FREP OP_SQBKT_NUM OP_SQBKT_SEP OP_SQBKT_NUM OP_SQBKT_CLOSE
subformula %prec OP_FREP
{ $$ = fnode::nested_unop_range(op::X, op::Or, $2, $4, $6); }
| OP_FREP OP_SQBKT_NUM OP_SQBKT_SEP_unbounded OP_SQBKT_CLOSE
subformula %prec OP_FREP
{ $$ = fnode::nested_unop_range(op::X, op::Or, $2,
fnode::unbounded(), $5); }
| OP_FREP OP_SQBKT_NUM OP_SQBKT_SEP OP_SQBKT_NUM OP_SQBKT_CLOSE
error
{ missing_right_op($$, @1 + @5, "F[.] operator"); }
@ -904,6 +908,10 @@ subformula: booleanatom
| OP_GREP OP_SQBKT_NUM OP_SQBKT_SEP OP_SQBKT_NUM OP_SQBKT_CLOSE
subformula %prec OP_GREP
{ $$ = fnode::nested_unop_range(op::X, op::And, $2, $4, $6); }
| OP_GREP OP_SQBKT_NUM OP_SQBKT_SEP_unbounded OP_SQBKT_CLOSE
subformula %prec OP_GREP
{ $$ = fnode::nested_unop_range(op::X, op::And, $2,
fnode::unbounded(), $5); }
| OP_GREP OP_SQBKT_NUM OP_SQBKT_CLOSE subformula %prec OP_GREP
{ $$ = fnode::nested_unop_range(op::X, op::And, $2, $2, $4);
error_list.emplace_back(@1 + @3,

View file

@ -1657,11 +1657,14 @@ namespace spot
const fnode* res = f;
if (max < min)
std::swap(min, max);
for (unsigned i = min; i < max; ++i)
{
const fnode* a = f->clone();
res = fnode::multop(bo, {a, fnode::unop(uo, res)});
}
if (max != unbounded())
for (unsigned i = min; i < max; ++i)
{
const fnode* a = f->clone();
res = fnode::multop(bo, {a, fnode::unop(uo, res)});
}
else
res = fnode::unop(bo == op::Or ? op::F : op::G, res);
for (unsigned i = 0; i < min; ++i)
res = fnode::unop(uo, res);
return res;

View file

@ -906,7 +906,8 @@ namespace spot
/// \brief Construct F[n:m]
///
/// F[2:3] = XX(a | Xa)
/// F[2:3]a = XX(a | Xa)
/// F[2:$]a = XXFa
///
/// This syntax is from TSLF; the operator is called next_e![n..m] in PSL.
static formula F(unsigned min_level, unsigned max_level, const formula& f)
@ -916,7 +917,8 @@ namespace spot
/// \brief Construct G[n:m]
///
/// G[2:3] = XX(a & Xa)
/// G[2:3]a = XX(a & Xa)
/// G[2:$]a = XXGa
///
/// This syntax is from TSLF; the operator is called next_a![n..m] in PSL.
static formula G(unsigned min_level, unsigned max_level, const formula& f)
@ -1217,6 +1219,10 @@ namespace spot
///
/// For instance nested_unup_range(op::X, op::Or, 2, 4, a) returns
/// XX(a | X(a | Xa)).
///
/// For `max==unbounded()`, \a uo is repeated \a min times, and
/// its child is set to `F(a)` if \a bo is `op::Or` or to `G(a)`
/// otherwise.
static const formula nested_unop_range(op uo, op bo, unsigned min,
unsigned max, formula f)
{