[antlr-interest] New article on StringTemplates and Treewalkers

Andy Tripp atripp at comcast.net
Tue Jan 10 21:00:45 PST 2006


I must be driving you guys nuts by not posting any code, so here is some.

On the issue of that we stumbled on of checking for "if (x=5)", here's 
what I
do. I have a ForceToBooleanRule that checks for all the places that
Java requires a boolean expression. At each of those, I use ANTLR to
parse the expression into an AST, and then traverse that tree, changing 
things
from int to boolean type. That's a bit vague, I know. And the 
lexer/parser/expressionChanger
 code isn't even shown here, it's within the 
ExpressionUtils.forceToBoolean() call.
What is shown here is just the "ForceToBooleanRule" code: A rule that's 
written
in plain Java code, that looks for various patterns in a Token stream 
(NOT an AST).

As always, I do think I have a point here. That is the issue of "where 
would a Rule like this be
invoked in the treewalker approach?" Do you really want to go through 
the bother
of finding the right place for this inside the ANTLR C grammar?
Is there even really a valid set of "right places" that represent the 
four bullet items
in the code below (beneath "for", "while", "do-while", and "if")?
 I don't want to bother with all that. I'd rather do what this code does...
just assume that we're looking through a sequence of Tokens, and do just 
two checks:
 Are we at a "for" (and if so, the expression is between the next ";" 
and the following ";")?
 Are we at a "while" or "if" (if so the expression is everything between 
the next "(" and its matching ")".

No AST tree structure knowledge required! Just write the rule code using
the more intuitive "sequence of tokens" mental image.

(Some background: the match() method is called on every Token in every C 
file. If
it returns true, then the apply() method is called to make the change. 
The Source class
has lots of methods for working with a sequence of Tokens.)
--------------------------------------------------------------------------------------
// certain places in Java require a boolean type, where C allows "int" type:
// * for condition:  for (int i=0; b; i++)
// * while:  while (b)
// * do-while: do { } while (b);
// * if: if (b)

public class ForceToBooleanRule extends Rule {
    private String newexpr;
    private Token startToken = null;
    private Token endToken = null;

    // if we see one of the patterns listed above, set startToken and 
endToken and return true.
    public boolean match(Source source) {
        String current = source.currentToken.getText();
        if (current.equals("for")) {
            startToken = source.findToken(";");
            endToken = source.findToken(source.getTokenAt(startToken, 
+1), ";");
        }
        else if (current.equals("while") ||
                 current.equals("if")) {
            startToken = source.getTokenAt(+1); // '('
            endToken = source.findMatchingParen(startToken);
        }
        else {
            return false;
        }
        String expr = source.getTextBetween(startToken, endToken);

        // here is where the expression is parsed and changed to be 
boolean type:
        newexpr = ExpressionUtils.forceToBoolean(expr, source);
        return !expr.equals(newexpr);
    }

    // change the expression:
    public void apply(Source source) {
        source.replaceTokenRange(startToken, endToken, 
startToken.getText()+newexpr+endToken.getText());
    }
}



More information about the antlr-interest mailing list