parse_acc: cleanup error reporting

* spot/twa/acc.cc: Factor all the error reporting code in a single
place, and improve the error message at end of acceptance.
* tests/core/randaut.test: Add more tests.
This commit is contained in:
Alexandre Duret-Lutz 2016-02-04 10:48:40 +01:00
parent 30b996460c
commit 91bb93eeaa
2 changed files with 51 additions and 62 deletions

View file

@ -1,6 +1,6 @@
// -*- coding: utf-8 -*- // -*- coding: utf-8 -*-
// Copyright (C) 2015 Laboratoire de Recherche et Développement de // Copyright (C) 2015, 2016 Laboratoire de Recherche et Développement
// l'Epita. // de l'Epita.
// //
// This file is part of Spot, a model checking library. // This file is part of Spot, a model checking library.
// //
@ -564,10 +564,7 @@ namespace spot
codes.reserve(n_accs); codes.reserve(n_accs);
for (unsigned i = 0; i < n_accs; ++i) for (unsigned i = 0; i < n_accs; ++i)
{ {
if (drand() < 0.5) codes.push_back(drand() < 0.5 ? inf({i}) : fin({i}));
codes.push_back(inf({i}));
else
codes.push_back(fin({i}));
if (reuse > 0.0 && drand() < reuse) if (reuse > 0.0 && drand() < reuse)
--i; --i;
} }
@ -1277,6 +1274,19 @@ namespace spot
namespace namespace
{ {
static void
syntax_error(const char* input, const char* message)
{
std::ostringstream s;
s << "syntax error at ";
if (*input)
s << '\'' << input << "': ";
else
s << "end of acceptance: ";
s << message;
throw parse_error(s.str());
}
/// acc ::= term | term "|" acc /// acc ::= term | term "|" acc
/// term := "t" | "f" | "Inf" "(" num ")" /// term := "t" | "f" | "Inf" "(" num ")"
/// | "Fin" "(" num ") " | "(" acc ") /// | "Fin" "(" num ") " | "(" acc ")
@ -1294,9 +1304,9 @@ namespace spot
{ {
if (*input != c) if (*input != c)
{ {
std::ostringstream s; char msg[20];
s << "syntax error at '" << input << "', was expecting " << c << '.'; sprintf(msg, "was expecting %c '.'", c);
throw parse_error(s.str()); syntax_error(input, msg);
} }
++input; ++input;
skip_space(input); skip_space(input);
@ -1328,11 +1338,7 @@ namespace spot
unsigned long n = strtoul(input, &end, 10); unsigned long n = strtoul(input, &end, 10);
unsigned num = n; unsigned num = n;
if (errno || num != n) if (errno || num != n)
{ syntax_error(input, "invalid number.");
std::ostringstream s;
s << "syntax error at '" << input << "': invalid number.";
throw parse_error(s.str());
}
input = end; input = end;
return n; return n;
} }
@ -1347,14 +1353,9 @@ namespace spot
min = strtol(str, &end, 10); min = strtol(str, &end, 10);
if (end == str || errno) if (end == str || errno)
{ {
// No leading number. It's OK as long as the string is not // No leading number. It's OK as long as '..' or ':' are next.
// empty. if (errno || (*end != ':' && *end != '.'))
if (!*end || errno) syntax_error(str, "invalid range.");
{
std::ostringstream s;
s << "syntax error at '" << str << "': invalid range.";
throw parse_error(s.str());
}
min = 1; min = 1;
} }
if (!*end || (*end != ':' && *end != '.')) if (!*end || (*end != ':' && *end != '.'))
@ -1374,22 +1375,12 @@ namespace spot
char* end2; char* end2;
max = strtol(end, &end2, 10); max = strtol(end, &end2, 10);
if (end == end2 || errno) if (end == end2 || errno)
{ syntax_error(str, "invalid range (missing end?)");
std::ostringstream s;
s << "syntax error at '" << str
<< "': invalid range (missing end?)";
throw parse_error(s.str());
}
end = end2; end = end2;
} }
if (min < 0 || max < 0) if (min < 0 || max < 0)
{ syntax_error(str, "values in range must be positive.");
std::ostringstream s;
s << "invalid range '" << str
<< "': values must be positive";
throw parse_error(s.str());
}
str = end; str = end;
@ -1417,18 +1408,9 @@ namespace spot
char* end; char* end;
double n = strtod(input, &end); double n = strtod(input, &end);
if (errno) if (errno)
{ syntax_error(input, "cannot convert to double.");
std::ostringstream s;
s << "syntax error at '" << input << "': can't convert to double";
throw parse_error(s.str());
}
if (!(n >= 0.0 && n <= 1.0)) if (!(n >= 0.0 && n <= 1.0))
{ syntax_error(input, "value should be between 0 and 1.");
std::ostringstream s;
s << "syntax error at '" << input
<< "': value should be between 0 and 1.";
throw parse_error(s.str());
}
input = end; input = end;
return n; return n;
} }
@ -1466,9 +1448,7 @@ namespace spot
} }
else else
{ {
std::ostringstream s; syntax_error(input, "unexpected character.");
s << "syntax error at '" << input << "', unexpected character.";
throw parse_error(s.str());
} }
skip_space(input); skip_space(input);
@ -1507,10 +1487,9 @@ namespace spot
input += 6; input += 6;
return drand() < 0.5; return drand() < 0.5;
} }
std::ostringstream s; syntax_error(input, "expecting 'min', 'max', or 'rand'.");
s << "syntax error at '" << input SPOT_UNREACHABLE();
<< "': expecting 'min' or 'max'"; return false;
throw parse_error(s.str());
} }
static bool odd_or_even(const char*& input) static bool odd_or_even(const char*& input)
@ -1536,10 +1515,9 @@ namespace spot
input += 6; input += 6;
return drand() < 0.5; return drand() < 0.5;
} }
std::ostringstream s; syntax_error(input, "expecting 'odd', 'even', or 'rand'.");
s << "syntax error at '" << input SPOT_UNREACHABLE();
<< "': expecting 'odd' or 'even'"; return false;
throw parse_error(s.str());
} }
} }
@ -1614,9 +1592,10 @@ namespace spot
input += 6; input += 6;
unsigned n = parse_range(input); unsigned n = parse_range(input);
skip_space(input); skip_space(input);
auto setreuse = input;
double reuse = (*input) ? parse_proba(input) : 0.0; double reuse = (*input) ? parse_proba(input) : 0.0;
if (reuse >= 1.0) if (reuse >= 1.0)
throw parse_error("probability for set reuse should be <1."); syntax_error(setreuse, "probability for set reuse should be <1.");
c = acc_cond::acc_code::random(n, reuse); c = acc_cond::acc_code::random(n, reuse);
} }
else else
@ -1625,11 +1604,8 @@ namespace spot
} }
skip_space(input); skip_space(input);
if (*input) if (*input)
{ syntax_error(input, "unexpected character.");
std::ostringstream s;
s << "syntax error at '" << input << "', unexpected character.";
throw parse_error(s.str());
}
std::swap(c, *this); std::swap(c, *this);
} }
} }

View file

@ -141,6 +141,19 @@ grep 'randaut: --colored requires' stderr
randaut -S -A'parity min even 0..3' -q -n10 --colored 2 2>stderr && exit 1 randaut -S -A'parity min even 0..3' -q -n10 --colored 2 2>stderr && exit 1
grep 'randaut: --colored requires' stderr grep 'randaut: --colored requires' stderr
randaut -A'parity foo' 2 -q 2>stderr && exit 1
grep 'randaut:.*foo.*min.*max.*rand' stderr
randaut -A'parity ' 2 -q 2>stderr && exit 1
grep 'randaut:.*end of acceptance.*min.*max.*rand' stderr
randaut -A'parity min foo' 2 -q 2>stderr && exit 1
grep 'randaut:.*foo.*odd.*even.*rand' stderr
randaut -A'parity min' 2 -q 2>stderr && exit 1
grep 'randaut:.*end of acceptance.*odd.*even.*rand' stderr
randaut -A'parity min rand foo' 2 -q 2>stderr && exit 1
grep 'randaut:.*foo.*invalid range' stderr
randaut -A'parity min rand ' 2 -q 2>stderr && exit 1
grep 'randaut:.*end of acceptance.*invalid range' stderr
randaut -Q0 1 2>stderr && exit 1 randaut -Q0 1 2>stderr && exit 1
grep '0 states' stderr grep '0 states' stderr