--
-- You received this message because you are subscribed to the SableCC group. To post to this group, send email to sab...@googlegroups.com. To unsubscribe from this group, send email to sablecc+u...@googlegroups.com. For more options, visit this group at https://groups.google.com/d/forum/sablecc?hl=en
---
You received this message because you are subscribed to the Google Groups "SableCC" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sablecc+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
public class InterpreterEngine
extends Walker {
// instance variable to hold the result of last expression evaluation
private Instance expEval;
// method to visit a node
public void visit(
Node node) {
node.apply(this);
}
// method to evaluate a node and get the result
private Instance getExpEval(
Node node) {
visit(node);
Instance expEval = this.expEval;
this.expEval = null;
return expEval;
}
// typical binary expression operation (add)
@Override
public void caseAddExp_Add(
NAddExp_Add node) {
// compute the left expression and get the result
Instance left = getExpEval(node.get_AddExp());
// compute the right expression and get the result
Instance right = getExpEval(node.get_LeftUnaryExp());
// check for error situations
if (left == null) {
throw new InterpreterException("left argument of + method is null",
node.get_Plus());
}
else if (right == null) {
throw new InterpreterException(
"right argument of + method is null", node.get_Plus());
}
else {
// everything is OK, compute the result...
MethodInfo invokedMethod = left.getClassInfo().getMethodTable()
.getMethodInfo(node.get_Plus());
Frame frame = new Frame(this.currentFrame, left, invokedMethod);
frame.setParam(right);
// ... and store it in expEval
this.expEval = execute(invokedMethod, frame, node.get_Plus());
}
}
As you see, this avoids having to use a hash table to store
intermediate values.Etienne Gagnon, Ph.D. http://sablecc.org
Hi all,
Me and my partner are now at the translation phase of our school compiler project. That is, we're about to translate the AST given to us by SableCC into a more primitive intermediate representation (IR) that is closer to the target machine language.
In the type-checking phase, we used the technique with a map to store the types of expression nodes, and then did the type-checking in the out*-methods, on our way back up the AST so to speak. E.g. as a simple example, our type-checking for == looks like:
[...]
Where "types" is our Node -> Type map. We have to use this technique since in SableCC we have no control over the generated AST node classes (except indirectly through the grammar of course), and can't make a completely custom visitor that would return a Type. If we could, the above check would be something like:
if (!expression.getLeft().visit().isEqualComparableTo(expression.getRight().visit())) {...}
Which is more commonly seen in compilers, AFAICS.
Now, for the AST -> IR translation phase we're kind of in the same boat: We need the translation of subexpressions/statements ready and waiting on our way back up to the tree. So I guess the natural thing is to use the same tecnique: Store the translation in a Node -> IRNode map.
But before we start I thought I'd ask here on the list: Has anyone else been in a similar situation? If so, how did you handle this? Just using the map technique, or did you hack the SableCC code generation so that you could make completely custom visitors (including control of the method return type)?
Wow, mail got longer than I intended, sorry about that :)
Anyway, quite interested in anyone who has experience with SableCC AST -> IR translation.
Best regards,Elvis Stansvik
Hello Elvis, what I normally do is to modify the class Node, root of all nodes in the AST. There I put additional attributes and methods to be inherited for all nodes (as the type, but can be whatever).