Auto commit

上级 5b0ce43e
.idea
.settings
bin
out
.classpath
.project
PL0.iml
\ No newline at end of file
# pl0-complier
## 写在前面
这是一个使用Java编写的简易的pl0语言编译器,所有的源代码均在src文件中。
## 目录结构
- code:pl0样例代码、pl0样例目标代码、pl0语言翻译规则
- compiler:主程序、文件IO操作
- error:编译错误类
- execute:执行目标代码类
- lexical:词法分析相关类
- parsing:语法分析以及生成目标代码相关类
## 运行相关
注意,运行之前需要先确认Main类中源文件路径是否正确。
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
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
这是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
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
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<Token> 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<Declaration> declarationList = DeclarationTableParser.parse(wordsToken, 0, 3);
for (Declaration declaration : declarationList) {
System.out.println(declaration.toString());
}
System.out.println("\n==========翻译成的中间代码==========");
// ArrayList<Code> codeList = importTest(); // 使用测试中间代码
Parser.init(wordsToken, declarationList);
ArrayList<Code> 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<Code> 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<Code> codeList = new ArrayList<Code>();
for (String code : testCodeLine) {
String[] detail = code.split(" ");
Code temp = new Code(detail[0], detail[1], detail[2]);
codeList.add(temp);
}
return codeList;
}
}
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();
}
}
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]);
}
}
}
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<Code> 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;
}
}
}
package lexical;
import java.util.ArrayList;
import java.util.Arrays;
/**
* 词法分析类
*
* @author ZY
*/
public class LexicalAnalyzer {
// 关键字
private static ArrayList<String> keywords = new ArrayList<String>(Arrays.asList("const", "var", "procedure",
"begin", "end", "if", "then", "call", "while", "do", "read", "write"));
// 运算符
private static ArrayList<String> operator = new ArrayList<String>(
Arrays.asList("=", "<>", "<", ">", "<=", ">=", ":=", "+", "-", "*", "/", "#"));
// 界符
private static ArrayList<String> delimiters = new ArrayList<String>(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<String> target) {
ArrayList<String> outputList = new ArrayList<String>();
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<Token> getsym(String input) {
String str = filterBlank(input);
ArrayList<Token> wordToken = new ArrayList<Token>();
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;
}
}
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 + '\'' +
'}';
}
}
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;
}
}
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 +
'}';
}
}
}
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<Declaration> declarationList = new ArrayList<Declaration>(); // 生成的declaration list
/**
* 生成declaration list的方法
*
* @param tokenList token列表
* @param level 初始深度
* @param adr 初始地址
* @return declaration list
*/
public static ArrayList<Declaration> parse(ArrayList<Token> 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<Token> 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<Token> 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<Token> 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<Token> 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);
}
}
}
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> code = new ArrayList<Code>(); // 生成的output list,即为作业中的code数组
private static int filledId = -1; // 回填用的id
public static void init(ArrayList<Token> tokenList, ArrayList<Declaration> 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<Token> tokenList, ArrayList<Declaration> 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<Token> tokenList, ArrayList<Declaration> 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<Token> tokenList, ArrayList<Declaration> 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<Token> tokenList, ArrayList<Declaration> 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<Token> tokenList, ArrayList<Declaration> 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<Token> tokenList, ArrayList<Declaration> 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<Token> tokenList, ArrayList<Declaration> 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<Declaration> 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<Declaration> 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<Token> tokenList, ArrayList<Declaration> 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<Token> 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<Declaration> 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<Token> 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<Code> getCode() {
return code;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册