Commit ae35cc29 authored by Alexandre Duret-Lutz's avatar Alexandre Duret-Lutz

Better formula I/O for ipython.

* src/ltlparse/public.hh, src/ltlparse/ltlparse.yy,
src/ltlparse/ltlscan.ll (parse_error): New class.
(parse_formula): New function that raises a parse_error
exception on error.
* src/ltlvisit/tostring.hh, src/ltlvisit/tostring.cc:
(to_sclatex_string): New method.
* wrap/python/spot.i: Catch the parser_error exception,
and use the to_sclatex_string for MathJax rendering.
* wrap/python/tests/run.in: Start ipython on demand.
parent 6d7c258f
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
%code requires %code requires
{ {
#include <string> #include <string>
#include <sstream>
#include "public.hh" #include "public.hh"
#include "ltlast/allnodes.hh" #include "ltlast/allnodes.hh"
#include "ltlvisit/tostring.hh" #include "ltlvisit/tostring.hh"
...@@ -1034,6 +1035,24 @@ namespace spot ...@@ -1034,6 +1035,24 @@ namespace spot
return result; return result;
} }
const formula*
parse_formula(const std::string& ltl_string, environment& env)
{
parse_error_list pel;
const formula* f = parse(ltl_string, pel, env);
std::ostringstream s;
if (format_parse_errors(s, ltl_string, pel))
{
parse_error_list pel2;
const formula* g = parse_lbt(ltl_string, pel2, env);
if (pel2.empty())
return g;
else
throw parse_error(s.str());
}
return f;
}
} }
} }
......
...@@ -110,7 +110,7 @@ BOXDARROW {BOX}{DARROWL}|"|"{DARROWL}|"⤇" ...@@ -110,7 +110,7 @@ BOXDARROW {BOX}{DARROWL}|"|"{DARROWL}|"⤇"
unput(')'); unput(')');
if (!missing_parent) if (!missing_parent)
error_list.push_back( error_list.push_back(
spot::ltl::parse_error(*yylloc, spot::ltl::one_parse_error(*yylloc,
"missing closing parenthese")); "missing closing parenthese"));
missing_parent = true; missing_parent = true;
} }
...@@ -164,7 +164,7 @@ BOXDARROW {BOX}{DARROWL}|"|"{DARROWL}|"⤇" ...@@ -164,7 +164,7 @@ BOXDARROW {BOX}{DARROWL}|"|"{DARROWL}|"⤇"
unput(')'); unput(')');
if (!missing_parent) if (!missing_parent)
error_list.push_back( error_list.push_back(
spot::ltl::parse_error(*yylloc, spot::ltl::one_parse_error(*yylloc,
"missing closing brace")); "missing closing brace"));
missing_parent = true; missing_parent = true;
} }
...@@ -204,7 +204,7 @@ BOXDARROW {BOX}{DARROWL}|"|"{DARROWL}|"⤇" ...@@ -204,7 +204,7 @@ BOXDARROW {BOX}{DARROWL}|"|"{DARROWL}|"⤇"
if (errno || yylval->num != n) if (errno || yylval->num != n)
{ {
error_list.push_back( error_list.push_back(
spot::ltl::parse_error(*yylloc, spot::ltl::one_parse_error(*yylloc,
"value too large ignored")); "value too large ignored"));
// Skip this number and read next token // Skip this number and read next token
yylloc->step(); yylloc->step();
......
// -*- coding: utf-8 -*- // -*- coding: utf-8 -*-
// Copyright (C) 2010, 2011, 2012, 2013 Laboratoire de Recherche et // Copyright (C) 2010, 2011, 2012, 2013, 2014 Laboratoire de Recherche
// Développement de l'Epita (LRDE). // et Développement de l'Epita (LRDE).
// Copyright (C) 2003, 2004, 2005, 2006 Laboratoire d'Informatique de // Copyright (C) 2003, 2004, 2005, 2006 Laboratoire d'Informatique de
// Paris 6 (LIP6), département Systèmes Répartis Coopératifs (SRC), // Paris 6 (LIP6), département Systèmes Répartis Coopératifs (SRC),
// Université Pierre et Marie Curie. // Université Pierre et Marie Curie.
...@@ -40,9 +40,9 @@ namespace spot ...@@ -40,9 +40,9 @@ namespace spot
#ifndef SWIG #ifndef SWIG
/// \brief A parse diagnostic with its location. /// \brief A parse diagnostic with its location.
typedef std::pair<location, std::string> parse_error; typedef std::pair<location, std::string> one_parse_error;
/// \brief A list of parser diagnostics, as filled by parse. /// \brief A list of parser diagnostics, as filled by parse.
typedef std::list<parse_error> parse_error_list; typedef std::list<one_parse_error> parse_error_list;
#else #else
// Turn parse_error_list into an opaque type for Swig. // Turn parse_error_list into an opaque type for Swig.
struct parse_error_list {}; struct parse_error_list {};
...@@ -124,6 +124,24 @@ namespace spot ...@@ -124,6 +124,24 @@ namespace spot
environment& env = default_environment::instance(), environment& env = default_environment::instance(),
bool debug = false); bool debug = false);
struct SPOT_API parse_error: public std::runtime_error
{
parse_error(const std::string& s): std::runtime_error(s)
{
}
};
/// \brief A simple wrapper to parse() and parse_lbt().
///
/// This is mostly meant for interactive use. It first tries parse(); if
/// this fails it tries parse_lbt(); and if both fails it returns the errors
/// of the first call to parse() as a std::runtime_error().
SPOT_API const formula*
parse_formula(const std::string& ltl_string,
environment& env = default_environment::instance());
/// \brief Build a formula from a string representing a SERE. /// \brief Build a formula from a string representing a SERE.
/// \param sere_string The string to parse. /// \param sere_string The string to parse.
/// \param error_list A list that will be filled with /// \param error_list A list that will be filled with
......
...@@ -260,6 +260,47 @@ namespace spot ...@@ -260,6 +260,47 @@ namespace spot
"\\SereGoto{", "\\SereGoto{",
}; };
const char* sclatex_kw[] = {
"\\ffalse",
"\\ttrue",
"\\varepsilon",
" \\oplus ",
" \\rightarrow ",
" \\leftrightarrow ",
" \\mathbin{\\mathsf{U}} ",
" \\mathbin{\\mathsf{R}} ",
" \\mathbin{\\mathsf{W}} ",
" \\mathbin{\\mathsf{M}} ",
("\\mathrel{\\Diamond\\kern-1.7pt\\raise.4pt"
"\\hbox{$\\mathord{\\rightarrow}$}} "),
("\\mathrel{\\Diamond\\kern-1.7pt\\raise.4pt"
"\\hbox{$\\mathord{\\Rightarrow}$}} "),
"\\seqM ",
"\\seqXM ",
("\\mathrel{\\Box\\kern-1.7pt\\raise.4pt"
"\\hbox{$\\mathord{\\rightarrow}$}} "),
("\\mathrel{\\Box\\kern-1.7pt\\raise.4pt"
"\\hbox{$\\mathord{\\Rightarrow}$}} "),
"\\lnot ",
"\\mathsf{X} ",
"\\mathsf{F} ",
"\\mathsf{G} ",
" \\lor ",
" \\cup ",
" \\land ",
" \\cap ",
" \\mathbin{\\mathsf{\\&}} ",
" \\mathbin{\\mathsf{;}} ",
" \\mathbin{\\mathsf{:}} ",
"\\{",
"\\}",
"}",
"^{\\star",
"^+",
"^{=",
"^{\\to",
};
static bool static bool
is_bare_word(const char* str) is_bare_word(const char* str)
{ {
...@@ -370,7 +411,7 @@ namespace spot ...@@ -370,7 +411,7 @@ namespace spot
} }
else else
{ {
if (kw_ == latex_kw) if (kw_ == latex_kw || kw_ == sclatex_kw)
{ {
size_t s = str.size(); size_t s = str.size();
while (str[s - 1] >= '0' && str[s - 1] <= '9') while (str[s - 1] >= '0' && str[s - 1] <= '9')
...@@ -945,6 +986,24 @@ namespace spot ...@@ -945,6 +986,24 @@ namespace spot
return os.str(); return os.str();
} }
std::ostream&
to_sclatex_string(const formula* f, std::ostream& os,
bool full_parent, bool ratexp)
{
to_string_visitor v(os, full_parent, ratexp, sclatex_kw);
f->accept(v);
return os;
}
std::string
to_sclatex_string(const formula* f,
bool full_parent, bool ratexp)
{
std::ostringstream os;
to_sclatex_string(f, os, full_parent, ratexp);
return os.str();
}
} }
} }
// -*- coding: utf-8 -*- // -*- coding: utf-8 -*-
// Copyright (C) 2010, 2011, 2012, 2013 Laboratoire de Recherche et // Copyright (C) 2010, 2011, 2012, 2013, 2014 Laboratoire de Recherche et
// Développement de l'Epita (LRDE). // Développement de l'Epita (LRDE).
// Copyright (C) 2003, 2004 Laboratoire d'Informatique de Paris 6 (LIP6), // Copyright (C) 2003, 2004 Laboratoire d'Informatique de Paris 6 (LIP6),
// département Systèmes Répartis Coopératifs (SRC), Université Pierre // département Systèmes Répartis Coopératifs (SRC), Université Pierre
...@@ -101,8 +101,7 @@ namespace spot ...@@ -101,8 +101,7 @@ namespace spot
SPOT_API std::string SPOT_API std::string
to_wring_string(const formula* f); to_wring_string(const formula* f);
/// \brief Output a formula as an LaTeX string which is parsable unless /// \brief Output a formula as an LaTeX string which is parsable.
/// the formula contains automaton operators (used in ELTL formulae).
/// \param f The formula to translate. /// \param f The formula to translate.
/// \param os The stream where it should be output. /// \param os The stream where it should be output.
/// \param full_parent Whether or not the string should by fully /// \param full_parent Whether or not the string should by fully
...@@ -112,7 +111,7 @@ namespace spot ...@@ -112,7 +111,7 @@ namespace spot
to_latex_string(const formula* f, std::ostream& os, to_latex_string(const formula* f, std::ostream& os,
bool full_parent = false, bool ratexp = false); bool full_parent = false, bool ratexp = false);
/// \brief Output a formula as a LaTeX string which is parsable /// \brief Output a formula as a LaTeX string which is parsable.
/// unless the formula contains automaton operators (used in ELTL formulae). /// unless the formula contains automaton operators (used in ELTL formulae).
/// \param f The formula to translate. /// \param f The formula to translate.
/// \param full_parent Whether or not the string should by fully /// \param full_parent Whether or not the string should by fully
...@@ -122,6 +121,29 @@ namespace spot ...@@ -122,6 +121,29 @@ namespace spot
to_latex_string(const formula* f, to_latex_string(const formula* f,
bool full_parent = false, bool ratexp = false); bool full_parent = false, bool ratexp = false);
/// \brief Output a formula as a self-contained LaTeX string.
///
/// The result cannot be parsed back.
/// \param f The formula to translate.
/// \param os The stream where it should be output.
/// \param full_parent Whether or not the string should by fully
/// parenthesized.
/// \param ratexp Whether we are printing a SERE.
SPOT_API std::ostream&
to_sclatex_string(const formula* f, std::ostream& os,
bool full_parent = false, bool ratexp = false);
/// \brief Output a formula as a self-contained LaTeX string.
///
/// The result cannot be parsed bacl.
/// \param f The formula to translate.
/// \param full_parent Whether or not the string should by fully
/// parenthesized.
/// \param ratexp Whether we are printing a SERE.
SPOT_API std::string
to_sclatex_string(const formula* f,
bool full_parent = false, bool ratexp = false);
/// @} /// @}
} }
} }
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
%include "std_shared_ptr.i" %include "std_shared_ptr.i"
%include "std_string.i" %include "std_string.i"
%include "std_list.i" %include "std_list.i"
%include "exception.i"
// git grep 'typedef.*std::shared_ptr' | grep -v const // git grep 'typedef.*std::shared_ptr' | grep -v const
// sed 's/.*<\(.*\)>.*/%shared_ptr(spot::\1)/g' // sed 's/.*<\(.*\)>.*/%shared_ptr(spot::\1)/g'
...@@ -172,6 +173,19 @@ using namespace spot; ...@@ -172,6 +173,19 @@ using namespace spot;
}; };
%apply char** OUTPUT { char** err }; %apply char** OUTPUT { char** err };
%exception {
try {
$action
}
catch (const spot::ltl::parse_error& e)
{
std::string er("\n");
er += e.what();
SWIG_exception(SWIG_SyntaxError, er.c_str());
}
}
// False and True cannot be redefined in Python3, even in a class. // False and True cannot be redefined in Python3, even in a class.
// Spot uses these in an enum of the constant class. // Spot uses these in an enum of the constant class.
%rename(FalseVal) False; %rename(FalseVal) False;
...@@ -286,12 +300,12 @@ namespace spot { ...@@ -286,12 +300,12 @@ namespace spot {
size_t __hash__() { return self->hash(); } size_t __hash__() { return self->hash(); }
std::string std::string __repr__() { return spot::ltl::to_string(self); }
__str__(void) std::string _repr_latex_()
{ {
return spot::ltl::to_string(self); return std::string("$") + spot::ltl::to_sclatex_string(self) + '$';
} }
std::string __str__() { return spot::ltl::to_string(self); }
} }
%nodefaultctor std::ostream; %nodefaultctor std::ostream;
......
...@@ -40,6 +40,8 @@ case $1 in ...@@ -40,6 +40,8 @@ case $1 in
PYTHONPATH=$pypath DYLD_LIBRARY_PATH=$modpath exec @PYTHON@ "$@";; PYTHONPATH=$pypath DYLD_LIBRARY_PATH=$modpath exec @PYTHON@ "$@";;
*.test) *.test)
exec sh -x "$@";; exec sh -x "$@";;
ipython*)
PYTHONPATH=$pypath DYLD_LIBRARY_PATH=$modpath exec "$@";;
*) *)
echo "Unknown extension" >&2 echo "Unknown extension" >&2
exit 2;; exit 2;;
......
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