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:
parent
b91ba58bbe
commit
be389c5c25
26 changed files with 434 additions and 134 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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(); }
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ namespace spot
|
|||
case op::ap:
|
||||
case op::Not:
|
||||
case op::X:
|
||||
case op::strong_X:
|
||||
case op::F:
|
||||
case op::G:
|
||||
case op::Closure:
|
||||
|
|
|
|||
|
|
@ -242,6 +242,7 @@ namespace spot
|
|||
C(Star);
|
||||
C(FStar);
|
||||
C(first_match);
|
||||
C(strong_X);
|
||||
#undef C
|
||||
}
|
||||
SPOT_UNREACHABLE();
|
||||
|
|
@ -788,10 +789,20 @@ namespace spot
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case op::X:
|
||||
// X(1) = 1, X(0) = 0
|
||||
if (f->is_tt() || f->is_ff())
|
||||
// X(1) = 1
|
||||
if (f->is_tt())
|
||||
return f;
|
||||
// We do not have X(0)=0 because that
|
||||
// is not true with finite semantics.
|
||||
assert(!f->is_eword());
|
||||
break;
|
||||
case op::strong_X:
|
||||
// X[!](0) = 0
|
||||
if (f->is_ff())
|
||||
return f;
|
||||
// Note: with finite semantics X[!](1)≠1.
|
||||
assert(!f->is_eword());
|
||||
break;
|
||||
|
||||
|
|
@ -1176,6 +1187,7 @@ namespace spot
|
|||
is_.accepting_eword = false;
|
||||
break;
|
||||
case op::X:
|
||||
case op::strong_X:
|
||||
props = children[0]->props;
|
||||
is_.not_marked = true;
|
||||
is_.boolean = false;
|
||||
|
|
@ -1186,6 +1198,10 @@ namespace spot
|
|||
// is_.syntactic_obligation inherited
|
||||
// is_.syntactic_recurrence inherited
|
||||
// is_.syntactic_persistence inherited
|
||||
|
||||
// is_.accepting_eword is currently unused outside SEREs, but
|
||||
// we could make sense of it if we start supporting LTL over
|
||||
// finite traces.
|
||||
is_.accepting_eword = false;
|
||||
break;
|
||||
case op::F:
|
||||
|
|
|
|||
|
|
@ -57,8 +57,22 @@
|
|||
#include <cstddef>
|
||||
#include <limits>
|
||||
|
||||
// The strong_X operator was introduced in Spot 2.8.2 to fix an issue
|
||||
// with from_ltlf(). As adding a new operator is a backward
|
||||
// incompatibility, causing new warnings from the compiler.
|
||||
#if defined(SPOT_BUILD) or defined(SPOT_USES_STRONG_X)
|
||||
// Use #if SPOT_HAS_STRONG_X in code that need to be backward
|
||||
// compatible with older Spot versions.
|
||||
# define SPOT_HAS_STRONG_X 1
|
||||
// You me #define SPOT_WANT_STRONG_X yourself before including
|
||||
// this file to force the use of STRONG_X
|
||||
# define SPOT_WANT_STRONG_X 1
|
||||
#endif
|
||||
|
||||
namespace spot
|
||||
{
|
||||
|
||||
|
||||
/// \ingroup tl_essentials
|
||||
/// \brief Operator types
|
||||
enum class op: uint8_t
|
||||
|
|
@ -98,6 +112,9 @@ namespace spot
|
|||
Star, ///< Star
|
||||
FStar, ///< Fustion Star
|
||||
first_match, ///< first_match(sere)
|
||||
#ifdef SPOT_WANT_STRONG_X
|
||||
strong_X, ///< strong Next
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifndef SWIG
|
||||
|
|
@ -899,6 +916,22 @@ namespace spot
|
|||
return nested_unop_range(op::X, op::Or /* unused */, level, level, f);
|
||||
}
|
||||
|
||||
#if SPOT_WANT_STRONG_X
|
||||
/// \brief Construct a strong_X
|
||||
/// @{
|
||||
SPOT_DEF_UNOP(strong_X);
|
||||
/// @}
|
||||
|
||||
/// \brief Construct a strong_X[n]
|
||||
///
|
||||
/// strong_X[3]f = strong_X strong_X strong_X f
|
||||
static formula strong_X(unsigned level, const formula& f)
|
||||
{
|
||||
return nested_unop_range(op::strong_X, op::Or /* unused */,
|
||||
level, level, f);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// \brief Construct an F
|
||||
/// @{
|
||||
SPOT_DEF_UNOP(F);
|
||||
|
|
@ -1662,6 +1695,9 @@ namespace spot
|
|||
return *this;
|
||||
case op::Not:
|
||||
case op::X:
|
||||
#if SPOT_HAS_STRONG_X
|
||||
case op::strong_X:
|
||||
#endif
|
||||
case op::F:
|
||||
case op::G:
|
||||
case op::Closure:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2016, 2018 Laboratoire de Recherche et Développement
|
||||
// de l'Epita (LRDE).
|
||||
// Copyright (C) 2016, 2018, 2019 Laboratoire de Recherche et
|
||||
// Développement de l'Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
|
|
@ -29,11 +29,12 @@ namespace spot
|
|||
auto t = [&alive] (formula f) { return from_ltlf_aux(f, alive); };
|
||||
switch (auto o = f.kind())
|
||||
{
|
||||
case op::X:
|
||||
case op::strong_X:
|
||||
case op::F:
|
||||
return formula::unop(o, formula::And({alive, t(f[0])}));
|
||||
case op::X: // weak
|
||||
case op::G:
|
||||
return formula::G(formula::Or({formula::Not(alive), t(f[0])}));
|
||||
return formula::unop(o, formula::Or({formula::Not(alive), t(f[0])}));
|
||||
// Note that the t() function given in the proof of Theorem 1 of
|
||||
// the IJCAI'13 paper by De Giacomo & Vardi has a typo.
|
||||
// t(a U b) should be equal to t(a) U t(b & alive).
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ namespace spot
|
|||
case op::ap:
|
||||
case op::Not:
|
||||
case op::X:
|
||||
case op::strong_X:
|
||||
case op::F:
|
||||
case op::G:
|
||||
case op::Closure:
|
||||
|
|
@ -109,6 +110,7 @@ namespace spot
|
|||
case op::ap:
|
||||
case op::Not:
|
||||
case op::X:
|
||||
case op::strong_X:
|
||||
case op::F:
|
||||
case op::G:
|
||||
case op::Closure:
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ namespace spot
|
|||
return f;
|
||||
case op::Not:
|
||||
case op::X:
|
||||
case op::strong_X:
|
||||
case op::F:
|
||||
case op::G:
|
||||
case op::first_match:
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ namespace spot
|
|||
KEqualBunop,
|
||||
KGotoBunop,
|
||||
KFirstMatch,
|
||||
KStrongX,
|
||||
};
|
||||
|
||||
const char* spot_kw[] = {
|
||||
|
|
@ -112,6 +113,7 @@ namespace spot
|
|||
"[=",
|
||||
"[->",
|
||||
"first_match",
|
||||
"X[!]",
|
||||
};
|
||||
|
||||
const char* spin_kw[] = {
|
||||
|
|
@ -138,60 +140,62 @@ namespace spot
|
|||
" || ",
|
||||
" || ",
|
||||
" && ",
|
||||
" && ", // not supported
|
||||
" & ", // not supported
|
||||
";", // not supported
|
||||
":", // not supported
|
||||
"{", // not supported
|
||||
"}", // not supported
|
||||
"]", // not supported
|
||||
"[*", // not supported
|
||||
"[+]", // not supported
|
||||
"[:*", // not supported
|
||||
"[:+]", // not supported
|
||||
"[=", // not supported
|
||||
"[->", // not supported
|
||||
"first_match", // not supported
|
||||
" && ", // not supported
|
||||
" & ", // not supported
|
||||
";", // not supported
|
||||
":", // not supported
|
||||
"{", // not supported
|
||||
"}", // not supported
|
||||
"]", // not supported
|
||||
"[*", // not supported
|
||||
"[+]", // not supported
|
||||
"[:*", // not supported
|
||||
"[:+]", // not supported
|
||||
"[=", // not supported
|
||||
"[->", // not supported
|
||||
"first_match", // not supported
|
||||
"!X!",
|
||||
};
|
||||
|
||||
const char* wring_kw[] = {
|
||||
"FALSE",
|
||||
"TRUE",
|
||||
"[*0]", // not supported
|
||||
"[*0]", // not supported
|
||||
" ^ ",
|
||||
" -> ",
|
||||
" <-> ",
|
||||
" U ",
|
||||
" R ",
|
||||
" W ", // rewritten
|
||||
" M ", // rewritten
|
||||
"<>-> ", // not supported
|
||||
"<>=> ", // not supported
|
||||
"<>+> ", // not supported
|
||||
"<>=+> ", // not supported
|
||||
"[]-> ", // not supported
|
||||
"[]=> ", // not supported
|
||||
" W ", // rewritten
|
||||
" M ", // rewritten
|
||||
"<>-> ", // not supported
|
||||
"<>=> ", // not supported
|
||||
"<>+> ", // not supported
|
||||
"<>=+> ", // not supported
|
||||
"[]-> ", // not supported
|
||||
"[]=> ", // not supported
|
||||
"!",
|
||||
"X",
|
||||
"F",
|
||||
"G",
|
||||
" + ",
|
||||
" | ", // not supported
|
||||
" | ", // not supported
|
||||
" * ",
|
||||
" && ", // not supported
|
||||
" & ", // not supported
|
||||
";", // not supported
|
||||
":", // not supported
|
||||
"{", // not supported
|
||||
"}", // not supported
|
||||
"]", // not supported
|
||||
"[*", // not supported
|
||||
"[+]", // not supported
|
||||
"[:*", // not supported
|
||||
"[:+]", // not supported
|
||||
"[=", // not supported
|
||||
"[->", // not supported
|
||||
"first_match", // not supported
|
||||
" && ", // not supported
|
||||
" & ", // not supported
|
||||
";", // not supported
|
||||
":", // not supported
|
||||
"{", // not supported
|
||||
"}", // not supported
|
||||
"]", // not supported
|
||||
"[*", // not supported
|
||||
"[+]", // not supported
|
||||
"[:*", // not supported
|
||||
"[:+]", // not supported
|
||||
"[=", // not supported
|
||||
"[->", // not supported
|
||||
"first_match", // not supported
|
||||
"X[!]", // not supported, FIXME: we need a syntax
|
||||
};
|
||||
|
||||
const char* utf8_kw[] = {
|
||||
|
|
@ -232,6 +236,7 @@ namespace spot
|
|||
"[=",
|
||||
"[->",
|
||||
"first_match",
|
||||
"Ⓧ",
|
||||
};
|
||||
|
||||
const char* latex_kw[] = {
|
||||
|
|
@ -272,6 +277,7 @@ namespace spot
|
|||
"\\SereEqual{",
|
||||
"\\SereGoto{",
|
||||
"\\FirstMatch",
|
||||
"\\StrongX",
|
||||
};
|
||||
|
||||
const char* sclatex_kw[] = {
|
||||
|
|
@ -316,6 +322,7 @@ namespace spot
|
|||
"^{=",
|
||||
"^{\\to",
|
||||
"\\mathsf{first\\_match}",
|
||||
"\\textcircled{\\mathsf{X}}",
|
||||
};
|
||||
|
||||
static bool
|
||||
|
|
@ -519,7 +526,18 @@ namespace spot
|
|||
break;
|
||||
}
|
||||
case op::X:
|
||||
emit(KX);
|
||||
{
|
||||
emit(KX);
|
||||
bool cst = f[0].is_constant();
|
||||
if (cst)
|
||||
openp();
|
||||
visit(f[0]);
|
||||
if (cst)
|
||||
closep();
|
||||
break;
|
||||
}
|
||||
case op::strong_X:
|
||||
emit(KStrongX);
|
||||
visit(f[0]);
|
||||
break;
|
||||
case op::F:
|
||||
|
|
@ -1076,6 +1094,9 @@ namespace spot
|
|||
case op::X:
|
||||
os_ << 'X';
|
||||
break;
|
||||
case op::strong_X:
|
||||
os_ << 'X'; // unsupported
|
||||
break;
|
||||
case op::F:
|
||||
os_ << 'F';
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -489,7 +489,13 @@ namespace spot
|
|||
result = negated ? formula::Not(f) : f;
|
||||
break;
|
||||
case op::X:
|
||||
// !Xa == X!a
|
||||
case op::strong_X:
|
||||
// Currently we don't distinguish between weak and
|
||||
// strong semantics, so we treat the two operators
|
||||
// identically.
|
||||
//
|
||||
// !Xa == X!a
|
||||
// !X[!]a = X!a
|
||||
result = formula::X(rec(f[0], negated));
|
||||
break;
|
||||
case op::F:
|
||||
|
|
@ -714,7 +720,10 @@ namespace spot
|
|||
formula
|
||||
unop_multop(op uop, op mop, vec v)
|
||||
{
|
||||
return formula::unop(uop, formula::multop(mop, v));
|
||||
formula f = formula::unop(uop, formula::multop(mop, v));
|
||||
if (f.is(op::X) && f[0].is_ff())
|
||||
return formula::ff();
|
||||
return f;
|
||||
}
|
||||
|
||||
formula
|
||||
|
|
@ -797,6 +806,7 @@ namespace spot
|
|||
switch (f.kind())
|
||||
{
|
||||
case op::X:
|
||||
case op::strong_X:
|
||||
if (res_X && !eu)
|
||||
{
|
||||
res_X->emplace_back(f[0]);
|
||||
|
|
@ -950,8 +960,15 @@ namespace spot
|
|||
case op::FStar:
|
||||
return f;
|
||||
case op::X:
|
||||
case op::strong_X:
|
||||
{
|
||||
formula c = f[0];
|
||||
// The following rules are not trivial simplifications,
|
||||
// because they are not true in LTLf.
|
||||
// X(0)=0
|
||||
// X[!](1)=1
|
||||
if (c.is_constant())
|
||||
return c;
|
||||
// Xf = f if f is both eventual and universal.
|
||||
if (c.is_universal() && c.is_eventual())
|
||||
{
|
||||
|
|
@ -3731,9 +3748,10 @@ namespace spot
|
|||
switch (f.kind())
|
||||
{
|
||||
case op::X:
|
||||
case op::strong_X:
|
||||
if (g.is_eventual() && syntactic_implication(f[0], g))
|
||||
return true;
|
||||
if (g.is(op::X) && syntactic_implication(f[0], g[0]))
|
||||
if (g.is(op::X, op::strong_X) && syntactic_implication(f[0], g[0]))
|
||||
return true;
|
||||
break;
|
||||
|
||||
|
|
@ -3893,6 +3911,7 @@ namespace spot
|
|||
|
||||
case op::G:
|
||||
case op::X:
|
||||
case op::strong_X:
|
||||
if (f.is_universal() && syntactic_implication(f, g[0]))
|
||||
return true;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ namespace spot
|
|||
case op::ap:
|
||||
case op::Not:
|
||||
case op::X:
|
||||
case op::strong_X:
|
||||
case op::F:
|
||||
case op::G:
|
||||
case op::Closure:
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ namespace spot
|
|||
case op::ap:
|
||||
case op::Not:
|
||||
case op::X:
|
||||
case op::strong_X:
|
||||
case op::Closure:
|
||||
case op::NegClosure:
|
||||
case op::NegClosureMarked:
|
||||
|
|
|
|||
|
|
@ -84,6 +84,7 @@ namespace spot
|
|||
case op::F:
|
||||
case op::G:
|
||||
case op::X:
|
||||
case op::strong_X:
|
||||
case op::Closure:
|
||||
case op::NegClosure:
|
||||
case op::NegClosureMarked:
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ namespace spot
|
|||
return;
|
||||
}
|
||||
case op::X:
|
||||
case op::strong_X:
|
||||
{
|
||||
ltl2taa_visitor v = recurse(f[0]);
|
||||
std::vector<formula> dst;
|
||||
|
|
|
|||
|
|
@ -585,6 +585,7 @@ namespace spot
|
|||
case op::F:
|
||||
case op::G:
|
||||
case op::X:
|
||||
case op::strong_X:
|
||||
case op::Closure:
|
||||
case op::NegClosure:
|
||||
case op::NegClosureMarked:
|
||||
|
|
@ -1215,6 +1216,7 @@ namespace spot
|
|||
return bdd_not(recurse(node[0]));
|
||||
}
|
||||
case op::X:
|
||||
case op::strong_X:
|
||||
{
|
||||
// r(Xy) = Next[y]
|
||||
// r(X(a&b&c)) = Next[a]&Next[b]&Next[c]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue