parsetl: change the interface to return a parsed_formula

This gets the interface of all the functions parsing formula in line
with the interface of the automaton parser: both return a "parsed_*"
object (parsed_formula or parsed_automaton) that contains the said
object and its list of errors.  Doing so avoid having to declare the
parse_error_list in advance.

* spot/tl/parse.hh, spot/parsetl/parsetl.yy: Do the change.
* spot/parsetl/fmterror.cc: Adjust the error printer.
* NEWS: Document it.
* bin/common_finput.cc, bin/common_finput.hh, bin/ltlcross.cc,
bin/ltldo.cc, bin/ltlfilt.cc, doc/org/tut01.org, doc/org/tut02.org,
doc/org/tut10.org, doc/org/tut20.org, python/ajax/spotcgi.in,
python/spot/impl.i, spot/parseaut/parseaut.yy, tests/core/checkpsl.cc,
tests/core/checkta.cc, tests/core/consterm.cc, tests/core/emptchk.cc,
tests/core/equalsf.cc, tests/core/ikwiad.cc, tests/core/kind.cc,
tests/core/length.cc, tests/core/ltlprod.cc, tests/core/ltlrel.cc,
tests/core/randtgba.cc, tests/core/readltl.cc, tests/core/reduc.cc,
tests/core/safra.cc, tests/core/syntimpl.cc, tests/core/tostring.cc,
tests/ltsmin/modelcheck.cc, tests/python/alarm.py,
tests/python/interdep.py, tests/python/ltl2tgba.py,
tests/python/ltlparse.py: Adjust all uses.
This commit is contained in:
Alexandre Duret-Lutz 2016-02-17 19:39:43 +01:00
parent cf4f58c34b
commit 22f442f758
37 changed files with 359 additions and 374 deletions

View file

@ -119,11 +119,10 @@ Here is how to call the infix parser explicitly:
int main()
{
std::string input = "[]<>p0 || <>[]p1";
spot::parse_error_list pel;
spot::formula f = spot::parse_infix_psl(input, pel);
if (spot::format_parse_errors(std::cerr, input, pel))
spot::parsed_formula pf = spot::parse_infix_psl(input);
if (pf.format_errors(std::cerr))
return 1;
std::cout << f << '\n';
std::cout << pf.f << '\n';
return 0;
}
#+END_SRC
@ -131,26 +130,27 @@ Here is how to call the infix parser explicitly:
#+RESULTS:
: GFp0 | FGp1
So =parse_infix_psl()= processes =input=, and stores any diagnostic in
=pel=, which is a list of pairs associating each error to a location.
You could iterate over that list to print it by yourself as you wish,
or you can call =format_parse_errors()= to do that for you. Note that
as its name implies, this parser can read more than LTL formulas (the
fragment of PSL we support is basically LTL extended with regular
expressions).
Note that as its name implies, this parser can read more than LTL
formulas: the fragment of PSL we support is basically LTL extended
with regular expressions.
If =pel= is empty, =format_parse_errors()= will do nothing and return
false.
The =parse_infix_psl()= function processes =input=, and returns a
=spot::parsed_formula= object. In addition to the =spot::formula= we
desire (stored as the =spot::parsed_formula::f= attribute), the
=spot::parsed_formula= also stores any diagnostic collected during the
parsing. Those diagnostics are stored in the
=spot::parsed_formula::errors= attribute, but they can conveniently be
printed by calling the =spot::parsed::format_errors()= method: this
method returns true if and only if a diagnostic was output, so this is
usually used to abort the program with an error status as above.
If =pel= is non empty, =format_parse_errors()= will display the errors
messages and return true. In the above code, we have decided to
aborts the execution in this case.
However the parser usually tries to do some error recovery. For
instance if you have input =(a U b))= the parser will complain about
the extra parenthesis (=pel= not empty), but it will still return an
=f= that is equivalent to =a U b=. So you could decide to continue
with the "fixed" formula if you wish. Here is an example:
The parser usually tries to do some error recovery, so the =f=
attribute can be non-null even if some parsing errors where returned.
For instance if you have input =(a U b))= the parser will complain
about the extra parenthesis, but it will still return a formula that
is equivalent to =a U b=. So you could decide to continue with the
"fixed" formula if you wish. Here is an example:
#+BEGIN_SRC C++ :results verbatim :exports both
#include <string>
@ -161,14 +161,13 @@ with the "fixed" formula if you wish. Here is an example:
int main()
{
std::string input = "(a U b))";
spot::parse_error_list pel;
spot::formula f = spot::parse_infix_psl(input, pel);
spot::parsed_formula pf = spot::parse_infix_psl(input);
// Use std::cout instead of std::cerr because we can only
// show the output of std::cout in this documentation.
(void) spot::format_parse_errors(std::cout, input, pel);
if (f == nullptr)
(void) pf.format_errors(std::cout);
if (pf.f == nullptr)
return 1;
std::cout << "Parsed formula: " << f << '\n';
std::cout << "Parsed formula: " << pf.f << '\n';
return 0;
}
#+END_SRC
@ -185,8 +184,8 @@ with the "fixed" formula if you wish. Here is an example:
: Parsed formula: a U b
The formula =f= is only returned as null when the parser really cannot
recover anything.
The formula =pf.f= would only be returned as null when the parser
really cannot recover anything.
** Calling the prefix parser explicitly
@ -202,10 +201,10 @@ of =parse_infix_psl()=.
int main()
{
std::string input = "& & G p0 p1 p2";
spot::parse_error_list pel;
spot::formula f = spot::parse_prefix_ltl(input, pel);
if (spot::format_parse_errors(std::cerr, input, pel))
spot::parsed_formula pf = spot::parse_prefix_ltl(input);
if (pf.format_errors(std::cerr))
return 1;
spot::formula f = pf.f;
print_latex_psl(std::cout, f) << '\n';
print_lbt_ltl(std::cout, f) << '\n';
print_spin_ltl(std::cout, f, true) << '\n';
@ -246,11 +245,10 @@ For instance, let's see what happens if a PSL formulas is passed to
int main()
{
std::string input = "{a*;b}<>->(a U (b & GF c))";
spot::parse_error_list pel;
spot::formula f = spot::parse_infix_psl(input, pel);
if (spot::format_parse_errors(std::cerr, input, pel))
spot::parsed_formula pf = spot::parse_infix_psl(input);
if (pf.format_errors(std::cerr))
return 1;
print_spin_ltl(std::cout, f) << '\n';
print_spin_ltl(std::cout, pf.f) << '\n';
return 0;
}
#+END_SRC
@ -276,10 +274,10 @@ The first is to simply diagnose non-LTL formulas.
int main()
{
std::string input = "{a*;b}<>->(a U (b & GF c))";
spot::parse_error_list pel;
spot::formula f = spot::parse_infix_psl(input, pel);
if (spot::format_parse_errors(std::cerr, input, pel))
spot::parsed_formula pf = spot::parse_infix_psl(input);
if (pf.format_errors(std::cerr))
return 1;
spot::formula f = pf.f;
if (!f.is_ltl_formula())
{
std::cerr << "Only LTL formulas are supported.\n";
@ -306,10 +304,10 @@ prepared to reject the formula any way. In our example, we are lucky
int main()
{
std::string input = "{a*;b}<>->(a U (b & GF c))";
spot::parse_error_list pel;
spot::formula f = spot::parse_infix_psl(input, pel);
if (spot::format_parse_errors(std::cerr, input, pel))
spot::parsed_formula pf = spot::parse_infix_psl(input);
if (pf.format_errors(std::cerr))
return 1;
spot::formula f = pf.f;
if (!f.is_ltl_formula())
{
spot::tl_simplifier simp;

View file

@ -85,10 +85,10 @@ destructor.
int main()
{
std::string input = "\"Proc@Here\" U (\"var > 10\" | \"var < 4\")";
spot::parse_error_list pel;
spot::formula f = spot::parse_infix_psl(input, pel);
if (spot::format_parse_errors(std::cerr, input, pel))
spot::parsed_formula pf = spot::parse_infix_psl(input);
if (pf.format_errors(std::cerr))
return 1;
spot::formula f = pf.f;
spot::relabeling_map m;
f = spot::relabel(f, spot::Pnn, &m);
for (auto& i: m)

View file

@ -137,13 +137,12 @@ never claim is done via the =print_never_claim= function.
int main()
{
std::string input = "[]<>p0 || <>[]p1";
spot::parse_error_list pel;
spot::formula f = spot::parse_infix_psl(input, pel);
if (spot::format_parse_errors(std::cerr, input, pel))
spot::parsed_formula pf = spot::parse_infix_psl(input);
if (pf.format_errors(std::cerr))
return 1;
spot::translator trans;
trans.set_type(spot::postprocessor::BA);
spot::twa_graph_ptr aut = trans.run(f);
spot::twa_graph_ptr aut = trans.run(pf.f);
print_never_claim(std::cout, aut) << '\n';
return 0;
}
@ -154,23 +153,23 @@ never claim is done via the =print_never_claim= function.
never {
T0_init:
if
:: ((p1)) -> goto accept_S0
:: ((true)) -> goto T0_init
:: ((p0)) -> goto accept_S2
:: (p1) -> goto accept_S0
:: (true) -> goto T0_init
:: (p0) -> goto accept_S2
fi;
accept_S0:
if
:: ((p1)) -> goto accept_S0
:: (p1) -> goto accept_S0
fi;
accept_S2:
if
:: ((p0)) -> goto accept_S2
:: ((!(p0))) -> goto T0_S3
:: (p0) -> goto accept_S2
:: (!(p0)) -> goto T0_S3
fi;
T0_S3:
if
:: ((p0)) -> goto accept_S2
:: ((!(p0))) -> goto T0_S3
:: (p0) -> goto accept_S2
:: (!(p0)) -> goto T0_S3
fi;
}
#+end_example

View file

@ -122,7 +122,7 @@ State: 4
* C++
Parsing an automaton is almost similar to [[file:tut01.org][parsing an LTL formula]]. The
Parsing an automaton is similar to [[file:tut01.org][parsing an LTL formula]]. The
=parse_aut()= function takes a filename and a BDD dictionary (to be
discussed later on this page). It returns a shared pointer to a
structure that has a couple of important fields: =aborted= is a