完整cmm解释器构造实践(五):解释执行与GUI

解释执行

接下来要做的事情就是解释执行, 我们只需要将中间代码一条一条执行下来就行. 我们可以模仿CPU的执行方式, 使用一个叫pc的变量存储下一条需要执行的指令的序号. 每次执行一条执行就将pc+1, 当然, 如果是跳转指令要求跳转, 就将值赋给pc, 而不是加1.
中间代码的意思可以自己理解, 根据代码很容易完成.
上一次忘记讲了, 在生成代码的时候, 由于TreeNode的存储结构, 导致表达式的计算是从右往左进行, 一般情况下计算出来的结果是没有问题的, 但是在下面的情况会出问题

write 2*9/10

在整数乘法中, 从右往左计算的结果是1, 从左往右计算的结果是0.
所以我们在代码中可以看到, interpretAddtiveExpinterpretTermExp在逻辑上是一样的, 但是实现起来完全不同.

    private String interpretAddtiveExp(TreeNode node) throws InterpretException {
        String temp = symbolTable.getTempSymbol().getName();
        switch (node.getMiddle().getDataType()) {
        case Token.PLUS:
            codes.add(new FourCode(FourCode.PLUS, interpretExp(node.getLeft()), interpretExp(node.getRight()), temp));

            break;
        case Token.MINUS:
            codes.add(new FourCode(FourCode.MINUS, interpretExp(node.getLeft()), interpretExp(node.getRight()), temp));

            break;
        default:
            throw new InterpretException("算数运算非法");
        }
        mLine++;
        return temp;
    }

    /**
     * 修正存储结构带来的整数乘除法从右往左的计算错误
     * 注意term的TreeNode left一定是factor
     * @param node
     * @return
     * @throws InterpretException
     */
    private String interpretTermExp(TreeNode node) throws InterpretException {
        String opcode = getOpcode(node.getMiddle().getDataType());
        String temp1 = symbolTable.getTempSymbol().getName();
        if (node.getRight().getType() == TreeNode.FACTOR) {
            codes.add(new FourCode(opcode, interpretExp(node.getLeft()), interpretExp(node.getRight()), temp1));
            mLine++;
        } else {
            codes.add(new FourCode(opcode, interpretExp(node.getLeft()), interpretExp(node.getRight().getLeft()), temp1));
            mLine++;
            node = node.getRight();
            String temp2 = null;
            while (node.getRight() != null && node.getRight().getType() != TreeNode.FACTOR) {
                opcode = getOpcode(node.getMiddle().getDataType());
                temp2 = symbolTable.getTempSymbol().getName();
                codes.add(new FourCode(opcode, temp1, interpretExp(node.getRight().getLeft()), temp2));
                mLine++;
                node = node.getRight();
                temp1 = temp2;
            }
            opcode = getOpcode(node.getMiddle().getDataType());
            temp2 = symbolTable.getTempSymbol().getName();
            codes.add(new FourCode(opcode, temp1, interpretExp(node.getRight()), temp2));
            mLine++;
            temp1 = temp2;
        }
        return temp1;
    }

其他的地方就没有什么好说的了.

GUI

我使用了SWT框架实现GUI, 关于SWT框架, 可以参考SWT: A Developer’s Notebook一书.
我的界面比较简单, 只是代码编辑部分使用了一下SWT官方的范例代码, 实现了语法高亮.

交互式窗口

我们是做解释器, 要做一个交互式窗口实在太麻烦, 而且周围有些人完全就是乱作, 虽然效果是一样的, 但是实现方法非常诡异, 这里我们用的方法是将让工程里面存在两个main入口, 一个是带有GUI的入口, 一个是不带有GUI的解释器入口, 解释器入口需要一个参数指明cmm文件的路径. 通过java代码调用一个bat文件(如果是Linux则同理), 传入cmm文件路径, bat文件的作用就是调用解释器入口并传入cmm文件路径.
所以最终我们需要分别打包出两个jar文件, 对应两个入口, 同时组织目录如下:
/cmm.jar
/res/interpret.bat
/res/interpret.jar
最后的成品截图, 打印词法分析结果, 语法分析结果, 中间代码的功能也有, 但是我没截图
截图

点我下载代码

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值