From d59beda068aef97834ea84ce4f5cc99b487e4b68 Mon Sep 17 00:00:00 2001 From: "Joel E. Denny" Date: Fri, 18 Dec 2009 23:57:18 -0500 Subject: [PATCH] lalr1.cc: don't discard non-existent lookahead on syntax error. * data/lalr1.cc (parser::parse): Check yyempty first. * tests/c++.at (Syntax error discarding no lookahead): New test group. --- ChangeLog | 7 +++++ data/lalr1.cc | 2 +- tests/c++.at | 79 +++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 85 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2926da79..1c15cc5e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2009-12-18 Joel E. Denny + + lalr1.cc: don't discard non-existent lookahead on syntax error. + * data/lalr1.cc (parser::parse): Check yyempty first. + * tests/c++.at (Syntax error discarding no lookahead): New test + group. + 2009-12-17 Joel E. Denny Code cleanup. diff --git a/data/lalr1.cc b/data/lalr1.cc index 9e0d522b..6174e824 100644 --- a/data/lalr1.cc +++ b/data/lalr1.cc @@ -876,7 +876,7 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param)));])[ /* Return failure if at end of input. */ if (yyla.type == yyeof_) YYABORT; - else + else if (!yyempty) { yy_destroy_ ("Error: discarding", yyla); yyempty = true; diff --git a/tests/c++.at b/tests/c++.at index beffb1c6..ce64d6d6 100644 --- a/tests/c++.at +++ b/tests/c++.at @@ -286,8 +286,6 @@ AT_CHECK_DOXYGEN([Public]) AT_CHECK_DOXYGEN([Private]) - - ## ------------ ## ## Namespaces. ## ## ------------ ## @@ -369,3 +367,80 @@ AT_CHECK_NAMESPACE([[foo[3]::bar::baz]], [[-]]) AT_CHECK_NAMESPACE([[foo::bar,baz]], [[-]]) AT_CHECK_NAMESPACE([[foo::bar::(baz /* Pacify Emacs ) */]], [[-]]) AT_CLEANUP + + +## -------------------------------------- ## +## Syntax error discarding no lookahead. ## +## -------------------------------------- ## + +# After a syntax error, lalr1.cc used to not check whether there +# actually is a lookahead before discarding the lookahead. As a result, +# it mistakenly invoked the destructor for the previous lookahead. + +AT_SETUP([[Syntax error discarding no lookahead]]) + +AT_DATA_GRAMMAR([[input.yy]], +[[%skeleton "lalr1.cc" + +%code { + #include + int yylex (yy::parser::semantic_type *, yy::location *); + #define USE(Args) +} + +%defines +%locations +%define parse.error verbose + +%nonassoc 'a' ; + +%destructor { + std::cerr << "Discarding 'a'." << std::endl; +} 'a' + +%% + +start: error-reduce consistent-error 'a' { USE ($3); }; + +error-reduce: + 'a' 'a' consistent-error 'a' { USE (($1, $2, $4)); } +| 'a' error { std::cerr << "Reducing 'a'." << std::endl; USE ($1); } +; + +consistent-error: + 'a' +| /*empty*/ %prec 'a' +; + +%% + +int +yylex (yy::parser::semantic_type *, yy::location *) +{ + static char const *input = "aa"; + return *input++; +} + +void +yy::parser::error (const location_type &, const std::string &m) +{ + std::cerr << m << std::endl; +} + +int +main (void) +{ + yy::parser parser; + return parser.parse (); +} +]]) +AT_BISON_CHECK([[-o input.cc input.yy]], [[0]], [[]], [[ignore-nolog]]) +AT_COMPILE_CXX([[input]]) +# This used to print "Discarding 'a'." again at the end. +AT_PARSER_CHECK([[./input]], [[1]], [[]], +[[syntax error +Discarding 'a'. +Reducing 'a'. +]]) + +AT_CLEANUP -- 2.47.2