Antlr4.Codegen.OutputModelController.BuildLeftRecursiveRuleFunction C# (CSharp) Method

BuildLeftRecursiveRuleFunction() public method

public BuildLeftRecursiveRuleFunction ( LeftRecursiveRule r, LeftRecursiveRuleFunction function ) : void
r Antlr4.Tool.LeftRecursiveRule
function Antlr4.Codegen.Model.LeftRecursiveRuleFunction
return void
        public virtual void BuildLeftRecursiveRuleFunction(LeftRecursiveRule r, LeftRecursiveRuleFunction function)
        {
            BuildNormalRuleFunction(r, function);

            // now inject code to start alts
            AbstractTarget target = @delegate.GetTarget();
            TemplateGroup codegenTemplates = target.GetTemplates();

            // pick out alt(s) for primaries
            CodeBlockForOuterMostAlt outerAlt = (CodeBlockForOuterMostAlt)function.code[0];
            IList<CodeBlockForAlt> primaryAltsCode = new List<CodeBlockForAlt>();
            SrcOp primaryStuff = outerAlt.ops[0];
            if (primaryStuff is Choice)
            {
                Choice primaryAltBlock = (Choice)primaryStuff;
                foreach (var alt in primaryAltBlock.alts)
                    primaryAltsCode.Add(alt);
            }
            else
            { // just a single alt I guess; no block
                primaryAltsCode.Add((CodeBlockForAlt)primaryStuff);
            }

            // pick out alt(s) for op alts
            StarBlock opAltStarBlock = (StarBlock)outerAlt.ops[1];
            CodeBlockForAlt altForOpAltBlock = opAltStarBlock.alts[0];
            IList<CodeBlockForAlt> opAltsCode = new List<CodeBlockForAlt>();
            SrcOp opStuff = altForOpAltBlock.ops[0];
            if (opStuff is AltBlock)
            {
                AltBlock opAltBlock = (AltBlock)opStuff;
                foreach (var alt in opAltBlock.alts)
                    opAltsCode.Add(alt);
            }
            else
            { // just a single alt I guess; no block
                opAltsCode.Add((CodeBlockForAlt)opStuff);
            }

            // Insert code in front of each primary alt to create specialized context if there was a label
            for (int i = 0; i < primaryAltsCode.Count; i++)
            {
                LeftRecursiveRuleAltInfo altInfo = r.recPrimaryAlts[i];
                if (altInfo.altLabel == null)
                    continue;
                Template altActionST = codegenTemplates.GetInstanceOf("recRuleReplaceContext");
                altActionST.Add("ctxName", Utils.Capitalize(altInfo.altLabel));
                AltLabelStructDecl ctx = null;
                if (altInfo.altLabel != null)
                    function.altLabelCtxs.TryGetValue(altInfo.altLabel, out ctx);
                Action altAction = new Action(@delegate, ctx, altActionST);
                CodeBlockForAlt alt = primaryAltsCode[i];
                alt.InsertOp(0, altAction);
            }

            // Insert code to set ctx.stop after primary block and before op * loop
            Template setStopTokenAST = codegenTemplates.GetInstanceOf("recRuleSetStopToken");
            Action setStopTokenAction = new Action(@delegate, function.ruleCtx, setStopTokenAST);
            outerAlt.InsertOp(1, setStopTokenAction);

            // Insert code to set _prevctx at start of * loop
            Template setPrevCtx = codegenTemplates.GetInstanceOf("recRuleSetPrevCtx");
            Action setPrevCtxAction = new Action(@delegate, function.ruleCtx, setPrevCtx);
            opAltStarBlock.AddIterationOp(setPrevCtxAction);

            // Insert code in front of each op alt to create specialized context if there was an alt label
            for (int i = 0; i < opAltsCode.Count; i++)
            {
                Template altActionST;
                LeftRecursiveRuleAltInfo altInfo = r.recOpAlts.GetElement(i);
                string templateName;
                if (altInfo.altLabel != null)
                {
                    templateName = "recRuleLabeledAltStartAction";
                    altActionST = codegenTemplates.GetInstanceOf(templateName);
                    altActionST.Add("currentAltLabel", altInfo.altLabel);
                }
                else
                {
                    templateName = "recRuleAltStartAction";
                    altActionST = codegenTemplates.GetInstanceOf(templateName);
                    altActionST.Add("ctxName", Utils.Capitalize(r.name));
                }
                altActionST.Add("ruleName", r.name);
                // add label of any LR ref we deleted
                altActionST.Add("label", altInfo.leftRecursiveRuleRefLabel);
                if (altActionST.impl.FormalArguments.Any(x => x.Name == "isListLabel"))
                {
                    altActionST.Add("isListLabel", altInfo.isListLabel);
                }
                else if (altInfo.isListLabel)
                {
                    @delegate.GetGenerator().tool.errMgr.ToolError(ErrorType.CODE_TEMPLATE_ARG_ISSUE, templateName, "isListLabel");
                }
                AltLabelStructDecl ctx = null;
                if (altInfo.altLabel != null)
                    function.altLabelCtxs.TryGetValue(altInfo.altLabel, out ctx);
                Action altAction = new Action(@delegate, ctx, altActionST);
                CodeBlockForAlt alt = opAltsCode[i];
                alt.InsertOp(0, altAction);
            }
        }