/* * Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. * Use of this file is governed by the BSD 3-clause license that * can be found in the LICENSE.txt file in the project root. */ package org.antlr.v4.codegen.model; import org.antlr.v4.codegen.CodeGenerator; import org.antlr.v4.codegen.OutputModelFactory; import org.antlr.v4.codegen.model.decl.RuleContextDecl; import org.antlr.v4.codegen.model.decl.RuleContextListDecl; import org.antlr.v4.codegen.model.decl.StructDecl; import org.antlr.v4.parse.ANTLRParser; import org.antlr.v4.runtime.misc.Pair; import org.antlr.v4.tool.LeftRecursiveRule; import org.antlr.v4.tool.Rule; import org.antlr.v4.tool.ast.GrammarAST; public class LeftRecursiveRuleFunction extends RuleFunction { public LeftRecursiveRuleFunction(OutputModelFactory factory, LeftRecursiveRule r) { super(factory, r); CodeGenerator gen = factory.getGenerator(); // Since we delete x=lr, we have to manually add decls for all labels // on left-recur refs to proper structs for (Pair<GrammarAST,String> pair : r.leftRecursiveRuleRefLabels) { GrammarAST idAST = pair.a; String altLabel = pair.b; String label = idAST.getText(); GrammarAST rrefAST = (GrammarAST)idAST.getParent().getChild(1); if ( rrefAST.getType() == ANTLRParser.RULE_REF ) { Rule targetRule = factory.getGrammar().getRule(rrefAST.getText()); String ctxName = gen.getTarget().getRuleFunctionContextStructName(targetRule); RuleContextDecl d; if (idAST.getParent().getType() == ANTLRParser.ASSIGN) { d = new RuleContextDecl(factory, label, ctxName); } else { d = new RuleContextListDecl(factory, label, ctxName); } StructDecl struct = ruleCtx; if ( altLabelCtxs!=null ) { StructDecl s = altLabelCtxs.get(altLabel); if ( s!=null ) struct = s; // if alt label, use subctx } struct.addDecl(d); // stick in overall rule's ctx } } } }