/// <summary> /// Exit a parse tree produced by <see cref="CMMParser.forStatement"/>. /// <para>The default implementation does nothing.</para> /// </summary> /// <param name="context">The parse tree.</param> public virtual void ExitForStatement([NotNull] CMMParser.ForStatementContext context) { }
/// <summary> /// Visit a parse tree produced by <see cref="CMMParser.forStatement"/>. /// <para> /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/> /// on <paramref name="context"/>. /// </para> /// </summary> /// <param name="context">The parse tree.</param> /// <return>The visitor result.</return> public virtual Result VisitForStatement([NotNull] CMMParser.ForStatementContext context) { return(VisitChildren(context)); }
/* * 处理for语句 */ public override object VisitForStatement([NotNull] CMMParser.ForStatementContext context) { // 当前局部变量表的大小,访问完ForStatement之后要恢复局部变量表 int curSize = curLocalVariablesTableLength; // 这里面可能会定义新的变量,不过没关系,直接插入局部变量表中就可以了,最后我们恢复的。 if (context.forInitializer() != null) { Visit(context.forInitializer()); } // 访问expression,将执行的结果压入栈中 // addr_expression是expression(比较)的地址 int addr_expression = codes.Count; IntermediateCode code0, code1 = null; if (context.expression() != null) { Visit(context.expression()); // 如果expression的结果是真,才会访问 // 这里的0是数字,不是索引,要加上范围!! code0 = new IntermediateCode(0, InstructionType.push, context.Start.Line); // 如果是0的话,就直接跳转到codeBlock之后,并且释放局部变量。目的地址待回填 code1 = new IntermediateCode(InstructionType.je, context.Start.Line); // addr0是codeBlock的起始地址 codes.Add(code0); codes.Add(code1); } int addr0 = codes.Count; // 访问codeBlock if (context.codeBlock() != null) { Visit(context.codeBlock()); } // 访问更新操作,更新操作的起始地址是addr1 int addr1 = codes.Count; if (context.assignment() != null) { Visit(context.assignment()); } // 跳转回去expression去判断 codes.Add(new IntermediateCode(addr_expression, InstructionType.j, context.Start.Line)); // addr2是执行完codeBlock,而且判断确定不跳转的代码 int addr2 = codes.Count; if (code1 != null) { code1.setOperant(addr2); } // 替换所有出现的continue break,代码的范围是addr0-add2, 更新操作的代码在addr1 replaceBreakAndConti(codes, addr0, addr2 - 1, addr1); //局部变量表大于curSize的部分全部删掉! codes.Add(new IntermediateCode(curSize, InstructionType.delv, context.Stop.Line)); curLocalVariablesTableLength = curSize; removeVariableBiggerThanK(curSize); return(null); }