[antlr-interest] Syntactic anti-predicates

Steve Bennett stevagewp at gmail.com
Mon Feb 11 05:45:53 PST 2008


On 2/10/08, Gavin Lambert <antlr at mirality.co.nz> wrote:
> Why not just use:
>
> ruleA
>    :  (X Y Z) => ruleXYZ
>    |  ruleNotXYZ
>    ;

Ok, I've now got a good, non-contrived example to show the problem:

table:
   LEFT_BRACE PIPE ws? table_format? NL
   table_line*
   ws? PIPE RIGHT_BRACE;

table_line:
   ws?
   (
   (PIPE PLUS) => table_caption
   | (PIPE HYPHEN) => table_row_separator
   | (EXCLAMATION) => table_header_cells
   | (PIPE) => table_data_cells
   );

----
Here, the problem is that table_line is inside a looping construct.
Each time it loops, there can be whitespace, then a |} (end of table),
or one of the other forms: |-, |+, |text.

By the time the syntactic predicate inside fails the match, it's too
late. I could left factor table_line:

table_line:
   (
   (ws? PIPE PLUS) => ws? table_caption
   | (ws? PIPE HYPHEN) => ws? table_row_separator
   | (ws? EXCLAMATION) => ws? table_header_cells
   | (ws? PIPE) => ws? table_data_cells
   );

But that's inelegant. My ideal solution would have this line:

   table_line*

replaced with something like:

   (~(ws? PIPE RIGHT_BRACE) => table_line)*

The only way to get around it at the moment that I can see is to
either left factor as above, or use a semantic predicate - which I'm
not really sure how to use with an arbitrary length rule like ws.

Oh, or I can turn the loop inside out:

table:
   LEFT_BRACE PIPE ws? table_format? NL
   ws?
   (table_line ws?)*
   PIPE RIGHT_BRACE;

This does actually work. It's slightly disconcerting having the
whitespace grouped with the previous line, but it's less bad than the
other alternatives I think.

Steve


More information about the antlr-interest mailing list