【P4911】Java题解

· · 题解

啊这,貌似是第一份 JavaAC 欸。

一遍过(是数据太水了大概咳咳)

虽然好像评论区说数据有些指令没有然而还是都写了,没看到没空行所以空行也处理了一下。

我怀疑有 bug 但数据测试不出来(小声

(嗯,这次 O2 又是会逆向优化)

是刚学了 Java 用来巩固写的 emm ,所以也做了奇怪的封装什么的,也没有注重代码长度和效率,写长点多爽啊(暴论

后半部分写得比较肿,主要是看不清了要。

具体嘛就是假装词法分析一下(见 public void Compiler.Lexer() )。这里面是先割词,然后识别到标识符再向前归纳和可能存在的 %, @ 之类的合并起来变成变量。

按词分好,按行分好,然后执行(见 public void Interpreter.run() )。

运行前还要处理一下函数地址(见 public void Interpreter.loadup() )。

为了体现面向对象各种结构都定义了对应的类( CPU, Memory, Compiler, Interpreter, Stream, IStream, OStream )。

sAddr 栈和各种寄存器在 CPU 类里,内存就是内存。

class IStream extends Stream 和 class OStream extends Stream 分别模拟输入输出流。

各自成员变量都设为 private 做了封装(自虐)。

所以 main 函数看起来很舒服咳咳。

所以全收起来之后比较清晰:

import java.util.*;

// 内存
class Memory {...}

// 处理器
class CPU {...}

// 流
class Stream {...}

// 输入流 extends 流
class IStream extends Stream {...}

// 输出流 extends 流
class OStream extends Stream {...}

// 编译器(伪
class Compiler {...}

// 解释器(伪
class Interpreter {...}

public class Main {
    public static void main(String[] args) {...}
}

最后贴上代码,写了不少注释:

import java.util.*;

// 内存
class Memory {
    // 0 - 1677216
    private int[] data = new int[16777300];

    // 构造函数
    Memory() {
        Arrays.fill(data, 0);
    }

    // 调取和设置方法
    public int getAddr(int _a) {
        return data[_a];
    }
    public void setAddr(int _a, int _d) {
        data[_a] = _d;
    }
}

// 处理器
class CPU {
    // 栈元素
    private class Tsta {
        int next;
        int line;

        Tsta(int next, int line) {
            this.next = next;
            this.line = line;
        }
    }

    // 栈
    private Stack<Tsta> sAddr = new Stack<>();

    // 寄存器
    private int R1 = 0, R2 = 0, R3 = 0, R4 = 0;
    private int E1 = 0, E2 = 0, E3 = 0, E4 = 0;
    private int Flag = 0, Val = 0, Ret = 0, Line = 0;

    // 调取和设置方法
    public int Get(String name) {
        switch (name) {
            case "r1": return R1;
            case "r2": return R2;
            case "r3": return R3;
            case "r4": return R4;
            case "e1": return E1;
            case "e2": return E2;
            case "e3": return E3;
            case "e4": return E4;
            case "flag": return Flag;
            case "val": return Val;
            case "ret": return Ret;
            case "line": return Line;
        }
        return 0;
    }
    public void Set(String name, int t) {
        switch (name) {
            case "r1": R1 = t; break;
            case "r2": R2 = t; break;
            case "r3": R3 = t; break;
            case "r4": R4 = t; break;
            case "e1": E1 = t; break;
            case "e2": E2 = t; break;
            case "e3": E3 = t; break;
            case "e4": E4 = t; break;
            case "flag": Flag = t; break;
            case "val": Val = t; break;
            case "ret": Ret = t; break;
            case "line": Line = t; break;
        }
    }
    public void push(int next, int line) {
        sAddr.push(new Tsta(next, line));
    }
    public int pop() {
        // 弹栈返回目标行,并复位%Line
        Tsta t = sAddr.pop();
        Line = t.line;
        return t.next;
    }
}

// 流
class Stream {
    // 数据
    private ArrayList<String> data = new ArrayList<>();

    // 调取和设置方法
    public ArrayList<String> get() {
        return data;
    }
    public void add(String s) {
        data.add(s);
    }
}

// 输入流 extends 流
class IStream extends Stream {
    // 指针
    private int current = 0;

    // 是否为空白符
    private boolean isWhite(char _peek) {
        return _peek == ' ' || _peek == '\t';
    }

    // 构造函数,按空白符划词
    IStream() {}
    IStream(Stream _in) {
        for (String _line : _in.get()) {
            int len = _line.length();
            int j = 0;
            for (int i = 1; i < len; i++) {
                // 词尾
                if (isWhite(_line.charAt(i)) && !isWhite(_line.charAt(i - 1))) {
                    add(_line.substring(j, i));
                }
                // 词头,头指针更新
                if (!isWhite(_line.charAt(i)) && isWhite(_line.charAt(i - 1))) {
                    j = i;
                }
            }
            // 行末 -> 词尾
            add(_line.substring(j));
        }
    }

    // 按序读取
    public String getNext() {
        return get().get(current++);
    }
}

// 输出流 extends 流
class OStream extends Stream {
    // 输出
    public void output() {
        for (String _l : get()) {
            System.out.print(_l);
        }
    }
}

// 编译器(伪
class Compiler {
    // 词
    private class Ttoken {
        // 词类型
        private int type = 0;

        // 词属性
        private String property;

        // 构词法
        Ttoken(int type, String property) {
            this.type = type;
            this.property = property;
        }

        // 调取和设置方法
        public int getT() {
            return type;
        }
        public void setT(int type) {
            this.type = type;
        }
        public String getP() {
            return property;
        }
        public void setP(String property) {
            this.property = property;
        }
    }

    // 词表
    private ArrayList<Ttoken> tokens = new ArrayList<>();

    // 句首词表
    private ArrayList<Integer> cmds = new ArrayList<>();

    // 是否为空白符
    private boolean isWhite(char _peek) {
        return _peek == ' ' || _peek == '\t';
    }

    // 是否为标识符字符
    private boolean isLetter(char _peek) {
        return _peek >= 'A' && _peek <= 'z' || _peek >= '0' && _peek <= '9';
    }

    // 词法分析,并记录句首词
    public void Lexer(Stream _code) {
        int anno = 0;
        cmds.add(0); // 行号从1开始标记
        for (String _line : _code.get()) {
            cmds.add(tokens.size());
            int len = _line.length();
            for (int i = 0; i < len; i++) {
                char _peek = _line.charAt(i);
                // 空白、注释处理
                if (_peek == '[') {
                    anno++;
                    continue;
                }
                if (_peek == ']') {
                    anno--;
                    continue;
                }
                if (anno != 0 || isWhite(_peek)) continue;

                // 特殊符号
                if (_peek == '%') {
                    tokens.add(new Ttoken(-1, ""));
                    continue;
                }
                if (_peek == '@') {
                    tokens.add(new Ttoken(-2, ""));
                    continue;
                }
                if (_peek == '#') {
                    tokens.add(new Ttoken(-3, ""));
                    continue;
                }
                if (_peek == '$') {
                    tokens.add(new Ttoken(-4, ""));
                    continue;
                }
                if (_peek == ';') {
                    tokens.add(new Ttoken(-5, ""));
                    continue;
                }

                // 标识符
                tokens.add(new Ttoken(1,"" + _peek));
                if (i < len - 1) {
                    _peek = _line.charAt(++i);
                    while (i < len && isLetter(_peek)) {
                        tokens.get(tokens.size() - 1).property += _peek;
                        _peek = _line.charAt(++i);
                    }
                    i--;
                }

                // 标识符向前归纳
                if (tokens.size() <= 2) continue;
                Ttoken A = tokens.get(tokens.size() - 3);
                Ttoken B = tokens.get(tokens.size() - 2);
                Ttoken C = tokens.get(tokens.size() - 1);
                if (A.type == -2 && B.type == -1) {
                    A.type = 4;
                    A.property = C.property;
                    tokens.remove(tokens.size() - 1);
                    tokens.remove(tokens.size() - 1);
                    continue;
                } // @%... -> 4
                if (B.type == -1) {
                    B.type = 2;
                    B.property = C.property;
                    tokens.remove(tokens.size() - 1);
                    continue;
                } // %... -> 2
                if (B.type == -2) {
                    B.type = 3;
                    B.property = C.property;
                    tokens.remove(tokens.size() - 1);
                    continue;
                } // @... -> 3
                if (B.type == -3) {
                    B.type = 5;
                    B.property = C.property;
                    tokens.remove(tokens.size() - 1);
                    continue;
                } // #... -> 5
                if (B.type == -4) {
                    B.type = 6;
                    B.property = C.property;
                    tokens.remove(tokens.size() - 1);
                    // continue;
                } // $... -> 6
            }
        }
        cmds.add(cmds.get(cmds.size() - 1) + 1); // 结尾加空行防止ptr+1溢出
    }

    // 获取第_n行句首词编号
    public Integer getCmd(int _n) {
        return cmds.get(_n);
    }

    // 获取第_n个词
    public int GetT(int _n) {
        return tokens.get(_n).type;
    }
    public String GetP(int _n) {
        return tokens.get(_n).property;
    }
}

// 解释器(伪
class Interpreter {
    // 处理器
    private CPU cpu = new CPU();

    // 内存
    private Memory mem = new Memory();

    // 当前执行行号,即#Line
    private int ptr;

    // 函数头行号记录
    private HashMap<String, Integer> func = new HashMap<>();

    // 函数加载器
    public void loadup(int _n, Compiler com) {
        for (int i = 1; i <= _n; i++) {
            if (com.getCmd(i + 1).equals(com.getCmd(i))) continue;
            int num = com.getCmd(i);
            if (com.GetP(num).contains("function")) {
                func.put(com.GetP(num + 1), i); // 关联函数名与行号
            }
        }
    }

    // 获取变量值
    public int FET(int ty0, String pr0) {
        switch (ty0) {
            case -1: return (int)pr0.charAt(0);
            case 1: return Integer.parseInt(pr0);
            case 2: return cpu.Get(pr0);
            case 3: return mem.getAddr(Integer.parseInt(pr0));
            case 4: return mem.getAddr(cpu.Get(pr0));
            case 5: return ptr;
            case 6: return func.get(pr0);
        }
        return 0;
    }

    // SET操作
    public void SET(int ty0, String pr0, int ty1, String pr1) {
        int arg0 = FET(ty0, pr0);
        switch (ty1) {
            case 2: cpu.Set(pr1, arg0); break;
            case 3: mem.setAddr(Integer.parseInt(pr1), arg0); break;
            case 4: mem.setAddr(cpu.Get(pr1), arg0); break;
        }
    }

    // 运行
    public void run(Compiler com, IStream in, OStream out) {
        ptr = 1;
        while (true) {
            if (com.getCmd(ptr + 1).equals(com.getCmd(ptr))) {
                ptr++;
                continue;
            }
            if (com.GetP(com.getCmd(ptr)).contains("hlt")) {
                break;
            } else if (com.GetP(com.getCmd(ptr)).contains("set")) {
                SET(com.GetT(com.getCmd(ptr) + 1), com.GetP(com.getCmd(ptr) + 1),
                    com.GetT(com.getCmd(ptr) + 2), com.GetP(com.getCmd(ptr) + 2));
            } else if (com.GetP(com.getCmd(ptr)).contains("jmp")) {
                ptr = FET(com.GetT(com.getCmd(ptr) + 1), com.GetP(com.getCmd(ptr) + 1))
                    + cpu.Get("line");
                continue;
            } else if (com.GetP(com.getCmd(ptr)).contains("jif")) {
                if (com.getCmd(ptr + 1) - com.getCmd(ptr) == 3) {
                    if (cpu.Get("flag") == 1) {
                        ptr = FET(com.GetT(com.getCmd(ptr) + 1), com.GetP(com.getCmd(ptr) + 1))
                                + cpu.Get("line");
                        continue;
                    }
                } else {
                    if (FET(com.GetT(com.getCmd(ptr) + 2), com.GetP(com.getCmd(ptr) + 2)) != 0) {
                        ptr = FET(com.GetT(com.getCmd(ptr) + 1), com.GetP(com.getCmd(ptr) + 1))
                                + cpu.Get("line");
                        continue;
                    }
                }
            } else if (com.GetP(com.getCmd(ptr)).contains("call")) {
                cpu.push(ptr + 1, cpu.Get("line")); // 压栈
                ptr = FET(com.GetT(com.getCmd(ptr) + 1), com.GetP(com.getCmd(ptr) + 1)); // 跳转至函数
                cpu.Set("line", ptr); // 设置当前函数头
                continue;
            } else if (com.GetP(com.getCmd(ptr)).contains("ret")) {
                if (com.getCmd(ptr + 1) - com.getCmd(ptr) == 3) {
                    cpu.Set("ret", FET(com.GetT(com.getCmd(ptr) + 1), com.GetP(com.getCmd(ptr) + 1))); // 返回值
                }
                ptr = cpu.pop(); // 弹栈并跳回,同时复位%Line
                continue;
            } else if (com.GetP(com.getCmd(ptr)).contains("inv")) {
                int t = - FET(com.GetT(com.getCmd(ptr) + 1), com.GetP(com.getCmd(ptr) + 1));
                if (com.getCmd(ptr + 1) - com.getCmd(ptr) == 3) {
                    cpu.Set("val", t);
                } else {
                    SET(1, ((Integer)t).toString(), com.GetT(com.getCmd(ptr) + 2), com.GetP(com.getCmd(ptr) + 2));
                }
            } else if (com.GetP(com.getCmd(ptr)).contains("add")) {
                int t = FET(com.GetT(com.getCmd(ptr) + 1), com.GetP(com.getCmd(ptr) + 1))
                        + FET(com.GetT(com.getCmd(ptr) + 2), com.GetP(com.getCmd(ptr) + 2));
                if (com.getCmd(ptr + 1) - com.getCmd(ptr) == 4) {
                    cpu.Set("val", t);
                } else {
                    SET(1, ((Integer)t).toString(), com.GetT(com.getCmd(ptr) + 3), com.GetP(com.getCmd(ptr) + 3));
                }
            } else if (com.GetP(com.getCmd(ptr)).contains("sub")) {
                int t = FET(com.GetT(com.getCmd(ptr) + 1), com.GetP(com.getCmd(ptr) + 1))
                        - FET(com.GetT(com.getCmd(ptr) + 2), com.GetP(com.getCmd(ptr) + 2));
                if (com.getCmd(ptr + 1) - com.getCmd(ptr) == 4) {
                    cpu.Set("val", t);
                } else {
                    SET(1, ((Integer)t).toString(), com.GetT(com.getCmd(ptr) + 3), com.GetP(com.getCmd(ptr) + 3));
                }
            } else if (com.GetP(com.getCmd(ptr)).contains("mult")) {
                int t = FET(com.GetT(com.getCmd(ptr) + 1), com.GetP(com.getCmd(ptr) + 1))
                        * FET(com.GetT(com.getCmd(ptr) + 2), com.GetP(com.getCmd(ptr) + 2));
                if (com.getCmd(ptr + 1) - com.getCmd(ptr) == 4) {
                    cpu.Set("val", t);
                } else {
                    SET(1, ((Integer)t).toString(), com.GetT(com.getCmd(ptr) + 3), com.GetP(com.getCmd(ptr) + 3));
                }
            } else if (com.GetP(com.getCmd(ptr)).contains("idiv")) {
                int t = (int)Math.floor(1.0d * FET(com.GetT(com.getCmd(ptr) + 1), com.GetP(com.getCmd(ptr) + 1))
                        / FET(com.GetT(com.getCmd(ptr) + 2), com.GetP(com.getCmd(ptr) + 2)));
                if (com.getCmd(ptr + 1) - com.getCmd(ptr) == 4) {
                    cpu.Set("val", t);
                } else {
                    SET(1, ((Integer)t).toString(), com.GetT(com.getCmd(ptr) + 3), com.GetP(com.getCmd(ptr) + 3));
                }
            } else if (com.GetP(com.getCmd(ptr)).contains("mod")) {
                int t = FET(com.GetT(com.getCmd(ptr) + 1), com.GetP(com.getCmd(ptr) + 1))
                        % FET(com.GetT(com.getCmd(ptr) + 2), com.GetP(com.getCmd(ptr) + 2));
                if (com.getCmd(ptr + 1) - com.getCmd(ptr) == 4) {
                    cpu.Set("val", t);
                } else {
                    SET(1, ((Integer)t).toString(), com.GetT(com.getCmd(ptr) + 3), com.GetP(com.getCmd(ptr) + 3));
                }
            } else if (com.GetP(com.getCmd(ptr)).contains("lsft")) {
                int t = FET(com.GetT(com.getCmd(ptr) + 1), com.GetP(com.getCmd(ptr) + 1))
                        << FET(com.GetT(com.getCmd(ptr) + 2), com.GetP(com.getCmd(ptr) + 2));
                if (com.getCmd(ptr + 1) - com.getCmd(ptr) == 4) {
                    cpu.Set("val", t);
                } else {
                    SET(1, ((Integer)t).toString(), com.GetT(com.getCmd(ptr) + 3), com.GetP(com.getCmd(ptr) + 3));
                }
            } else if (com.GetP(com.getCmd(ptr)).contains("rsft")) {
                int t = FET(com.GetT(com.getCmd(ptr) + 1), com.GetP(com.getCmd(ptr) + 1))
                        >> FET(com.GetT(com.getCmd(ptr) + 2), com.GetP(com.getCmd(ptr) + 2));
                if (com.getCmd(ptr + 1) - com.getCmd(ptr) == 4) {
                    cpu.Set("val", t);
                } else {
                    SET(1, ((Integer)t).toString(), com.GetT(com.getCmd(ptr) + 3), com.GetP(com.getCmd(ptr) + 3));
                }
            } else if (com.GetP(com.getCmd(ptr)).contains("band")) {
                int t = FET(com.GetT(com.getCmd(ptr) + 1), com.GetP(com.getCmd(ptr) + 1))
                        & FET(com.GetT(com.getCmd(ptr) + 2), com.GetP(com.getCmd(ptr) + 2));
                if (com.getCmd(ptr + 1) - com.getCmd(ptr) == 4) {
                    cpu.Set("val", t);
                } else {
                    SET(1, ((Integer)t).toString(), com.GetT(com.getCmd(ptr) + 3), com.GetP(com.getCmd(ptr) + 3));
                }
            } else if (com.GetP(com.getCmd(ptr)).contains("bor")) {
                int t = FET(com.GetT(com.getCmd(ptr) + 1), com.GetP(com.getCmd(ptr) + 1))
                        | FET(com.GetT(com.getCmd(ptr) + 2), com.GetP(com.getCmd(ptr) + 2));
                if (com.getCmd(ptr + 1) - com.getCmd(ptr) == 4) {
                    cpu.Set("val", t);
                } else {
                    SET(1, ((Integer)t).toString(), com.GetT(com.getCmd(ptr) + 3), com.GetP(com.getCmd(ptr) + 3));
                }
            } else if (com.GetP(com.getCmd(ptr)).contains("bxor")) {
                int t = FET(com.GetT(com.getCmd(ptr) + 1), com.GetP(com.getCmd(ptr) + 1))
                        ^ FET(com.GetT(com.getCmd(ptr) + 2), com.GetP(com.getCmd(ptr) + 2));
                if (com.getCmd(ptr + 1) - com.getCmd(ptr) == 4) {
                    cpu.Set("val", t);
                } else {
                    SET(1, ((Integer)t).toString(), com.GetT(com.getCmd(ptr) + 3), com.GetP(com.getCmd(ptr) + 3));
                }
            } else if (com.GetP(com.getCmd(ptr)).contains("lgr")) {
                int t = (FET(com.GetT(com.getCmd(ptr) + 1), com.GetP(com.getCmd(ptr) + 1))
                        > FET(com.GetT(com.getCmd(ptr) + 2), com.GetP(com.getCmd(ptr) + 2)))?1:0;
                if (com.getCmd(ptr + 1) - com.getCmd(ptr) == 4) {
                    cpu.Set("flag", t);
                } else {
                    SET(1, ((Integer)t).toString(), com.GetT(com.getCmd(ptr) + 3), com.GetP(com.getCmd(ptr) + 3));
                }
            } else if (com.GetP(com.getCmd(ptr)).contains("lls")) {
                int t = (FET(com.GetT(com.getCmd(ptr) + 1), com.GetP(com.getCmd(ptr) + 1))
                        < FET(com.GetT(com.getCmd(ptr) + 2), com.GetP(com.getCmd(ptr) + 2)))?1:0;
                if (com.getCmd(ptr + 1) - com.getCmd(ptr) == 4) {
                    cpu.Set("flag", t);
                } else {
                    SET(1, ((Integer)t).toString(), com.GetT(com.getCmd(ptr) + 3), com.GetP(com.getCmd(ptr) + 3));
                }
            } else if (com.GetP(com.getCmd(ptr)).contains("lge")) {
                int t = (FET(com.GetT(com.getCmd(ptr) + 1), com.GetP(com.getCmd(ptr) + 1))
                        >= FET(com.GetT(com.getCmd(ptr) + 2), com.GetP(com.getCmd(ptr) + 2)))?1:0;
                if (com.getCmd(ptr + 1) - com.getCmd(ptr) == 4) {
                    cpu.Set("flag", t);
                } else {
                    SET(1, ((Integer)t).toString(), com.GetT(com.getCmd(ptr) + 3), com.GetP(com.getCmd(ptr) + 3));
                }
            } else if (com.GetP(com.getCmd(ptr)).contains("lle")) {
                int t = (FET(com.GetT(com.getCmd(ptr) + 1), com.GetP(com.getCmd(ptr) + 1))
                        <= FET(com.GetT(com.getCmd(ptr) + 2), com.GetP(com.getCmd(ptr) + 2)))?1:0;
                if (com.getCmd(ptr + 1) - com.getCmd(ptr) == 4) {
                    cpu.Set("flag", t);
                } else {
                    SET(1, ((Integer)t).toString(), com.GetT(com.getCmd(ptr) + 3), com.GetP(com.getCmd(ptr) + 3));
                }
            } else if (com.GetP(com.getCmd(ptr)).contains("leql")) {
                int t = (FET(com.GetT(com.getCmd(ptr) + 1), com.GetP(com.getCmd(ptr) + 1))
                        == FET(com.GetT(com.getCmd(ptr) + 2), com.GetP(com.getCmd(ptr) + 2)))?1:0;
                if (com.getCmd(ptr + 1) - com.getCmd(ptr) == 4) {
                    cpu.Set("flag", t);
                } else {
                    SET(1, ((Integer)t).toString(), com.GetT(com.getCmd(ptr) + 3), com.GetP(com.getCmd(ptr) + 3));
                }
            } else if (com.GetP(com.getCmd(ptr)).contains("land")) {
                int t = (FET(com.GetT(com.getCmd(ptr) + 1), com.GetP(com.getCmd(ptr) + 1)) == 1
                        && FET(com.GetT(com.getCmd(ptr) + 2), com.GetP(com.getCmd(ptr) + 2)) == 1)?1:0;
                if (com.getCmd(ptr + 1) - com.getCmd(ptr) == 4) {
                    cpu.Set("flag", t);
                } else {
                    SET(1, ((Integer)t).toString(), com.GetT(com.getCmd(ptr) + 3), com.GetP(com.getCmd(ptr) + 3));
                }
            } else if (com.GetP(com.getCmd(ptr)).contains("lor")) {
                int t = (FET(com.GetT(com.getCmd(ptr) + 1), com.GetP(com.getCmd(ptr) + 1)) == 0
                        && FET(com.GetT(com.getCmd(ptr) + 2), com.GetP(com.getCmd(ptr) + 2)) == 0)?0:1;
                if (com.getCmd(ptr + 1) - com.getCmd(ptr) == 4) {
                    cpu.Set("flag", t);
                } else {
                    SET(1, ((Integer)t).toString(), com.GetT(com.getCmd(ptr) + 3), com.GetP(com.getCmd(ptr) + 3));
                }
            } else if (com.GetP(com.getCmd(ptr)).contains("rint")) {
                SET(1, in.getNext(), com.GetT(com.getCmd(ptr) + 1), com.GetP(com.getCmd(ptr) + 1));
            } else if (com.GetP(com.getCmd(ptr)).contains("rch")) {
                SET(-1, in.getNext(), com.GetT(com.getCmd(ptr) + 1), com.GetP(com.getCmd(ptr) + 1));
            } else if (com.GetP(com.getCmd(ptr)).contains("wint")) {
                if (com.getCmd(ptr + 1) - com.getCmd(ptr) == 2) {
                    out.add(((Integer) cpu.Get("val")).toString());
                } else {
                    out.add(((Integer) FET(com.GetT(com.getCmd(ptr) + 1), com.GetP(com.getCmd(ptr) + 1))).toString());
                }
            } else if (com.GetP(com.getCmd(ptr)).contains("wch")) {
                if (com.getCmd(ptr + 1) - com.getCmd(ptr) == 2) {
                    out.add("" + (char)cpu.Get("val"));
                } else {
                    out.add("" + (char)FET(com.GetT(com.getCmd(ptr) + 1), com.GetP(com.getCmd(ptr) + 1)));
                }
            }
            ptr++; // 除跳转语句外,行号指针默认+1
        }
    }
}

public class Main {
    public static void main(String[] args) {
        // 创建Scanner对象
        Scanner scanner = new Scanner(System.in);

        // 读入程序
        Stream code = new Stream();
        int totalLines = scanner.nextInt();
        scanner.nextLine();
        for (int i = 0; i < totalLines; i++) {
            code.add(scanner.nextLine());
        }

        // 读入输入并加载至输入流
        Stream input = new Stream();
        while (scanner.hasNextLine()) {
            input.add(scanner.nextLine());
        }
        IStream in = new IStream(input);

        // 编译,数据保证无编译错误
        Compiler compiler = new Compiler();
        compiler.Lexer(code);

        // 解释,数据保证无运行时错误
        Interpreter interpreter = new Interpreter();
        OStream out = new OStream();
        interpreter.loadup(totalLines, compiler);
        interpreter.run(compiler, in, out);

        // 输出
        out.output();
    }
}