[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH 0/5] glr.cc: support syntax_error exceptions
From: |
Akim Demaille |
Subject: |
Re: [PATCH 0/5] glr.cc: support syntax_error exceptions |
Date: |
Wed, 2 Jan 2019 12:09:23 +0100 |
Hi Askar!
> Le 2 janv. 2019 à 01:41, Askar Safin <address@hidden> a écrit :
>
> Hi.
>
>> I'll push these commits to master once the CI validates them
>> ( https://travis-ci.com/akimd/bison/builds/95974577 ).
> Thanks a lot for this fix. Unfortunately, it seems it is buggy.
>
> I tested it on that code from paste.gg (I attached the code here in case that
> paste.gg paste disappears). Command line is same:
>
> flex -o lex.yy.cpp scanner.lpp && bison -do parser.tab.cpp parser.ypp &&
> g++ lex.yy.cpp parser.tab.cpp && echo 2 + 2 | ./a.out # Should print 4
>
> And your patches work. But when I type this:
>
> echo 2 + % | ./a.out
>
> I see this:
>
> Invalid character: %
> syntax error: unexpected $undefined, expecting NUMBER or '('
>
> But if I replace %skeleton "glr.cc" with %skeleton "lalr1.cc", I see this:
>
> Invalid character: %
>
> So, it seems that now syntax_error support in glr.cc is inconsistent with
> lalr1.cc .
Indeed, it is. I'll install this when it passes on the CI.
commit 80ef7e7639f99618bee490b2dea02b5fd9ab28e5
Author: Akim Demaille <address@hidden>
Date: Wed Jan 2 11:43:08 2019 +0100
glr.cc: don't issue two error messages when syntax_error is thrown
Reported by Askar Safin.
https://lists.gnu.org/archive/html/bison-patches/2019-01/msg00000.html
* data/skeletons/glr.c (yygetToken): Return YYEMPTY when an exception
is thrown.
* data/skeletons/lalr1.cc: Log when an exception is caught.
* tests/c++.at (Syntax error as exception): Be sure to recover from
error before triggering another error.
diff --git a/data/skeletons/glr.c b/data/skeletons/glr.c
index 20add6f7..779c1c91 100644
--- a/data/skeletons/glr.c
+++ b/data/skeletons/glr.c
@@ -778,11 +778,12 @@ yygetToken (int *yycharp][]b4_pure_if([, yyGLRStack*
yystackp])[]b4_user_formals
#if YY_EXCEPTIONS
}
catch (const ]b4_namespace_ref[::]b4_parser_class[::syntax_error& yyexc)
- {]b4_locations_if([
+ {
+ YYDPRINTF ((stderr, "Caught exception: %s\n",
yyexc.what()));]b4_locations_if([
yylloc = yyexc.location;])[
yyerror (]b4_lyyerror_args[yyexc.what ());
- // Map to the undef token.
- *yycharp = YYMAXUTOK + 1;
+ // Leave yytoken/yychar to YYEMPTY.
+ return YYEMPTY;
}
#endif // YY_EXCEPTIONS]], [[
*yycharp = ]b4_lex[;]])[
@@ -871,7 +872,8 @@ yyuserAction (yyRuleNum yyn, int yyrhslen, yyGLRStackItem*
yyvsp,
#if YY_EXCEPTIONS
}
catch (const syntax_error& yyexc)
- {]b4_locations_if([
+ {
+ YYDPRINTF ((stderr, "Caught exception: %s\n",
yyexc.what()));]b4_locations_if([
*yylocp = yyexc.location;])[
yyerror (]b4_yyerror_args[yyexc.what ());
YYERROR;
@@ -2353,7 +2355,10 @@ b4_dollar_popdef])[]dnl
else if (yyisErrorAction (yyaction))
{]b4_locations_if([[
yystack.yyerror_range[1].yystate.yyloc = yylloc;]])[
- yyreportSyntaxError (&yystack]b4_user_args[);
+ /* If yylex returned no token (YYEMPTY), it already
+ issued an error message. */
+ if (yytoken != YYEMPTY)
+ yyreportSyntaxError (&yystack]b4_user_args[);
goto yyuser_error;
}
else
diff --git a/data/skeletons/lalr1.cc b/data/skeletons/lalr1.cc
index 58e8f897..aa777ec1 100644
--- a/data/skeletons/lalr1.cc
+++ b/data/skeletons/lalr1.cc
@@ -827,6 +827,7 @@ b4_dollar_popdef])[]dnl
#if YY_EXCEPTIONS
catch (const syntax_error& yyexc)
{
+ YYCDEBUG << "Caught exception: " << yyexc.what() << '\n';
error (yyexc);
goto yyerrlab1;
}
@@ -916,6 +917,7 @@ b4_dollar_popdef])[]dnl
#if YY_EXCEPTIONS
catch (const syntax_error& yyexc)
{
+ YYCDEBUG << "Caught exception: " << yyexc.what() << '\n';
error (yyexc);
YYERROR;
}
diff --git a/tests/c++.at b/tests/c++.at
index c2b892bc..6b6d2e41 100644
--- a/tests/c++.at
+++ b/tests/c++.at
@@ -941,7 +941,7 @@ AT_CLEANUP
m4_pushdef([AT_TEST],
[AT_SETUP([[Syntax error as exception: $1]])
-AT_BISON_OPTION_PUSHDEFS([$1])
+AT_BISON_OPTION_PUSHDEFS([$1 %debug])
AT_DATA_GRAMMAR([[input.yy]],
[[$1
@@ -984,6 +984,7 @@ yy::parser::error (const std::string &m)
]AT_MAIN_DEFINE[
]])
+# Another file to check syntax_error's linkage.
AT_DATA_SOURCE([scan.cc],
[[#include "input.hh"
@@ -991,7 +992,11 @@ int
yylex (yy::parser::semantic_type *)
{
// 's': syntax error, 'l': lexical error.
- static char const *input = "asal";
+ //
+ // Leave enough valid tokens to make sure we recovered from the
+ // previous error, otherwise we might hide some error messages
+ // (discarded during error recovery).
+ static char const *input = "asaaalaa";
switch (int res = *input++)
{
case 'l':
#