dstarparse: Preliminary work on a parser for ltl2dstar.
Supports reading Rabin and Streett automata, and converting them to nondeterministic Büchi automata (for Rabin) or TGBA (for Streett). * src/dstarparse/Makefile.am, src/dstarparse/dstarparse.yy, src/dstarparse/dstarscan.ll, src/dstarparse/fmterror.cc, src/dstarparse/parsedecl.hh, src/dstarparse/public.hh, src/dstarparse/nra2nba.cc, src/dstarparse/nsa2tgba.cc: New files. * configure.ac, src/Makefile.am, README: Adjust. * src/tgbatest/ltl2tgba.cc: Add options -XD, -XDB. * src/tgbatest/dstar.test: New file. * src/tgbatest/Makefile.am (TESTS): Add it.
This commit is contained in:
parent
5a3b1a9905
commit
2da0053c53
15 changed files with 1390 additions and 55 deletions
1
README
1
README
|
|
@ -157,6 +157,7 @@ Core directories
|
|||
src/ Sources for libspot.
|
||||
bin/ User tools built using the Spot library.
|
||||
man/ Man pages for the above tools.
|
||||
dstarparse/ Parser for the output of ltl2dstar.
|
||||
eltlparse/ Parser for ELTL formulae.
|
||||
eltltest/ Tests for ELTL nodes in ltlast/ and eltlparse/.
|
||||
kripke/ Kripke Structure interface.
|
||||
|
|
|
|||
|
|
@ -147,6 +147,7 @@ AC_CONFIG_FILES([
|
|||
lib/Makefile
|
||||
src/bin/Makefile
|
||||
src/bin/man/Makefile
|
||||
src/dstarparse/Makefile
|
||||
src/eltlparse/Makefile
|
||||
src/eltltest/defs
|
||||
src/eltltest/Makefile
|
||||
|
|
|
|||
|
|
@ -27,13 +27,14 @@ AUTOMAKE_OPTIONS = subdir-objects
|
|||
# libspot.la needed by the tests)
|
||||
SUBDIRS = misc priv ltlenv ltlast ltlvisit ltlparse eltlparse tgba \
|
||||
tgbaalgos tgbaparse ta taalgos kripke saba sabaalgos \
|
||||
neverparse kripkeparse . bin ltltest eltltest tgbatest \
|
||||
sabatest sanity kripketest
|
||||
neverparse kripkeparse dstarparse . bin ltltest eltltest \
|
||||
tgbatest sabatest kripketest sanity
|
||||
|
||||
lib_LTLIBRARIES = libspot.la
|
||||
libspot_la_SOURCES =
|
||||
libspot_la_LDFLAGS = $(BUDDY_LDFLAGS) -no-undefined
|
||||
libspot_la_LIBADD = \
|
||||
dstarparse/libdstarparse.la \
|
||||
eltlparse/libeltlparse.la \
|
||||
kripke/libkripke.la \
|
||||
kripkeparse/libkripkeparse.la \
|
||||
|
|
|
|||
7
src/dstarparse/.gitignore
vendored
Normal file
7
src/dstarparse/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
position.hh
|
||||
dstarparse.cc
|
||||
dstarparse.output
|
||||
dstarparse.hh
|
||||
dstarscan.cc
|
||||
stack.hh
|
||||
location.hh
|
||||
59
src/dstarparse/Makefile.am
Normal file
59
src/dstarparse/Makefile.am
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
## -*- coding: utf-8 -*-
|
||||
## Copyright (C) 2013 Laboratoire de Recherche et Développement de
|
||||
## l'Epita (LRDE).
|
||||
##
|
||||
## This file is part of Spot, a model checking library.
|
||||
##
|
||||
## Spot is free software; you can redistribute it and/or modify it
|
||||
## under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 3 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
## or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
## License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
AM_CPPFLAGS = -I$(srcdir)/.. -I.. $(BUDDY_CPPFLAGS) -DYY_NO_INPUT
|
||||
# Disable -Werror because too many versions of flex yield warnings.
|
||||
AM_CXXFLAGS = $(WARNING_CXXFLAGS:-Werror=)
|
||||
|
||||
dstarparsedir = $(pkgincludedir)/dstarparse
|
||||
|
||||
dstarparse_HEADERS = public.hh
|
||||
|
||||
noinst_LTLIBRARIES = libdstarparse.la
|
||||
|
||||
DSTARPARSE_YY = dstarparse.yy
|
||||
FROM_DSTARPARSE_YY_MAIN = dstarparse.cc
|
||||
FROM_DSTARPARSE_YY_OTHERS = \
|
||||
stack.hh \
|
||||
dstarparse.hh
|
||||
|
||||
FROM_DSTARPARSE_YY = $(FROM_DSTARPARSE_YY_MAIN) $(FROM_DSTARPARSE_YY_OTHERS)
|
||||
|
||||
BUILT_SOURCES = $(FROM_DSTARPARSE_YY)
|
||||
MAINTAINERCLEANFILES = $(FROM_DSTARPARSE_YY)
|
||||
|
||||
$(FROM_DSTARPARSE_YY_MAIN): $(srcdir)/$(DSTARPARSE_YY)
|
||||
## We must cd into $(srcdir) first because if we tell bison to read
|
||||
## $(srcdir)/$(DSTARPARSE_YY), it will also use the value of $(srcdir)/
|
||||
## in the generated include statements.
|
||||
cd $(srcdir) && \
|
||||
bison -Wall -Werror --report=all \
|
||||
$(DSTARPARSE_YY) -o $(FROM_DSTARPARSE_YY_MAIN)
|
||||
$(FROM_DSTARPARSE_YY_OTHERS): $(DSTARPARSE_YY)
|
||||
@test -f $@ || $(MAKE) $(AM_MAKEFLAGS) $(FROM_DSTARPARSE_YY_MAIN)
|
||||
|
||||
EXTRA_DIST = $(DSTARPARSE_YY)
|
||||
|
||||
libdstarparse_la_SOURCES = \
|
||||
fmterror.cc \
|
||||
nra2nba.cc \
|
||||
nsa2tgba.cc \
|
||||
$(FROM_DSTARPARSE_YY) \
|
||||
dstarscan.ll \
|
||||
parsedecl.hh
|
||||
352
src/dstarparse/dstarparse.yy
Normal file
352
src/dstarparse/dstarparse.yy
Normal file
|
|
@ -0,0 +1,352 @@
|
|||
/* -*- coding: utf-8 -*-
|
||||
** Copyright (C) 2013 Laboratoire de Recherche et Développement de
|
||||
** l'Epita (LRDE).
|
||||
**
|
||||
** This file is part of Spot, a model checking library.
|
||||
**
|
||||
** Spot is free software; you can redistribute it and/or modify it
|
||||
** under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation; either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
** or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
** License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
%language "C++"
|
||||
%locations
|
||||
%defines
|
||||
%expect 0 // No shift/reduce
|
||||
%name-prefix "dstaryy"
|
||||
%debug
|
||||
%error-verbose
|
||||
%lex-param { spot::dstar_parse_error_list& error_list }
|
||||
%define api.location.type "spot::location"
|
||||
|
||||
%code requires
|
||||
{
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include "ltlast/constant.hh"
|
||||
#include "public.hh"
|
||||
|
||||
typedef std::map<int, bdd> map_t;
|
||||
|
||||
struct result_
|
||||
{
|
||||
spot::dstar_aut* d;
|
||||
spot::ltl::environment* env;
|
||||
std::vector<bdd> guards;
|
||||
std::vector<bdd>::const_iterator cur_guard;
|
||||
map_t dest_map;
|
||||
int cur_state;
|
||||
|
||||
unsigned state_count;
|
||||
std::vector<std::string> aps;
|
||||
|
||||
bool state_count_seen:1;
|
||||
bool accpair_count_seen:1;
|
||||
bool start_state_seen:1;
|
||||
bool aps_seen:1;
|
||||
|
||||
result_() :
|
||||
state_count_seen(false),
|
||||
accpair_count_seen(false),
|
||||
start_state_seen(false),
|
||||
aps_seen(false)
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
%parse-param {spot::dstar_parse_error_list& error_list}
|
||||
%parse-param {result_& result}
|
||||
%union
|
||||
{
|
||||
std::string* str;
|
||||
unsigned int num;
|
||||
}
|
||||
|
||||
%code
|
||||
{
|
||||
#include <sstream>
|
||||
/* dstarparse.hh and parsedecl.hh include each other recursively.
|
||||
We must ensure that YYSTYPE is declared (by the above %union)
|
||||
before parsedecl.hh uses it. */
|
||||
#include "parsedecl.hh"
|
||||
|
||||
static void fill_guards(result_& res);
|
||||
}
|
||||
|
||||
%token DRA "DRA"
|
||||
%token DSA "DSA"
|
||||
%token V2 "v2"
|
||||
%token EXPLICIT "explicit"
|
||||
%token ACCPAIRS "Acceptance-Pairs:"
|
||||
%token AP "AP:";
|
||||
%token START "Start:";
|
||||
%token STATES "States:";
|
||||
%token STATE "State:";
|
||||
%token ACCSIG "Acc-Sig:";
|
||||
%token ENDOFHEADER "---";
|
||||
%token EOL "new line";
|
||||
%token <str> STRING "string";
|
||||
%token <num> NUMBER "number";
|
||||
|
||||
%type <num> sign
|
||||
|
||||
%destructor { delete $$; } <str>
|
||||
%printer {
|
||||
if ($$)
|
||||
debug_stream() << *$$;
|
||||
else
|
||||
debug_stream() << "\"\""; } <str>
|
||||
%printer { debug_stream() << $$; } <num>
|
||||
|
||||
%%
|
||||
dstar: header ENDOFHEADER eols states
|
||||
|
||||
eols : EOL | eols EOL
|
||||
opt_eols: | opt_eols EOL
|
||||
|
||||
auttype: DRA { result.d->type = spot::Rabin; }
|
||||
| DSA { result.d->type = spot::Streett; }
|
||||
|
||||
|
||||
header: auttype opt_eols V2 opt_eols EXPLICIT opt_eols sizes
|
||||
{
|
||||
bool err = false;
|
||||
if (!result.state_count_seen)
|
||||
{
|
||||
error(@5, "missing state count");
|
||||
err = true;
|
||||
}
|
||||
if (!result.accpair_count_seen)
|
||||
{
|
||||
error(@5, "missing acceptance-pair count");
|
||||
err = true;
|
||||
}
|
||||
if (!result.start_state_seen)
|
||||
{
|
||||
error(@5, "missing start-state number");
|
||||
err = true;
|
||||
}
|
||||
if (!result.aps_seen)
|
||||
{
|
||||
error(@5, "missing atomic proposition definition");
|
||||
err = true;
|
||||
}
|
||||
if (err)
|
||||
{
|
||||
delete result.d->aut;
|
||||
result.d->aut = 0;
|
||||
YYABORT;
|
||||
}
|
||||
fill_guards(result);
|
||||
}
|
||||
|
||||
aps:
|
||||
| aps STRING opt_eols
|
||||
{
|
||||
result.aps.push_back(*$2);
|
||||
delete $2;
|
||||
}
|
||||
|
||||
sizes:
|
||||
| sizes error eols
|
||||
{
|
||||
error(@2, "unknown header ignored");
|
||||
}
|
||||
| sizes ACCPAIRS opt_eols NUMBER opt_eols
|
||||
{
|
||||
result.d->accpair_count = $4;
|
||||
result.accpair_count_seen = true;
|
||||
}
|
||||
| sizes STATES opt_eols NUMBER opt_eols
|
||||
{
|
||||
result.state_count = $4;
|
||||
result.state_count_seen = true;
|
||||
}
|
||||
| sizes START opt_eols NUMBER opt_eols
|
||||
{
|
||||
result.d->aut->set_init_state($4);
|
||||
result.start_state_seen = true;
|
||||
}
|
||||
| sizes AP opt_eols NUMBER opt_eols aps
|
||||
{
|
||||
int announced = $4;
|
||||
int given = result.aps.size();
|
||||
if (given != announced)
|
||||
{
|
||||
std::ostringstream str;
|
||||
str << announced << " atomic propositions announced but "
|
||||
<< given << " given";
|
||||
error(@4 + @6, str.str());
|
||||
}
|
||||
if (given > 31)
|
||||
{
|
||||
error(@4 + @6,
|
||||
"ltl2star does not support more than 31 atomic propositions");
|
||||
}
|
||||
result.aps_seen = true;
|
||||
}
|
||||
|
||||
opt_name: | STRING opt_eols
|
||||
{
|
||||
delete $1;
|
||||
}
|
||||
|
||||
state_id: STATE opt_eols NUMBER opt_eols opt_name
|
||||
{
|
||||
if (result.cur_guard != result.guards.end())
|
||||
error(@1, "not enough transitions for previous state");
|
||||
if ($3 >= result.state_count)
|
||||
{
|
||||
std::ostringstream o;
|
||||
if (result.state_count > 0)
|
||||
{
|
||||
o << "state numbers should be in the range [0.."
|
||||
<< result.state_count - 1<< "]";
|
||||
}
|
||||
else
|
||||
{
|
||||
o << "no states have been declared";
|
||||
}
|
||||
error(@3, o.str());
|
||||
}
|
||||
result.cur_guard = result.guards.begin();
|
||||
result.dest_map.clear();
|
||||
result.cur_state = $3;
|
||||
}
|
||||
|
||||
sign: '+' { $$ = 0; }
|
||||
| '-' { $$ = 1; }
|
||||
|
||||
// Membership to a pair is represented as (+NUM,-NUM)
|
||||
accsigs: opt_eols
|
||||
| accsigs sign NUMBER opt_eols
|
||||
{
|
||||
if ((unsigned) result.cur_state >= result.state_count)
|
||||
break;
|
||||
assert(result.d->accsets);
|
||||
if ($3 < result.d->accpair_count)
|
||||
{
|
||||
result.d->accsets->at(result.cur_state * 2 + $2).set($3);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ostringstream o;
|
||||
if (result.d->accpair_count > 0)
|
||||
{
|
||||
o << "acceptance pairs should be in the range [0.."
|
||||
<< result.d->accpair_count - 1<< "]";
|
||||
}
|
||||
else
|
||||
{
|
||||
o << "no acceptance pairs have been declared";
|
||||
}
|
||||
error(@3, o.str());
|
||||
}
|
||||
}
|
||||
|
||||
state_accsig: ACCSIG accsigs
|
||||
|
||||
transitions:
|
||||
| transitions NUMBER opt_eols
|
||||
{
|
||||
std::pair<map_t::iterator, bool> i =
|
||||
result.dest_map.insert(std::make_pair($2, *result.cur_guard));
|
||||
if (!i.second)
|
||||
i.first->second |= *result.cur_guard;
|
||||
++result.cur_guard;
|
||||
}
|
||||
|
||||
states:
|
||||
| states state_id state_accsig transitions
|
||||
{
|
||||
for (map_t::const_iterator i = result.dest_map.begin();
|
||||
i != result.dest_map.end(); ++i)
|
||||
{
|
||||
spot::tgba_explicit_number::transition* t =
|
||||
result.d->aut->create_transition(result.cur_state, i->first);
|
||||
t->condition = i->second;
|
||||
}
|
||||
}
|
||||
%%
|
||||
|
||||
static void fill_guards(result_& r)
|
||||
{
|
||||
spot::bdd_dict* d = r.d->aut->get_dict();
|
||||
|
||||
size_t nap = r.aps.size();
|
||||
int* vars = new int[nap];
|
||||
|
||||
// Get a BDD variable for each atomic proposition
|
||||
for (size_t i = 0; i < nap; ++i)
|
||||
{
|
||||
const spot::ltl::formula* f = r.env->require(r.aps[i]);
|
||||
vars[nap - 1 - i] = d->register_proposition(f, r.d->aut);
|
||||
f->destroy();
|
||||
}
|
||||
|
||||
// build the 2^nap possible guards
|
||||
r.guards.reserve(1U << nap);
|
||||
for (size_t i = 0; i < (1U << nap); ++i)
|
||||
r.guards.push_back(bdd_ibuildcube(i, nap, vars));
|
||||
|
||||
delete[] vars;
|
||||
r.cur_guard = r.guards.end();
|
||||
|
||||
r.d->accsets = spot::make_bitvect_array(r.d->accpair_count,
|
||||
2 * r.state_count);
|
||||
}
|
||||
|
||||
void
|
||||
dstaryy::parser::error(const location_type& location,
|
||||
const std::string& message)
|
||||
{
|
||||
error_list.push_back(spot::dstar_parse_error(location, message));
|
||||
}
|
||||
|
||||
namespace spot
|
||||
{
|
||||
dstar_aut*
|
||||
dstar_parse(const std::string& name,
|
||||
dstar_parse_error_list& error_list,
|
||||
bdd_dict* dict,
|
||||
ltl::environment& env,
|
||||
bool debug)
|
||||
{
|
||||
if (dstaryyopen(name))
|
||||
{
|
||||
error_list.push_back
|
||||
(dstar_parse_error(spot::location(),
|
||||
std::string("Cannot open file ") + name));
|
||||
return 0;
|
||||
}
|
||||
result_ r;
|
||||
r.d = new dstar_aut;
|
||||
r.d->aut = new tgba_explicit_number(dict);
|
||||
r.d->accsets = 0;
|
||||
r.env = &env;
|
||||
dstaryy::parser parser(error_list, r);
|
||||
parser.set_debug_level(debug);
|
||||
parser.parse();
|
||||
dstaryyclose();
|
||||
|
||||
if (!r.d->aut || !r.d->accsets)
|
||||
{
|
||||
delete r.d;
|
||||
return 0;
|
||||
}
|
||||
return r.d;
|
||||
}
|
||||
}
|
||||
|
||||
// Local Variables:
|
||||
// mode: c++
|
||||
// End:
|
||||
149
src/dstarparse/dstarscan.ll
Normal file
149
src/dstarparse/dstarscan.ll
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
/* Copyright (C) 2013 Laboratoire de Recherche et Développement
|
||||
** de l'Epita (LRDE).
|
||||
**
|
||||
** This file is part of Spot, a model checking library.
|
||||
**
|
||||
** Spot is free software; you can redistribute it and/or modify it
|
||||
** under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation; either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
** or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
** License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
%option noyywrap
|
||||
%option prefix="dstaryy"
|
||||
%option outfile="lex.yy.c"
|
||||
/* %option debug */
|
||||
|
||||
%{
|
||||
#include <string>
|
||||
#include "dstarparse/parsedecl.hh"
|
||||
|
||||
#define YY_USER_ACTION yylloc->columns(yyleng);
|
||||
#define YY_NEVER_INTERACTIVE 1
|
||||
|
||||
typedef dstaryy::parser::token token;
|
||||
%}
|
||||
|
||||
eol \n|\r|\n\r|\r\n
|
||||
%x in_COMMENT in_STRING
|
||||
|
||||
%%
|
||||
|
||||
%{
|
||||
std::string s;
|
||||
yylloc->step();
|
||||
%}
|
||||
|
||||
{eol} yylloc->lines(yyleng); return token::EOL;
|
||||
|
||||
/* skip blanks and comments */
|
||||
[ \t]+ yylloc->step();
|
||||
"/*" BEGIN(in_COMMENT);
|
||||
"//".* continue;
|
||||
"Comment:".* yylloc->step();
|
||||
|
||||
"DRA" return token::DRA;
|
||||
"DSA" return token::DSA;
|
||||
"v2" return token::V2;
|
||||
"explicit" return token::EXPLICIT;
|
||||
|
||||
"Acceptance-Pairs:" return token::ACCPAIRS;
|
||||
"AP:" return token::AP;
|
||||
"Start:" return token::START;
|
||||
"States:" return token::STATES;
|
||||
"State:" return token::STATE;
|
||||
"Acc-Sig:" return token::ACCSIG;
|
||||
"---" return token::ENDOFHEADER;
|
||||
|
||||
[0-9]+ {
|
||||
errno = 0;
|
||||
unsigned long n = strtoul(yytext, 0, 10);
|
||||
yylval->num = n;
|
||||
if (errno || yylval->num != n)
|
||||
{
|
||||
error_list.push_back(
|
||||
spot::dstar_parse_error(*yylloc,
|
||||
"value too large"));
|
||||
yylval->num = 0;
|
||||
}
|
||||
return token::NUMBER;
|
||||
}
|
||||
|
||||
"\"" BEGIN(in_STRING);
|
||||
|
||||
<in_COMMENT>{
|
||||
[^*\n]* continue;
|
||||
"*"+[^*/\n]* continue;
|
||||
"\n"+ yylloc->end.column = 1; yylloc->lines(yyleng);
|
||||
"*"+"/" BEGIN(INITIAL);
|
||||
<<EOF>> {
|
||||
error_list.push_back(
|
||||
spot::dstar_parse_error(*yylloc,
|
||||
"unclosed comment"));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
<in_STRING>{
|
||||
\" {
|
||||
BEGIN(INITIAL);
|
||||
yylval->str = new std::string(s);
|
||||
return token::STRING;
|
||||
}
|
||||
\\\" s += '"';
|
||||
\\. s += yytext[1];
|
||||
[^\\\"]+ s.append(yytext, yyleng);
|
||||
<<EOF>> {
|
||||
error_list.push_back(
|
||||
spot::dstar_parse_error(*yylloc,
|
||||
"unclosed string"));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
. return *yytext;
|
||||
|
||||
|
||||
%{
|
||||
/* Dummy use of yyunput to shut up a gcc warning. */
|
||||
(void) &yyunput;
|
||||
%}
|
||||
|
||||
%%
|
||||
|
||||
namespace spot
|
||||
{
|
||||
int
|
||||
dstaryyopen(const std::string &name)
|
||||
{
|
||||
// yy_flex_debug = 1;
|
||||
if (name == "-")
|
||||
{
|
||||
yyin = stdin;
|
||||
}
|
||||
else
|
||||
{
|
||||
yyin = fopen(name.c_str(), "r");
|
||||
if (!yyin)
|
||||
return 1;
|
||||
}
|
||||
// Reset the lexer in case a previous parse
|
||||
// ended badly.
|
||||
YY_NEW_FILE;
|
||||
BEGIN(INITIAL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
dstaryyclose()
|
||||
{
|
||||
fclose(yyin);
|
||||
}
|
||||
}
|
||||
41
src/dstarparse/fmterror.cc
Normal file
41
src/dstarparse/fmterror.cc
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright (C) 2013 Laboratoire de Recherche et Développement de
|
||||
// l'Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
// Spot is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
// License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <ostream>
|
||||
#include "public.hh"
|
||||
|
||||
namespace spot
|
||||
{
|
||||
bool
|
||||
format_dstar_parse_errors(std::ostream& os,
|
||||
const std::string& filename,
|
||||
dstar_parse_error_list& error_list)
|
||||
{
|
||||
bool printed = false;
|
||||
spot::dstar_parse_error_list::iterator it;
|
||||
for (it = error_list.begin(); it != error_list.end(); ++it)
|
||||
{
|
||||
if (filename != "-")
|
||||
os << filename << ":";
|
||||
os << it->first << ": ";
|
||||
os << it->second << std::endl;
|
||||
printed = true;
|
||||
}
|
||||
return printed;
|
||||
}
|
||||
}
|
||||
128
src/dstarparse/nra2nba.cc
Normal file
128
src/dstarparse/nra2nba.cc
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
// Copyright (C) 2013 Laboratoire de Recherche et Développement de
|
||||
// l'Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
// Spot is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
// License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "public.hh"
|
||||
#include "tgbaalgos/reachiter.hh"
|
||||
#include "tgbaalgos/sccfilter.hh"
|
||||
#include "ltlast/constant.hh"
|
||||
|
||||
namespace spot
|
||||
{
|
||||
namespace
|
||||
{
|
||||
// Christof Löding's Diploma Thesis: Methods for the
|
||||
// Transformation of ω-Automata: Complexity and Connection to
|
||||
// Second Order Logic. Section 3.4.3: Rabin to Büchi.
|
||||
//
|
||||
// However beware that the {...,(Ei,Fi),...} pairs used by
|
||||
// are the reversed compared to the {...,(Li,Ui),...} pairs
|
||||
// used by several other people. We have Ei=Ui and Fi=Li.
|
||||
class nra_to_nba_worker: public tgba_reachable_iterator_depth_first
|
||||
{
|
||||
public:
|
||||
nra_to_nba_worker(const dstar_aut* a):
|
||||
tgba_reachable_iterator_depth_first(a->aut),
|
||||
out_(new tgba_explicit_number(a->aut->get_dict())),
|
||||
d_(a),
|
||||
num_states_(a->aut->num_states())
|
||||
{
|
||||
bdd_dict* bd = out_->get_dict();
|
||||
bd->register_all_variables_of(a->aut, out_);
|
||||
|
||||
// Invent a new acceptance set for the degeneralized automaton.
|
||||
int accvar =
|
||||
bd->register_acceptance_variable(ltl::constant::true_instance(),
|
||||
out_);
|
||||
acc_ = bdd_ithvar(accvar);
|
||||
out_->set_acceptance_conditions(acc_);
|
||||
}
|
||||
|
||||
tgba_explicit_number*
|
||||
result()
|
||||
{
|
||||
return out_;
|
||||
}
|
||||
|
||||
void
|
||||
process_link(const state* sin, int,
|
||||
const state* sout, int,
|
||||
const tgba_succ_iterator* si)
|
||||
{
|
||||
int in = d_->aut->get_label(sin);
|
||||
int out = d_->aut->get_label(sout);
|
||||
|
||||
typedef state_explicit_number::transition trans;
|
||||
trans* t = out_->create_transition(in, out);
|
||||
bdd cond = t->condition = si->current_condition();
|
||||
|
||||
// Create one clone of the automaton per accepting pair,
|
||||
// removing states from the Ui part of the (Li, Ui) pairs.
|
||||
// (Or the Ei part of Löding's (Ei, Fi) pairs.)
|
||||
bitvect& l = d_->accsets->at(2 * in);
|
||||
bitvect& u = d_->accsets->at(2 * in + 1);
|
||||
for (size_t i = 0; i < d_->accpair_count; ++i)
|
||||
{
|
||||
int shift = num_states_ * (i + 1);
|
||||
// In the Ui set. (Löding's Ei set.)
|
||||
if (!u.get(i))
|
||||
{
|
||||
// Transition t1 is a non-deterministic jump
|
||||
// from the original automaton to the i-th clone.
|
||||
//
|
||||
// Transition t2 constructs the clone.
|
||||
//
|
||||
// Löding creates transition t1 regardless of the
|
||||
// acceptance set. We restrict it to the non-Li
|
||||
// states. Both his definition and this
|
||||
// implementation create more transitions than needed:
|
||||
// we do not need more than one transition per
|
||||
// accepting cycle.
|
||||
trans* t1 = out_->create_transition(in, out + shift);
|
||||
t1->condition = cond;
|
||||
|
||||
trans* t2 = out_->create_transition(in + shift, out + shift);
|
||||
t2->condition = cond;
|
||||
// In the Li set. (Löding's Fi set.)
|
||||
if (l.get(i))
|
||||
t2->acceptance_conditions = acc_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
tgba_explicit_number* out_;
|
||||
const dstar_aut* d_;
|
||||
size_t num_states_;
|
||||
bdd acc_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
SPOT_API
|
||||
tgba* nra_to_nba(const dstar_aut* nra)
|
||||
{
|
||||
assert(nra->type == Rabin);
|
||||
nra_to_nba_worker w(nra);
|
||||
w.run();
|
||||
tgba_explicit_number* aut = w.result();
|
||||
tgba* res = scc_filter_states(aut);
|
||||
delete aut;
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
245
src/dstarparse/nsa2tgba.cc
Normal file
245
src/dstarparse/nsa2tgba.cc
Normal file
|
|
@ -0,0 +1,245 @@
|
|||
// Copyright (C) 2013 Laboratoire de Recherche et Développement de
|
||||
// l'Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
// Spot is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
// License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <sstream>
|
||||
#include <deque>
|
||||
#include "public.hh"
|
||||
#include "tgbaalgos/sccfilter.hh"
|
||||
#include "ltlenv/defaultenv.hh"
|
||||
|
||||
namespace spot
|
||||
{
|
||||
// Christof Löding's Diploma Thesis: Methods for the
|
||||
// Transformation of ω-Automata: Complexity and Connection to
|
||||
// Second Order Logic. Section 3.4.3, gives a transition
|
||||
// from Streett with |Q| states to BA with |Q|*(4^n-3^n+2)
|
||||
// states, if n is the number of acceptance pairs.
|
||||
//
|
||||
// Duret-Lutz et al. (ATVA'2009): On-the-fly Emptiness Check of
|
||||
// Transition-based Streett Automata. Section 3.3 contains a
|
||||
// conversion from transition-based Streett Automata to TGBA using
|
||||
// the generalized Büchi acceptance to limit the explosion. It goes
|
||||
// from Streett with |Q| states to (T)GBA with |Q|*(2^n+1) states.
|
||||
// However the definition of the number of acceptance sets in that
|
||||
// paper is suboptimal: only n are needed, not 2^n.
|
||||
//
|
||||
// This implements this second version.
|
||||
|
||||
namespace
|
||||
{
|
||||
// A state in the resulting automaton corresponds is either a
|
||||
// state of the original automaton (in which case bv == 0) or a
|
||||
// state of the original automaton associated to a set of pending
|
||||
// acceptance represented by a bitvect.
|
||||
|
||||
struct build_state
|
||||
{
|
||||
int s;
|
||||
const bitvect* pend;
|
||||
|
||||
build_state(int st, const bitvect* bv = 0):
|
||||
s(st),
|
||||
pend(bv)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::pair<const state*, build_state> degen_state;
|
||||
|
||||
struct build_state_hash
|
||||
{
|
||||
size_t
|
||||
operator()(const build_state& s) const
|
||||
{
|
||||
if (!s.pend)
|
||||
return s.s;
|
||||
else
|
||||
return s.s ^ s.pend->hash();
|
||||
}
|
||||
};
|
||||
|
||||
struct build_state_equal
|
||||
{
|
||||
bool
|
||||
operator()(const build_state& left,
|
||||
const build_state& right) const
|
||||
{
|
||||
if (left.s != right.s)
|
||||
return false;
|
||||
if (left.pend == right.pend)
|
||||
return true;
|
||||
if (!right.pend || !left.pend)
|
||||
return false;
|
||||
return *left.pend == *right.pend;
|
||||
}
|
||||
};
|
||||
|
||||
// Associate the build state to its number.
|
||||
typedef Sgi::hash_map<build_state, int,
|
||||
build_state_hash, build_state_equal> bs2num_map;
|
||||
|
||||
// Queue of state to be processed.
|
||||
typedef std::deque<build_state> queue_t;
|
||||
|
||||
}
|
||||
|
||||
int label(const tgba_explicit_number* aut, state* s)
|
||||
{
|
||||
int label = aut->get_label(s);
|
||||
s->destroy();
|
||||
return label;
|
||||
}
|
||||
|
||||
SPOT_API
|
||||
tgba* nsa_to_tgba(const dstar_aut* nsa)
|
||||
{
|
||||
assert(nsa->type == Streett);
|
||||
tgba_explicit_number* a = nsa->aut;
|
||||
bdd_dict* dict = a->get_dict();
|
||||
|
||||
tgba_explicit_number* res = new tgba_explicit_number(dict);
|
||||
dict->register_all_variables_of(a, res);
|
||||
|
||||
// Create accpair_count acceptance sets for tge TGBA.
|
||||
size_t npairs = nsa->accpair_count;
|
||||
std::vector<bdd> acc_b(npairs);
|
||||
{
|
||||
ltl::environment& envacc = ltl::default_environment::instance();
|
||||
std::vector<const ltl::formula*> acc_f(npairs);
|
||||
for (unsigned n = 0; n < npairs; ++n)
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << n;
|
||||
const ltl::formula* af = acc_f[n] = envacc.require(s.str());
|
||||
res->declare_acceptance_condition(af->clone());
|
||||
}
|
||||
bdd allacc = bddfalse;
|
||||
for (unsigned n = 0; n < npairs; ++n)
|
||||
{
|
||||
const ltl::formula* af = acc_f[n];
|
||||
allacc |= acc_b[n] = res->get_acceptance_condition(af);
|
||||
}
|
||||
}
|
||||
|
||||
// These maps make it possible to convert build_state to number
|
||||
// and vice-versa.
|
||||
bs2num_map bs2num;
|
||||
|
||||
queue_t todo;
|
||||
|
||||
build_state s(label(a, a->get_init_state()));
|
||||
|
||||
bs2num[s] = 0;
|
||||
todo.push_back(s);
|
||||
|
||||
while (!todo.empty())
|
||||
{
|
||||
s = todo.front();
|
||||
todo.pop_front();
|
||||
int src = bs2num[s];
|
||||
|
||||
tgba_succ_iterator* i = a->succ_iter(a->get_state(s.s));
|
||||
for (i->first(); !i->done(); i->next())
|
||||
{
|
||||
int dlabel = label(a, i->current_state());
|
||||
|
||||
bitvect* pend = 0;
|
||||
bdd acc = bddfalse;
|
||||
if (s.pend)
|
||||
{
|
||||
pend = s.pend->clone();
|
||||
*pend |= nsa->accsets->at(2 * dlabel); // L
|
||||
*pend -= nsa->accsets->at(2 * dlabel + 1); // U
|
||||
|
||||
for (size_t i = 0; i < npairs; ++i)
|
||||
if (!pend->get(i))
|
||||
acc |= acc_b[i];
|
||||
}
|
||||
|
||||
|
||||
build_state d(dlabel, pend);
|
||||
// Have we already seen this destination?
|
||||
int dest;
|
||||
std::pair<bs2num_map::iterator, bool> dres =
|
||||
bs2num.insert(bs2num_map::value_type(d, 0));
|
||||
if (!dres.second)
|
||||
{
|
||||
dest = dres.first->second;
|
||||
delete d.pend;
|
||||
}
|
||||
else
|
||||
{
|
||||
dest = dres.first->second = bs2num.size() - 1;
|
||||
todo.push_back(d);
|
||||
}
|
||||
state_explicit_number::transition* t =
|
||||
res->create_transition(src, dest);
|
||||
t->condition = i->current_condition();
|
||||
t->acceptance_conditions = acc;
|
||||
|
||||
// Jump to level ∅
|
||||
if (s.pend == 0)
|
||||
{
|
||||
bitvect* pend = make_bitvect(npairs);
|
||||
build_state d(label(a, i->current_state()), pend);
|
||||
// Have we already seen this destination?
|
||||
int dest;
|
||||
std::pair<bs2num_map::iterator, bool> dres =
|
||||
bs2num.insert(bs2num_map::value_type(d, 0));
|
||||
if (!dres.second)
|
||||
{
|
||||
dest = dres.first->second;
|
||||
delete d.pend;
|
||||
}
|
||||
else
|
||||
{
|
||||
dest = dres.first->second = bs2num.size() - 1;
|
||||
todo.push_back(d);
|
||||
}
|
||||
state_explicit_number::transition* t =
|
||||
res->create_transition(src, dest);
|
||||
t->condition = i->current_condition();
|
||||
}
|
||||
}
|
||||
delete i;
|
||||
}
|
||||
|
||||
|
||||
// {
|
||||
// bs2num_map::iterator i = bs2num.begin();
|
||||
// while (i != bs2num.end())
|
||||
// {
|
||||
// std::cerr << i->second << ": (" << i->first.s << ",";
|
||||
// if (i->first.pend)
|
||||
// std::cerr << *i->first.pend << ")\n";
|
||||
// else
|
||||
// std::cerr << "-)\n";
|
||||
// ++i;
|
||||
// }
|
||||
// }
|
||||
|
||||
// Cleanup the bs2num map.
|
||||
bs2num_map::iterator i = bs2num.begin();
|
||||
while (i != bs2num.end())
|
||||
delete (i++)->first.pend;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
39
src/dstarparse/parsedecl.hh
Normal file
39
src/dstarparse/parsedecl.hh
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2013 Laboratoire de Recherche et Développement
|
||||
// de l'EPITA.
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
// Spot is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
// License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef SPOT_DSTARPARSE_PARSEDECL_HH
|
||||
# define SPOT_DSTARPARSE_PARSEDECL_HH
|
||||
|
||||
#include <string>
|
||||
#include "dstarparse.hh"
|
||||
#include "misc/location.hh"
|
||||
|
||||
# define YY_DECL \
|
||||
int dstaryylex(dstaryy::parser::semantic_type *yylval, \
|
||||
spot::location *yylloc, \
|
||||
spot::dstar_parse_error_list& error_list)
|
||||
YY_DECL;
|
||||
|
||||
namespace spot
|
||||
{
|
||||
int dstaryyopen(const std::string& name);
|
||||
void dstaryyclose();
|
||||
}
|
||||
|
||||
#endif // SPOT_DSTARPARSE_PARSEDECL_HH
|
||||
120
src/dstarparse/public.hh
Normal file
120
src/dstarparse/public.hh
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2013 Laboratoire de Recherche et Développement de
|
||||
// l'Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
// Spot is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
// License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef SPOT_DSTARPARSE_PUBLIC_HH
|
||||
# define SPOT_DSTARPARSE_PUBLIC_HH
|
||||
|
||||
# include "tgba/tgbaexplicit.hh"
|
||||
# include "misc/location.hh"
|
||||
# include "ltlenv/defaultenv.hh"
|
||||
# include <string>
|
||||
# include <list>
|
||||
# include <utility>
|
||||
# include <iosfwd>
|
||||
# include <misc/bitvect.hh>
|
||||
|
||||
namespace spot
|
||||
{
|
||||
/// \addtogroup tgba_io
|
||||
/// @{
|
||||
|
||||
/// \brief A parse diagnostic with its location.
|
||||
typedef std::pair<spot::location, std::string> dstar_parse_error;
|
||||
/// \brief A list of parser diagnostics, as filled by parse.
|
||||
typedef std::list<dstar_parse_error> dstar_parse_error_list;
|
||||
|
||||
enum dstar_type { Rabin, Streett };
|
||||
|
||||
/// \brief Temporary encoding of an omega automaton produced by
|
||||
/// ltl2dstar.
|
||||
struct SPOT_API dstar_aut
|
||||
{
|
||||
// Transition structure of the automaton.
|
||||
// This is encoded as a TGBA without acceptance condition.
|
||||
tgba_explicit_number* aut;
|
||||
/// Type of the acceptance.
|
||||
dstar_type type;
|
||||
/// Number of acceptance pairs.
|
||||
size_t accpair_count;
|
||||
/// \brief acceptance sets encoded as 2*num_state bit-vectors of
|
||||
/// num_pairs bits
|
||||
///
|
||||
/// Assuming $F=\{(L_0,U_0),\ldots,(L_i,U_i),\ldots\}$,
|
||||
/// $s\in L_i$ iff <code>accsets->at(s * 2).get(i)$</code>,
|
||||
/// an $s\in $U_i$ iff <code>accsets->at(s * 2 + 1).get(i)</code>.
|
||||
bitvect_array* accsets;
|
||||
|
||||
~dstar_aut()
|
||||
{
|
||||
delete aut;
|
||||
delete accsets;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// \brief Build a spot::tgba_explicit from ltl2dstar's output.
|
||||
/// \param filename The name of the file to parse.
|
||||
/// \param error_list A list that will be filled with
|
||||
/// parse errors that occured during parsing.
|
||||
/// \param dict The BDD dictionary where to use.
|
||||
/// \param env The environment of atomic proposition into which parsing
|
||||
/// should take place.
|
||||
/// \param debug When true, causes the parser to trace its execution.
|
||||
/// \return A pointer to the tgba built from \a filename, or
|
||||
/// 0 if the file could not be opened.
|
||||
///
|
||||
/// Note that the parser usually tries to recover from errors. It can
|
||||
/// return an non zero value even if it encountered error during the
|
||||
/// parsing of \a filename. If you want to make sure \a filename
|
||||
/// was parsed succesfully, check \a error_list for emptiness.
|
||||
///
|
||||
/// \warning This function is not reentrant.
|
||||
SPOT_API dstar_aut*
|
||||
dstar_parse(const std::string& filename,
|
||||
dstar_parse_error_list& error_list,
|
||||
bdd_dict* dict,
|
||||
ltl::environment& env = ltl::default_environment::instance(),
|
||||
bool debug = false);
|
||||
|
||||
/// \brief Format diagnostics produced by spot::dstar_parse.
|
||||
/// \param os Where diagnostics should be output.
|
||||
/// \param filename The filename that should appear in the diagnostics.
|
||||
/// \param error_list The error list filled by spot::ltl::parse while
|
||||
/// parsing \a ltl_string.
|
||||
/// \return \c true iff any diagnostic was output.
|
||||
SPOT_API bool
|
||||
format_dstar_parse_errors(std::ostream& os,
|
||||
const std::string& filename,
|
||||
dstar_parse_error_list& error_list);
|
||||
|
||||
|
||||
/// \brief Convert a non-deterministic Rabin automaton into a
|
||||
/// non-deterministic Büchi automaton.
|
||||
SPOT_API
|
||||
tgba* nra_to_nba(const dstar_aut* nra);
|
||||
|
||||
/// \brief Convert a non-deterministic Streett automaton into a
|
||||
/// non-deterministic tgba.
|
||||
SPOT_API
|
||||
tgba* nsa_to_tgba(const dstar_aut* nra);
|
||||
|
||||
/// @}
|
||||
}
|
||||
|
||||
#endif // SPOT_DSTARPARSE_PUBLIC_HH
|
||||
|
|
@ -80,6 +80,7 @@ TESTS = \
|
|||
renault.test \
|
||||
nondet.test \
|
||||
neverclaimread.test \
|
||||
dstar.test \
|
||||
readsave.test \
|
||||
simdet.test \
|
||||
sim.test \
|
||||
|
|
|
|||
131
src/tgbatest/dstar.test
Executable file
131
src/tgbatest/dstar.test
Executable file
|
|
@ -0,0 +1,131 @@
|
|||
#!/bin/sh
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2013 Laboratoire de Recherche et
|
||||
# Développement de l'Epita (LRDE).
|
||||
#
|
||||
# This file is part of Spot, a model checking library.
|
||||
#
|
||||
# Spot is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
# License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Do some quick translations to make sure the neverclaims produced by
|
||||
# spot actually look correct! We do that by parsing them via ltlcross.
|
||||
# ltl2neverclaim-lbtt.test does the same with LBTT if it is installed.
|
||||
|
||||
. ./defs
|
||||
set -e
|
||||
|
||||
cat >dra.dstar <<EOF
|
||||
DRA v2 explicit
|
||||
Comment: "Safra[NBA=2]"
|
||||
States: 3
|
||||
Acceptance-Pairs: 1
|
||||
Start: 0
|
||||
AP: 2 "a" "b"
|
||||
---
|
||||
State: 0
|
||||
Acc-Sig:
|
||||
1
|
||||
0
|
||||
2
|
||||
2
|
||||
State: 1
|
||||
Acc-Sig: -0
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
State: 2
|
||||
Acc-Sig: +0
|
||||
2
|
||||
2
|
||||
2
|
||||
2
|
||||
EOF
|
||||
|
||||
run 0 ../ltl2tgba -XD dra.dstar | tee stdout
|
||||
|
||||
cat >expected <<EOF
|
||||
digraph G {
|
||||
0 [label="", style=invis, height=0]
|
||||
0 -> 1
|
||||
1 [label="0"]
|
||||
1 -> 1 [label="a & !b\n"]
|
||||
1 -> 2 [label="!a & !b\n"]
|
||||
1 -> 3 [label="b\n"]
|
||||
2 [label="1"]
|
||||
2 -> 2 [label="1\n"]
|
||||
3 [label="2"]
|
||||
3 -> 3 [label="1\n"]
|
||||
}
|
||||
EOF
|
||||
|
||||
diff expected stdout
|
||||
|
||||
cat >dsa.dstar <<EOF
|
||||
DSA v2 explicit
|
||||
Comment: "Streett{Safra[NBA=2]}"
|
||||
States: 3
|
||||
Acceptance-Pairs: 1
|
||||
Start: 1
|
||||
AP: 1 "a"
|
||||
---
|
||||
State: 0
|
||||
Acc-Sig: +0
|
||||
0
|
||||
2
|
||||
State: 1
|
||||
Acc-Sig:
|
||||
0
|
||||
0
|
||||
State: 2
|
||||
Acc-Sig:
|
||||
0
|
||||
2
|
||||
EOF
|
||||
|
||||
run 0 ../ltl2tgba -XDB dsa.dstar | tee stdout
|
||||
|
||||
cat >expected <<EOF
|
||||
digraph G {
|
||||
0 [label="", style=invis, height=0]
|
||||
0 -> 1
|
||||
1 [label="0"]
|
||||
1 -> 2 [label="1\n"]
|
||||
1 -> 3 [label="1\n"]
|
||||
2 [label="1"]
|
||||
2 -> 2 [label="!a\n"]
|
||||
2 -> 3 [label="!a\n"]
|
||||
2 -> 4 [label="a\n"]
|
||||
2 -> 5 [label="a\n"]
|
||||
3 [label="2"]
|
||||
3 -> 6 [label="!a\n"]
|
||||
3 -> 5 [label="a\n{Acc[\"0\"]}"]
|
||||
4 [label="3"]
|
||||
4 -> 2 [label="!a\n"]
|
||||
4 -> 3 [label="!a\n"]
|
||||
4 -> 4 [label="a\n"]
|
||||
4 -> 5 [label="a\n"]
|
||||
5 [label="4"]
|
||||
5 -> 6 [label="!a\n"]
|
||||
5 -> 5 [label="a\n{Acc[\"0\"]}"]
|
||||
6 [label="5"]
|
||||
6 -> 6 [label="!a\n"]
|
||||
6 -> 7 [label="a\n"]
|
||||
7 [label="6"]
|
||||
7 -> 6 [label="!a\n"]
|
||||
7 -> 7 [label="a\n"]
|
||||
}
|
||||
EOF
|
||||
|
||||
diff expected stdout
|
||||
|
|
@ -45,6 +45,7 @@
|
|||
#include "tgbaalgos/reducerun.hh"
|
||||
#include "tgbaparse/public.hh"
|
||||
#include "neverparse/public.hh"
|
||||
#include "dstarparse/public.hh"
|
||||
#include "tgbaalgos/dupexp.hh"
|
||||
#include "tgbaalgos/minimize.hh"
|
||||
#include "taalgos/minimize.hh"
|
||||
|
|
@ -119,6 +120,10 @@ syntax(char* prog)
|
|||
<< std::endl
|
||||
<< " -X do not compute an automaton, read it from a file"
|
||||
<< std::endl
|
||||
<< " -XD do not compute an automaton, read it from an"
|
||||
<< " ltl2dstar file" << std::endl
|
||||
<< " -XDB read the from an ltl2dstar file and convert it to "
|
||||
<< "TGBA" << std::endl
|
||||
<< " -XL do not compute an automaton, read it from an"
|
||||
<< " LBTT file" << std::endl
|
||||
<< " -XN do not compute an automaton, read it from a"
|
||||
|
|
@ -361,8 +366,8 @@ main(int argc, char** argv)
|
|||
bool accepting_run = false;
|
||||
bool accepting_run_replay = false;
|
||||
bool from_file = false;
|
||||
bool read_neverclaim = false;
|
||||
bool read_lbtt = false;
|
||||
enum { ReadSpot, ReadLbtt, ReadNeverclaim, ReadDstar } readformat = ReadSpot;
|
||||
bool nra2nba = false;
|
||||
bool scc_filter = false;
|
||||
bool simpltl = false;
|
||||
spot::ltl::ltl_simplifier_options redopt(false, false, false, false,
|
||||
|
|
@ -899,16 +904,28 @@ main(int argc, char** argv)
|
|||
else if (!strcmp(argv[formula_index], "-X"))
|
||||
{
|
||||
from_file = true;
|
||||
readformat = ReadSpot;
|
||||
}
|
||||
else if (!strcmp(argv[formula_index], "-XN"))
|
||||
else if (!strcmp(argv[formula_index], "-XD"))
|
||||
{
|
||||
from_file = true;
|
||||
read_neverclaim = true;
|
||||
readformat = ReadDstar;
|
||||
}
|
||||
else if (!strcmp(argv[formula_index], "-XDB"))
|
||||
{
|
||||
from_file = true;
|
||||
readformat = ReadDstar;
|
||||
nra2nba = true;
|
||||
}
|
||||
else if (!strcmp(argv[formula_index], "-XL"))
|
||||
{
|
||||
from_file = true;
|
||||
read_lbtt = true;
|
||||
readformat = ReadLbtt;
|
||||
}
|
||||
else if (!strcmp(argv[formula_index], "-XN"))
|
||||
{
|
||||
from_file = true;
|
||||
readformat = ReadNeverclaim;
|
||||
}
|
||||
else if (!strcmp(argv[formula_index], "-y"))
|
||||
{
|
||||
|
|
@ -1018,7 +1035,9 @@ main(int argc, char** argv)
|
|||
if (from_file)
|
||||
{
|
||||
spot::tgba_explicit_string* e = 0;
|
||||
if (!read_neverclaim && !read_lbtt)
|
||||
switch (readformat)
|
||||
{
|
||||
case ReadSpot:
|
||||
{
|
||||
spot::tgba_parse_error_list pel;
|
||||
tm.start("parsing automaton");
|
||||
|
|
@ -1032,7 +1051,8 @@ main(int argc, char** argv)
|
|||
return 2;
|
||||
}
|
||||
}
|
||||
else if (read_neverclaim)
|
||||
break;
|
||||
case ReadNeverclaim:
|
||||
{
|
||||
spot::neverclaim_parse_error_list pel;
|
||||
tm.start("parsing neverclaim");
|
||||
|
|
@ -1047,7 +1067,8 @@ main(int argc, char** argv)
|
|||
}
|
||||
assume_sba = true;
|
||||
}
|
||||
else
|
||||
break;
|
||||
case ReadLbtt:
|
||||
{
|
||||
std::string error;
|
||||
std::fstream f(input.c_str());
|
||||
|
|
@ -1069,8 +1090,47 @@ main(int argc, char** argv)
|
|||
return 2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ReadDstar:
|
||||
{
|
||||
spot::dstar_parse_error_list pel;
|
||||
tm.start("parsing dstar");
|
||||
spot::dstar_aut* daut;
|
||||
daut = spot::dstar_parse(input, pel, dict,
|
||||
env, debug_opt);
|
||||
if (nra2nba)
|
||||
{
|
||||
if (daut->type == spot::Rabin)
|
||||
{
|
||||
to_free = a = spot::nra_to_nba(daut);
|
||||
assume_sba = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
to_free = a = spot::nsa_to_tgba(daut);
|
||||
assume_sba = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
to_free = a = daut->aut;
|
||||
daut->aut = 0;
|
||||
assume_sba = false;
|
||||
}
|
||||
delete daut;
|
||||
tm.stop("parsing dstar");
|
||||
if (spot::format_dstar_parse_errors(std::cerr, input, pel))
|
||||
{
|
||||
delete to_free;
|
||||
delete dict;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (e)
|
||||
e->merge_transitions();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue