* src/ltltest/parseerr.test: Adjust.
* src/ltlparse/ltlparse.yy: Simplify error handling now that Bison will call destructors. Give each operator a full name, so that Bison uses it in error messages.
This commit is contained in:
parent
03704d635e
commit
a87c9d3d33
3 changed files with 92 additions and 101 deletions
|
|
@ -1,10 +1,17 @@
|
||||||
|
2004-01-05 Alexandre Duret-Lutz <adl@src.lip6.fr>
|
||||||
|
|
||||||
|
* src/ltltest/parseerr.test: Adjust.
|
||||||
|
* src/ltlparse/ltlparse.yy: Simplify error handling now that Bison
|
||||||
|
will call destructors. Give each operator a full name, so that
|
||||||
|
Bison uses it in error messages.
|
||||||
|
|
||||||
2003-12-30 Alexandre Duret-Lutz <adl@src.lip6.fr>
|
2003-12-30 Alexandre Duret-Lutz <adl@src.lip6.fr>
|
||||||
|
|
||||||
* iface/gspn/ltleesrg.cc: New file.
|
* iface/gspn/ltleesrg.cc: New file.
|
||||||
* iface/gspn/Makefile.am (check_PROGRAMS): Add ltleesrg.
|
* iface/gspn/Makefile.am (check_PROGRAMS): Add ltleesrg.
|
||||||
(ltleesrg_LDADD, ltleesrg_SOURCES): New variables.
|
(ltleesrg_LDADD, ltleesrg_SOURCES): New variables.
|
||||||
|
|
||||||
* src/ltltest/defs.in (run): Reun valgrind with --leak-check=yes.
|
* src/ltltest/defs.in (run): Rerun valgrind with --leak-check=yes.
|
||||||
* src/ltlparse/ltlparse.yy: Add `%destructor's.
|
* src/ltlparse/ltlparse.yy: Add `%destructor's.
|
||||||
|
|
||||||
2003-12-29 Alexandre Duret-Lutz <adl@src.lip6.fr>
|
2003-12-29 Alexandre Duret-Lutz <adl@src.lip6.fr>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2003 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
|
||||||
** et Marie Curie.
|
** et Marie Curie.
|
||||||
**
|
**
|
||||||
|
|
@ -50,69 +50,88 @@ using namespace spot::ltl;
|
||||||
(%name-prefix doesn't work for the lalr1.cc skeleton
|
(%name-prefix doesn't work for the lalr1.cc skeleton
|
||||||
at the time of writing.) */
|
at the time of writing.) */
|
||||||
#define yylex ltlyylex
|
#define yylex ltlyylex
|
||||||
|
|
||||||
|
#define missing_right_op(res, op, str) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
error_list.push_back(parse_error(op, \
|
||||||
|
"missing right operand for \"" str "\"")); \
|
||||||
|
res = constant::false_instance(); \
|
||||||
|
} \
|
||||||
|
while (0);
|
||||||
|
|
||||||
|
#define missing_right_binop(res, left, op, str) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
destroy(left); \
|
||||||
|
missing_right_op(res, op, str); \
|
||||||
|
} \
|
||||||
|
while (0);
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
|
||||||
|
/* All tokens. */
|
||||||
|
|
||||||
|
%token <token> PAR_OPEN "opening parenthesis" PAR_CLOSE "closing parenthesis"
|
||||||
|
%token <token> OP_OR "or operator" OP_XOR "xor operator" OP_AND "and operation"
|
||||||
|
%token <token> OP_IMPLIES "implication operator" OP_EQUIV "equivalent operator"
|
||||||
|
%token <token> OP_U "until operator" OP_R "release operator"
|
||||||
|
%token <token> OP_F "sometimes operator" OP_G "always operator"
|
||||||
|
%token <token> OP_X "next operator"
|
||||||
|
%token <str> ATOMIC_PROP "atomic proposition" OP_NOT "not operator"
|
||||||
|
%token CONST_TRUE "constant true" CONST_FALSE "constant false"
|
||||||
|
%token END_OF_INPUT "end of formula"
|
||||||
|
|
||||||
|
|
||||||
|
/* Priorities. */
|
||||||
|
|
||||||
/* Logical operators. */
|
/* Logical operators. */
|
||||||
%left <token> OP_OR
|
%left OP_OR
|
||||||
%left <token> OP_XOR
|
%left OP_XOR
|
||||||
%left <token> OP_AND
|
%left OP_AND
|
||||||
%left <token> OP_IMPLIES OP_EQUIV
|
%left OP_IMPLIES OP_EQUIV
|
||||||
|
|
||||||
/* LTL operators. */
|
/* LTL operators. */
|
||||||
%left <token> OP_U OP_R
|
%left OP_U OP_R
|
||||||
%nonassoc <token> OP_F OP_G
|
%nonassoc OP_F OP_G
|
||||||
%nonassoc <token> OP_X
|
%nonassoc OP_X
|
||||||
|
|
||||||
/* Not has the most important priority. */
|
/* Not has the most important priority. */
|
||||||
%nonassoc <token> OP_NOT
|
%nonassoc OP_NOT
|
||||||
|
|
||||||
/* Grouping (parentheses). */
|
%type <ltl> result subformula
|
||||||
%token <token> PAR_OPEN PAR_CLOSE
|
|
||||||
|
|
||||||
/* Atomic proposition. */
|
/* At the time of writing (2004-01-05) there is a bug in CVS Bison: if
|
||||||
%token <str> ATOMIC_PROP
|
you give a token (such a ATOMIC_PROP) a name (such as "atomic
|
||||||
|
proposition"), then the %destructor should refer to that name.
|
||||||
/* Constants */
|
References to ATOMIC_PROP are silently ignored. */
|
||||||
%token CONST_TRUE
|
%destructor { delete $$; } "atomic proposition"
|
||||||
%token CONST_FALSE
|
%destructor { spot::ltl::destroy($$); } result subformula
|
||||||
%token END_OF_INPUT
|
|
||||||
|
|
||||||
%type <ltl> result ltl_formula subformula
|
|
||||||
|
|
||||||
%destructor { delete $$; } ATOMIC_PROP
|
|
||||||
%destructor { spot::ltl::destroy($$); } result ltl_formula subformula
|
|
||||||
|
|
||||||
%%
|
%%
|
||||||
result: ltl_formula END_OF_INPUT
|
result: subformula END_OF_INPUT
|
||||||
{ result = $$ = $1;
|
{ result = $$ = $1;
|
||||||
YYACCEPT;
|
YYACCEPT;
|
||||||
}
|
}
|
||||||
| many_errors END_OF_INPUT
|
| error END_OF_INPUT
|
||||||
{ error_list.push_back(parse_error(@1,
|
{ error_list.push_back(parse_error(@1,
|
||||||
"couldn't parse anything sensible"));
|
"could not parse anything sensible"));
|
||||||
result = $$ = 0;
|
result = $$ = 0;
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
|
| subformula error END_OF_INPUT
|
||||||
|
{ error_list.push_back(parse_error(@2,
|
||||||
|
"ignoring trailing garbage"));
|
||||||
|
result = $$ = $1;
|
||||||
|
YYACCEPT;
|
||||||
|
}
|
||||||
| END_OF_INPUT
|
| END_OF_INPUT
|
||||||
{ error_list.push_back(parse_error(@1, "empty input"));
|
{ error_list.push_back(parse_error(@$, "empty input"));
|
||||||
result = $$ = 0;
|
result = $$ = 0;
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
many_errors_diagnosed : many_errors
|
|
||||||
{ error_list.push_back(parse_error(@1,
|
|
||||||
"unexpected input ignored")); }
|
|
||||||
|
|
||||||
ltl_formula: subformula
|
|
||||||
{ $$ = $1; }
|
|
||||||
| many_errors_diagnosed subformula
|
|
||||||
{ $$ = $2; }
|
|
||||||
| ltl_formula many_errors_diagnosed
|
|
||||||
{ $$ = $1; }
|
|
||||||
|
|
||||||
many_errors: error
|
|
||||||
| many_errors error
|
|
||||||
|
|
||||||
/* The reason we use `constant::false_instance()' for error recovery
|
/* The reason we use `constant::false_instance()' for error recovery
|
||||||
is that it isn't reference counted. (Hence it can't leak references.) */
|
is that it isn't reference counted. (Hence it can't leak references.) */
|
||||||
|
|
||||||
|
|
@ -144,96 +163,61 @@ subformula: ATOMIC_PROP
|
||||||
"treating this parenthetical block as false"));
|
"treating this parenthetical block as false"));
|
||||||
$$ = constant::false_instance();
|
$$ = constant::false_instance();
|
||||||
}
|
}
|
||||||
| PAR_OPEN subformula many_errors_diagnosed PAR_CLOSE
|
| PAR_OPEN subformula END_OF_INPUT
|
||||||
{ $$ = $2; }
|
|
||||||
| PAR_OPEN subformula many_errors_diagnosed END_OF_INPUT
|
|
||||||
{ error_list.push_back(parse_error(@1 + @2,
|
{ error_list.push_back(parse_error(@1 + @2,
|
||||||
"missing closing parenthesis"));
|
"missing closing parenthesis"));
|
||||||
$$ = $2;
|
$$ = $2;
|
||||||
}
|
}
|
||||||
| PAR_OPEN many_errors_diagnosed END_OF_INPUT
|
| PAR_OPEN error END_OF_INPUT
|
||||||
{ error_list.push_back(parse_error(@$,
|
{ error_list.push_back(parse_error(@$,
|
||||||
"missing closing parenthesis, "
|
"missing closing parenthesis, "
|
||||||
"treating this parenthetical block as false"));
|
"treating this parenthetical block as false"));
|
||||||
$$ = constant::false_instance();
|
$$ = constant::false_instance();
|
||||||
}
|
}
|
||||||
| OP_NOT subformula
|
|
||||||
{ $$ = unop::instance(unop::Not, $2); }
|
|
||||||
| subformula OP_AND subformula
|
| subformula OP_AND subformula
|
||||||
{ $$ = multop::instance(multop::And, $1, $3); }
|
{ $$ = multop::instance(multop::And, $1, $3); }
|
||||||
| subformula OP_AND error
|
| subformula OP_AND error
|
||||||
{
|
{ missing_right_binop($$, $1, @2, "and operator"); }
|
||||||
destroy($1);
|
|
||||||
error_list.push_back(parse_error(@2,
|
|
||||||
"missing right operand for OP_AND"));
|
|
||||||
$$ = constant::false_instance();
|
|
||||||
}
|
|
||||||
| subformula OP_OR subformula
|
| subformula OP_OR subformula
|
||||||
{ $$ = multop::instance(multop::Or, $1, $3); }
|
{ $$ = multop::instance(multop::Or, $1, $3); }
|
||||||
| subformula OP_OR error
|
| subformula OP_OR error
|
||||||
{
|
{ missing_right_binop($$, $1, @2, "or operator"); }
|
||||||
destroy($1);
|
|
||||||
error_list.push_back(parse_error(@2,
|
|
||||||
"missing right operand for OP_OR"));
|
|
||||||
$$ = constant::false_instance();
|
|
||||||
}
|
|
||||||
| subformula OP_XOR subformula
|
| subformula OP_XOR subformula
|
||||||
{ $$ = binop::instance(binop::Xor, $1, $3); }
|
{ $$ = binop::instance(binop::Xor, $1, $3); }
|
||||||
| subformula OP_XOR error
|
| subformula OP_XOR error
|
||||||
{
|
{ missing_right_binop($$, $1, @2, "xor operator"); }
|
||||||
destroy($1);
|
|
||||||
error_list.push_back(parse_error(@2,
|
|
||||||
"missing right operand for OP_XOR"));
|
|
||||||
$$ = constant::false_instance();
|
|
||||||
}
|
|
||||||
| subformula OP_IMPLIES subformula
|
| subformula OP_IMPLIES subformula
|
||||||
{ $$ = binop::instance(binop::Implies, $1, $3); }
|
{ $$ = binop::instance(binop::Implies, $1, $3); }
|
||||||
| subformula OP_IMPLIES error
|
| subformula OP_IMPLIES error
|
||||||
{
|
{ missing_right_binop($$, $1, @2, "implication operator"); }
|
||||||
destroy($1);
|
|
||||||
error_list.push_back(parse_error(@2,
|
|
||||||
"missing right operand for OP_IMPLIES"));
|
|
||||||
$$ = constant::false_instance();
|
|
||||||
}
|
|
||||||
| subformula OP_EQUIV subformula
|
| subformula OP_EQUIV subformula
|
||||||
{ $$ = binop::instance(binop::Equiv, $1, $3); }
|
{ $$ = binop::instance(binop::Equiv, $1, $3); }
|
||||||
| subformula OP_EQUIV error
|
| subformula OP_EQUIV error
|
||||||
{
|
{ missing_right_binop($$, $1, @2, "equivalent operator"); }
|
||||||
destroy($1);
|
|
||||||
error_list.push_back(parse_error(@2,
|
|
||||||
"missing right operand for OP_EQUIV"));
|
|
||||||
$$ = constant::false_instance();
|
|
||||||
}
|
|
||||||
| subformula OP_U subformula
|
| subformula OP_U subformula
|
||||||
{ $$ = binop::instance(binop::U, $1, $3); }
|
{ $$ = binop::instance(binop::U, $1, $3); }
|
||||||
| subformula OP_U error
|
| subformula OP_U error
|
||||||
{
|
{ missing_right_binop($$, $1, @2, "until operator"); }
|
||||||
destroy($1);
|
|
||||||
error_list.push_back(parse_error(@2,
|
|
||||||
"missing right operand for OP_U"));
|
|
||||||
$$ = constant::false_instance();
|
|
||||||
}
|
|
||||||
| subformula OP_R subformula
|
| subformula OP_R subformula
|
||||||
{ $$ = binop::instance(binop::R, $1, $3); }
|
{ $$ = binop::instance(binop::R, $1, $3); }
|
||||||
| subformula OP_R error
|
| subformula OP_R error
|
||||||
{
|
{ missing_right_binop($$, $1, @2, "release operator"); }
|
||||||
destroy($1);
|
|
||||||
error_list.push_back(parse_error(@2,
|
|
||||||
"missing right operand for OP_R"));
|
|
||||||
$$ = constant::false_instance();
|
|
||||||
}
|
|
||||||
| OP_F subformula
|
| OP_F subformula
|
||||||
{ $$ = unop::instance(unop::F, $2); }
|
{ $$ = unop::instance(unop::F, $2); }
|
||||||
|
| OP_F error
|
||||||
|
{ missing_right_op($$, @1, "sometimes operator"); }
|
||||||
| OP_G subformula
|
| OP_G subformula
|
||||||
{ $$ = unop::instance(unop::G, $2); }
|
{ $$ = unop::instance(unop::G, $2); }
|
||||||
|
| OP_G error
|
||||||
|
{ missing_right_op($$, @1, "always operator"); }
|
||||||
| OP_X subformula
|
| OP_X subformula
|
||||||
{ $$ = unop::instance(unop::X, $2); }
|
{ $$ = unop::instance(unop::X, $2); }
|
||||||
// | subformula many_errors
|
| OP_X error
|
||||||
// { error_list->push_back(parse_error(@2,
|
{ missing_right_op($$, @1, "next operator"); }
|
||||||
// "ignoring these unexpected trailing tokens"));
|
| OP_NOT subformula
|
||||||
// $$ = $1;
|
{ $$ = unop::instance(unop::Not, $2); }
|
||||||
// }
|
| OP_NOT error
|
||||||
|
{ missing_right_op($$, @1, "not operator"); }
|
||||||
;
|
;
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# Copyright (C) 2003 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
|
||||||
# et Marie Curie.
|
# et Marie Curie.
|
||||||
#
|
#
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
# 02111-1307, USA.
|
# 02111-1307, USA.
|
||||||
|
|
||||||
|
|
||||||
# Check error recovery in parsing. This also check how the
|
# Check error recovery in parsing. This also checks how the
|
||||||
# resulting tree looks like.
|
# resulting tree looks like.
|
||||||
|
|
||||||
. ./defs || exit 1
|
. ./defs || exit 1
|
||||||
|
|
@ -49,9 +49,9 @@ check()
|
||||||
# Empty or unparsable strings
|
# Empty or unparsable strings
|
||||||
check '' ''
|
check '' ''
|
||||||
check '+' ''
|
check '+' ''
|
||||||
|
check '/2/3/4/5 a + b /6/7/8/' ''
|
||||||
|
|
||||||
# leading and trailing garbage are skipped
|
# leading and trailing garbage are skipped
|
||||||
check '/2/3/4/5 a + b /6/7/8/' 'multop(Or, AP(a), AP(b))'
|
|
||||||
check 'a U b c' 'binop(U, AP(a), AP(b))'
|
check 'a U b c' 'binop(U, AP(a), AP(b))'
|
||||||
check 'a &&& b' 'multop(And, constant(0), AP(b))'
|
check 'a &&& b' 'multop(And, constant(0), AP(b))'
|
||||||
# (check multop merging while we are at it)
|
# (check multop merging while we are at it)
|
||||||
|
|
@ -64,12 +64,12 @@ check 'a U b V c R' 'constant(0)'
|
||||||
|
|
||||||
# Recovery inside parentheses
|
# Recovery inside parentheses
|
||||||
check 'a U (b c) U e R (f g <=> h)' \
|
check 'a U (b c) U e R (f g <=> h)' \
|
||||||
'binop(R, binop(U, binop(U, AP(a), AP(b)), AP(e)), AP(f))'
|
'binop(R, binop(U, binop(U, AP(a), constant(0)), AP(e)), constant(0))'
|
||||||
check 'a U ((c) U e) R (<=> f g)' \
|
check 'a U ((c) U e) R (<=> f g)' \
|
||||||
'binop(R, binop(U, AP(a), binop(U, AP(c), AP(e))), constant(0))'
|
'binop(R, binop(U, AP(a), binop(U, AP(c), AP(e))), constant(0))'
|
||||||
|
|
||||||
# Missing parentheses
|
# Missing parentheses
|
||||||
check 'a & (a + b' 'multop(And, AP(a), multop(Or, AP(a), AP(b)))'
|
check 'a & (a + b' 'multop(And, AP(a), multop(Or, AP(a), AP(b)))'
|
||||||
check 'a & (a + b c' 'multop(And, AP(a), multop(Or, AP(a), AP(b)))'
|
check 'a & (a + b c' 'multop(And, constant(0), AP(a))'
|
||||||
check 'a & (+' 'multop(And, constant(0), AP(a))'
|
check 'a & (+' 'multop(And, constant(0), AP(a))'
|
||||||
check 'a & (' 'multop(And, constant(0), AP(a))'
|
check 'a & (' 'multop(And, constant(0), AP(a))'
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue