0

In section 1.5.4 Controlling a Parse with Arbitrary Predicates: The bison manual specifies that you can make a parse fail up front for an option in a rule by checking the return of the predicate between the brackets in this format:

parent_rule: %?{ test_predicate_flag } child_rule_1 |
             %?{ !test_predicate_flag } child_rule_2;

The problem is that I get this syntax error with the above format in my grammar file:

error: invalid directive: ‘%?{’

I added the %glr-parser flag before the first %% as stated in the manual. Is there something I'm missing?

update: attempted this with bison version 3.0 prior to posting and didn't work. Not much information online about people's experience with this "experimental feature" as the doc says. Can anyone confirm or deny that it works for them?

update #2: After following the solution that rici posted, the resulting .c file has issues. It seems that in attempt to aid compile debug, bison outputs #line directives of the following format:

#line <line_no> <grammar_file_prefix>.tab.c

In the case of the arbitrary predicate generation, the above predicate option for the rule ends up in the parser file's main switch block as this:

if (! (#line <line_no> <grammar_file_prefix>.tab.c

This will of course not compile, and I'm guessing is intended to be output on the line before the start of the case statement like I see in the rest of the rule match options. Perhaps another bit of information to add to the bug report once it's filed? For now, I can search and replace these out to move forward.

  • I'm pretty sure it's a bug in bison's flex spec. At least, I got the example to not deliver the error message. Answer updated. Hopefully @Akim (http://stackoverflow.com/users/1353549/akim) will come around soon and save me the trouble of filing a bug report. – rici Oct 12 '13 at 04:28
  • Bug report filed: http://lists.gnu.org/archive/html/bug-bison/2013-10/msg00004.html – rici Oct 13 '13 at 06:09

1 Answers1

0

The semantic predicates feature was added in bison 3.0, released at the end of July, 2013; at this writing, it's not yet bundled into most OS distributions so you need to install from source to even try it. However, I took a quick glance at the bison source code (as of October 10, 2013, and found what looks like a bug in the scanner specification, at line 269 of scan.gram.l

The pattern in that line will match %{nonletter}[[::graph:]]+ (where nonletter is anything other than an alnum, % or {), which will certainly match %?{

However, it will not match %? {. I tried the example from the manual, and indeed:

widget:
       %?{  new_syntax } "widget" id new_args  { $$ = f($3, $4); }
     | %?{ !new_syntax } "widget" id old_args  { $$ = f($3, $4); }
     ;

produces the error you see, while

widget:
       %?  {  new_syntax } "widget" id new_args  { $$ = f($3, $4); }
     | %?  { !new_syntax } "widget" id old_args  { $$ = f($3, $4); }
     ;

does not.

I believe the fix would be to add ? to the characters not matched by {notletter}. At least, I tried that, and afterwards both of the above snippets "worked" (at least to the extent that bison generated a .c file.)

rici
  • 234,347
  • 28
  • 237
  • 341
  • Thanks for this! Will mark this as the answer for this issue and post an update to this question for any future error with this feature. What was the error you found after fixing the syntax to match the lexer? – crussell431 Oct 12 '13 at 13:55
  • @crussell431: It was the result of not running "make install". Apparently, if you want more than one bison on your system, you need to have different prefix directories; otherwise, it picks up the wrong m4 files. Removed the statement from the answer. – rici Oct 12 '13 at 14:40