bison-patches
[Top][All Lists]
Advanced

[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':
#


reply via email to

[Prev in Thread] Current Thread [Next in Thread]