Ejemplo n.º 1
0
        /*
         * 处理if语句
         */
        public override object VisitIfStatement([NotNull] CMMParser.IfStatementContext context)
        {
            // 查看expression的结果
            Visit(context.expression());
            IntermediateCode code0 = new IntermediateCode(0, InstructionType.push, context.expression().Start.Line);

            codes.Add(code0);
            // 比较expression的结果和0的关系,等于0的话就跳转走,code1的目的地址待回填
            IntermediateCode code1 = new IntermediateCode(InstructionType.je, context.expression().Stop.Line);

            codes.Add(code1);
            if (context.codeBlock() != null)
            {
                Visit(context.codeBlock());
            }
            IntermediateCode code3 = new IntermediateCode(InstructionType.j, context.codeBlock().Stop.Line);

            codes.Add(code3);
            // 条件不符合的情况应该执行的代码行号为addr0,回填一下
            int addr0 = codes.Count;

            code1.setOperant(addr0);
            List <IntermediateCode> needToAddFinishAddrCodes = new List <IntermediateCode>();

            needToAddFinishAddrCodes.Add(code3);

            // 每个else语句都执行一下
            if (context.elseClause() != null)
            {
                foreach (CMMParser.ElseClauseContext ctx in context.elseClause())
                {
                    if (ctx.ifStatement() == null)
                    {
                        Visit(ctx.codeBlock());
                        IntermediateCode code = new IntermediateCode(InstructionType.j, ctx.codeBlock().Stop.Line);
                        needToAddFinishAddrCodes.Add(code);
                        codes.Add(code);
                    }
                    else
                    {
                        Visit(ctx.ifStatement());
                    }
                }
            }
            foreach (IntermediateCode c in needToAddFinishAddrCodes)
            {
                c.operant = codes.Count;
            }

            return(null);
        }
Ejemplo n.º 2
0
        /**
         * 处理生成函数的中间代码时
         * 在函数的第一行地址前加入j指令跳转到函数的最后一行地址之后
         *
         */
        public override object VisitFunctionDeclaration([NotNull] CMMParser.FunctionDeclarationContext context)
        {
            string funcName = context.GetChild(1).GetText();
            // jump到函数ret的下一行代码 最后再回填
            IntermediateCode jumpCode = new IntermediateCode(InstructionType.j, context.Start.Line);

            codes.Add(jumpCode);
            // 保存局部变量表和大小
            Dictionary <string, int> storedVariableTable = curLocalVariablesTable;
            int storedVariableTableSize = curLocalVariablesTableLength;

            curLocalVariablesTable       = new Dictionary <string, int>();
            curLocalVariablesTableLength = 0;

            // 用于记录该函数的各种信息
            FunctionInformation funcInfo = new FunctionInformation(funcName);

            // 记录函数的起始地址
            int funcAddress = codes.Count;

            functionAddressTable.Add(funcName, funcAddress);
            funcInfo.enrtyAddress = funcAddress;

            // 访问参数列表
            Visit(context.parameterClause());
            // visit code block生成当前函数的中间代码
            Visit(context.codeBlock());

            // 填入函数的出口地址
            funcInfo.outAddress = codes.Count - 1;
            // 回填jump指令
            jumpCode.setOperant(codes.Count);
            funcInfo.localVariableTable = curLocalVariablesTable;
            // 将函数信息保存到函数信息表中
            functionInformations.Add(funcName, funcInfo);

            // 恢复局部变量表和大小
            curLocalVariablesTable       = storedVariableTable;
            curLocalVariablesTableLength = storedVariableTableSize;
            return(null);
        }
Ejemplo n.º 3
0
        /*
         *
         * 访问while表达式
         */
        public override object VisitWhileStatement([NotNull] CMMParser.WhileStatementContext context)
        {
            /*
             * 如果expression的操作结果是false,就在栈中压入0,否则压入1.
             *
             */
            int curSize            = curLocalVariablesTableLength;
            int idx                = codes.Count;
            IntermediateCode code0 = new IntermediateCode(0, InstructionType.push, context.Start.Line);

            codes.Add(code0);
            // 查看expression的结果
            Visit(context.expression());

            // 比较expression的结果和1的关系
            // code1的目的地址等待后续回填。因为如果与0相等,说明是false,则需要跳转到codeBlock后面的位置。
            IntermediateCode code1 = new IntermediateCode(InstructionType.je, context.expression().Start.Line);

            codes.Add(code1);
            // addr0是codeBlock的开始地址。
            int addr0 = codes.Count;

            Visit(context.codeBlock());
            IntermediateCode code2 = new IntermediateCode(0, InstructionType.j, context.codeBlock().Stop.Line);

            codes.Add(code2);
            int addr1 = codes.Count;

            // 这个时候回填地址,如果刚才的条件判断不满足,那么目的地址是codeBlock结束的地址addr1
            code1.setOperant(addr1);
            code2.setOperant(idx);
            codes.Add(new IntermediateCode(curSize, InstructionType.delv, context.codeBlock().Stop.Line));
            curLocalVariablesTableLength = curSize;
            removeVariableBiggerThanK(curSize);



            return(null);
        }