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);
            }
        }
Beispiel #2
0
        public virtual void AddContextGetters(OutputModelFactory factory, ICollection <RuleAST> contextASTs)
        {
            IList <AltAST> unlabeledAlternatives = new List <AltAST>();
            IDictionary <string, IList <AltAST> > labeledAlternatives = new Dictionary <string, IList <AltAST> >();

            foreach (RuleAST ast in contextASTs)
            {
                try
                {
                    foreach (var altAst in rule.g.GetUnlabeledAlternatives(ast))
                    {
                        unlabeledAlternatives.Add(altAst);
                    }

                    foreach (KeyValuePair <string, IList <System.Tuple <int, AltAST> > > entry in rule.g.GetLabeledAlternatives(ast))
                    {
                        IList <AltAST> list;
                        if (!labeledAlternatives.TryGetValue(entry.Key, out list))
                        {
                            list = new List <AltAST>();
                            labeledAlternatives[entry.Key] = list;
                        }

                        foreach (System.Tuple <int, AltAST> tuple in entry.Value)
                        {
                            list.Add(tuple.Item2);
                        }
                    }
                }
                catch (RecognitionException)
                {
                }
            }

            // Add ctx labels for elements in alts with no '#' label
            if (unlabeledAlternatives.Count > 0)
            {
                ISet <Decl.Decl> decls = GetDeclsForAllElements(unlabeledAlternatives);

                // put directly in base context
                foreach (Decl.Decl decl in decls)
                {
                    ruleCtx.AddDecl(decl);
                }
            }

            // make structs for '#' labeled alts, define ctx labels for elements
            altLabelCtxs = new Dictionary <string, AltLabelStructDecl>();
            if (labeledAlternatives.Count > 0)
            {
                foreach (KeyValuePair <string, IList <AltAST> > entry in labeledAlternatives)
                {
                    AltLabelStructDecl labelDecl = new AltLabelStructDecl(factory, rule, entry.Key);
                    altLabelCtxs[entry.Key] = labelDecl;
                    ISet <Decl.Decl> decls = GetDeclsForAllElements(entry.Value);
                    foreach (Decl.Decl decl in decls)
                    {
                        labelDecl.AddDecl(decl);
                    }
                }
            }
        }