[antlr-interest] mild simplification and tree grammars

Mark Wright markwright at internode.on.net
Wed Apr 21 04:10:49 PDT 2010


On Wed, Apr 21, 2010 at 12:32:58PM +0200, Giampaolo Tomassoni wrote:
> > Another extension of the example shows another ANTLR feature,
> > with associated subtle syntax.  Say the conditionalExpression
> > was being called with TheActualASTRoot being optional, then
> > ANTLR supports this with semantic predicates on the tree generation
> > options:
> > 
> > protected
> > conditionalExpression[CommonTree TheActualASTRoot]
> >     :   QMARK t=expression COMMA f=expression
> >             -> {(TheActualASTRoot != null)}? ^(ITE {$TheActualASTRoot}
> > $t $f)
> >             -> {(TheActualASTRoot == null)}? ^(ITE $t $f)
> >             ->
> >     |
> >     ;
> 
> Nice.
> 
> I didn't get why you were telling me that, but now I see: this way it is
> easier to avoid non-LLR notations.
> 
> Just, I can't turn on my shc (SomethingHasChanged) flag anymore: a rule
> like:
> 
> condExpr
> 	:    QMARK c=orExpression t=condExpr f=condExpr
> 		-> {($c.tree.getType()==TRUE)}?  {shc=true;} $t
> 		-> {($c.tree.getType()==FALSE)}? {shc=true;} $f
> 		->
> 	;
> 
> 
> Produces a java source with errors, because {shc=true;} is now interpreted
> like a tree node reference, not like a java statement to be passed to the
> compiler verbatim.
> 
> I had to use a function's side-effect to keep track of tree modifications:
> 
> 
> @members {
>     private boolean shc = false;
> 
>     private boolean sshc(boolean cond) {
>     	shc |= cond;
>     	return(cond); 
>     }
> }
> 
> ...
> 
> protected
> condExpr
>     :	QMARK c=orExpression t=condExpr f=condExpr
> 		-> {sshc($c.tree.getType()==TRUE)}?		$t
> 		-> {sshc($c.tree.getType()==FALSE)}?	$f
> 		-> QMARK $c $t $f
>     |	additiveExpression
>     ;
> 
> 
> Also note the last '->' term is non-empty, because I'm not rewriting (the
> ANTLR compiler says rewrite mode implies backtrack=true).
> 
> Do you think is it fine this way or there is some workaround I can implement
> to avoid the need of a side-effect function?
> 
> Giampaolo

Predicates should not have observable* side effects.

The solution seems simple: the actions should be called before the
tree rewrites, like:

condExpr
	:    QMARK c=orExpression t=condExpr f=condExpr
                {shc=true;}
		-> {($c.tree.getType()==TRUE)}?   $t
		-> {($c.tree.getType()==FALSE)}?  $f
		->
	;

Regards, Mark

PS * since disambiguating semantic predicates may be called tens or
hundreds of times at the same input file position in complex
predicated parsers by antlr generated code, for performance
reasons it may be necessary for complex semantic predicates to calculate the
result once at each input file position, and cache the result, to
avoid re-computing it over and over again.


More information about the antlr-interest mailing list