public override void VisitGoToNode(GoToNode g)
        {
            string labelName = g.Label.Name;
            // При посещении узла GoTо создаем соответсвующую команду трехадресного кода
            var gt = new TACNodes.Goto();

            code.AddNode(gt);

            // Если метка ведет в уже преобразованную часть программы
            if (labeledTANodes.ContainsKey(labelName))
            {
                // Получаем помеченную строку треадресного кода и задаем ее как цель перехода
                var target = labeledTANodes[labelName];
                gt.TargetLabel = target.Label;
            }
            else
            {
                // Иначе помещаем строку в лист ожидания пока помеченная часть программы не будет преобразована
                if (!forwardGotos.ContainsKey(labelName))
                {
                    forwardGotos.Add(labelName, new List <TACNodes.Goto>());
                }
                forwardGotos[labelName].Add(gt);
            }
        }
        public override void VisitIfNode(IfNode iif)
        {
            var ifGoto = new TACNodes.IfGoto();

            // Результат вычисления логического выражения
            var cond1 = RecAssign(iif.Conditon);

            ifGoto.Condition = cond1;

            code.AddNode(ifGoto);

            // Разбор тела else (если есть)
            iif.ElseClause?.Visit(this);

            // Пропускаем тело if
            var elseGoTo = new TACNodes.Goto();

            code.AddNode(elseGoTo);

            // Добавление новой метки непосредственно перед телом if
            var newLabelIf = GetEmptyLabeledNode();

            ifGoto.TargetLabel = newLabelIf.Label;

            // Обход выражений тела условного оператора
            iif.IfClause.Visit(this);

            // Метка после тела if, на нее передается управление из else
            var newLabelElse = GetEmptyLabeledNode();

            elseGoTo.TargetLabel = newLabelElse.Label;
        }
        public override void VisitCycleNode(CycleNode c)
        {
            // Метка в начале цикла
            var cycleLabel = GetEmptyLabeledNode();

            // Результат вычисления логического выражения
            var cond = RecAssign(c.Condition);

            // При истинности условия, переходим к телу цикла
            var ifGotoBody = new TACNodes.IfGoto {
                Condition = cond
            };

            code.AddNode(ifGotoBody);

            // Иначе переходим за тело цикла
            var gotoEnd = new TACNodes.Goto();

            code.AddNode(gotoEnd);

            // Добавление новой метки непосредственно перед телом цикла
            var bodyLabel = GetEmptyLabeledNode();

            ifGotoBody.TargetLabel = bodyLabel.Label;

            // Обход выражений тела цикла
            c.Body.Visit(this);

            // В конце цикла снова переходим к началу
            var cycleGoto = new TACNodes.Goto {
                TargetLabel = cycleLabel.Label
            };

            code.AddNode(cycleGoto);

            // Метка за телом цикла, сюда происходит переход, если не выполняется условие продолжения
            var endLabel = GetEmptyLabeledNode();

            gotoEnd.TargetLabel = endLabel.Label;
        }
        public override void VisitForNode(ForNode f)
        {
            // Значение счетчика цикла и инкремента при инициализации
            var counter = GetVarByName(f.Assign.Id.Name);
            var inc     = RecAssign(f.Inc);

            var init = new TACNodes.Assign()
            {
                Result    = counter,
                Left      = null,
                Right     = RecAssign(f.Assign.Expr),
                Operation = OpCode.Copy
            };

            code.AddNode(init);

            // Метка начала цикла
            var cycle = GetEmptyLabeledNode();

            // Условие выбора направления цикла
            var dirCond = new TACNodes.Assign()
            {
                Result    = new TACExpr.Var(),
                Left      = inc,
                Right     = new TACExpr.IntConst(0),
                Operation = OpCode.GreaterEq
            };

            code.AddNode(dirCond);

            // Выбор направления
            var dirIfGoto = new TACNodes.IfGoto();

            dirIfGoto.Condition = dirCond.Result;
            code.AddNode(dirIfGoto);

            // Для обратного направления счетчик сравнивается с границей на меньше равно - это условие выхода
            var initialBackwardCondition = new TACNodes.Assign
            {
                Result    = new TACExpr.Var(),
                Left      = counter,
                Right     = RecAssign(f.Border),
                Operation = OpCode.LessEq
            };

            code.AddNode(initialBackwardCondition);

            // Добавляем переход за конец цикла при выполнении условия выхода
            var ifGotoBackw = new TACNodes.IfGoto();
            var cond        = initialBackwardCondition.Result;

            ifGotoBackw.Condition = cond;
            code.AddNode(ifGotoBackw);

            // Пропускаем ветку прямого направления
            var forwSkipGoto = new TACNodes.Goto();

            code.AddNode(forwSkipGoto);

            // Начало ветки прямого направления
            var forwardLabel = GetEmptyLabeledNode();

            dirIfGoto.TargetLabel = forwardLabel.Label;

            // Для прямого направления счетчик сравнивается с границей на больше равно - это условие выхода
            var initialForwardCondition = new TACNodes.Assign
            {
                Result    = new TACExpr.Var(),
                Left      = counter,
                Right     = RecAssign(f.Border),
                Operation = OpCode.GreaterEq
            };

            code.AddNode(initialForwardCondition);

            // Добавляем переход за конец цикла при выполнении условия выхода
            var ifGotoForw = new TACNodes.IfGoto();

            ifGotoForw.Condition = initialForwardCondition.Result;
            code.AddNode(ifGotoForw);

            // Метка перед телом цикла - сюда происходит переход при пропуске ветки прямого обхода
            var forwSkipLabel = GetEmptyLabeledNode();

            forwSkipGoto.TargetLabel = forwSkipLabel.Label;

            // Дальнейший разбор тела выражения
            f.Body.Visit(this);

            // Пересчет инкремента
            inc = RecAssign(f.Inc);

            // Создаем строку с увеличением счетчика
            var ass1 = new TACNodes.Assign
            {
                Result    = counter,
                Left      = counter,
                Right     = inc,
                Operation = OpCode.Plus
            };

            code.AddNode(ass1);

            // Команда перехода к началу цикла
            var cycleGoto = new TACNodes.Goto {
                TargetLabel = cycle.Label
            };

            code.AddNode(cycleGoto);

            // Метка за концом цикла - сюда происходит переход при выполнении условия выхода
            var endCycle = GetEmptyLabeledNode();

            ifGotoForw.TargetLabel  = endCycle.Label;
            ifGotoBackw.TargetLabel = endCycle.Label;
        }