tl: fix handling of f##[0:0]g, and of ##[0:n]g

The first issue was reported by Victor Khomenko.

* spot/tl/formula.cc: Introduce a single-argument
version of sugar_delay().
* spot/parsetl/parsetl.yy: Use it.
* doc/tl/tl.tex, spot/tl/formula.hh: Adjust doc.
* tests/core/ltlfilt.test, tests/core/sugar.test: More tests.
This commit is contained in:
Alexandre Duret-Lutz 2019-05-20 20:59:33 +02:00
parent 66a3b6f7cb
commit 90a88d0b5a
6 changed files with 58 additions and 13 deletions

View file

@ -541,8 +541,7 @@ sere: booleanatom
| sere OP_FUSION error
{ missing_right_binop($$, $1, @2, "fusion operator"); }
| OP_DELAY_N sere
{ $$ = formula::sugar_delay(formula::tt(), formula($2),
$1, $1).to_node_(); }
{ $$ = formula::sugar_delay(formula($2), $1, $1).to_node_(); }
| OP_DELAY_N error
{ missing_right_binop($$, fnode::tt(), @1, "SVA delay operator"); }
| sere OP_DELAY_N sere
@ -557,7 +556,7 @@ sere: booleanatom
error_list.emplace_back(@1, "reversed range");
std::swap($1.max, $1.min);
}
$$ = formula::sugar_delay(formula::tt(), formula($2),
$$ = formula::sugar_delay(formula($2),
$1.min, $1.max).to_node_();
}
| delayargs error

View file

@ -1773,15 +1773,22 @@ namespace spot
return Concat({Star(Concat({s, b}), min, max), s});
}
formula formula::sugar_delay(const formula& b,
unsigned min, unsigned max)
{
// ##[min:max] b = 1[*min:max];b
return Concat({Star(tt(), min, max), b});
}
formula formula::sugar_delay(const formula& a, const formula& b,
unsigned min, unsigned max)
{
// If min>=1
// a ##[min:max] b = a;1[*min-1:max-1];b
// If min==0 we can use
// a ##[min:max] b = a:(1[*0:max];b) if a rejects [*0]
// a ##[min:max] b = (a;1[*0:max]):b if b rejects [*0]
// a ##[min:max] b = (a:b)|(a;[*0:max-1];b) else
// a ##[0:0] b = a:b
// a ##[0:max] b = a:(1[*0:max];b) if a rejects [*0]
// a ##[0:max] b = (a;1[*0:max]):b if b rejects [*0]
// a ##[0:max] b = (a:b)|(a;[*0:max-1];b) else
if (min > 0)
{
--min;
@ -1789,6 +1796,8 @@ namespace spot
--max;
return Concat({a, Star(tt(), min, max), b});
}
if (max == 0)
return Fusion({a, b});
if (!a.accepts_eword())
return Fusion({a, Concat({Star(tt(), 0, max), b})});
if (!b.accepts_eword())

View file

@ -1245,9 +1245,25 @@ namespace spot
///
/// The operator does not exist in Spot it is handled as syntactic
/// sugar by the parser. This function is used by the parser to
/// create the equivalent SERE.
/// create the equivalent SERE using PSL operators.
///
/// The rewriting rules depends on the values of a, n, and b.
/// If n≥1 `a ##[n:m] b` is encoded as `a;1[*n-1,m-1];b`.
/// Otherwise:
/// * `a ##[0:0] b` is encoded as `a:b`,
/// * For m>0, `a ##[0:m] b` is encoded as
/// - `a:(1[*0:m];b)` is `a` rejects `[*0]`,
/// - `(a;1[*0:m]):b` is `b` rejects `[*0]`,
/// - `(a:b) | (a;1[*0:m-1];b)` is `a` and `b` accept `[*0]`.
///
/// The left operand can also be missing, in which case
/// `##[n:m] b` is rewritten as `1[*n:m];b`.
/// @{
static formula sugar_delay(const formula& a, const formula& b,
unsigned min, unsigned max);
static formula sugar_delay(const formula& b,
unsigned min, unsigned max);
/// @}
#ifndef SWIG
/// \brief Return the underlying pointer to the formula.