[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