【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 Streamclass 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();
    }
}