[antlr-interest] How do you implement conditional blocks in tree grammars?

Kurt Otte kurtotte at gmail.com
Wed Sep 17 15:57:55 PDT 2008


How can I skip a section of the token stream when using a tree grammar
to implement a conditional block?

I have read the mailing list archives and come across several
references to using seek() to reposition the token stream, but how to
you resync the parser to match?

For example, suppose I have an IF construct in the AST similar to this

^(COND expression ^(IF ^(BLOCK statement+) )

>From the previous threads it seems like you would do something like

^(COND exp=expression
  {if (!$exp.bool) SeekTokenStream($statements.stop); }
  ^(IF ^(BLOCK statement+) )

Essentially, as I understand it this would make it so '^(IF ^(BLOCK
statement+)' would be skipped if the expression evaluated false.
SeekTokenStream() is a function I would need to write to call the
seek() method in the token istream.  Unfortunately, I can't seem to
find a way to get access to the stream from inside an action block.
It seemed from the mail archives there was a $input which would all
this, but that doesn't seem to be currently supported.  The next
problem is I can't access statements until after processing them which
defeats the purpose and 'stop' doesn't seem to be supported either.
Even if all of this did work to move the token stream forward, the
parser would be out of sync so I am a bit confused on what the design
model is for skipping a block.

To synchronize the parser, I thought it might make sense to use a
gated predicate such as

^(COND exp=expression
  ^(IF ^(b=BLOCK
    // conditionally enable the statements, and if they are disabled,
    // advance the token stream to skip the block
    {(!$exp.bool)}?=> statement+
    { if (!$exp.bool) { SkipBlock($b); }})

This is a bit ugly and redundant, but the hope was to turn off
statements and then SkipBlock() would have to do some manual work on
the token stream find the end of the block and then seek() to there;
however, the gated predicate doesn't turn off 'statement+' as I had
hoped.

To avoid heavy lifting in SkipBlock(), I was hoping to have ANTLR help
me with finding the end of the block by using wildcarding.  Something
like this

^(COND exp=expression ^(IF ^(BLOCK anything) )

anything
  : .+
  | ^(anything)
  ;

Then I could use ANTLR to match all of the statements generically, but
it seems '.' will only match a token not a tree since it gets hung up
on UP's and DOWN's and the above attempt to match tokens and trees
won't even compile.

Am I off in the weeds?  It seems like implementing a conditional block
should be a rather common and reasonable thing to do, but I haven't
been able to search out the necessary magic yet.

Does anyone have a good example of how to do this?  What am I missing?

Thanks,

Kurt


More information about the antlr-interest mailing list