语法制导的应用(二)
前面已经在语法分析过程中实现的语法分析树的构造
接下来,遍历语法分析树,并且加入动作
1.需要解决的问题
1)怎么加入动作,怎么方便的动态加入,简单表达
一个产生式样式如:E -> E + T,用符号作为分割符,0E1+2T3,4个位置加入Translator
动作的接口实现
public interface Translator {
void translate(Node pre, Node next);
}
例:语义规则E.val = E.val + T.val ,在所有节点后执行语义动作,则如下实现
Production.of("E -> E + T").addTranslator(3, (pre, next) -> {
Node e = pre.getParent().getChildren().get(0);
Node t = pre.getParent().getChildren().get(2);
pre.getParent().setVal((Integer)e.getVal() + (Integer)t.getVal());
})
2)在遍历的时候执行Translator
public void translateWithThree(Node root) {
if (root.getChildren() == null || root.getChildren().isEmpty()) {
return;
}
Node pre = null;
// E -> 0 E 1 + 2 T 3 节点加上可能插入的动作总共7个
// 0 1 2 3 4 5 6
int end = root.getChildren().size() * 2;
for (int i=0; i<=end; i++) {
if (i % 2 == 0) {// 动作
int t = i / 2;
Node next = null;
if (t < root.getChildren().size()) {
next = root.getChildren().get(t);
}
Translator translator = root.getProduction().getTranslator(t);
if (translator != null) {
translator.translate(pre, next);
}
} else {// 节点
int nodeIdx = (i - 1) / 2;
Node child = root.getChildren().get(nodeIdx);
translateWithThree(child);
pre = child;
}
}
}
3)翻译一下计算器
语法:
S' -> L L -> E E -> E + T E -> T T -> T * F F -> ( E ) F -> d
加入语义动作
Production.of("E -> E + T").addTranslator(3, (pre, next) -> {
Node e = pre.getParent().getChildren().get(0);
Node t = pre.getParent().getChildren().get(2);
pre.getParent().setVal((Integer)e.getVal() + (Integer)t.getVal());
})
Production.of("T -> T * F").addTranslator(3, (pre, next) -> {
Node e = pre.getParent().getChildren().get(0);
Node t = pre.getParent().getChildren().get(2);
pre.getParent().setVal((Integer)e.getVal() * (Integer)t.getVal());
})
其他都是赋值操作,将子节点赋值到父节点
执行,translateWithThree方法,参数
3 * 5 + 4
正确输出结果
19
浙公网安备 33010602011771号