Commit 0104587d authored by Akim Demaille's avatar Akim Demaille
Browse files

valuesets: improve the `text` format, and introduce `sname`

Clarify the `text` format.  Currently it serves two purposes:

- to present the user with a readable definition of the valueset.
  This is a failure: `lal_char(abc), b` is unpleasant to read.
  We would prefer `{abc} → 𝔹`.

- to build the snames.  This is a failure too, as we had to introduce
  a specific format (format::generators) to print generators, instead
  of `text`.

So rename `generators` as `sname`, and use the latter name instead of
`text` to build signatures.  Let's make `text` produce a human
readable result, using UTF-8.

* vcsn/misc/format.hh, lib/vcsn/misc/format.cc (generators): Rename as...
(sname): this.

* vcsn/alphabets/char.hh, vcsn/alphabets/setalpha.hh,
* vcsn/alphabets/string.hh, vcsn/core/rat/expansionset.hh,
* vcsn/core/rat/expressionset.hxx, vcsn/ctx/context.hh,
* vcsn/labelset/letterset.hh, vcsn/labelset/nullableset.hh,
* vcsn/labelset/oneset.hh, vcsn/labelset/tupleset.hh,
* vcsn/labelset/wordset.hh, vcsn/weightset/b.hh,
* vcsn/weightset/log.hh, vcsn/weightset/nmin.hh,
* vcsn/weightset/polynomialset.hh, vcsn/weightset/q.hh,
* vcsn/weightset/qmp.hh, vcsn/weightset/r.hh,
* vcsn/weightset/rmin.hh, vcsn/weightset/z.hh,
* vcsn/weightset/zmin.hh
(print_set): Be consistent in the support of `latex`, `sname`
and `text`.

* vcsn/algos/dot.hh: Adjust: ask for `sname`.
* tests/python/context.py: Likewise.
parent 0e0316b2
Pipeline #104 skipped
......@@ -16,9 +16,9 @@ namespace vcsn
{
{"auto", deflt},
{"default", deflt},
{"generators", generators},
{"latex", latex},
{"raw", raw},
{"sname", sname},
{"text", text},
};
format_ = getargs("format", map, f);
......@@ -28,12 +28,12 @@ namespace vcsn
{
switch (f.kind())
{
case format::generators:
return "generators";
case format::latex:
return "latex";
case format::raw:
return "raw";
case format::sname:
return "sname";
case format::text:
return "text";
}
......
......@@ -50,6 +50,7 @@ def _automaton_as_svg(self, format="dot", engine="dot"):
automaton.as_svg = _automaton_as_svg
# conjunction.
_automaton_conjunction_orig = automaton.conjunction
......
......@@ -1504,6 +1504,7 @@ BOOST_PYTHON_MODULE(vcsn_cxx)
bp::class_<expression>("expression", bp::no_init)
.def(bp::init<const context&, const std::string&, const std::string&>
((arg("context"), arg("data"), arg("identities") = "default")))
.def("automaton", &expression::to_automaton, (arg("algo") = "auto"))
.def("complement", &expression::complement)
.def("conjunction", &expression::conjunction)
.def("constant_term", &expression::constant_term)
......@@ -1539,7 +1540,6 @@ BOOST_PYTHON_MODULE(vcsn_cxx)
.def("star_normal_form", &expression::star_normal_form)
.def("sum", &expression::sum)
.def("thompson", &expression::thompson)
.def("automaton", &expression::to_automaton, (arg("algo") = "auto"))
.def("transpose", &expression::transpose)
.def("transposition", &expression::transposition)
.def("_tuple", &expression::tuple_).staticmethod("_tuple")
......
......@@ -153,11 +153,11 @@ def normalize(a):
# \e that remains, the following conversion _will_ reject it.
to = re.sub(r'nullableset<(lal_char\(.*?\)|letterset<char_letters\(.*?\)>)>',
r'\1',
a.context().format('text'))
a.context().format('sname'))
return a.automaton(vcsn.context(to))
def can_test_equivalence(a):
ctx = str(a.context())
ctx = a.context().format('sname')
expressionset_ws = re.match('.*expressionset<.*>', ctx) is None
return not(ctx.endswith('min')) and expressionset_ws
......
......@@ -5,7 +5,7 @@ import re
import vcsn
from test import *
def check(ctx, exp = None, format = "text"):
def check(ctx, exp = None, format = "sname"):
c = vcsn.context(ctx)
if exp is None:
exp = ctx
......@@ -25,8 +25,12 @@ XFAIL(lambda: vcsn.context("lal_char(a), b_z"))
check('letterset<char_letters>, b', 'letterset<char_letters()>, b')
check('lal_char, b', 'letterset<char_letters()>, b')
# An open context is printed as open in LaTeX.
check('letterset<char_letters>, b', r'\{\ldots\}\rightarrow\mathbb{B}', 'latex')
check('lal_char, b', r'\{\ldots\}\rightarrow\mathbb{B}', 'latex')
check('lal_char, b', r'\{\ldots\}\to\mathbb{B}', 'latex')
check('lal_char, b', r'{...} → 𝔹', 'text')
check('lal_char(abc), b', r'\{a, b, c\}\to\mathbb{B}', 'latex')
check('lal_char(abc), b', r'{abc} → 𝔹', 'text')
check('lal_char(), b', r'\{\}\to\mathbb{B}', 'latex')
check('lal_char(), b', r'{} → 𝔹', 'text')
# letterset and different char_letters.
check(r'lal_char(), b', r'letterset<char_letters()>, b')
......@@ -55,6 +59,7 @@ check('lal_char(ab), q', 'letterset<char_letters(ab)>, q')
check('wordset<string_letters>, b', 'wordset<string_letters()>, b')
## ------------------------- ##
## LabelSet: expressionset. ##
## ------------------------- ##
......@@ -104,12 +109,3 @@ exp = 'nullableset<lat<letterset<char_letters(ab)>, lat<nullableset<letterset<ch
check(ctx, exp)
ctx = re.sub(r'\s+', '', ctx)
check(ctx, exp)
## ------- ##
## LaTeX. ##
## ------- ##
check("lal_char(abc), b", r'\{a, b, c\}\rightarrow\mathbb{B}',
format = "latex")
check("lal_char(), b", r'\{\}\rightarrow\mathbb{B}',
format = "latex")
......@@ -14,7 +14,7 @@
[a-b] => a+b
[a-bc-d] => [a-d]
[b-a] ! 1.1-5: expressionset<wordset<char_letters(abcdefgh)>, b>(associative): invalid letter interval: b-a
[b-a] ! 1.1-5: RatE[{abcdefgh}* → 𝔹](associative): invalid letter interval: b-a
[] ! 1.1-2: invalid empty letter class
a|x ! 1.2: too many tapes
......
......@@ -36,8 +36,8 @@ a(bc) == a.b.c
# Base cases.
ab => ab
# Error cases.
x ! 1.1: char_letters(abcdefgh): invalid letter: x
axb ! 1.2: char_letters(abcdefgh): invalid letter: x
x ! 1.1: {abcdefgh}: invalid letter: x
axb ! 1.2: {abcdefgh}: invalid letter: x
# Precedence and associativity.
%identities: associative
......
......@@ -5,9 +5,9 @@
# Check the alphabets.
<j>a => <j>a
<i>x ! 1.4: char_letters(abcdefgh): invalid letter: x
<x>a ! 1.1-3: 1.1: char_letters(ijklmn): invalid letter: x
a<x> ! 1.2-4: 1.1: char_letters(ijklmn): invalid letter: x
<i>x ! 1.4: {abcdefgh}: invalid letter: x
<x>a ! 1.1-3: 1.1: {ijklmn}: invalid letter: x
a<x> ! 1.2-4: 1.1: {ijklmn}: invalid letter: x
# Check associativities.
%labels: letters
......
......@@ -4,9 +4,9 @@
# Check the alphabets.
<<<2>x>i>a => <<<2>x>i>a
<<<l>x>i>a ! 1.1-9: 1.1-6: 1.1-3: q: invalid numerator: l
<<<3>l>i>a ! 1.1-9: 1.1-6: 1.4: char_letters(wxyz): invalid letter: l
<<<4>x>L>a ! 1.1-9: 1.7: char_letters(ijklmn): invalid letter: L
<<<5>x>i>l ! 1.10: char_letters(abcdefgh): invalid letter: l
<<<3>l>i>a ! 1.1-9: 1.1-6: 1.4: {wxyz}: invalid letter: l
<<<4>x>L>a ! 1.1-9: 1.7: {ijklmn}: invalid letter: L
<<<5>x>i>l ! 1.10: {abcdefgh}: invalid letter: l
# Check weight products.
<<<1>\e>i>a => <i>a
......
......@@ -15,7 +15,7 @@
/// The name of \a vs.
template <typename ValueSet>
std::string
set_name(const ValueSet& vs, vcsn::format fmt = vcsn::format::text)
set_name(const ValueSet& vs, vcsn::format fmt = vcsn::format::sname)
{
std::ostringstream o;
vs.print_set(o, fmt);
......@@ -148,7 +148,7 @@ check_tupleset()
"lat<wordset<char_letters>, wordset<char_letters>>");
// print_set.
ASSERT_EQ(set_name(wwset, vcsn::format::text),
ASSERT_EQ(set_name(wwset, vcsn::format::sname),
"lat<wordset<char_letters(abc)>, wordset<char_letters(xyz)>>");
ASSERT_EQ(set_name(wwset, vcsn::format::latex),
"\\{a, b, c\\}^* \\times \\{x, y, z\\}^*");
......
......@@ -87,7 +87,7 @@ namespace vcsn
"{\n"
" vcsn_context = \"";
enable_();
aut_->context().print_set(bos_, format::text);
aut_->context().print_set(bos_, format::sname);
disable_();
bos_ << "\"\n"
" rankdir = LR\n"
......
......@@ -207,7 +207,7 @@ namespace vcsn
info(const Aut& aut, std::ostream& out, bool detailed = false)
{
out << "type: ";
aut->print_set(out, format::text) << '\n';
aut->print_set(out, format::sname) << '\n';
#define ECHO(Name, Value) \
out << Name ": " << Value << '\n'
ECHO("number of states", aut->num_states());
......@@ -275,7 +275,7 @@ namespace vcsn
std::ostream& o)
{
o << "type: ";
rs.print_set(o, format::text);
rs.print_set(o, format::sname);
o << "\nsize: " << rat::size<ExpSet>(e);
......
......@@ -201,11 +201,7 @@ namespace vcsn
else
switch (fmt.kind())
{
case format::raw:
o << l;
break;
case format::generators:
case format::sname:
// Escape dash and parens, which are special when parsed
// (actually, only the closing paren is special, but treating
// them symmetrically is better looking).
......@@ -216,9 +212,19 @@ namespace vcsn
break;
case format::latex:
if (l == '\\')
o << "\\backslash{}";
else
str_escape(o, l, "|',[-]<>");
break;
case format::raw:
o << l;
break;
case format::text:
if (l == '\\')
o << (fmt == format::latex ? "\\backslash{}" : "\\\\");
o << "\\\\";
else
str_escape(o, l, "|',[-]<>");
}
......
......@@ -258,35 +258,50 @@ namespace vcsn
std::ostream&
print_set(std::ostream& o, format fmt = {}) const
{
if (fmt == format::latex)
{
o << "\\{";
const char *sep = "";
for (letter_t l: alphabet_)
{
o << sep;
if (! this->is_letter(l))
o << "\\mathit{";
this->print(l, o, fmt);
if (! this->is_letter(l))
o << '}';
sep = ", ";
}
if (open_)
o << sep << "\\ldots";
o << "\\}";
}
else if (fmt == format::text)
switch (fmt.kind())
{
case format::latex:
{
o << "\\{";
const char *sep = "";
for (letter_t l: alphabet_)
{
o << sep;
if (! this->is_letter(l))
o << "\\mathit{";
this->print(l, o, fmt);
if (! this->is_letter(l))
o << '}';
sep = ", ";
}
if (open_)
o << sep << "\\ldots";
o << "\\}";
}
break;
case format::sname:
o << sname() << '(';
for (letter_t l: alphabet_)
this->print(l, o, format::generators);
this->print(l, o, format::sname);
// FIXME: Don't display openness here, as our "make()"
// parser is not ready for it.
o << ')';
break;
case format::text:
o << '{';
for (letter_t l: alphabet_)
this->print(l, o, format::sname);
if (open_)
o << "...";
o << '}';
break;
case format::raw:
assert(0);
break;
}
else
raise(sname(), ": print_set: invalid format: ", fmt);
return o;
}
......
......@@ -240,7 +240,7 @@ namespace vcsn
o << "`\\mathit{" << l << "}\\textrm{'}";
break;
case format::generators:
case format::sname:
case format::text:
if (l.get().size() == 1)
str_escape(o, l, "|',[-]<>");
......
......@@ -78,9 +78,28 @@ namespace vcsn
/// Print this valueset.
std::ostream& print_set(std::ostream& o, format fmt = {}) const
{
o << "expansionset<";
rs_.print_set(o, fmt);
return o << '>';
switch (fmt.kind())
{
case format::latex:
o << "\\mathsf{Expansion}[";
rs_.print_set(o, fmt);
o << ']';
break;
case format::sname:
o << "expansionset<";
rs_.print_set(o, fmt);
o << ">";
break;
case format::text:
o << "Expansion[";
rs_.print_set(o, fmt);
o << ']';
break;
case format::raw:
assert(0);
break;
}
return o;
}
/// Print this expansion.
......
......@@ -69,33 +69,43 @@ namespace vcsn
DEFINE::print_set(std::ostream& o, format fmt) const
-> std::ostream&
{
if (fmt == format::latex)
{
o << "\\mathsf{"
<< (identities().is_distributive() ? "Series" : "RatE")
<< "}[";
context().print_set(o, fmt);
o << ']';
}
else if (fmt == format::text)
{
if (identities().is_distributive())
switch (fmt.kind())
{
o << "seriesset<";
case format::latex:
o << "\\mathsf{"
<< (identities().is_distributive() ? "Series" : "RatE")
<< "}[";
context().print_set(o, fmt);
o << '>';
}
else
{
o << "expressionset<";
o << ']';
break;
case format::sname:
if (identities().is_distributive())
{
o << "seriesset<";
context().print_set(o, fmt);
o << '>';
}
else
{
o << "expressionset<";
context().print_set(o, fmt);
o << '>';
if (identities() != vcsn::rat::identities{})
o << '(' << identities() << ')';
}
break;
case format::text:
o << "RatE[";
context().print_set(o, fmt);
o << '>';
o << ']';
if (identities() != vcsn::rat::identities{})
o << '(' << identities() << ')';
break;
case format::raw:
assert(0);
break;
}
}
else
raise("invalid format: ", fmt);
return o;
return o;
}
......
......@@ -106,11 +106,23 @@ namespace vcsn
print_set(std::ostream& o, format fmt = {}) const
{
labelset()->print_set(o, fmt);
if (fmt == format::latex)
o << "\\rightarrow";
else
o << ", ";
return weightset()->print_set(o, fmt);
switch (fmt.kind())
{
case format::latex:
o << "\\to";
break;
case format::sname:
o << ", ";
break;
case format::text:
o << " → ";
break;
case format::raw:
assert(0);
break;
}
weightset()->print_set(o, fmt);
return o;
}
static constexpr bool
......
......@@ -264,16 +264,23 @@ namespace vcsn
std::ostream&
print_set(std::ostream& o, format fmt = {}) const
{
if (fmt == format::latex)
this->genset()->print_set(o, fmt);
else if (fmt == format::text)
switch (fmt.kind())
{
case format::latex:
this->genset()->print_set(o, fmt);
break;
case format::sname:
o << "letterset<";
this->genset()->print_set(o, fmt);
o << '>';
break;
case format::text:
this->genset()->print_set(o, fmt);
break;
case format::raw:
assert(0);
break;
}
else
raise("invalid format: ", fmt);
return o;
}
};
......
......@@ -498,13 +498,17 @@ namespace vcsn
o << ")^?";
break;
case format::text:
o << "nullableset<";
case format::sname:
o << "nullableset<";
ls_->print_set(o, fmt);
o << '>';
break;
case format::generators:
case format::text:
ls_->print_set(o, fmt);
o << '?';
break;
case format::raw:
assert(0);
break;
......
Supports Markdown
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