[antlr-interest] "explosion" rewrite
Jim Idle
jimi at temporal-wave.com
Sat May 2 09:22:24 PDT 2009
Steve Ebersole wrote:
> sortKey : expression;
>
> expression
> : QUOTED_IDENTIFIER -> ^( COLUMN ALIAS_REF[Template.TEMPLATE]
> QUOTED_IDENTIFIER[$QUOTED_IDENTIFIER] )
> // we treat the so-called standard functions differently because
> they are handled differently by the HQL lexer which we also use here...
> | standardFunction
> | literal
> // not identDotIdentStructure because we dont want
> QUOTED_IDENTIFIERs is here
> | ( IDENTIFIER ( DOT IDENTIFIER )* LEFT_PAREN ) => generalFunction
> // otherwise we fully expect a dot-identifier series, and then we
> just need to decode the semantic of that structure
> | identDotIdentStructure
> -> { ( isFunctionName($identDotIdentStructure.text) ) }?
> // we have a function with parens (thus no args)
> ^( FUNCTION[$identDotIdentStructure.start,
> $identDotIdentStructure.text] )
> -> { ( isPropertyName($identDotIdentStructure.text) ) }?
> // we have a reference to a mapped property
> { buildPropertyColumns( $identDotIdentStructure.tree ) }
> -> { ( $identDotIdentStructure.tree.getType() == DOT ) }?
> // we have a reference to a column which is already
> qualified
> identDotIdentStructure
> ->
> // we have a reference to a column which is not qualified
> ^( COLUMN ALIAS_REF[Template.TEMPLATE]
> IDENTIFIER[$identDotIdentStructure.start,$identDotIdentStructure.text] )
> ;
>
>
> The piece of interest here is fragment in expression that reads
>
> -> { ( isPropertyName($identDotIdentStructure.text) ) }?
> // we have a reference to a mapped property
> { buildPropertyColumns( $identDotIdentStructure.tree ) }
>
> buildPropertyColumns() is a java action where I account for the fact
> that in Hibernate a single property might map to multiple columns; in
> that case buildPropertyColumns() returns the VECTOR_EXPR
>
>
Hi Steve,
As the expression does not give you context as to whether you need the
vector node or not, I think that you have the following options:
1) Change expression to accept a parameter that says whether you need
the vector or not, pass this to your Java rule. So that you don't need
to change every reference to expression you can rename the current one
to expression_xyz then use expression (which calls xyz with
needsVector=true) and expression_novector and sets it to false. The
catch here is if you have any predicates in that expression rule that
may be hoisted, in which case your local variable will be out of scope
in the calling generated code.
2) As I think you mention in another email, keep a scope at a level high
enough in the tree that can hold flags and pass them in to your java code.
3) Have the expression return a value that says whether the expression
is VECTORABLE or not. In rules that require the node, then call a
different rule that calls expression and rewrites with a VECTOR node if
it is required. The ability to do this of course depends on whether the
return from your Java function can be just rewritten with a node.
It may be that your grammar can be "re-worked" not to need such nodes
though, or to produce a tree that while it may not be absolutely
intuitive when you look at it, is obvious when walking it that you
should treat the children in one way or another. I always try to avoid
as much logic as I can in parsing and do everything that can be in the
walkers. Perhaps you can wrap the expression in a higher node which
means it will take a different path through the tree walk. Many
different ways to crack a nut of course.
Jim
More information about the antlr-interest
mailing list