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); } }
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); } } } }