语法制导的应用(二)

发布时间 2024-01-06 16:22:25作者: kashin05

前面已经在语法分析过程中实现的语法分析树的构造

接下来,遍历语法分析树,并且加入动作

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