实验思路
依然是在遍历抽象语法树的时候生成中间代码。
因为四元式形式和 x86 汇编形式相差较多,为了相对简便的进行目标代码生成,因此中间代码构造时选择与 x86 汇编相近的形式。并且尽量使用伪指令,减少对代码的翻译。
四元式定义
采用(operator,operand1,operand2,result)的基本形式。对于程序控制流的if 等语句,不使用断点和jmp。
声明并归置临时变量
在中间代码生成中使用的局部变量,必须在过程开始的时刻定义,因此需要在使用临时 变量时,将声明加入四元式中,并且在 visitor 遍历语法树时生成的局部变量放到当前临时变 量过程声明的下方,如下图所示。
对 ICPrinter 进行打印顺序的改写,对一个函数首先打印参数四元式 (param,NULL,NULL,NULL)和局部变量定义四元式(var,NULL,NULL,NULL)部分,让局部变量的定义紧跟函数声明,最终在中间代码生成这样的格式。
数组的值访问和下标访问
当数组在赋值语句右边时,需要知道ArrayAccess本身的值,但是如果在数组在左边,那么我们需要知道它的下标或者偏移量。
如代码中:A[i] = A[i + 1]
,对于右边我们想知道A[i + 1]是多少,但是左边我们想知道i是多少。
目标代码生成
由于四元式在经过重排顺序后已经是正确汇编控制流代码了,在目标代码生成中,只需将每行的四元式翻译成对应的汇编代码即可。
- 全局整形变量, 判断当前变量是否有初始值,如果下一个 Quat 的操作符 是’= ’,那么当前变量有初始值,否则没有初始化为 0。
有初值:(var,int,NULL,x) (=,1,NULL,x) -> x DWORD 1
无初值:(var,int,NULL,x) -> x DWORD 0 - 字符串变量,需要去掉在字符串中显式定义的’\n ’,然后在字符串末 尾添加 0ah 作为换行符,否则会在运行时错误的输出不能解析的\n 换行符。也 要注意对仅为换行符的字符串的替换,不定义空字符串。
有内容: (var,”string\n”,NULL,String1) ->
String1 db“stirng”,0ah,0
仅为换行符: (var,”\n”,NULL,String2) ->
String2 db 0ah,0 - 数组声明 首先计算数组限定长度,因为 int 占 4 个字节,因此算出数组长度后×4 获 得数组大小。
(array,int,[5, 5],A) -> A 100 DWORD DUP(0) - 函数声明 需要在函数入口处声明参数,再检索到 FUNC_BEGIN 的四元式后, 向下检索连续的 param 的四元式,那么这些就是当前过程的参数列表。
(FUNC_BEGIN,int,NULL,func)
(param,int,NULL,x)
-> func PROC x :DWORD - 局部变量定义,在相同的声明函数下,需要打上 local 标签,并且汇编代码 有不同的声明形式。
(var,int,NULL,x) -> local x :DWORD
(array,int,[5, 5],A) -> local A[100]:DWORD - 调用函数,先把当前参数栈内的所有参数取出,然后附加到 Invoke 伪指 令后面,通过 invoke 伪指令调用子过程。
(arg,NULL,NULL,23) (invoke,f,NULL,t1) -> invoke f,23 - 四则运算示例
- 控制流 所有控制流和逻辑表达式都使用伪指令解决,能省则省。
代码:
ExampleICprinter:
package bit.minisys.minicc.icgen;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import bit.minisys.minicc.parser.ast.*;
public class ExampleICPrinter {
private List<Quat> quats;
private HashSet<String> nameSpace;
public ExampleICPrinter(List<Quat> quats) {
this.quats = quats;
}
public void print(String filename) {
nameSpace = new HashSet<>();
StringBuilder sb = new StringBuilder();
for (int i = 0;i < quats.size();++i) {
Quat quat = quats.get(i);
String op = quat.getOp();
String res = astStr(quat.getRes());
String opnd1 = astStr(quat.getOpnd1());
String opnd2 = astStr(quat.getOpnd2());
if(op.equals("FUNC_BEGIN")) {
nameSpace.clear();
sb.append("("+op+","+ opnd1+","+opnd2 +"," + res+")\n");
//打印Var 和 param
for(int j = i + 1;j < quats.size();++j) {
Quat quat1 = quats.get(j);
String op1 = quat1.getOp();
String res1 = astStr(quat1.getRes());
String opnd11 = astStr(quat1.getOpnd1());
String opnd21 = astStr(quat1.getOpnd2());
if(op1.equals("var") && !nameSpace.contains(res1)) {
sb.append("(" + op1 + "," + opnd11 + "," + opnd21 + "," + res1 + ")\n");
nameSpace.add(res1);
} else if(op1.equals("param")) {
sb.append("(" + op1 + "," + opnd11 + "," + opnd21 + "," + res1 + ")\n");
}
if(op1.equals("FUNC_END")) {
break;
}
}
//打印非Var
for(int j = i + 1;j < quats.size();++j) {
Quat quat1 = quats.get(j);
String op1 = quat1.getOp();
String res1 = astStr(quat1.getRes());
String opnd11 = astStr(quat1.getOpnd1());
String opnd21 = astStr(quat1.getOpnd2());
if(!op1.equals("var") && !op1.equals("param")) {
sb.append("(" + op1 + "," + opnd11 + "," + opnd21 + "," + res1 + ")\n");
}
if(op1.equals("FUNC_END")) {
i = j;
break;
}
}
}
else sb.append("("+op+","+ opnd1+","+opnd2 +"," + res+")\n");
}
// write
try {
FileWriter fileWriter = new FileWriter(new File(filename));
fileWriter.write(sb.toString());
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private String astStr(ASTNode node) {
if (node == null) {
return "";
}else if (node instanceof ASTIdentifier) {
return ((ASTIdentifier)node).value;
}else if (node instanceof TemporaryValue) {
return ((TemporaryValue)node).name();
}else if (node instanceof DescribeNode){
return node.getType();
} else if (node instanceof ASTVariableDeclarator) {
return ((ASTVariableDeclarator) node).getName();
} else if (node instanceof ASTIntegerConstant) {
return ((ASTIntegerConstant)node).value.toString();
} else if (node instanceof ASTStringConstant) {
return ((ASTStringConstant)node).value;
} else {
return "";
}
}
}
ExampleIBuilder:
package bit.minisys.minicc.icgen;
import java.util.*;
import bit.minisys.minicc.parser.ast.*;
import bit.minisys.minicc.pp.internal.D;
import bit.minisys.minicc.pp.internal.I;
import bit.minisys.minicc.pp.internal.Q;
import bit.minisys.minicc.pp.internal.X;
import bit.minisys.minicc.semantic.XYSymbolTable;
import org.python.antlr.op.In;
public class ExampleICBuilder implements ASTVisitor{
private XYSymbolTable globalTable;
private XYSymbolTable localTable;
private String declarationType;
private String identifierOfArray;
private Map<ASTNode, ASTNode> map;
private List<Quat> quats;
private int tmpId,StringId;
private LinkedList <String> equalOps;
public ExampleICBuilder() {
globalTable = new XYSymbolTable();
map = new HashMap<ASTNode, ASTNode>();
localTable = globalTable;
quats = new LinkedList<>();
tmpId = 0;
StringId = 0;
equalOps = new LinkedList<>();
equalOps.add("+="); equalOps.add("-="); equalOps.add("#="); equalOps.add("/=");
equalOps.add("%="); equalOps.add("&="); equalOps.add("|="); equalOps.add(">>=");
equalOps.add("<<=");
}
public List<Quat> getQuats() {
return quats;
}
private String getType(List<ASTToken> specifiers) {
StringBuilder type = new StringBuilder();
if( specifiers != null ){
for (ASTToken specifier : specifiers) {
type.append(specifier.value);
}
}
return type.toString();
}
//第一步进入CU
@Override
public void visit(ASTCompilationUnit program) throws Exception {
program.scope = localTable;
for (ASTNode node : program.items) {
if(node instanceof ASTFunctionDefine) {
visit((ASTFunctionDefine) node);
}else if(node instanceof ASTDeclaration) {
visit((ASTDeclaration)node);
}
}
}
//一个声明语句 (array, int , x , [3,2])
@Override
public void visit(ASTDeclaration declaration) throws Exception {
// TODO Auto-generated method stub
declaration.scope = this.localTable;
//传递声明语句类型
declarationType = declaration.specifiers.get(0).value;
for (ASTInitList node : declaration.initLists) {
if (node.declarator instanceof ASTArrayDeclarator) {
visit((ASTArrayDeclarator) node.declarator);
} else {
//里面定义变量
visit((ASTVariableDeclarator) node.declarator);
if (!node.exprs.isEmpty()) {
String op = "=";
//存到对应的declarator里 所以要对应起来
ASTNode res = node.declarator;
ASTNode operand_1 = null;
ASTNode operand_2 = null;
ASTExpression expr = node.exprs.get(0);
//only op
if (expr instanceof ASTIdentifier || expr instanceof ASTFloatConstant || expr instanceof ASTIntegerConstant
|| expr instanceof ASTCharConstant || expr instanceof ASTStringConstant) {
operand_1 = expr;
} else if (expr instanceof ASTUnaryExpression || expr instanceof ASTPostfixExpression
|| expr instanceof ASTFunctionCall || expr instanceof ASTArrayAccess) {
visit(expr);
operand_1 = map.get(expr);
} else if (expr instanceof ASTBinaryExpression) {
ASTBinaryExpression value = (ASTBinaryExpression) expr;
op = value.op.value;
visit(value.expr1);
operand_1 = map.get(value.expr1);
visit(value.expr2);
operand_2 = map.get(value.expr2);
}
Quat quat = new Quat(op,res, operand_1, operand_2);
quats.add(quat);
map.put(node, res);
}
}
}
}
@Override
public void visit(ASTArrayDeclarator arrayDeclarator) throws Exception {
arrayDeclarator.scope = localTable;
LinkedList bounds = new LinkedList();
ASTDeclarator declarator = arrayDeclarator.declarator;
ASTExpression expr = arrayDeclarator.expr;
while(true) {
int bound = ((ASTIntegerConstant)expr).value;
bounds.addFirst(bound);
if(declarator instanceof ASTArrayDeclarator) {
expr = ((ASTArrayDeclarator)declarator).expr;
declarator = ((ASTArrayDeclarator)declarator).declarator;
}else {
//到了声明数组名字的地方
break;
}
}
//通过identifier 找名字
String name = declarator.getName();
localTable.addArray(name,declarationType,bounds);
Quat quat0 = new Quat("array",new DescribeNode(name),new DescribeNode(declarationType),new DescribeNode(bounds.toString()));
quats.add(quat0);
}
@Override
public void visit(ASTVariableDeclarator variableDeclarator) throws Exception {
variableDeclarator.scope = localTable;
String name = variableDeclarator.getName();
localTable.addVar(name, variableDeclarator.getType());
Quat quat0 = new Quat("var",new DescribeNode(name),
new DescribeNode(declarationType),null);
quats.add(quat0);
}
@Override
public void visit(ASTFunctionDeclarator functionDeclarator) throws Exception {
}
@Override
public void visit(ASTParamsDeclarator paramsDeclarator) throws Exception {
}
// (=[], res, arrayName,offset)
public void visit(ASTArrayAccess arrayAccess) throws Exception {
arrayAccess.scope = localTable;
String name,type;
LinkedList arrayIndex = new LinkedList<ASTNode>();
ASTExpression expr = arrayAccess.arrayName;
ASTExpression index0 = arrayAccess.elements.get(0);
while(true) {
//表达式的话 需要计算一步
visit(index0);
ASTNode res = map.get(index0);
arrayIndex.addFirst(res);
//还有维数沒有遍历完
if(expr instanceof ASTArrayAccess) {
index0 = ((ASTArrayAccess)expr).elements.get(0);
expr = ((ASTArrayAccess)expr).arrayName;
} else {
name = ((ASTIdentifier)expr).value;
break;
}
}
LinkedList bounds = localTable.arrBounds(name);
ASTNode t1 = new TemporaryValue(++tmpId);
quats.add(new Quat("var",t1,new DescribeNode("int"),null));
//一维数组直接link到index上就可
if(bounds.size() == 1) {
Quat quat0 = new Quat("=[]",t1,new DescribeNode(name),(ASTNode)arrayIndex.get(0));
quats.add(quat0);
} else {
ASTNode t2 = new TemporaryValue(++tmpId);
quats.add(new Quat("var",t2,new DescribeNode("int"),null));
ASTNode t3 = new TemporaryValue(++tmpId);
quats.add(new Quat("var",t3,new DescribeNode("int"),null));
Quat quat0 = new Quat("*",t2,(ASTNode)arrayIndex.get(0),new DescribeNode(bounds.get(0).toString()));
Quat quat1 = new Quat("+",t3,t2,(ASTNode)arrayIndex.get(1));
Quat quat2 = new Quat("=[]",t1,new DescribeNode(name),t3);
quats.add(quat0);
quats.add(quat1);
quats.add(quat2);
}
map.put(arrayAccess,t1);
type = localTable.varType(name);
name = ((TemporaryValue)t1).name();
arrayAccess.scope.addVar(name,type);
}
public ASTNode visitOffset(ASTArrayAccess arrayAccess) throws Exception {
arrayAccess.scope = localTable;
LinkedList arrayIndex = new LinkedList<ASTNode>();
ASTExpression expr = arrayAccess.arrayName;
ASTExpression index0 = arrayAccess.elements.get(0);
while(true) {
visit(index0);
ASTNode res = map.get(index0);
arrayIndex.addFirst(res);
System.err.println("visit offset " + res.getType());
//还有维数沒有遍历完
if(expr instanceof ASTArrayAccess) {
index0 = ((ASTArrayAccess)expr).elements.get(0);
expr = ((ASTArrayAccess)expr).arrayName;
}else {
identifierOfArray = ((ASTIdentifier)expr).value;
break;
}
}
LinkedList bounds = localTable.arrBounds(identifierOfArray);
ASTNode t1 = new TemporaryValue(++tmpId);
quats.add(new Quat("var",t1,new DescribeNode("int"),null));
//一维数组直接link到index上就可
if(bounds.size() == 1) {
Quat quat0 = new Quat("=",t1,(ASTNode)arrayIndex.get(0),null);
quats.add(quat0);
} else {
ASTNode t2 = new TemporaryValue(++tmpId);
quats.add(new Quat("var",t2,new DescribeNode("int"),null));
ASTNode t3 = new TemporaryValue(++tmpId);
quats.add(new Quat("var",t3,new DescribeNode("int"),null));
Quat quat0 = new Quat("*",t2,(ASTNode)arrayIndex.get(0),new DescribeNode(bounds.get(0).toString()));
Quat quat1 = new Quat("+",t3,t2,(ASTNode)arrayIndex.get(1));
Quat quat2 = new Quat("=",t1,t3,null);
quats.add(quat0);
quats.add(quat1);
quats.add(quat2);
}
return t1;
}
@Override
public void visit(ASTBinaryExpression binaryExpression) throws Exception {
String op = binaryExpression.op.value;
ASTNode res = null;
ASTNode opnd1 = null;
ASTNode opnd2 = null;
if (op.equals("=")) {
// 赋值操作
// 获取被赋值的对象res
if(!(binaryExpression.expr1 instanceof ASTArrayAccess)) {
visit(binaryExpression.expr1);
res = map.get(binaryExpression.expr1);
}
// 判断源操作数类型, 为了避免出现a = b + c; 生成两个四元式:tmp1 = b + c; a = tmp1;的情况。也可以用别的方法解决
if (binaryExpression.expr2 instanceof ASTIdentifier) {
opnd1 = binaryExpression.expr2;
}else if(binaryExpression.expr2 instanceof ASTIntegerConstant) {
opnd1 = binaryExpression.expr2;
}else if(binaryExpression.expr2 instanceof ASTFloatConstant) {
opnd1 = binaryExpression.expr2;
}else if(binaryExpression.expr2 instanceof ASTCharConstant) {
opnd1 = binaryExpression.expr2;
}else if(binaryExpression.expr2 instanceof ASTStringConstant) {
opnd1 = binaryExpression.expr2;
}else if(binaryExpression.expr2 instanceof ASTBinaryExpression) {
ASTBinaryExpression value = (ASTBinaryExpression)binaryExpression.expr2;
op = value.op.value;
visit(value.expr1);
opnd1 = map.get(value.expr1);
visit(value.expr2);
opnd2 = map.get(value.expr2);
}else if(binaryExpression.expr2 instanceof ASTArrayAccess) {
visit((ASTArrayAccess)binaryExpression.expr2);
opnd1 = map.get(binaryExpression.expr2);
}else if(binaryExpression.expr2 instanceof ASTUnaryExpression) {
visit(binaryExpression.expr2);
opnd1 = map.get(binaryExpression.expr2);
}else if(binaryExpression.expr2 instanceof ASTPostfixExpression) {
visit(binaryExpression.expr2);
opnd1 = map.get(binaryExpression.expr2);
}else if(binaryExpression.expr2 instanceof ASTFunctionCall) {
visit(binaryExpression.expr2);
opnd1 = map.get(binaryExpression.expr2);
}
}else if (equalOps.contains(op)) {
op = op.substring(0, 1);
visit(binaryExpression.expr1);
res = map.get(binaryExpression.expr1);
opnd1 = res;
visit(binaryExpression.expr2);
opnd2 = map.get(binaryExpression.expr2);
}
else if (op.equals("+") || op.equals("-") || op.equals("*") || op.equals("/") ||
op.equals("%") || op.equals("<<")|| op.equals(">>")|| op.equals("<") ||
op.equals(">") || op.equals(">=")|| op.equals("<=")|| op.equals("==")||
op.equals("!=")|| op.equals("&&")|| op.equals("||")) {
// 加法操作,结果存储到中间变量
res = new TemporaryValue(++tmpId);
quats.add(new Quat("var",res,new DescribeNode("int"),null));
visit(binaryExpression.expr1);
opnd1 = map.get(binaryExpression.expr1);
visit(binaryExpression.expr2);
opnd2 = map.get(binaryExpression.expr2);
String name = ((TemporaryValue)res).name();
String type = null;
if(opnd1 instanceof ASTFloatConstant|| opnd2 instanceof ASTFloatConstant) {
type = "float";
}else if(opnd1 instanceof ASTIdentifier) {
type = "int";
}
localTable.addVar(name,type);
}else {
System.err.println("undefine");
// else..
}
// get 偏移量即可 ([]=,offset,value,arrayName)
// debug op != binary.op
if(binaryExpression.expr1 instanceof ASTArrayAccess && binaryExpression.op.value.equals("=")) {
if(opnd2 != null) {
TemporaryValue tmpRes = new TemporaryValue(++tmpId);
quats.add(new Quat("var",tmpRes,null,null));
Quat quat = new Quat(op, tmpRes, opnd1, opnd2);
quats.add(quat);
map.put(tmpRes, res);
res = visitOffset((ASTArrayAccess) binaryExpression.expr1);
Quat quat1 = new Quat("[]=",res,tmpRes,new DescribeNode(identifierOfArray));
quats.add(quat1);
map.put(binaryExpression, res);
}
else {
res = visitOffset((ASTArrayAccess) binaryExpression.expr1);
Quat quat = new Quat("[]=",res,opnd1,new DescribeNode(identifierOfArray));
quats.add(quat);
map.put(binaryExpression, res);
}
} else {
Quat quat = new Quat(op, res, opnd1, opnd2);
quats.add(quat);
map.put(binaryExpression, res);
}
}
@Override
public void visit(ASTBreakStatement breakStat) throws Exception {
Quat quat = new Quat(".break",null, null, null);
quats.add(quat);
}
@Override
public void visit(ASTContinueStatement continueStatement) throws Exception {
}
@Override
public void visit(ASTCastExpression castExpression) throws Exception {
this.visit(castExpression.expr);
}
@Override
public void visit(ASTCharConstant charConst) throws Exception {
map.put(charConst, charConst);
}
@Override
public void visit(ASTCompoundStatement compoundStat) throws Exception {
compoundStat.scope = new XYSymbolTable();
compoundStat.scope.father = localTable;
localTable = compoundStat.scope;
for (ASTNode node : compoundStat.blockItems) {
if(node instanceof ASTDeclaration) {
visit((ASTDeclaration)node);
}else if (node instanceof ASTStatement) {
visit((ASTStatement)node);
}
}
localTable = compoundStat.scope.father;
}
@Override
public void visit(ASTConditionExpression conditionExpression) throws Exception {
}
@Override
public void visit(ASTExpression expression) throws Exception {
if(expression instanceof ASTArrayAccess) {
visit((ASTArrayAccess)expression);
}else if(expression instanceof ASTBinaryExpression) {
visit((ASTBinaryExpression)expression);
}else if(expression instanceof ASTCastExpression) {
visit((ASTCastExpression)expression);
}else if(expression instanceof ASTCharConstant) {
visit((ASTCharConstant)expression);
}else if(expression instanceof ASTConditionExpression) {
visit((ASTConditionExpression)expression);
}else if(expression instanceof ASTFloatConstant) {
visit((ASTFloatConstant)expression);
}else if(expression instanceof ASTFunctionCall) {
visit((ASTFunctionCall)expression);
}else if(expression instanceof ASTIdentifier) {
visit((ASTIdentifier)expression);
}else if(expression instanceof ASTIntegerConstant) {
visit((ASTIntegerConstant)expression);
}else if(expression instanceof ASTMemberAccess) {
visit((ASTMemberAccess)expression);
}else if(expression instanceof ASTPostfixExpression) {
visit((ASTPostfixExpression)expression);
}else if(expression instanceof ASTStringConstant) {
visit((ASTStringConstant)expression);
}else if(expression instanceof ASTUnaryExpression) {
visit((ASTUnaryExpression)expression);
}else if(expression instanceof ASTUnaryTypename){
visit((ASTUnaryTypename)expression);
}
}
@Override
public void visit(ASTExpressionStatement expressionStat) throws Exception {
if( expressionStat.exprs != null ){
for (ASTExpression node : expressionStat.exprs) {
visit(node);
}
}
}
@Override
public void visit(ASTFloatConstant floatConst) throws Exception {
map.put(floatConst, floatConst);
}
@Override
public void visit(ASTFunctionCall funcCall) throws Exception {
funcCall.scope = localTable;
// TODO Auto-generated method stub
String funcname = ((ASTIdentifier)funcCall.funcname).value;
if(funcname.equals("Mars_PrintInt")) {
for(ASTExpression expr : funcCall.argList) {
visit(expr);
ASTNode arg = map.get(expr);
Quat quat = new Quat("arg",arg,null,null);
quats.add(quat);
}
Quat quat = new Quat("invoke",null,funcCall.funcname,null);
quats.add(quat);
return;
} else if(funcname.equals("Mars_PrintStr")) {
for(ASTExpression expr : funcCall.argList) {
visit(expr);
ASTNode arg = map.get(expr);
Quat quat = new Quat("var",new DescribeNode("String" + String.valueOf(++StringId)),arg,null);
quats.add(0,quat);
}
Quat quat = new Quat("invoke",null,funcCall.funcname,new DescribeNode("String" + String.valueOf(StringId)));
quats.add(quat);
return;
} else if(funcname.equals("Mars_GetInt")) {
ASTNode tmp = new TemporaryValue(++tmpId);
quats.add(new Quat("var",tmp,new DescribeNode("int"),null));
String name = ((TemporaryValue)tmp).name();
String type = "int";
localTable.addVar(name,type);
Quat quat = new Quat("invoke",tmp,funcCall.funcname,null);
quats.add(quat);
map.put(funcCall,tmp);
return;
}
for(ASTExpression expr : funcCall.argList) {
visit(expr);
ASTNode arg = map.get(expr);
Quat quat = new Quat("arg",arg,null,null);
quats.add(quat);
}
if(localTable.funcType(funcname) != null && localTable.funcType(funcname).equals("void")) {
Quat quat = new Quat("invoke",null,funcCall.funcname,null);
quats.add(quat);
return;
} else{
ASTNode tmp = new TemporaryValue(++tmpId);
quats.add(new Quat("var",tmp,new DescribeNode("int"),null));
String name = ((TemporaryValue)tmp).name();
String type = localTable.funcType(funcname);
localTable.addVar(name,type);
Quat quat = new Quat("invoke",tmp,funcCall.funcname,null);
quats.add(quat);
map.put(funcCall,tmp);
}
}
@Override
public void visit(ASTGotoStatement gotoStat) throws Exception {
String op = "jmp";
ASTNode res = gotoStat.label;
Quat quat = new Quat(op,res, null, null);
quats.add(quat);
}
@Override
public void visit(ASTIdentifier identifier) throws Exception {
map.put(identifier, identifier);
}
@Override
public void visit(ASTInitList initList) throws Exception {
}
@Override
public void visit(ASTIntegerConstant intConst) throws Exception {
map.put(intConst, intConst);
}
@Override
public void visit(ASTIterationDeclaredStatement iterationDeclaredStat) throws Exception {
// TODO Auto-generated method stub
if(iterationDeclaredStat == null) return;
//先定义循环域
iterationDeclaredStat.scope = new XYSymbolTable();
iterationDeclaredStat.scope.father = localTable;
localTable = iterationDeclaredStat.scope;
//访问准备
if(iterationDeclaredStat.init != null)
visit((ASTDeclaration)iterationDeclaredStat.init);
//循环前条件计算
if(iterationDeclaredStat.cond !=null) {
for(ASTExpression expr : iterationDeclaredStat.cond) {
this.visit(expr);
}
}
ASTNode res = map.get(iterationDeclaredStat.cond.get(0));
//进入循环
quats.add(new Quat(".while",null,res,null));
this.visit(iterationDeclaredStat.stat);
if(iterationDeclaredStat.step !=null) {
for(ASTExpression expr : iterationDeclaredStat.step) {
this.visit(expr);
}
}
if(iterationDeclaredStat.cond !=null) {
for(ASTExpression expr : iterationDeclaredStat.cond) {
this.visit(expr);
}
}
quats.add(new Quat("=",res,map.get(iterationDeclaredStat.cond.get(0)),null));
quats.add(new Quat(".endw",null,null,null));
localTable = iterationDeclaredStat.scope;
}
@Override
public void visit(ASTIterationStatement iterationStat) throws Exception {
// TODO Auto-generated method stub
if(iterationStat == null) return;
//先定义循环域
iterationStat.scope = new XYSymbolTable();
iterationStat.scope.father = localTable;
localTable = iterationStat.scope;
//访问准备
if(iterationStat.init !=null) {
for(ASTExpression expr : iterationStat.init) {
this.visit(expr);
}
}
//循环前条件计算
if(iterationStat.cond !=null) {
for(ASTExpression expr : iterationStat.cond) {
this.visit(expr);
}
}
ASTNode res = map.get(iterationStat.cond.get(0));
//进入循环
quats.add(new Quat(".while",null,res,null));
this.visit(iterationStat.stat);
if(iterationStat.step !=null) {
for(ASTExpression expr : iterationStat.step) {
this.visit(expr);
}
}
if(iterationStat.cond !=null) {
for(ASTExpression expr : iterationStat.cond) {
this.visit(expr);
}
}
quats.add(new Quat("=",res,map.get(iterationStat.cond.get(0)),null));
quats.add(new Quat(".endw",null,null,null));
localTable= iterationStat.scope;
}
@Override
public void visit(ASTLabeledStatement labeledStat) throws Exception {
String op = "label";
ASTNode res = labeledStat.label;
Quat quat = new Quat(op,res, null, null);
quats.add(quat);
visit(labeledStat.stat);
}
@Override
public void visit(ASTMemberAccess memberAccess) throws Exception {
}
private String PostfixType(String type, String op){
if(op.equals("++") || op.equals("--")) return type;
return "int";
}
@Override
public void visit(ASTPostfixExpression postfixExpression) throws Exception {
postfixExpression.scope = localTable;
// TODO Auto-generated method stub
String op = postfixExpression.op.value;
ASTNode res = null;
ASTNode tmp = new TemporaryValue(++tmpId);
quats.add(new Quat("var",tmp,new DescribeNode("int"),null));
String name = ((TemporaryValue)tmp).name();
String type = "int";
localTable.addVar(name,type);
Quat quat1 = new Quat("=", tmp, postfixExpression.expr, null);
quats.add(quat1);
Quat quat2 = new Quat(op, postfixExpression.expr, null, null);
quats.add(quat2);
res = tmp;
map.put(postfixExpression, res);
}
@Override
public void visit(ASTReturnStatement returnStat) throws Exception {
String op = "return";
ASTNode opnd1 = null;
if( returnStat.expr != null ){
for(ASTExpression exp : returnStat.expr){
visit(exp);
}
opnd1 = map.get(returnStat.expr.getLast());
}
Quat quat = new Quat(op, null, opnd1, null);
quats.add(quat);
}
@Override
public void visit(ASTSelectionStatement selectionStat) throws Exception {
String op;
ASTNode opnd1 = null;
Quat quat;
if(selectionStat.cond != null ){
for(ASTExpression expr : selectionStat.cond){
visit(expr);
}
opnd1 = map.get(selectionStat.cond.getLast());
}
op = ".IF";
quat = new Quat(op,opnd1,null,null);
quats.add(quat);
visit(selectionStat.then);
if(selectionStat.otherwise != null ){
op = ".ELSE";
quat = new Quat(op,null,null,null);
quats.add(quat);
visit(selectionStat.otherwise);
}
quats.add(new Quat(".ENDIF",null,null,null));
}
@Override
public void visit(ASTStringConstant stringConst) throws Exception {
map.put(stringConst, stringConst);
}
@Override
public void visit(ASTTypename typename) throws Exception {
}
private String UnaryType(String type){
return type;
}
@Override
public void visit(ASTUnaryExpression unaryExpression) throws Exception {
// TODO Auto-generated method stub
String op = unaryExpression.op.value;
ASTNode res = null;
if(op.equals("++") ||
op.equals("--")) {
visit(unaryExpression.expr);
res = map.get(unaryExpression.expr);
if(unaryExpression.expr instanceof ASTIdentifier) {
Quat quat = new Quat(op, res, null, null);
quats.add(quat);
map.put(unaryExpression, res);
}
}else {
res = new TemporaryValue(++tmpId);
quats.add(new Quat("var",res,new DescribeNode("int"),null));
String name = ((TemporaryValue)res).name();
String type = "int";
localTable.addVar(name,type);
visit(unaryExpression.expr);
ASTNode expr = map.get(unaryExpression.expr);
Quat quat = new Quat(op, res, expr,null);
quats.add(quat);
map.put(unaryExpression, res);
}
}
@Override
public void visit(ASTUnaryTypename unaryTypename) throws Exception {
}
@Override
public void visit(ASTFunctionDefine functionDefine) throws Exception {
functionDefine.scope = new XYSymbolTable();
functionDefine.scope.father = localTable;
localTable = functionDefine.scope;
String funcname = functionDefine.declarator.getName();
String specifier = "";
for (ASTToken specifierToken : functionDefine.specifiers) {
specifier = specifier + specifierToken.value;
}
Quat quat0 = new Quat("FUNC_BEGIN",new DescribeNode(funcname),new DescribeNode(specifier),null);
quats.add(quat0);
//加上参数定义四元式
LinkedList params = new LinkedList();
for(ASTParamsDeclarator param :((ASTFunctionDeclarator)functionDefine.declarator).params) {
String paramType = "";
String paramName = param.declarator.getName();
for (ASTToken specifierToken : param.specfiers) {
paramType = paramType + specifierToken.value;
}
params.add(paramName);
this.localTable.addVar(paramName,paramType);
//加上四元式
quats.add(new Quat("param",new DescribeNode(paramName),
new DescribeNode(paramType),null));
}
globalTable.addFunc(funcname, specifier, params);
//没必要访问 visit(functionDefine.declarator);
visit(functionDefine.body);
//函数结束四元式
Quat quat1 = new Quat("FUNC_END",new DescribeNode(funcname),null,null);
quats.add(quat1);
localTable = functionDefine.scope.father;
}
@Override
public void visit(ASTDeclarator declarator) throws Exception {
}
public void visit(ASTDeclarator declarator, String type) throws Exception {
if(declarator instanceof ASTVariableDeclarator){
this.visit((ASTVariableDeclarator)declarator, type);
}else if(declarator instanceof ASTFunctionDeclarator){
this.visit((ASTFunctionDeclarator)declarator, type);
}else if(declarator instanceof ASTArrayDeclarator){
this.visit((ASTArrayDeclarator)declarator, type);
}
}
@Override
public void visit(ASTStatement statement) throws Exception {
if(statement instanceof ASTIterationDeclaredStatement) {
visit((ASTIterationDeclaredStatement)statement);
}else if(statement instanceof ASTIterationStatement) {
visit((ASTIterationStatement)statement);
}else if(statement instanceof ASTCompoundStatement) {
visit((ASTCompoundStatement)statement);
}else if(statement instanceof ASTSelectionStatement) {
visit((ASTSelectionStatement)statement);
}else if(statement instanceof ASTExpressionStatement) {
visit((ASTExpressionStatement)statement);
}else if(statement instanceof ASTBreakStatement) {
visit((ASTBreakStatement)statement);
}else if(statement instanceof ASTContinueStatement) {
visit((ASTContinueStatement)statement);
}else if(statement instanceof ASTReturnStatement) {
visit((ASTReturnStatement)statement);
}else if(statement instanceof ASTGotoStatement) {
visit((ASTGotoStatement)statement);
}else if(statement instanceof ASTLabeledStatement) {
visit((ASTLabeledStatement)statement);
}
}
@Override
public void visit(ASTToken token) throws Exception {
}
}
参考 CSDN 寒士 and songshangru
感恩学长