Commit 961d005b authored by Alexandre Duret-Lutz's avatar Alexandre Duret-Lutz
Browse files

python: read automata from pipes

* src/hoaparse/hoaparse.yy, src/hoaparse/hoascan.ll,
src/hoaparse/parsedecl.hh, src/hoaparse/public.hh:
Add a way to read automata from a file descriptor.
* wrap/python/spot.py: Add machinery to read from
pipes.
* wrap/python/tests/piperead.ipynb: New file.
* wrap/python/tests/Makefile.am: Add it.
* wrap/python/tests/run.in: Setup PATH.
parent af8e7d62
......@@ -1620,6 +1620,15 @@ namespace spot
throw std::runtime_error(std::string("Cannot open file ") + name);
}
hoa_stream_parser::hoa_stream_parser(int fd,
const std::string& name,
bool ignore_abort)
: filename_(name), ignore_abort_(ignore_abort)
{
if (hoayyopen(fd))
throw std::runtime_error(std::string("Cannot open file ") + name);
}
hoa_stream_parser::~hoa_stream_parser()
{
hoayyclose();
......
......@@ -388,6 +388,31 @@ namespace spot
return 0;
}
int
hoayyopen(int fd)
{
bool want_interactive = false;
yyin = fdopen(fd, "r");
// If the input is a pipe, make the scanner
// interactive so that it does not wait for the input
// buffer to be full to process automata.
struct stat s;
if (fstat(fd, &s) < 0)
throw std::runtime_error("fstat failed");
if (S_ISFIFO(s.st_mode))
want_interactive = true;
// Reset the lexer in case a previous parse
// ended badly.
YY_NEW_FILE;
hoayyreset();
if (want_interactive)
yy_set_interactive(true);
return 0;
}
void
hoayyclose()
{
......
// -*- coding: utf-8 -*-
// Copyright (C) 2014 Laboratoire de Recherche et Développement
// Copyright (C) 2014, 2015 Laboratoire de Recherche et Développement
// de l'EPITA.
//
// This file is part of Spot, a model checking library.
......@@ -33,6 +33,7 @@ namespace spot
{
void hoayyreset();
int hoayyopen(const std::string& name);
int hoayyopen(int fd);
void hoayyclose();
// This exception is thrown by the lexer when it reads "--ABORT--".
......
......@@ -64,6 +64,10 @@ namespace spot
bool ignore_abort_;
public:
hoa_stream_parser(const std::string& filename, bool ignore_abort = false);
// Read from an already open file descriptor.
// Use filename in error messages.
hoa_stream_parser(int fd, const std::string& filename,
bool ignore_abort = false);
~hoa_stream_parser();
hoa_aut_ptr parse(hoa_parse_error_list& error_list,
const bdd_dict_ptr& dict,
......
......@@ -111,14 +111,54 @@ def _tgba_save(a, filename, format='hoa', opt=None, append=False):
tgba.to_str = _tgba_to_str
tgba.save = _tgba_save
def automata(filename):
p = hoa_stream_parser(filename, True)
while True:
a = p.parse_strict(_bdd_dict)
if a == None:
return
yield a
def automata(*filenames):
"""Read automata from a list of filenames.
The automata can be written in the
[HOA format](http://adl.github.io/hoaf/), as
[never claims](http://spinroot.com/spin/Man/never.html),
or in [LBTT's format]
(http://www.tcs.hut.fi/Software/lbtt/doc/html/Format-for-automata.html).
If a filename ends with a `|`, then the filename is interpreted as
a shell command, and the output of that command (without the `|`)
is parsed."""
for filename in filenames:
try:
if filename[-1] != '|':
proc = None
p = hoa_stream_parser(filename, True)
else:
proc = subprocess.Popen(filename[:-1], shell=True,
stdout=subprocess.PIPE)
p = hoa_stream_parser(proc.stdout.fileno(), filename, True)
a = True
while a:
a = p.parse_strict(_bdd_dict)
if a:
yield a
finally:
# Make sure we destroy the parser and the subprocess in
# the correct order...
del p
if proc != None:
proc.poll()
ret = proc.returncode
del proc
if ret:
raise RuntimeError("Command {} exited with exit status {}"
.format(filename[:-1], ret))
return
def automaton(filename):
"""Read a single automaton from a file.
See `spot.automata()` for a list of supported format."""
try:
return next(automata(filename))
except StopIteration:
raise RuntimeError("Failed to read automaton from {}".format(filename))
def translate(formula, output='tgba', pref='small', level='high',
complete=False):
......
......@@ -44,5 +44,6 @@ TESTS = \
minato.py \
optionmap.py \
parsetgba.py \
piperead.ipynb \
randltl.ipynb \
setxor.py
This diff is collapsed.
......@@ -32,6 +32,9 @@ modpath='../.libs:@top_builddir@/src/.libs:@top_builddir@/buddy/src/.libs'
# Python 2.6.
pypath='..:../.libs:@srcdir@/..:@srcdir@/../.libs:$PYTHONPATH'
PATH="@abs_top_builddir@/src/bin:$PATH"
export PATH
test -z "$1" &&
PYTHONPATH=$pypath DYLD_LIBRARY_PATH=$modpath exec @PYTHON@
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment