private void GetQuadruples(AstNode now, int Level)//dfs { if (now == null) { return; } switch (now.Type) { case AstType.SubProgram: GetQuadruples(now.Left, Level); if (CodeEntrance == -1) //为1尚未被赋值 { if (now.Right == null) //没有起始语句 { CodeEntrance = -2; } else { CodeEntrance = CodeSeg.Count; } } GetQuadruples(now.Right, Level); if (now.Right != null) { CodeSeg.Add(new QuadrupleNode(QuadrupleType.Return)); } break; case AstType.Define: GetQuadruples(now.Left, Level); GetQuadruples(now.Right, Level + 1); break; case AstType.IdDefine: GetQuadruples(now.Left, Level); GetQuadruples(now.Right, Level); break; case AstType.ConstDefine: List <AstNode> list = now.Info as List <AstNode>; if (list == null) { return; } foreach (var i in list) { i.Offset = ConstSeg.Count; ConstSeg.Add(Convert.ToInt32(i.Right.Info)); } break; case AstType.VarDefine: list = now.Info as List <AstNode>; if (list == null) { return; } int cnt = 0; foreach (var i in list) { i.Offset = VarSeg.Count; QuadrupleNode var = new QuadrupleNode(QuadrupleType.Var) { Value = i.Left.Info, Offset = i.Offset, AddressOffset = cnt++, Level = Level }; VarSeg.Add(var); } break; case AstType.ProcsDefine: list = now.Info as List <AstNode>; if (list == null) { return; } foreach (var i in list) { i.Offset = ProcedureSeg.Count; var proc = new QuadrupleNode(QuadrupleType.Proc) { Value = i.Left.Info, Level = Level }; ProcedureSeg.Add(proc); GetQuadruples(i.Right.Left, Level); proc.Offset = CodeSeg.Count; //调用直接跳转到当前行 GetQuadruples(i.Right.Right, Level); CodeSeg.Add(new QuadrupleNode(QuadrupleType.Return)); FreeAllTempData(); } break; case AstType.Statements: list = now.Info as List <AstNode>; foreach (var i in list) { GetQuadruples(i, Level); } break; case AstType.Assign: QuadrupleNode assign = new QuadrupleNode(QuadrupleType.Assign, new QuadrupleNode(VarSeg[now.Left.Offset], Level)) { Arg2 = GetArg(now.Right, Level) }; if (assign.Arg2 == null) { GetQuadruples(now.Right, Level); assign.Arg2 = ResultIndex; } CodeSeg.Add(assign); break; case AstType.Call: CodeSeg.Add(new QuadrupleNode(QuadrupleType.Call) { Result = ProcedureSeg[now.Left.Offset].Offset //跳转地址 }); break; case AstType.IfElse: QuadrupleNode node = new QuadrupleNode(GetOppositeJumpInstruction(now.Left.Left.Info)) { Arg1 = GetArg(now.Left.Left.Left, Level) }; if (node.Arg1 == null) { GetQuadruples(now.Left.Left.Left, Level); //左边表达式 node.Arg1 = ResultIndex; } if (node.Type != QuadrupleType.JO && node.Type != QuadrupleType.JNO) { node.Arg2 = GetArg(now.Left.Left.Right, Level); if (node.Arg2 == null) { GetQuadruples(now.Left.Left.Right, Level); node.Arg2 = ResultIndex; } } CodeSeg.Add(node); FreeAllTempData(); GetQuadruples(now.Left.Right, Level); node.Result = CodeSeg.Count; //不成立跳转到隶属then的语句的之后 //跳转指令的result(即目标地址)需要指向一个节点 //扫描一遍回填 if (now.Right != null) //有else { //if x then y else z ; t QuadrupleNode LeaveIf = new QuadrupleNode(QuadrupleType.JMP); //goto t CodeSeg.Add(LeaveIf); node.Result = CodeSeg.Count; GetQuadruples(now.Right, Level); //goto t LeaveIf.Result = CodeSeg.Count; FreeAllTempData(); } FreeAllTempData(); break; case AstType.RepeatUntil: node = new QuadrupleNode(GetOppositeJumpInstruction(now.Left.Info)) { Result = CodeSeg.Count //当前位置 }; GetQuadruples(now.Right, Level); node.Arg1 = GetArg(now.Left.Left, Level); if (node.Arg1 == null) { GetQuadruples(now.Left.Left, Level); node.Arg1 = ResultIndex; } if (node.Type != QuadrupleType.JNO && node.Type != QuadrupleType.JO) { node.Arg2 = GetArg(now.Left.Right, Level); if (node.Arg2 == null) { GetQuadruples(now.Left.Right, Level); node.Arg2 = ResultIndex; } } CodeSeg.Add(node); FreeAllTempData(); break; case AstType.WhileDo: object op = now.Left.Info; node = new QuadrupleNode(GetOppositeJumpInstruction(op)) { Arg1 = GetArg(now.Left.Left, Level) }; if (node.Arg1 == null) { GetQuadruples(now.Left.Left, Level); node.Arg1 = ResultIndex; } if (node.Type != QuadrupleType.JNO && node.Type != QuadrupleType.JO) { node.Arg2 = GetArg(now.Left.Right, Level); if (node.Arg2 == null) { GetQuadruples(now.Left.Right, Level); node.Arg2 = ResultIndex; } } CodeSeg.Add(node); int location = CodeSeg.Count; FreeAllTempData(); GetQuadruples(now.Right, Level); node.Result = CodeSeg.Count; //while 条件不成立跳转 QuadrupleNode back = new QuadrupleNode(GetJumpInstruction(op)) { Result = location }; back.Arg1 = GetArg(now.Left.Left, Level); if (back.Arg1 == null) { GetQuadruples(now.Left.Left, Level); back.Arg1 = ResultIndex; } if (back.Type != QuadrupleType.JNO && back.Type != QuadrupleType.JO) { back.Arg2 = GetArg(now.Left.Right, Level); if (back.Arg2 == null) { GetQuadruples(now.Left.Right, Level); back.Arg2 = ResultIndex; } } CodeSeg.Add(back); node.Result = CodeSeg.Count; FreeAllTempData(); break; case AstType.Expr: var node1 = new QuadrupleNode(GetOperator(now.Info)) { Arg2 = GetArg(now.Right, Level) }; if (node1.Arg2 == null) { GetQuadruples(now.Right, Level); node1.Arg2 = ResultIndex; } if (now.Left.Type == AstType.Minus) // -x -> 0 - x { node = new QuadrupleNode(QuadrupleType.Sub) { Arg1 = "#0", Arg2 = GetArg(now.Left.Right, Level) }; if (node.Arg2 == null) { GetQuadruples(now.Left.Right, Level); node.Arg2 = ResultIndex; } node.Result = GetTemp(); CodeSeg.Add(node); node1.Arg1 = node.Result; } else { node1.Arg1 = GetArg(now.Left, Level); if (node1.Arg1 == null) { GetQuadruples(now.Left, Level); node1.Arg1 = ResultIndex; } } CodeSeg.Add(node1); ResultIndex = GetTemp(); node1.Result = ResultIndex; break; case AstType.Term: node = new QuadrupleNode(GetOperator(now.Info)) { Arg2 = GetArg(now.Right, Level) }; if (node.Arg2 == null) { GetQuadruples(now.Right, Level); node.Arg2 = ResultIndex; } node.Arg1 = GetArg(now.Left, Level); if (node.Arg1 == null) { GetQuadruples(now.Left, Level); node.Arg1 = ResultIndex; } node.Result = GetTemp(); ResultIndex = (int)node.Result; CodeSeg.Add(node); break; case AstType.Read: //需要自己平衡栈,Write & Read ArrayList param = new ArrayList(); foreach (var i in (List <AstNode>)now.Info) { var n = new QuadrupleNode(VarSeg[i.Offset], Level); param.Add(n); } CodeSeg.Add(new QuadrupleNode(QuadrupleType.Read, param)); break; case AstType.Write: param = new ArrayList(); foreach (var i in (List <AstNode>)now.Info) { if (i.Type == AstType.NUM) { param.Add(i.Info); } else if (i.Type == AstType.Var) { var n = new QuadrupleNode(VarSeg[i.Offset], Level); param.Add(n); } else if (i.Type == AstType.Const) { param.Add("#" + ConstSeg[i.Offset]); } } CodeSeg.Add(new QuadrupleNode(QuadrupleType.Write, param)); break; default: throw new Exception($"{now.Type}"); } }
private void Clear() { VarSeg.Clear(); ConstSeg.Clear(); CodeSeg.Clear(); }