【编译】北京理工大学BITMINICC lab8+lab7 中间代码 & 目标代码生成

实验思路

  依然是在遍历抽象语法树的时候生成中间代码。
  因为四元式形式和 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是多少。

目标代码生成

  由于四元式在经过重排顺序后已经是正确汇编控制流代码了,在目标代码生成中,只需将每行的四元式翻译成对应的汇编代码即可。

  1. 全局整形变量, 判断当前变量是否有初始值,如果下一个 Quat 的操作符 是’= ’,那么当前变量有初始值,否则没有初始化为 0。
      有初值:(var,int,NULL,x) (=,1,NULL,x) -> x DWORD 1
      无初值:(var,int,NULL,x) -> x DWORD 0
  2. 字符串变量,需要去掉在字符串中显式定义的’\n ’,然后在字符串末 尾添加 0ah 作为换行符,否则会在运行时错误的输出不能解析的\n 换行符。也 要注意对仅为换行符的字符串的替换,不定义空字符串。
      有内容: (var,”string\n”,NULL,String1) ->
      String1 db“stirng”,0ah,0
      仅为换行符: (var,”\n”,NULL,String2) ->
      String2 db 0ah,0
  3. 数组声明 首先计算数组限定长度,因为 int 占 4 个字节,因此算出数组长度后×4 获 得数组大小。
      (array,int,[5, 5],A) -> A 100 DWORD DUP(0)
  4. 函数声明 需要在函数入口处声明参数,再检索到 FUNC_BEGIN 的四元式后, 向下检索连续的 param 的四元式,那么这些就是当前过程的参数列表。
      (FUNC_BEGIN,int,NULL,func)
      (param,int,NULL,x)
      -> func PROC x :DWORD
  5. 局部变量定义,在相同的声明函数下,需要打上 local 标签,并且汇编代码 有不同的声明形式。
      (var,int,NULL,x) -> local x :DWORD
      (array,int,[5, 5],A) -> local A[100]:DWORD
  6. 调用函数,先把当前参数栈内的所有参数取出,然后附加到 Invoke 伪指 令后面,通过 invoke 伪指令调用子过程。
      (arg,NULL,NULL,23) (invoke,f,NULL,t1) -> invoke f,23
  7. 四则运算示例在这里插入图片描述
  8. 控制流 所有控制流和逻辑表达式都使用伪指令解决,能省则省。
    在这里插入图片描述

代码:

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
感恩学长

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值