1
votes

So I am trying to use bison's semantic predicate feature, but I've been running into a few issues trying to have it work.

The problem comes when I try to compile the generated .tab.c file with gcc. I am using gcc 7.1.0 and bison 3.0.4. Here's a snippet of the compile error:

test2.tab.c: In function ‘yyuserAction’:
test2.tab.c:811:12: error: stray ‘#’ in program
     if (! (#line 19 "test2.y" /* glr.c:816  */
            ^
test2.tab.c:811:13: error: ‘line’ undeclared (first use in this function); did you mean ‘uint’?
     if (! (#line 19 "test2.y" /* glr.c:816  */
             ^~~~
             uint

So I've taken bison's example for semantic predicate, and made it a working example:

%{

int new_syntax = 0;
int yyerror(const char* msg) { /* some error handling */ }

%}

%token id

%glr-parser

%%

prog: %empty
    | prog widget
    | prog flip
    ;

widget: %?{  new_syntax } "widget" id old_arg
      | %?{ !new_syntax } "widget" id new_arg
      ;

flip: "flip" { new_syntax = !new_syntax; }
    ;

old_arg: /* something here */
       ;
new_arg: /* something else here */
       ;

%%

After playing around with the tab file, I realized that adding a newline before the #line directives resolves the syntax error, (but it feels kinda hacky directly modifying the generated file. Plus, you would have to align with some spaces in order for gcc to compute the right column position of the code).

I wonder if is this a bug with bison itself, or is it that I'm using semantic predicates wrong, or if this syntax was correct in an earlier version of gcc, or something else.

I've also tried searching the web for this issue, or for a bug already filed with bison, but I found none. (The latest bison version seems to be 3-ish years old. I would be surprised if this issue has not been addressed anywhere at all). Can someone enlighten me about this issue? Thanks.

If necessary, I could try filing a bug with bison (need to figure out how to do that), but I'm not sure if it's my own issue or what not.

1
The answer to SO: #line keyword in C explains very nicely what #line is good for. Although it looks like a pre-processor statement it is (the only) left in files after pre-processing. However, like for any pre-processing stuff, # must be the first token in its line to be recognized correctly. (This is what you already realized.) So, why this wrong output from bison? I guess "(This feature is experimental and may evolve. We welcome user feedback.)" should be considered honestly in this case. (Got it from your link.)Scheff's Cat
Hmm interesting... Thanks. I also saw the fact that this is an experimental feature, but I would assume that this would have at least some basic tests to see if it actually works or not. Hmm oh well, time to figure out how to work a mailing list to make this bug report...theKidOfArcrania

1 Answers

1
votes

As far as I can see, this bug has been present for some time (possibly since the semantic predicate feature was introduced, although it seems like someone should have tested it at some point with some version of bison.)

The simplest workaround is to turn off the generation of #line directives, which you can do by simply adding -l (or --no-lines) to the bison command line. However, that will make it harder to interpret error messages which would otherwise refer to line numbers in your bison grammar file.

As a second workaround, you could find the file c.m4, which is probably in /usr/share/bison/c.m4 (of course, that depends on your distribution). Line 462 of that file (in bison 3.0.4) reads:

    if (! ($2)) YYERROR;

If you add a newline just before $2, so that it reads

    if (! (
           $2)) YYERROR;

then everything should work out fine. (At least, it did when I tested it.)