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