[antlr-interest] Processing/traversing a rule -- dealing with conditionals

Tyler Distad tyler.distad at gmail.com
Thu Apr 8 18:42:54 PDT 2010


John,

Yes, I'm trying to deal with the conditional aspects of my grammar, but not
quite in the sense you suggest. My processor is not interpreting the
grammar, it's emitting assembly code for later compilation by gcc.

So, I want to process all of the expressions regardless of the truth value
of the conditional. In between each node of my stmtIf rule, I need to emit
assembly to account for tests, jumps, etc.

Do I have to "physically" place calls to my processor actions in between
each of the grammar nodes? I have multiple processing classes that each do
different things depending on their intent. I don't really want to create
excess methods on the root class for things that only my code generator pass
will do.

I guess my question boils back down to: Is there a way to override the
traversal of a single rule?

Tyler Distad

On Thu, Apr 8, 2010 at 11:39 AM, Farr, John <john.farr at medtronic.com> wrote:

> Tyler,
>
> It appears that you're trying to deal with the conditional aspect of your
> IF and WHILE statements in the tree grammar actions. I haven't found a way
> to do this exclusively in actions because the conditions determine which
> parts of the tree to "evaluate" and which parts to "skip over".
>
> The way I deal with this in an expression evaluator tree is something like
> the following:
>
> //-------------
>
> @header { bool booleanResult; }
>
> expression returns [Result result]
>    : ^( IF     cond=expression
>                { booleanResult = $cond.result.asBool(); }
>                ( { booleanResult }?=>
>                  s1=expression unevaluatedExpression
>                  { $result = $s1.result; }
>                | unevaluatedExpression s2=expression
>                  { $result = $s2.result; }
>                )
>       )
>    | ^( OR     op1=expression { booleanResult = $op1.result.asBool(); }
>                ( { booleanResult }?=> unevaluatedExpression { $result =
> $op1.result; }
>                | op2=expression { $result = $op2.result; }
>                )
>       )
>    | ^( AND    op1=expression
>                { booleanResult = $op1.result.asBool(); }
>                ( { !booleanResult }?=>
>                  unevaluatedExpression
>                  { $result = $op1.result; }
>                | op2=expression
>                  { $result = $op2.result; }
>                )
>       )
>    // ... other operators, literals, etc.
>    ;
>
> unevaluatedExpression
>    : ^( ( IF | OR | AND
>         | // other operators, etc.
>         ) unevaluatedExpression* )
>    | // literals, etc.
>    ;
>
> //-------------
>
> This is obviously simplified and incomplete but I hope you'll get the idea.
> There are a couple of things this approach depends on:
>
> 1. A rule, unevaluatedExpression, that is like the main expression rule,
> but contains no evaluating actions.
>
> 2. A data member of the parser class, booleanResult, used in semantic
> predicates to select which subexpressions to evaluate. It needs to be at the
> parser level (or in a scope), so that it can be seen by the code generated
> for the semantic predicate.
>
> 3. The semantic predicates that select the appropriate subexpressions.
>
> I hope this helps.
>
> --John
>
>
> -----Original Message-----
> From: antlr-interest-bounces at antlr.org [mailto:
> antlr-interest-bounces at antlr.org] On Behalf Of Tyler Distad
> Sent: Thursday, April 08, 2010 6:16 AM
> To: antlr-interest at antlr.org
> Subject: [antlr-interest] Processing/traversing a rule
>
> I have a tree parser which is traversing the nodes of my AST. At points
> within the grammar, I use action blocks to call methods on my processing
> object, thus keeping large amounts of action code abstracted into a separate
> file.
>
> This has worked fine, but now I have the "if" and "while" statements
> visible
> below:
>
> stmtIf
>    : ^(STMT_IF expr trueStmts=stmt* (ELSE_KW falseStmts=stmt*)?)
>        { proc.outStmtIf($expr.start, $trueStmts.start,
> $falseStmts.start);    }
>    ;
>
> stmtWhile
>    : ^(STMT_WHILE expr stmt*)
>        { proc.outStmtWhile($expr.start, $stmt.start);    }
>    ;
>
> Obviously, this works fine for actions which take place after the entire if
> or while tree has been processed. But I want to do some processing before
> the tree is traversed, as well as some at specific points during. I could
> create more method calls in my processing object and sprinkle them
> throughout the above AST, but that feels so clunky. I'd like to be able to
> override the entire traversal of the rule at this point and do some custom
> work.
>
> So, two questions:
>  * In general, is my method of making calls to a processing object
> sane/normal/best practice?
>  * In the above cases, is there any practical method of manually processing
> an entire rule and its descendant tree?
>
> Tyler Distad
>
> List: http://www.antlr.org/mailman/listinfo/antlr-interest
> Unsubscribe:
> http://www.antlr.org/mailman/options/antlr-interest/your-email-address
>
>
> [CONFIDENTIALITY AND PRIVACY NOTICE]
>
> Information transmitted by this email is proprietary to Medtronic and is
> intended for use only by the individual or entity to which it is addressed,
> and may contain information that is private, privileged, confidential or
> exempt from disclosure under applicable law. If you are not the intended
> recipient or it appears that this mail has been forwarded to you without
> proper authority, you are notified that any use or dissemination of this
> information in any manner is strictly prohibited. In such cases, please
> delete this mail from your records.
>
> To view this notice in other languages you can either select the following
> link or manually copy and paste the link into the address bar of a web
> browser: http://emaildisclaimer.medtronic.com
>
>


More information about the antlr-interest mailing list