[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Two problems with the GLR parsers

From: Akim Demaille
Subject: Two problems with the GLR parsers
Date: 12 Nov 2002 11:18:01 +0100
User-agent: Gnus/5.0808 (Gnus v5.8.8) XEmacs/21.4 (Honest Recruiter)

Hi Paul,

There are two issues which are uncovered by the test suite:

   42. actions.at:368: testing Printers and Destructors: %glr-parser...
   actions.at:368: bison -o input.c input.y
   actions.at:368: $CC $CFLAGS $CPPFLAGS input.c -o input
   actions.at:368: $PREPARSER ./input
   --- -   2002-11-12 11:16:02.000000000 +0100
   +++ /home/lrde/prof/akim/src/bison/tests/testsuite.dir/at-stdout        
2002-11-12 11:16:02.000000000 +0100
   @@ -15,7 +15,7 @@
    sending: 'x' (value = 5, line 50)
    Freeing token 'x' (address@hidden)
    sending: ';' (value = 6, line 60)
   -line(address@hidden): error(@50) ';'
   +line(address@hidden): error(@30) ';'
    sending: 'x' (value = 7, line 70)
    thing(address@hidden): 'x'(address@hidden)
    sending: 'x' (value = 8, line 80)
   @@ -31,6 +31,6 @@
    sending: EOF
    Freeing nterm line (address@hidden)
    Freeing nterm line (address@hidden)
   -Freeing nterm line (address@hidden)
   -Parsing FAILED.
   +Freeing nterm line (address@hidden)
   +Successful parse.
   actions.at:368: exit code was 0, expected 1
   42. actions.at:368: FAILED near `actions.at:368'

One problem is that for unknown reasons, it is not the same location
that is associated to the error token as the one from yacc.c.  This
might be completely benign, I have not really tracked it down.  This
symbol comes from

| error ';'
      $$ = -1;
      printf ("line(address@hidden): error(@%d) ';'\n",
              $$, @$.first_line, @1.first_line);

I have not looked at it in details yet, maybe there is no reason to
waste time on this.

But the second issue is a bit different: the parse exits with success
although it actually failed.  The problem is that 

   /* Recover from a syntax error on YYSTACK, assuming that YYTOKENP,
      YYLVALP, and YYLLOCP point to the syntactic category, semantic
      value, and location of the lookahead.  */
   static void
   yyrecoverParseError (yyGLRStack* yystack,
                        YYSTYPE* yylvalp, YYLTYPE* yyllocp]b4_user_formals[)
     yySymbol* const yytokenp = yystack->yytokenp;
     size_t yyk;
     int yyj;
     if (yystack->yyerrState == 0)
       yystack->yyerrState = 3;
     else if (yystack->yyerrState == 3)
       /* We just shifted the error token and (perhaps) took some
          reductions.  Skip tokens until we can proceed.  */
       while (yytrue)
           if (*yytokenp == YYEOF)
               /* Now pop stack until we find a state that shifts the
                  error token.  */
               while (yystack->yytops.yystates[0] != NULL)
                   yyGLRState *yys = yystack->yytops.yystates[0];
                   YYDPRINTF ((stderr, "Error: popping "));
                   YYDSYMPRINT ((stderr,
                   YYDPRINTF ((stderr, "\n"));
                   yydestruct (yystos[yys->yylrState],
                   yystack->yytops.yystates[0] = yys->yypred;
                   yystack->yynextFree -= 1;
                   yystack->yyspaceLeft += 1;
               yyFail (yystack][]b4_lpure_args[, NULL);

we arrive here after having called yyerror via yyreportParseError.
yyerror does not set errflag, as it is yyFail that calls yyerror, not
the converse.

I see several means to fix this issue, but I am not sure how you'd do
it.  One obvious fix is to add yystack->errflag = 1 right before the
yyFail call above.  Another is to have yyFail always do it, included
when called with NULL.  But I'm not sure of the semantics of yyFail :(

Also, yyparse looks like this:

   | yyparse.  |
   yyparse (void)
        while (yytrue)
             int yys;
             int yyn = yystack.yytops.yysize;
             for (yys = 0; yys < yyn; yys += 1)
               YYCHK1 (yyprocessOneStack (&yystack, yys, yyposn,
                                          yylvalp, yyllocp));
             yytoken = YYEMPTY;
             yyposn += 1;
             yyremoveDeletes (&yystack);
             if (yystack.yytops.yysize == 0)
                 yyundeleteLastStack (&yystack);
                 if (yystack.yytops.yysize == 0)
   =====>          yyFail (&yystack, "parse error");
                 YYCHK1 (yyresolveStack (&yystack));
                 YYDPRINTF ((stderr, "Returning to deterministic 
                 yyreportParseError (&yystack, yylvalp, yyllocp);
                 goto yyuser_error;
             else if (yystack.yytops.yysize == 1)
                 YYCHK1 (yyresolveStack (&yystack));
                 YYDPRINTF ((stderr, "Returning to deterministic 
                 yycompressStack (&yystack);
         yyrecoverParseError (&yystack, yylvalp, yyllocp);
         yyposn = yystack.yytops.yystates[0]->yyposn;
     yyfreeGLRStack (&yystack);
     return yystack.yyerrflag;

I don't know why this line is not using yyreportParseError.  Actually,
I don't know what yystack.yytops.yysize == 0 means :(

reply via email to

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