2

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 (2017-05-02) 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

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 kind of 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.) What is the explanation?

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
theKidOfArcrania
  • 488
  • 4
  • 13
  • 3
    The answer to [SO: #line keyword in C](https://stackoverflow.com/a/7109819/7478597) 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 May 27 '18 at 12:32
  • 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 May 27 '18 at 12:38

1 Answers1

2

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.)

rici
  • 234,347
  • 28
  • 237
  • 341
  • Thanks! I will go test this out later on. – theKidOfArcrania May 28 '18 at 05:12
  • @theKidOfArcrania: OK, let us know how it worked out. – rici May 28 '18 at 05:14
  • It works mostly but if you had like a syntax error or something in the semantic predicate, sometimes the `^` does not point to the right character position, but I think this works well enough – theKidOfArcrania May 28 '18 at 05:17
  • @tkeKidOfArcrania: Yeah, that's quite possible. I reported the bug, anyway. (Did you mean a syntax error reported by bison, or one reported by GCC?) – rici May 28 '18 at 05:25
  • Syntax error reported by GCC compiler. Sorry that was kinda vague – theKidOfArcrania May 28 '18 at 05:27
  • @theKidOfArcrania: that's pretty common with generated code because GCC uses the caret position from the code actually generated but the line in the original `.y` file. Because of the way the code generator works, the indents might not be the same and the caret will show up in the wrong place. You might be able to fool around with the indent in the m4 file to get it into the right place. By the way, bison 3.0.5 is in its final release cycle, or maybe it has been released, so this fix might not get in. – rici May 28 '18 at 05:32