[antlr-interest] Semantic Predicates Depending On Rule Results

Zachary Palmer zep_antlr at bahj.com
Sun Oct 24 13:26:06 PDT 2010

I'm just posting this follow-up message to indicate that this problem 
can be solved by using the forced semantic predicate syntax: 
{{action}}.  Thanks to Terence for pointing it out to me.  The 
discussion was in a different thread, so I wanted to tie up this loose 
end.  Here's hoping that this is helpful to anyone who finds my message 
in the archives someday.

- Zach
> All,
> I have a bit of a challenging problem at hand.  I've been using ANTLR
> quite successfully for a language development project on which I have
> been working for about a year now.  We are using an ANTLR grammar to
> build the AST for the language from source.  Due to the requirement that
> our AST nodes be heterogeneously typed and constructed via a particular
> factory, we are not using output=AST; we are instead having each rule
> return the type of AST node it generates a la the Java.g grammar found
> on the ANTLRv3 site.
> We've recently introduced a new language construct with rather peculiar
> needs.  When the parser is created, it is provided with a typechecker.
> The new grammar rule for the language looks like the following (sans
> actions and predicates):
>       '~:' expression ':~'
> Whenever this rule (termed "splice") is invoked, it receives an expected
> type for the expression.  The ANTLR grammar rule should only match this
> production if it matches syntactically *and* the typechecker indicates
> that the expression has the type provided as input to the splice rule.
> The idea is that this rule can then be used as follows:
>       ident returns [IdentNode ret]:
>           splice[Type.IDENT] { $ret = factory.makeIdentNode($splice.ret); }
>           | IDENTIFIER { $ret = factory.makeIdentNode($IDENTIFIER.text); }
>           ;
>       name returns [NameNode ret]:
>           splice[Type.NAME] { $ret = factory.makeNameNode($splice.ret); }
>           | a=ident { $ret = factory.makeNameNode($a.ret); }
>           ('.' b=ident { $ret = factory.makeNameNode($b.ret, $ret); })*
>           ;
> This means that we can decide which AST to use based on the type of the
> provided expression.  For the code
>       ~: stuff :~
> we produce a different tree based on whether "stuff" typechecks as a
> NAME or an IDENT.
> The following definition of the splice rule comes very close to what I want:
>       splice[Type expectedType] returns [SpliceNode ret] :
>           '~:' { this.spliceTypechecker != null }?
>           expression
>           ':~' {
> this.spliceTypechecker.typecheck($expression.ret).equals(expectedType) }
>           { $ret = factory.makeSpliceNode($expression.ret); }
>           ;
> Sadly, I have to turn off the "memoize" option or the first try to parse
> splice will fail and the failure will be memoized.  I'd be okay with
> that for the time being (as I have an approaching deadline) except that
> it still doesn't work.  The problem appears to be that the backtracking
> step that determines whether or not splicing is viable here does not
> actually execute the actions I have attached to this grammar.  As a
> result, the "expression" nonterminal parses an expression but does not
> fill any values into $ret.  The typechecker is therefore asked to
> typecheck null, which always results in the semantic predicate failing.
> The problem seems to lie with the fact that I have a semantic predicate
> that relies on the return value of a rule to function correctly.  I
> can't just hack this together by checking the predicate in an action of
> my own (thereby deferring the predicate until after backtracking
> analysis) because then backtracking will pick the wrong path.  I
> absolutely must predicate based on the AST node which is produced from
> the expression nonterminal.  Does anyone have any suggestions?
> I've been quite impressed with ANTLR thus far and we've invested a fair
> amount of work in creating this grammar.  Between that and the
> aforementioned deadline, I'd really like to convince ANTLR to do this
> job for me.  And thanks for reading this far.  :)
> My appreciations,
> Zachary Palmer
> List: http://www.antlr.org/mailman/listinfo/antlr-interest
> Unsubscribe: http://www.antlr.org/mailman/options/antlr-interest/your-email-address

More information about the antlr-interest mailing list