diff --git a/pl0-complier-master/.gitignore b/pl0-complier-master/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..c9de4ef54a308c02dd2e93881597df4f154dd6ae
--- /dev/null
+++ b/pl0-complier-master/.gitignore
@@ -0,0 +1,7 @@
+.idea
+.settings
+bin
+out
+.classpath
+.project
+PL0.iml
\ No newline at end of file
diff --git a/pl0-complier-master/README.md b/pl0-complier-master/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..6be2f1586f70d3fe9132578f86e924efaba5a401
--- /dev/null
+++ b/pl0-complier-master/README.md
@@ -0,0 +1,15 @@
+# pl0-complier
+
+## 写在前面
+这是一个使用Java编写的简易的pl0语言编译器,所有的源代码均在src文件中。
+
+## 目录结构
+- code:pl0样例代码、pl0样例目标代码、pl0语言翻译规则
+- compiler:主程序、文件IO操作
+- error:编译错误类
+- execute:执行目标代码类
+- lexical:词法分析相关类
+- parsing:语法分析以及生成目标代码相关类
+
+## 运行相关
+注意,运行之前需要先确认Main类中源文件路径是否正确。
\ No newline at end of file
diff --git a/pl0-complier-master/pl0-complier-master.iml b/pl0-complier-master/pl0-complier-master.iml
new file mode 100644
index 0000000000000000000000000000000000000000..9465dd864f0bbf5233af344982a638534a50275d
--- /dev/null
+++ b/pl0-complier-master/pl0-complier-master.iml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pl0-complier-master/src/code/code.pl0code b/pl0-complier-master/src/code/code.pl0code
new file mode 100644
index 0000000000000000000000000000000000000000..be825c8d6466f654697212b0946fcd9ccd92bf41
--- /dev/null
+++ b/pl0-complier-master/src/code/code.pl0code
@@ -0,0 +1,20 @@
+JMP 0 10
+JMP 0 2
+INT 0 3
+LIT 0 1
+STO 0 3
+LIT 0 2
+STO 0 4
+LOD 0 3
+STO 0 5
+OPR 0 0
+INT 0 3
+LIT 0 20
+STO 0 3
+LIT 0 30
+STO 0 4
+LOD 0 3
+LOD 0 4
+STO 0 5
+CAL 0 2
+OPR 0 0
\ No newline at end of file
diff --git a/pl0-complier-master/src/code/demo.txt b/pl0-complier-master/src/code/demo.txt
new file mode 100644
index 0000000000000000000000000000000000000000..a78a107b41f9aba6f4a20ddc6f221f63ec6b97b3
--- /dev/null
+++ b/pl0-complier-master/src/code/demo.txt
@@ -0,0 +1,74 @@
+这是pl0语言中所有语句的翻译方式
+
+====================
+x := 20
+
+LIT 20
+STO level_x address_x
+====================
+
+
+====================
+z := x + y
+
+LOD level_x address_x
+LOD level_y address_y
+OPR +
+STO level_z address_z
+====================
+
+
+====================
+if x < 20 then
+begin
+z := x + y;
+end;
+
+LOD level_x address_x
+LIT 20
+OPR <
+JPC L1
+LOD level_x address_x
+LOD level_y address_y
+OPR +
+STO level_z address_z
+L1: ...
+====================
+
+
+====================
+while x < 20 do
+begin
+ x := x + y
+end;
+
+L1: LOD level_x address_x
+LIT 20
+OPR <
+JPC L2
+LOD level_x address_x
+LOD level_y address_y
+OPR +
+STO level_x address_x
+JMP L1
+L2: ....
+====================
+
+
+====================
+procedure test;
+begin
+ z := x + y;
+end;
+
+call test;
+
+JMP L1
+L2: JMP L3
+L3: LOD level_x address_x
+LOD level_y address_y
+OPR +
+STO level_z address_z
+OPR return
+L1: CAL L2
+====================
\ No newline at end of file
diff --git a/pl0-complier-master/src/code/test.pl0 b/pl0-complier-master/src/code/test.pl0
new file mode 100644
index 0000000000000000000000000000000000000000..efed470a3130d3ec74fe4f5c581773f2e3004bb1
--- /dev/null
+++ b/pl0-complier-master/src/code/test.pl0
@@ -0,0 +1,36 @@
+var x, y, z;
+
+procedure test;
+var a, b, c;
+begin
+ a := 5;
+ b := 7;
+ c := b * a;
+end;
+
+procedure divide;
+var d, e, f;
+begin
+ d := 20;
+ e := 5;
+ f := d / e;
+end;
+
+begin
+ x := 4;
+ y := 100;
+
+ if x < y then
+ begin
+ z := y / x;
+ y := x + y;
+ end;
+
+ while x < y do
+ begin
+ x := x + z;
+ end;
+
+ call test;
+ call divide;
+end.
\ No newline at end of file
diff --git a/pl0-complier-master/src/compiler/Main.java b/pl0-complier-master/src/compiler/Main.java
new file mode 100644
index 0000000000000000000000000000000000000000..25798d2cb70180335ca7bb9b1188f3489f8fab3f
--- /dev/null
+++ b/pl0-complier-master/src/compiler/Main.java
@@ -0,0 +1,72 @@
+package compiler;
+
+import execute.ExecuteCode;
+import lexical.LexicalAnalyzer;
+import lexical.Token;
+import parsing.Code;
+import parsing.Declaration;
+import parsing.DeclarationTableParser;
+import parsing.Parser;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+
+public class Main {
+ static String sourcePath = "/src/code/test.pl0"; // 测试代码地址
+ static String testPath = "/src/code/code.pl0code"; // 测试目标代码地址
+
+ public static void main(String[] args) throws IOException {
+ File directory = new File("");// 参数为空
+ String courseFile = directory.getCanonicalPath();
+ String sourceCodePath = courseFile + sourcePath;
+
+ System.out.println("\n==========源代码==========");
+ String sourceCode = SourceCodeFileReader.readFileContent(sourceCodePath, "\n");
+ System.out.println(sourceCode);
+
+ System.out.println("\n==========词法分析后的Token==========");
+ ArrayList wordsToken = LexicalAnalyzer.getsym(sourceCode);
+ for (int a = 0; a < wordsToken.size(); a++) {
+ System.out.println(a + " " + wordsToken.get(a).toString());
+ }
+
+ System.out.println("\n==========声明的引用table表==========");
+ ArrayList declarationList = DeclarationTableParser.parse(wordsToken, 0, 3);
+ for (Declaration declaration : declarationList) {
+ System.out.println(declaration.toString());
+ }
+
+ System.out.println("\n==========翻译成的中间代码==========");
+// ArrayList codeList = importTest(); // 使用测试中间代码
+ Parser.init(wordsToken, declarationList);
+ ArrayList codeList = Parser.getCode();
+ for (int a = 0; a < codeList.size(); a++) {
+ System.out.println(a + " " + codeList.get(a).toString());
+ }
+
+
+
+ System.out.println("\n==========执行代码==========");
+ ExecuteCode.execute(codeList);
+ }
+
+ /**
+ * 导入测试中间代码
+ * @return code list
+ */
+ public static ArrayList importTest() throws IOException {
+ File directory = new File("");// 参数为空
+ String courseFile = directory.getCanonicalPath();
+ String testCodePath = courseFile + testPath;
+ String testCode = SourceCodeFileReader.readFileContent(testCodePath, "\n");
+ String[] testCodeLine = testCode.split("\n");
+ ArrayList codeList = new ArrayList();
+ for (String code : testCodeLine) {
+ String[] detail = code.split(" ");
+ Code temp = new Code(detail[0], detail[1], detail[2]);
+ codeList.add(temp);
+ }
+ return codeList;
+ }
+}
diff --git a/pl0-complier-master/src/compiler/SourceCodeFileReader.java b/pl0-complier-master/src/compiler/SourceCodeFileReader.java
new file mode 100644
index 0000000000000000000000000000000000000000..d55ba58c52b623879cfd568f40b1eac1c69b5e1f
--- /dev/null
+++ b/pl0-complier-master/src/compiler/SourceCodeFileReader.java
@@ -0,0 +1,40 @@
+package compiler;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+
+class SourceCodeFileReader {
+ /**
+ * 读取源程序文件的方法,配合charAt,就成为了作业中的GETCH方法。
+ * @param fileName 源程序文件路径
+ * @param lineFeed 指定换行字符
+ * @return 返回读入的文件内容字符串
+ */
+ static String readFileContent(String fileName, String lineFeed) {
+ File file = new File(fileName);
+ BufferedReader reader = null;
+ StringBuffer fileStringBuffer = new StringBuffer();
+ try {
+ reader = new BufferedReader(new FileReader(file));
+ String tempStr;
+ while ((tempStr = reader.readLine()) != null) {
+ fileStringBuffer.append(tempStr + lineFeed);
+ }
+ reader.close();
+ return fileStringBuffer.toString();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (IOException e1) {
+ e1.printStackTrace();
+ }
+ }
+ }
+ return fileStringBuffer.toString();
+ }
+}
diff --git a/pl0-complier-master/src/error/PL0Error.java b/pl0-complier-master/src/error/PL0Error.java
new file mode 100644
index 0000000000000000000000000000000000000000..a04f10ab282de5ce5320b7783f6a4151e85dd5c6
--- /dev/null
+++ b/pl0-complier-master/src/error/PL0Error.java
@@ -0,0 +1,30 @@
+package error;
+
+public class PL0Error {
+ public static void log(int errorType) {
+ String[] error = new String[] {
+ "[0 undefined error]",
+ "[1 constant definition error] undefined const ident",
+ "[2 constant definition error] const syntax error",
+ "[3 constant definition error] undefined var ident",
+ "[4 constant definition error] var syntax error",
+ "[5 token error] unknown token",
+ "[6 procedure error] procedure layer more than 3",
+ "[7 procedure error] undefined procedure ident",
+ "[8 ident error] ident syntax error",
+ "[9 ident error] undefined ident",
+ "[10 ident parse error] assign ident error",
+ "[11 if parse error] if syntax error",
+ "[12 boolean parse error] boolean expression syntax error",
+ "[13 while parse error] while syntax error",
+ "[14 begin end parse error] missing . or ;",
+ "[15 call parse error] missing call ident",
+ "[16 call parse error] missing ;",
+ };
+ if (errorType < error.length) {
+ System.out.println(error[errorType]);
+ } else {
+ System.out.println(error[0]);
+ }
+ }
+}
diff --git a/pl0-complier-master/src/execute/ExecuteCode.java b/pl0-complier-master/src/execute/ExecuteCode.java
new file mode 100644
index 0000000000000000000000000000000000000000..e554a1d79927fef66188fbeb55f72af0f43705a0
--- /dev/null
+++ b/pl0-complier-master/src/execute/ExecuteCode.java
@@ -0,0 +1,163 @@
+package execute;
+
+import parsing.Code;
+
+import java.util.ArrayList;
+
+/**
+ * 执行生成的目标代码类
+ */
+public class ExecuteCode {
+ private static final int MAX = 1000;
+ private static int[] stack = new int[MAX]; // 执行栈
+ private static int top = 3; // 栈顶元素位置
+ private static int base = 1; // program, base, and top-stack register
+ private static int programCounter = 0; // 程序计数器
+
+
+ /**
+ * 执行中间代码
+ *
+ * @param codeList 中间代码列表
+ */
+ public static void execute(ArrayList codeList) {
+ stack[1] = 0;
+ stack[2] = 0;
+ stack[3] = 0;
+
+ do {
+ Code code = codeList.get(programCounter++);
+ int levelDifference = Integer.parseInt(code.getLevelDifference());
+ int addressOffset = Integer.parseInt(code.getAddressOffset());
+ switch (code.getFunction()) {
+ case "LIT":
+ stack[++top] = addressOffset;
+ break;
+ case "LOD":
+ stack[++top] = stack[calculateBase(base, levelDifference) + addressOffset];
+ break;
+ case "STO":
+ stack[calculateBase(base, levelDifference) + addressOffset] = stack[top];
+ System.out.println(stack[top]);
+ top--;
+ break;
+ case "CAL":
+ stack[top + 1] = calculateBase(base, levelDifference);
+ stack[top + 2] = base;
+ stack[top + 3] = programCounter;
+ base = top + 1;
+ programCounter = addressOffset;
+ break;
+ case "INT":
+ top += addressOffset;
+ break;
+ case "JMP":
+ programCounter = addressOffset;
+ break;
+ case "JPC":
+ if (stack[top] == 0) {
+ programCounter = addressOffset;
+ }
+ top--;
+ break;
+ case "OPR":
+ handleOperator(code);
+ break;
+ }
+ } while (programCounter > 0 && programCounter < codeList.size());
+ }
+
+ /**
+ * 计算偏移量
+ *
+ * @param currentLevel 当前层级
+ * @param levelDiff 层极差
+ * @return 正确的地址
+ */
+ private static int calculateBase(int currentLevel, int levelDiff) {
+ int address = currentLevel;
+ for (int a = levelDiff; a > 0; a--){
+ address = stack[address];
+ }
+ return address;
+ }
+
+ /**
+ * 处理operator的方法
+ * 0: return
+ * 1: 相反数
+ * 2: +
+ * 3: -
+ * 4: *
+ * 5: /
+ * 6: #
+ * 7: ==
+ * 8: <>
+ * 9: <
+ * 10: <=
+ * 11: >
+ * 12: >=
+ *
+ * @param code 中间代码
+ */
+ private static void handleOperator(Code code) {
+ int addressOffset = Integer.parseInt(code.getAddressOffset());
+ switch (addressOffset) // operator
+ {
+ case 0:
+ top = base - 1;
+ programCounter = stack[top + 3];
+ base = stack[top + 2];
+ break;
+ case 1:
+ stack[top] = -stack[top];
+ break;
+ case 2:
+ top--;
+ stack[top] += stack[top + 1];
+ break;
+ case 3:
+ top--;
+ stack[top] -= stack[top + 1];
+ break;
+ case 4:
+ top--;
+ stack[top] *= stack[top + 1];
+ break;
+ case 5:
+ top--;
+ if (stack[top + 1] == 0) {
+ System.out.println("Runtime Error: Divided by zero. Fix it as 1");
+ stack[top + 1] = 1;
+ stack[top] /= stack[top + 1];
+ } else {
+ stack[top] /= stack[top + 1];
+ }
+ break;
+ case 6:
+ stack[top] %= 2;
+ break;
+ case 7:
+ top--;
+ stack[top] = (stack[top] == stack[top + 1]) ? 1 : 0;
+ break;
+ case 8:
+ top--;
+ stack[top] = (stack[top] != stack[top + 1]) ? 1 : 0;
+ case 9:
+ top--;
+ stack[top] = (stack[top] < stack[top + 1]) ? 1 : 0;
+ break;
+ case 10:
+ top--;
+ stack[top] = (stack[top] <= stack[top + 1]) ? 1 : 0;
+ case 11:
+ top--;
+ stack[top] = (stack[top] > stack[top + 1]) ? 1 : 0;
+ break;
+ case 12:
+ top--;
+ stack[top] = (stack[top] >= stack[top + 1]) ? 1 : 0;
+ }
+ }
+}
diff --git a/pl0-complier-master/src/lexical/LexicalAnalyzer.java b/pl0-complier-master/src/lexical/LexicalAnalyzer.java
new file mode 100644
index 0000000000000000000000000000000000000000..d35cf4b4b99d314ce4608b691b935999edb154d4
--- /dev/null
+++ b/pl0-complier-master/src/lexical/LexicalAnalyzer.java
@@ -0,0 +1,163 @@
+package lexical;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/**
+ * 词法分析类
+ *
+ * @author ZY
+ */
+public class LexicalAnalyzer {
+ // 关键字
+ private static ArrayList keywords = new ArrayList(Arrays.asList("const", "var", "procedure",
+ "begin", "end", "if", "then", "call", "while", "do", "read", "write"));
+
+ // 运算符
+ private static ArrayList operator = new ArrayList(
+ Arrays.asList("=", "<>", "<", ">", "<=", ">=", ":=", "+", "-", "*", "/", "#"));
+
+ // 界符
+ private static ArrayList delimiters = new ArrayList(Arrays.asList(";", ".", ",", "(", ")"));
+
+ // 过滤掉所有的空格
+ private static String filterBlank(String str) {
+ return str.replace(" ", "").replace("\n", "").replace("\t", "");
+ }
+
+ /**
+ * 判断str中从第index位开始,是否能匹配到target中的某一项,若能,则返回该项,否则返回空,若匹配出多项,以最长的为准
+ *
+ * @param str 输入的字符串
+ * @param index 词法分析器扫描到哪一个字符
+ * @param target 关键字数组
+ * @return 返回匹配的字符
+ */
+ private static String matchList(String str, int index, ArrayList target) {
+ ArrayList outputList = new ArrayList();
+ for (int a = 0; a < target.size(); a++) {
+ int endIndex = index + target.get(a).length();
+ if (endIndex <= str.length()) {
+ String tempStr = str.substring(index, endIndex);
+ if (target.indexOf(tempStr) != -1) {
+ outputList.add(tempStr);
+ }
+ }
+ }
+
+ if (outputList.size() > 0) {
+ // 获取最长的字符
+ int maxLength = outputList.get(0).length();
+ int maxLengthIndex = 0;
+ for (int a = 0; a < outputList.size(); a++) {
+ if (outputList.get(a).length() > maxLength) {
+ maxLength = outputList.get(a).length();
+ maxLengthIndex = a;
+ }
+ }
+ return outputList.get(maxLengthIndex);
+ }
+ return "";
+ }
+
+ /**
+ * 匹配关键字
+ *
+ * @param str 关键字
+ * @param index 扫描到的位置
+ * @return 返回匹配的字符
+ */
+ private static String isKeywords(String str, int index) {
+ return matchList(str, index, keywords);
+ }
+
+ /**
+ * 匹配数字
+ *
+ * @param str 关键字
+ * @param index 扫描到的位置
+ * @return 返回匹配的字符
+ */
+ private static String isNumber(String str, int index) {
+ StringBuilder tempNum = new StringBuilder();
+ while (index < str.length() && Character.isDigit(str.charAt(index))) {
+ tempNum.append(str.charAt(index));
+ index++;
+ }
+ return tempNum.toString();
+ }
+
+ /**
+ * 匹配运算符
+ *
+ * @param str 关键字
+ * @param index 扫描到的位置
+ * @return 返回匹配的字符
+ */
+ private static String isOperator(String str, int index) {
+ return matchList(str, index, operator);
+ }
+
+ /**
+ * 匹配界符
+ *
+ * @param str 关键字
+ * @param index 扫描到的位置
+ * @return 返回匹配的字符
+ */
+ private static String isDelimiters(String str, int index) {
+ return matchList(str, index, delimiters);
+ }
+
+ /**
+ * 词法分析函数,也就是作业中要求的GETSYM函数
+ *
+ * @param input 输入的字符串
+ * @return 返回Token数组
+ */
+ public static ArrayList getsym(String input) {
+ String str = filterBlank(input);
+ ArrayList wordToken = new ArrayList();
+ int index = 0;
+ StringBuilder temp = new StringBuilder(); // 用于缓存ident字符
+ while (index < str.length()) {
+ String keywords = isKeywords(str, index);
+ String number = isNumber(str, index);
+ String operator = isOperator(str, index);
+ String delimiters = isDelimiters(str, index);
+ if (keywords.length() != 0) {
+ if (temp.length() != 0) {
+ wordToken.add(new Token("IDENT", temp.toString(), ""));
+ temp = new StringBuilder();
+ }
+ wordToken.add(new Token(keywords.toUpperCase() + "SYM", "", ""));
+ index += keywords.length();
+ } else if (number.length() != 0) {
+ if (temp.length() != 0) {
+ wordToken.add(new Token("IDENT", temp.toString(), ""));
+ temp = new StringBuilder();
+ }
+ wordToken.add(new Token("NUMBER", "", number));
+ index += number.length();
+ } else if (operator.length() != 0) {
+ if (temp.length() != 0) {
+ wordToken.add(new Token("IDENT", temp.toString(), ""));
+ temp = new StringBuilder();
+ }
+ wordToken.add(new Token("SYM_" + operator, "", ""));
+ index += operator.length();
+ } else if (delimiters.length() != 0) {
+ if (temp.length() != 0) {
+ wordToken.add(new Token("IDENT", temp.toString(), ""));
+ temp = new StringBuilder();
+ }
+ wordToken.add(new Token("SYM_" + delimiters, "", ""));
+ index += delimiters.length();
+ } else {
+ temp.append(str.charAt(index));
+ index++;
+ }
+ }
+ return wordToken;
+ }
+}
diff --git a/pl0-complier-master/src/lexical/Token.java b/pl0-complier-master/src/lexical/Token.java
new file mode 100644
index 0000000000000000000000000000000000000000..c2973f362559703c3e47446a2146c02393517eef
--- /dev/null
+++ b/pl0-complier-master/src/lexical/Token.java
@@ -0,0 +1,52 @@
+package lexical;
+
+/**
+ * 符号类,用于词法分析
+ *
+ * @author ZY
+ */
+public class Token {
+ private String sym = "";
+ private String id = "";
+ private String num = "";
+
+ public Token(String sym, String id, String num) {
+ super();
+ this.sym = sym;
+ this.id = id;
+ this.num = num;
+ }
+
+ public String getSym() {
+ return sym;
+ }
+
+ public void setSym(String sym) {
+ this.sym = sym;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getNum() {
+ return num;
+ }
+
+ public void setNum(String num) {
+ this.num = num;
+ }
+
+ @Override
+ public String toString() {
+ return "Token{" +
+ "sym='" + sym + '\'' +
+ ", id='" + id + '\'' +
+ ", num='" + num + '\'' +
+ '}';
+ }
+}
diff --git a/pl0-complier-master/src/parsing/Code.java b/pl0-complier-master/src/parsing/Code.java
new file mode 100644
index 0000000000000000000000000000000000000000..e93a44f15fa1675ce5eb3fa91222c0dfd4c0c0aa
--- /dev/null
+++ b/pl0-complier-master/src/parsing/Code.java
@@ -0,0 +1,42 @@
+package parsing;
+
+public class Code {
+ private String function;
+ private String levelDifference;
+ private String addressOffset;
+
+ public Code(String function, String levelDifference, String addressOffset) {
+ this.function = function;
+ this.levelDifference = levelDifference;
+ this.addressOffset = addressOffset;
+ }
+
+ public String getFunction() {
+ return function;
+ }
+
+ public void setFunction(String function) {
+ this.function = function;
+ }
+
+ public String getLevelDifference() {
+ return levelDifference;
+ }
+
+ public void setLevelDifference(String levelDifference) {
+ this.levelDifference = levelDifference;
+ }
+
+ public String getAddressOffset() {
+ return addressOffset;
+ }
+
+ public void setAddressOffset(String addressOffset) {
+ this.addressOffset = addressOffset;
+ }
+
+ @Override
+ public String toString() {
+ return "\t" + function + "\t\t" + levelDifference + "\t" + addressOffset;
+ }
+}
diff --git a/pl0-complier-master/src/parsing/Declaration.java b/pl0-complier-master/src/parsing/Declaration.java
new file mode 100644
index 0000000000000000000000000000000000000000..c2c48ff5b85c19a5d7a71a243c61e97fdacd7e0f
--- /dev/null
+++ b/pl0-complier-master/src/parsing/Declaration.java
@@ -0,0 +1,131 @@
+package parsing;
+
+/**
+ * 声明的元素类,用于记录程序中声明的不同种类的变量/常量/函数
+ * 用于语法分析
+ *
+ * @author ZY
+ */
+public class Declaration {
+ private String name = "";
+ private String kind = "";
+ private String val = "";
+ private String level = "";
+ private String adr = "";
+ private int start = -1;
+ private int end = -1;
+ private int codeStartIndex = -1;
+
+ public Declaration(String name, String kind, String val, String level, String adr, int start, int end) {
+ this.name = name;
+ this.kind = kind;
+ this.val = val;
+ this.level = level;
+ this.adr = adr;
+ this.start = start;
+ this.end = end;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getKind() {
+ return kind;
+ }
+
+ public void setKind(String kind) {
+ this.kind = kind;
+ }
+
+ public String getVal() {
+ return val;
+ }
+
+ public void setVal(String val) {
+ this.val = val;
+ }
+
+ public String getLevel() {
+ return level;
+ }
+
+ public void setLevel(String level) {
+ this.level = level;
+ }
+
+ public String getAdr() {
+ return adr;
+ }
+
+ public void setAdr(String adr) {
+ this.adr = adr;
+ }
+
+ public int getStart() {
+ return start;
+ }
+
+ public void setStart(int start) {
+ this.start = start;
+ }
+
+ public int getEnd() {
+ return end;
+ }
+
+ public void setEnd(int end) {
+ this.end = end;
+ }
+
+ public int getCodeStartIndex() {
+ return codeStartIndex;
+ }
+
+ public void setCodeStartIndex(int codeStartIndex) {
+ this.codeStartIndex = codeStartIndex;
+ }
+
+ @Override
+ public String toString() {
+ switch (kind) {
+ case "CONSTANT":
+ return "Declaration{" +
+ "name='" + name + '\'' +
+ ", kind='" + kind + '\'' +
+ ", val='" + val + '\'' +
+ '}';
+ case "VARIABLE":
+ return "Declaration{" +
+ "name='" + name + '\'' +
+ ", kind='" + kind + '\'' +
+ ", val='" + val + '\'' +
+ ", level='" + level + '\'' +
+ ", adr='" + adr + '\'' +
+ '}';
+ case "PROCEDURE":
+ return "Declaration{" +
+ "name='" + name + '\'' +
+ ", kind='" + kind + '\'' +
+ ", val='" + val + '\'' +
+ ", level='" + level + '\'' +
+ ", start=" + start +
+ ", end=" + end +
+ '}';
+ default:
+ return "Declaration{" +
+ "name='" + name + '\'' +
+ ", kind='" + kind + '\'' +
+ ", val='" + val + '\'' +
+ ", level='" + level + '\'' +
+ ", adr='" + adr + '\'' +
+ ", start=" + start +
+ ", end=" + end +
+ '}';
+ }
+ }
+}
diff --git a/pl0-complier-master/src/parsing/DeclarationTableParser.java b/pl0-complier-master/src/parsing/DeclarationTableParser.java
new file mode 100644
index 0000000000000000000000000000000000000000..722d222c34cabc510cb34739db205e73a81af20a
--- /dev/null
+++ b/pl0-complier-master/src/parsing/DeclarationTableParser.java
@@ -0,0 +1,165 @@
+package parsing;
+
+import lexical.Token;
+import error.PL0Error;
+
+import java.util.ArrayList;
+
+/**
+ * 生成声明变量表的类
+ * 声明变量表就是作业中的TABLE
+ *
+ * @author ZY
+ */
+public class DeclarationTableParser {
+ private static int tokenListIndex = 0; // 扫描token表用的指针
+ private static int initLevel = 0; // 初始深度,即为作业中的BLOCK
+ private static int initAdr = 3; // 初始地址,即为作业中的DX
+ private static int procedureCounter = 2; // 给procedure的index
+ private static ArrayList declarationList = new ArrayList(); // 生成的declaration list
+
+ /**
+ * 生成declaration list的方法
+ *
+ * @param tokenList token列表
+ * @param level 初始深度
+ * @param adr 初始地址
+ * @return declaration list
+ */
+ public static ArrayList parse(ArrayList tokenList, int level, int adr) {
+ initLevel = level;
+ initAdr = adr;
+ while (tokenListIndex < tokenList.size()) {
+ switch (tokenList.get(tokenListIndex).getSym()) {
+ case "CONSTSYM":
+ constantDefinitionParser(tokenList);
+ break;
+ case "VARSYM":
+ variableDefinitionParser(tokenList, initLevel, initAdr);
+ break;
+ case "PROCEDURESYM":
+ procedureDefinitionParser(tokenList, initLevel);
+ break;
+ }
+ tokenListIndex++;
+ }
+
+ return declarationList;
+ }
+
+ /**
+ * 对const进行语法翻译
+ *
+ * @param tokenList token列表
+ */
+ private static void constantDefinitionParser(ArrayList tokenList) {
+ while (tokenListIndex < tokenList.size() - 1) {
+ tokenListIndex++;
+ if (tokenList.get(tokenListIndex).getSym().equals("IDENT")) {
+ // 新建一个常量声明
+ String identName = tokenList.get(tokenListIndex).getId();
+ Declaration constDeclaration = new Declaration(identName, "CONSTANT", "", "", "", -1, -1);
+
+ // 检测是否对常量进行了赋值
+ checkAndAddDeclaration(tokenList, constDeclaration);
+
+ // 若读取到分号,则结束,若读取到逗号,则什么都不做,若读取到其他,则抛异常
+ if (tokenList.get(tokenListIndex).getSym().equals("SYM_;")) {
+ break;
+ } else if (!tokenList.get(tokenListIndex).getSym().equals("SYM_,")) {
+ PL0Error.log(2);
+ break;
+ }
+ } else {
+ PL0Error.log(1);
+ break;
+ }
+ }
+ }
+
+ /**
+ * 对var进行语法翻译
+ *
+ * @param tokenList token列表
+ */
+ private static void variableDefinitionParser(ArrayList tokenList, int level, int adr) {
+ while (tokenListIndex < tokenList.size() - 1) {
+ tokenListIndex++;
+ if (tokenList.get(tokenListIndex).getSym().equals("IDENT")) {
+ // 新建一个变量声明
+ String identName = tokenList.get(tokenListIndex).getId();
+ Declaration varDeclaration = new Declaration(identName, "VARIABLE", "", level + "", (adr++) + "", -1, -1);
+
+ // 检测是否对变量进行了赋值
+ checkAndAddDeclaration(tokenList, varDeclaration);
+
+ // 若读取到分号,则结束,若读取到逗号,则什么都不做,若读取到其他,则抛异常
+ if (tokenList.get(tokenListIndex).getSym().equals("SYM_;")) {
+ break;
+ } else if (!tokenList.get(tokenListIndex).getSym().equals("SYM_,")) {
+ PL0Error.log(4);
+ break;
+ }
+ } else {
+ PL0Error.log(3);
+ break;
+ }
+ }
+ }
+
+ /**
+ * 对procedure进行语法翻译
+ *
+ * @param tokenList token列表
+ */
+ private static void procedureDefinitionParser(ArrayList tokenList, int level) {
+ if (tokenListIndex < tokenList.size() - 1) {
+ tokenListIndex++;
+ if (tokenList.get(tokenListIndex).getSym().equals("IDENT")) {
+ String identName = tokenList.get(tokenListIndex).getId();
+ Declaration procedureDeclaration = new Declaration(identName, "PROCEDURE", "", level + "", "", tokenListIndex - 1, -1);
+ declarationList.add(procedureDeclaration);
+ tokenListIndex++;
+
+ label:
+ while (tokenListIndex < tokenList.size() - 1) {
+ // 如果在函数中还有var或者procedure,则递归继续执行
+ switch (tokenList.get(tokenListIndex).getSym()) {
+ case "VARSYM":
+ variableDefinitionParser(tokenList, level + 1, initAdr);
+ break;
+ case "PROCEDURESYM":
+ if (level < 3) {
+ procedureDefinitionParser(tokenList, level + 1);
+ } else {
+ PL0Error.log(6);
+ }
+ break;
+ case "ENDSYM":
+ procedureDeclaration.setEnd(tokenListIndex);
+ break label;
+ }
+ tokenListIndex++;
+ }
+ } else {
+ PL0Error.log(7);
+ }
+ }
+ }
+
+ /**
+ * 检查是否对某个变量/常量进行了赋值,即判断x := 20;
+ * @param tokenList token列表
+ * @param declaration 声明
+ */
+ private static void checkAndAddDeclaration(ArrayList tokenList, Declaration declaration) {
+ tokenListIndex++;
+ if (tokenList.get(tokenListIndex).getSym().equals("SYM_=") && tokenList.get(tokenListIndex + 1).getSym().equals("NUMBER")) {
+ declaration.setVal(tokenList.get(tokenListIndex + 1).getNum());
+ declarationList.add(declaration);
+ tokenListIndex += 2;
+ } else {
+ declarationList.add(declaration);
+ }
+ }
+}
diff --git a/pl0-complier-master/src/parsing/Parser.java b/pl0-complier-master/src/parsing/Parser.java
new file mode 100644
index 0000000000000000000000000000000000000000..a156e5cbccd3b20cbc9816b774ae871980076024
--- /dev/null
+++ b/pl0-complier-master/src/parsing/Parser.java
@@ -0,0 +1,400 @@
+package parsing;
+
+import error.PL0Error;
+import lexical.Token;
+
+import java.util.ArrayList;
+
+/**
+ * 语句分析类,生成目标代码
+ *
+ * @author ZY
+ */
+public class Parser {
+ private static int tokenListIndex = 0; // 扫描token表用的指针
+ private static ArrayList code = new ArrayList(); // 生成的output list,即为作业中的code数组
+ private static int filledId = -1; // 回填用的id
+
+ public static void init(ArrayList tokenList, ArrayList declarationList) {
+ gen("JMP", "0", "main");
+ for (Declaration declaration : declarationList) {
+ if (declaration.getKind().equals("PROCEDURE")) {
+ gen("JMP", "0", declaration.getName());
+ }
+ }
+ for (Declaration declaration : declarationList) {
+ if (declaration.getKind().equals("PROCEDURE")) {
+ declaration.setCodeStartIndex(code.size());
+ gen("INT", "0", "3");
+ parse(tokenList, declarationList, declaration.getStart(), declaration.getEnd());
+ gen("OPR", "0", "0");
+ }
+ }
+
+ filledCodeList("main", code.size() + ""); // 回填main函数指令
+ gen("INT", "0", "3");
+ parse(tokenList, declarationList, declarationList.get(declarationList.size() - 1).getEnd(), tokenList.size());
+ gen("OPR", "0", "0");
+
+ // 回填call中的所有函数地址
+ for (Declaration declaration : declarationList) {
+ if (declaration.getKind().equals("PROCEDURE")) {
+ filledCodeList(declaration.getName(), declaration.getCodeStartIndex() + "");
+ }
+ }
+ }
+
+ /**
+ * 对语句进行翻译,生成code list
+ * read和write暂时不进行处理(因为不知道怎么处理,demo中也并没有给出io相关的指令)
+ *
+ * @param tokenList token列表
+ */
+ private static void parse(ArrayList tokenList, ArrayList declarationList, int startIndex, int endIndex) {
+ while (tokenListIndex < endIndex) {
+ switch (tokenList.get(tokenListIndex).getSym()) {
+ case "IDENT":
+ identParser(tokenList, declarationList);
+ break;
+ case "BEGINSYM":
+ beginParser(tokenList, declarationList, startIndex);
+ break;
+ case "IFSYM":
+ ifParser(tokenList, declarationList, startIndex, endIndex);
+ break;
+ case "CALLSYM":
+ callParser(tokenList, declarationList);
+ break;
+ case "WHILESYM":
+ whileParser(tokenList, declarationList, startIndex, endIndex);
+ break;
+ }
+ tokenListIndex++;
+ }
+ }
+
+ /**
+ * 翻译ident,例如 x := x + y 或 x := 20
+ *
+ * @param tokenList token列表
+ * @param declarationList 声明table
+ */
+ private static void identParser(ArrayList tokenList, ArrayList declarationList) {
+ Token left = tokenList.get(tokenListIndex);
+ int leftIndex = getItemIndexInDeclarationList(left, declarationList);
+ if (left != null && leftIndex != -1) {
+ Token equals = getNext(tokenList);
+ if (equals != null && equals.getSym().equals("SYM_:=")) {
+ expressionParser(tokenList, declarationList, declarationList.get(leftIndex));
+ } else if (equals != null && !(equals.getSym().equals("SYM_,") || equals.getSym().equals("SYM_;"))) {
+ PL0Error.log(8);
+ }
+ } else {
+ PL0Error.log(9);
+ }
+ }
+
+ /**
+ * 处理赋值时 := 的右半部分,即处理表达式
+ * TODO:可简化代码
+ *
+ * @param tokenList token列表
+ * @param declarationList 变量声明表
+ * @param left := 的左半部分
+ */
+ private static void expressionParser(ArrayList tokenList, ArrayList declarationList, Declaration left) {
+ Token first = getNext(tokenList);
+ int firstIndex = getItemIndexInDeclarationList(first, declarationList);
+ if (first != null && firstIndex != -1 && first.getSym().equals("IDENT")) {
+ Token next = getNext(tokenList);
+ if (next != null && next.getSym().equals("SYM_+")) {
+ // 如 x := x + y;
+ generateOperatorCode(tokenList, declarationList, left, firstIndex, "2");
+ } else if (next != null && next.getSym().equals("SYM_-")) {
+ // 如 x := x - y
+ generateOperatorCode(tokenList, declarationList, left, firstIndex, "3");
+ } else if (next != null && next.getSym().equals("SYM_*")) {
+ // 如 x := x * y
+ generateOperatorCode(tokenList, declarationList, left, firstIndex, "4");
+ } else if (next != null && next.getSym().equals("SYM_/")) {
+ // 如 x := x / y
+ generateOperatorCode(tokenList, declarationList, left, firstIndex, "5");
+ } else if (next != null && next.getSym().equals("SYM_;")) {
+ // 如 x := y;
+ gen("LOD", declarationList.get(firstIndex).getLevel(), declarationList.get(firstIndex).getAdr());
+ gen("STO", left.getLevel(), left.getAdr());
+ } else {
+ PL0Error.log(10);
+ }
+ } else if (first != null && first.getSym().equals("NUMBER")) {
+ // 如 x := 20;
+ gen("LIT", "0", first.getNum());
+ gen("STO", left.getLevel(), left.getAdr());
+ } else {
+ PL0Error.log(9);
+ }
+ }
+
+ /**
+ * 翻译call
+ *
+ * @param tokenList token列表
+ * @param declarationList 声明列表
+ */
+ private static void callParser(ArrayList tokenList, ArrayList declarationList) {
+ Token ident = getNext(tokenList);
+ int identIndex = getItemIndexInDeclarationList(ident, declarationList);
+ if (ident != null && ident.getSym().equals("IDENT")) {
+ Token end = getNext(tokenList);
+ if (end != null && end.getSym().equals("SYM_;")) {
+ if (identIndex != -1) {
+ gen("CAL", declarationList.get(identIndex).getLevel(), declarationList.get(identIndex).getName());
+ }
+ } else {
+ PL0Error.log(16);
+ }
+ } else {
+ PL0Error.log(15);
+ }
+ }
+
+ private static void beginParser(ArrayList tokenList, ArrayList declarationList, int startIndex) {
+ int endIndex = findEnd(tokenList, tokenListIndex);
+ while (tokenListIndex < endIndex) {
+ Token next = getNext(tokenList);
+ if (next != null && next.getSym().equals("ENDSYM")) {
+ Token end = getNext(tokenList);
+ if (end != null && (end.getSym().equals("SYM_.") || end.getSym().equals("SYM_;"))) {
+ gen("OPR", "0", "0");
+ return;
+ } else {
+ PL0Error.log(14);
+ }
+ } else {
+ parse(tokenList, declarationList, startIndex, endIndex);
+ }
+ }
+ }
+
+ /**
+ * 翻译if
+ *
+ * @param tokenList token列表
+ * @param declarationList 声明列表
+ */
+ private static void ifParser(ArrayList tokenList, ArrayList declarationList, int startIndex, int endIndex) {
+ Token left = getNext(tokenList);
+ Token operator = getNext(tokenList);
+ Token right = getNext(tokenList);
+ Token then = getNext(tokenList);
+ if (left != null && operator != null && right != null && then != null && then.getSym().equals("THENSYM")) {
+ booleanParser(left, right, operator, declarationList);
+
+ Token next = getNext(tokenList);
+ if (next != null && next.getSym().equals("BEGINSYM")) {
+ int tempKey = --filledId;
+ gen("JPC", "0", tempKey + "");
+ beginParser(tokenList, declarationList, startIndex);
+ filledCodeList(tempKey + "", code.size() + "");
+ } else {
+ PL0Error.log(11);
+ }
+ } else {
+ PL0Error.log(11);
+ }
+ }
+
+ /**
+ * 翻译while
+ *
+ * @param tokenList token列表
+ * @param declarationList 声明列表
+ */
+ private static void whileParser(ArrayList tokenList, ArrayList declarationList, int startIndex, int endIndex) {
+ Token left = getNext(tokenList);
+ Token operator = getNext(tokenList);
+ Token right = getNext(tokenList);
+ Token doIdent = getNext(tokenList);
+ if (left != null && operator != null && right != null && doIdent != null && doIdent.getSym().equals("DOSYM")) {
+ int loopStartPosition = code.size();
+ booleanParser(left, right, operator, declarationList);
+
+ Token next = getNext(tokenList);
+ if (next != null && next.getSym().equals("BEGINSYM")) {
+ int tempKey = --filledId;
+ gen("JPC", "0", filledId + "");
+ beginParser(tokenList, declarationList, startIndex);
+ gen("JMP", "0", loopStartPosition + "");
+ filledCodeList(tempKey + "", code.size() + "");
+ } else {
+ PL0Error.log(13);
+ }
+ } else {
+ PL0Error.log(13);
+ }
+ }
+
+ /**
+ * 翻译布尔表达式,如 x < y
+ *
+ * @param left 左面的元素
+ * @param right 右面的元素
+ * @param operator 操作符
+ * @param declarationList 声明列表
+ */
+ private static void booleanParser(Token left, Token right, Token operator, ArrayList declarationList) {
+ booleanItemParser(left, declarationList);
+ booleanItemParser(right, declarationList);
+ switch (operator.getSym()) {
+ case "SYM_==":
+ gen("OPR", "0", "7");
+ break;
+ case "SYM_<>":
+ gen("OPR", "0", "8");
+ break;
+ case "SYM_<":
+ gen("OPR", "0", "9");
+ break;
+ case "SYM_<=":
+ gen("OPR", "0", "10");
+ break;
+ case "SYM_>":
+ gen("OPR", "0", "11");
+ break;
+ case "SYM_>=":
+ gen("OPR", "0", "12");
+ break;
+ }
+ }
+
+ /**
+ * 翻译布尔表达式中的某一项
+ *
+ * @param token 某一个token
+ * @param declarationList 声明列表
+ */
+ private static void booleanItemParser(Token token, ArrayList declarationList) {
+ if (token.getSym().equals("IDENT")) {
+ int index = getItemIndexInDeclarationList(token, declarationList);
+ if (index != -1) {
+ gen("LOD", declarationList.get(index).getLevel(), declarationList.get(index).getAdr());
+ } else {
+ PL0Error.log(9);
+ }
+ } else if (token.getSym().equals("NUMBER")) {
+ gen("LIT", "0", token.getNum());
+ } else {
+ PL0Error.log(12);
+ }
+ }
+
+ /**
+ * 根据操作符生成目标代码
+ *
+ * @param tokenList token列表
+ * @param declarationList 声明列表
+ * @param left 操作符左面的声明
+ * @param firstIndex :=左面的声明
+ * @param offset 操作符的偏移量
+ */
+ private static void generateOperatorCode(ArrayList tokenList, ArrayList declarationList, Declaration left, int firstIndex, String offset) {
+ Token second = getNext(tokenList);
+ int secondIndex = getItemIndexInDeclarationList(second, declarationList);
+ Token end = getNext(tokenList);
+ if (second != null && end != null && end.getSym().equals("SYM_;")) {
+ gen("LOD", declarationList.get(firstIndex).getLevel(), declarationList.get(firstIndex).getAdr());
+ gen("LOD", declarationList.get(secondIndex).getLevel(), declarationList.get(secondIndex).getAdr());
+ gen("OPR", "0", offset);
+ gen("STO", left.getLevel(), left.getAdr());
+ }
+ }
+
+ /**
+ * 回填数组
+ *
+ * @param key 占位数值
+ * @param value 回填的数值
+ */
+ private static void filledCodeList(String key, String value) {
+ for (Code item : code) {
+ if (item.getAddressOffset().equals(key)) {
+ item.setAddressOffset(value);
+ }
+ }
+ }
+
+ /**
+ * 获取下一个token
+ *
+ * @param tokenList token列表
+ * @return token
+ */
+ private static Token getNext(ArrayList tokenList) {
+ if (tokenListIndex < tokenList.size() - 1) {
+ tokenListIndex++;
+ return tokenList.get(tokenListIndex);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * 判断某个token是否已经在declaration list中声明
+ *
+ * @param token token
+ * @param declarationList 声明列表
+ * @return 如果有,返回index,若没有,返回-1
+ */
+ private static int getItemIndexInDeclarationList(Token token, ArrayList declarationList) {
+ for (int a = 0; a < declarationList.size(); a++) {
+ if (token.getId().equals(declarationList.get(a).getName())) {
+ return a;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * 将翻译好的功能码加入code数组中
+ *
+ * @param function 功能码
+ * @param levelDifference 层次差
+ * @param addressOffset 位移量
+ */
+ private static void gen(String function, String levelDifference, String addressOffset) {
+ if (levelDifference.equals("")) {
+ levelDifference = "0";
+ }
+ if (addressOffset.equals("")) {
+ addressOffset = "0";
+ }
+ Code addCode = new Code(function, levelDifference, addressOffset);
+ code.add(addCode);
+ }
+
+ /**
+ * 匹配与当前begin对应的end
+ *
+ * @param tokenArrayList token列表
+ * @param index begin的位置
+ * @return 对应的end的位置
+ */
+ private static int findEnd(ArrayList tokenArrayList, int index) {
+ int begin = 1;
+ for (int a = index + 1; a < tokenArrayList.size(); a++) {
+ if (tokenArrayList.get(a).getSym().equals("BEGINSYM")) {
+ begin++;
+ } else if (tokenArrayList.get(a).getSym().equals("ENDSYM")) {
+ begin--;
+ if (begin == 0) {
+ return a;
+ }
+ }
+ }
+ return 0;
+ }
+
+ public static ArrayList getCode() {
+ return code;
+ }
+}