introduce op::strong_X

This was prompted by reports by Andrew Wells and Yong Li.

* NEWS, doc/tl/tl.tex: Document the changes.
* THANKS: Add Andrew.
* bin/ltlfilt.cc: Match --ltl before --from-ltlf if needed.
* spot/parsetl/parsedecl.hh, spot/parsetl/parsetl.yy,
spot/parsetl/scantl.ll: Parse X[!].
* spot/tl/formula.cc, spot/tl/formula.hh: Declare the new operator.
* spot/tl/ltlf.cc: Adjust to handle op::X and op::strong_X correctly.
* spot/tl/dot.cc, spot/tl/mark.cc, spot/tl/mutation.cc,
spot/tl/print.cc, spot/tl/simplify.cc, spot/tl/snf.cc,
spot/tl/unabbrev.cc, spot/twa/formula2bdd.cc,
spot/twaalgos/ltl2taa.cc, spot/twaalgos/ltl2tgba_fm.cc,
tests/core/ltlgrind.test, tests/core/rand.test,
tests/core/sugar.test, tests/python/randltl.ipynb: Adjust.
* tests/core/ltlfilt.test, tests/core/sugar.test,
tests/core/utf8.test: More tests.
This commit is contained in:
Alexandre Duret-Lutz 2019-09-22 21:15:55 +02:00
parent b91ba58bbe
commit be389c5c25
26 changed files with 434 additions and 134 deletions

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*-
// Copyright (C) 2010, 2012, 2013, 2014, 2015 Laboratoire de Recherche et
// Copyright (C) 2010, 2012, 2013, 2014, 2015, 2019 Laboratoire de Recherche et
// Développement de l'Epita (LRDE)
// Copyright (C) 2003, 2005 Laboratoire d'Informatique de Paris 6 (LIP6),
// département Systèmes Répartis Coopératifs (SRC), Université Pierre

View file

@ -207,8 +207,10 @@ using namespace spot;
%token OP_U "until operator" OP_R "release operator"
%token OP_W "weak until operator" OP_M "strong release operator"
%token OP_F "sometimes operator" OP_G "always operator"
%token OP_X "next operator" OP_NOT "not operator"
%token OP_XREP "X[.] operator" OP_FREP "F[.] operator" OP_GREP "G[.] operator"
%token OP_X "next operator" OP_STRONG_X "strong next operator"
%token OP_NOT "not operator"
%token OP_XREP "X[.] operator"
%token OP_FREP "F[.] operator" OP_GREP "G[.] operator"
%token OP_STAR "star operator" OP_BSTAR "bracket star operator"
%token OP_BFSTAR "bracket fusion-star operator"
%token OP_PLUS "plus operator"
@ -218,6 +220,7 @@ using namespace spot;
%token OP_EQUAL_OPEN "opening bracket for equal operator"
%token OP_GOTO_OPEN "opening bracket for goto operator"
%token OP_SQBKT_CLOSE "closing bracket"
%token OP_SQBKT_STRONG_CLOSE "closing !]"
%token <num> OP_SQBKT_NUM "number for square bracket operator"
%token OP_UNBOUNDED "unbounded mark"
%token OP_SQBKT_SEP "separator for square bracket operator"
@ -261,7 +264,7 @@ using namespace spot;
/* LTL operators. */
%right OP_U OP_R OP_M OP_W
%precedence OP_F OP_G OP_FREP OP_GREP
%precedence OP_X OP_XREP
%precedence OP_X OP_XREP OP_STRONG_X
/* High priority regex operator. */
%precedence OP_BSTAR OP_STAR_OPEN OP_PLUS
@ -887,16 +890,33 @@ subformula: booleanatom
error_list.emplace_back(@1 + @3,
"F[n:m] expects two parameters");
}
| OP_FREP OP_SQBKT_NUM OP_SQBKT_STRONG_CLOSE subformula
%prec OP_FREP
{ $$ = fnode::nested_unop_range(op::strong_X, op::Or, $2, $2, $4);
error_list.emplace_back(@1 + @3,
"F[n:m!] expects two parameters");
}
| 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 OP_SQBKT_NUM
OP_SQBKT_STRONG_CLOSE subformula %prec OP_FREP
{ $$ = fnode::nested_unop_range(op::strong_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_unbounded OP_SQBKT_STRONG_CLOSE
subformula %prec OP_FREP
{ $$ = fnode::nested_unop_range(op::strong_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"); }
| OP_FREP OP_SQBKT_NUM OP_SQBKT_SEP OP_SQBKT_NUM
OP_SQBKT_STRONG_CLOSE error
{ missing_right_op($$, @1 + @5, "F[.!] operator"); }
| OP_FREP error_opt END_OF_INPUT
{ error_list.emplace_back(@$, "missing closing bracket for F[.]");
$$ = fnode::ff(); }
@ -904,6 +924,10 @@ subformula: booleanatom
{ error_list.emplace_back(@1 + @3,
"treating this F[.] as a simple F");
$$ = fnode::unop(op::F, $4); }
| OP_FREP error OP_SQBKT_STRONG_CLOSE subformula %prec OP_FREP
{ error_list.emplace_back(@1 + @3,
"treating this F[.!] as a simple F");
$$ = fnode::unop(op::F, $4); }
| OP_G subformula
{ $$ = fnode::unop(op::G, $2); }
| OP_G error
@ -911,18 +935,36 @@ 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 OP_SQBKT_NUM
OP_SQBKT_STRONG_CLOSE subformula %prec OP_GREP
{ $$ = fnode::nested_unop_range(op::strong_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_SEP_unbounded OP_SQBKT_STRONG_CLOSE
subformula %prec OP_GREP
{ $$ = fnode::nested_unop_range(op::strong_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,
"G[n:m] expects two parameters");
}
| OP_GREP OP_SQBKT_NUM OP_SQBKT_STRONG_CLOSE subformula
%prec OP_GREP
{ $$ = fnode::nested_unop_range(op::strong_X, op::And,
$2, $2, $4);
error_list.emplace_back(@1 + @3,
"G[n:m!] expects two parameters");
}
| OP_GREP OP_SQBKT_NUM OP_SQBKT_SEP OP_SQBKT_NUM OP_SQBKT_CLOSE
error
{ missing_right_op($$, @1 + @5, "G[.] operator"); }
| OP_GREP OP_SQBKT_NUM OP_SQBKT_SEP OP_SQBKT_NUM
OP_SQBKT_STRONG_CLOSE error
{ missing_right_op($$, @1 + @5, "G[.!] operator"); }
| OP_GREP error_opt END_OF_INPUT
{ error_list.emplace_back(@$, "missing closing bracket for G[.]");
$$ = fnode::ff(); }
@ -930,10 +972,18 @@ subformula: booleanatom
{ error_list.emplace_back(@1 + @3,
"treating this G[.] as a simple G");
$$ = fnode::unop(op::F, $4); }
| OP_GREP error OP_SQBKT_STRONG_CLOSE subformula %prec OP_GREP
{ error_list.emplace_back(@1 + @3,
"treating this G[.!] as a simple G");
$$ = fnode::unop(op::F, $4); }
| OP_X subformula
{ $$ = fnode::unop(op::X, $2); }
| OP_X error
{ missing_right_op($$, @1, "next operator"); }
| OP_STRONG_X subformula
{ $$ = fnode::unop(op::strong_X, $2); }
| OP_STRONG_X error
{ missing_right_op($$, @1, "strong next operator"); }
| OP_XREP OP_SQBKT_NUM OP_SQBKT_CLOSE subformula %prec OP_XREP
{ $$ = fnode::nested_unop_range(op::X, op::Or, $2, $2, $4); }
| OP_XREP OP_SQBKT_NUM OP_SQBKT_CLOSE error
@ -941,6 +991,15 @@ subformula: booleanatom
| OP_XREP error OP_SQBKT_CLOSE subformula %prec OP_XREP
{ error_list.emplace_back(@$, "treating this X[.] as a simple X");
$$ = fnode::unop(op::X, $4); }
| OP_XREP OP_SQBKT_STRONG_CLOSE subformula %prec OP_XREP
{ $$ = fnode::unop(op::strong_X, $3); }
| OP_XREP OP_SQBKT_NUM OP_SQBKT_STRONG_CLOSE subformula
%prec OP_XREP
{ $$ = fnode::nested_unop_range(op::strong_X,
op::Or, $2, $2, $4); }
| OP_XREP error OP_SQBKT_STRONG_CLOSE subformula %prec OP_XREP
{ error_list.emplace_back(@$, "treating this X[.!] as a simple X[!]");
$$ = fnode::unop(op::strong_X, $4); }
| OP_XREP error_opt END_OF_INPUT
{ error_list.emplace_back(@$, "missing closing bracket for X[.]");
$$ = fnode::ff(); }

View file

@ -64,6 +64,7 @@ DARROWL "=>"|"⇒"|"⟹"
ARROWLR "<->"|"<-->"|"↔"
DARROWLR "<=>"|"⇔"
CIRCLE "()"|"○"|"◯"
CIRCLEX "Ⓧ"
NOT "!"|"~"|"¬"
BOXARROW {BOX}{ARROWL}|"|"{ARROWL}|"↦"
BOXDARROW {BOX}{DARROWL}|"|"{DARROWL}|"⤇"
@ -254,6 +255,7 @@ eol2 (\n\r)+|(\r\n)+
"[=" BEGIN(sqbracket); return token::OP_EQUAL_OPEN;
"["{ARROWL} BEGIN(sqbracket); return token::OP_GOTO_OPEN;
<sqbracket>"]" BEGIN(0); return token::OP_SQBKT_CLOSE;
<sqbracket>"!]" BEGIN(0); return token::OP_SQBKT_STRONG_CLOSE;
<sqbracket>[0-9]+ {
errno = 0;
unsigned long n = strtoul(yytext, 0, 10);
@ -313,6 +315,7 @@ eol2 (\n\r)+|(\r\n)+
"U" BEGIN(0); return token::OP_U;
"R"|"V" BEGIN(0); return token::OP_R;
"X"|{CIRCLE} BEGIN(0); return token::OP_X;
{CIRCLEX} BEGIN(0); return token::OP_STRONG_X;
"W" BEGIN(0); return token::OP_W;
"M" BEGIN(0); return token::OP_M;