Search in sources :

Example 16 with LeftRecursiveRule

use of org.antlr.v4.tool.LeftRecursiveRule in project antlr4 by tunnelvisionlabs.

the class LeftRecursiveRuleTransformer method translateLeftRecursiveRules.

public void translateLeftRecursiveRules() {
    String language = g.getOptionString("language");
    // translate all recursive rules
    List<String> leftRecursiveRuleNames = new ArrayList<String>();
    for (Rule r : rules) {
        if (!Grammar.isTokenName(r.name)) {
            if (LeftRecursiveRuleAnalyzer.hasImmediateRecursiveRuleRefs(r.ast, r.name)) {
                boolean fitsPattern = translateLeftRecursiveRule(ast, (LeftRecursiveRule) r, language);
                if (fitsPattern) {
                    leftRecursiveRuleNames.add(r.name);
                } else {
                // Suppressed since this build has secondary support for left recursive rules that don't
                // match the patterns for precedence rules.
                // better given an error that non-conforming left-recursion exists
                // tool.errMgr.grammarError(ErrorType.NONCONFORMING_LR_RULE, g.fileName, ((GrammarAST)r.ast.getChild(0)).token, r.name);
                }
            }
        }
    }
    // update all refs to recursive rules to have [0] argument
    for (GrammarAST r : ast.getNodesWithType(ANTLRParser.RULE_REF)) {
        // must be rule def
        if (r.getParent().getType() == ANTLRParser.RULE)
            continue;
        // already has arg; must be in rewritten rule
        if (((GrammarASTWithOptions) r).getOptionString(PRECEDENCE_OPTION_NAME) != null)
            continue;
        if (leftRecursiveRuleNames.contains(r.getText())) {
            // found ref to recursive rule not already rewritten with arg
            ((GrammarASTWithOptions) r).setOption(PRECEDENCE_OPTION_NAME, new GrammarASTAdaptor().create(ANTLRParser.INT, "0"));
        }
    }
}
Also used : GrammarAST(org.antlr.v4.tool.ast.GrammarAST) ArrayList(java.util.ArrayList) GrammarASTAdaptor(org.antlr.v4.parse.GrammarASTAdaptor) Rule(org.antlr.v4.tool.Rule) LeftRecursiveRule(org.antlr.v4.tool.LeftRecursiveRule) GrammarASTWithOptions(org.antlr.v4.tool.ast.GrammarASTWithOptions)

Example 17 with LeftRecursiveRule

use of org.antlr.v4.tool.LeftRecursiveRule in project antlr4 by tunnelvisionlabs.

the class ParserATNFactory method createATN.

@NotNull
@Override
public ATN createATN() {
    _createATN(g.rules.values());
    assert atn.maxTokenType == g.getMaxTokenType();
    addRuleFollowLinks();
    addEOFTransitionToStartRules();
    ATNOptimizer.optimize(g, atn);
    for (Tuple3<? extends Rule, ? extends ATNState, ? extends ATNState> pair : preventEpsilonClosureBlocks) {
        LL1Analyzer analyzer = new LL1Analyzer(atn);
        ATNState blkStart = pair.getItem2();
        ATNState blkStop = pair.getItem3();
        IntervalSet lookahead = analyzer.LOOK(blkStart, blkStop, PredictionContext.EMPTY_LOCAL);
        if (lookahead.contains(org.antlr.v4.runtime.Token.EPSILON)) {
            ErrorType errorType = pair.getItem1() instanceof LeftRecursiveRule ? ErrorType.EPSILON_LR_FOLLOW : ErrorType.EPSILON_CLOSURE;
            g.tool.errMgr.grammarError(errorType, g.fileName, ((GrammarAST) pair.getItem1().ast.getChild(0)).getToken(), pair.getItem1().name);
        }
    }
    optionalCheck: for (Tuple3<? extends Rule, ? extends ATNState, ? extends ATNState> pair : preventEpsilonOptionalBlocks) {
        int bypassCount = 0;
        for (int i = 0; i < pair.getItem2().getNumberOfTransitions(); i++) {
            ATNState startState = pair.getItem2().transition(i).target;
            if (startState == pair.getItem3()) {
                bypassCount++;
                continue;
            }
            LL1Analyzer analyzer = new LL1Analyzer(atn);
            if (analyzer.LOOK(startState, pair.getItem3(), PredictionContext.EMPTY_LOCAL).contains(org.antlr.v4.runtime.Token.EPSILON)) {
                g.tool.errMgr.grammarError(ErrorType.EPSILON_OPTIONAL, g.fileName, ((GrammarAST) pair.getItem1().ast.getChild(0)).getToken(), pair.getItem1().name);
                continue optionalCheck;
            }
        }
        if (bypassCount != 1) {
            throw new UnsupportedOperationException("Expected optional block with exactly 1 bypass alternative.");
        }
    }
    return atn;
}
Also used : LeftRecursiveRule(org.antlr.v4.tool.LeftRecursiveRule) LL1Analyzer(org.antlr.v4.runtime.atn.LL1Analyzer) ErrorType(org.antlr.v4.tool.ErrorType) IntervalSet(org.antlr.v4.runtime.misc.IntervalSet) Tuple3(org.antlr.v4.runtime.misc.Tuple3) GrammarAST(org.antlr.v4.tool.ast.GrammarAST) Rule(org.antlr.v4.tool.Rule) LeftRecursiveRule(org.antlr.v4.tool.LeftRecursiveRule) ATNState(org.antlr.v4.runtime.atn.ATNState) NotNull(org.antlr.v4.runtime.misc.NotNull)

Example 18 with LeftRecursiveRule

use of org.antlr.v4.tool.LeftRecursiveRule in project antlr4 by tunnelvisionlabs.

the class TestATNParserPrediction method testAltsForLRRuleComputation3.

@Test
public void testAltsForLRRuleComputation3() throws Exception {
    Grammar g = new Grammar("grammar T;\n" + // should have no effect
    "random : 'blort';\n" + "e : '--' e\n" + "  | e '*' e\n" + "  | e '+' e\n" + "  | e '--'\n" + "  | ID\n" + "  ;\n" + "ID : [a-z]+ ;\n" + "INT : [0-9]+ ;\n" + "WS : [ \\r\\t\\n]+ ;");
    Rule e = g.getRule("e");
    assertTrue(e instanceof LeftRecursiveRule);
    LeftRecursiveRule lr = (LeftRecursiveRule) e;
    assertEquals("[0, 1, 5]", Arrays.toString(lr.getPrimaryAlts()));
    assertEquals("[0, 2, 3, 4]", Arrays.toString(lr.getRecursiveOpAlts()));
}
Also used : LeftRecursiveRule(org.antlr.v4.tool.LeftRecursiveRule) Grammar(org.antlr.v4.tool.Grammar) LexerGrammar(org.antlr.v4.tool.LexerGrammar) Rule(org.antlr.v4.tool.Rule) LeftRecursiveRule(org.antlr.v4.tool.LeftRecursiveRule) Test(org.junit.Test)

Example 19 with LeftRecursiveRule

use of org.antlr.v4.tool.LeftRecursiveRule in project antlr4 by antlr.

the class RuleCollector method discoverRule.

@Override
public void discoverRule(RuleAST rule, GrammarAST ID, List<GrammarAST> modifiers, ActionAST arg, ActionAST returns, GrammarAST thrws, GrammarAST options, ActionAST locals, List<GrammarAST> actions, GrammarAST block) {
    int numAlts = block.getChildCount();
    Rule r;
    if (LeftRecursiveRuleAnalyzer.hasImmediateRecursiveRuleRefs(rule, ID.getText())) {
        r = new LeftRecursiveRule(g, ID.getText(), rule);
    } else {
        r = new Rule(g, ID.getText(), rule, numAlts);
    }
    rules.put(r.name, r);
    if (arg != null) {
        r.args = ScopeParser.parseTypedArgList(arg, arg.getText(), g);
        r.args.type = AttributeDict.DictType.ARG;
        r.args.ast = arg;
        arg.resolver = r.alt[currentOuterAltNumber];
    }
    if (returns != null) {
        r.retvals = ScopeParser.parseTypedArgList(returns, returns.getText(), g);
        r.retvals.type = AttributeDict.DictType.RET;
        r.retvals.ast = returns;
    }
    if (locals != null) {
        r.locals = ScopeParser.parseTypedArgList(locals, locals.getText(), g);
        r.locals.type = AttributeDict.DictType.LOCAL;
        r.locals.ast = locals;
    }
    for (GrammarAST a : actions) {
        // a = ^(AT ID ACTION)
        ActionAST action = (ActionAST) a.getChild(1);
        r.namedActions.put(a.getChild(0).getText(), action);
        action.resolver = r;
    }
}
Also used : LeftRecursiveRule(org.antlr.v4.tool.LeftRecursiveRule) GrammarAST(org.antlr.v4.tool.ast.GrammarAST) Rule(org.antlr.v4.tool.Rule) LeftRecursiveRule(org.antlr.v4.tool.LeftRecursiveRule) ActionAST(org.antlr.v4.tool.ast.ActionAST)

Example 20 with LeftRecursiveRule

use of org.antlr.v4.tool.LeftRecursiveRule in project antlr4 by antlr.

the class OutputModelController method buildLeftRecursiveRuleFunction.

public void buildLeftRecursiveRuleFunction(LeftRecursiveRule r, LeftRecursiveRuleFunction function) {
    buildNormalRuleFunction(r, function);
    // now inject code to start alts
    CodeGenerator gen = delegate.getGenerator();
    STGroup codegenTemplates = gen.getTemplates();
    // pick out alt(s) for primaries
    CodeBlockForOuterMostAlt outerAlt = (CodeBlockForOuterMostAlt) function.code.get(0);
    List<CodeBlockForAlt> primaryAltsCode = new ArrayList<CodeBlockForAlt>();
    SrcOp primaryStuff = outerAlt.ops.get(0);
    if (primaryStuff instanceof Choice) {
        Choice primaryAltBlock = (Choice) primaryStuff;
        primaryAltsCode.addAll(primaryAltBlock.alts);
    } 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.get(1);
    CodeBlockForAlt altForOpAltBlock = opAltStarBlock.alts.get(0);
    List<CodeBlockForAlt> opAltsCode = new ArrayList<CodeBlockForAlt>();
    SrcOp opStuff = altForOpAltBlock.ops.get(0);
    if (opStuff instanceof AltBlock) {
        AltBlock opAltBlock = (AltBlock) opStuff;
        opAltsCode.addAll(opAltBlock.alts);
    } else {
        // just a single alt I guess; no block
        opAltsCode.add((CodeBlockForAlt) opStuff);
    }
    // Insert code in front of each primary alt to create specialized ctx if there was a label
    for (int i = 0; i < primaryAltsCode.size(); i++) {
        LeftRecursiveRuleAltInfo altInfo = r.recPrimaryAlts.get(i);
        if (altInfo.altLabel == null)
            continue;
        ST altActionST = codegenTemplates.getInstanceOf("recRuleReplaceContext");
        altActionST.add("ctxName", Utils.capitalize(altInfo.altLabel));
        Action altAction = new Action(delegate, function.altLabelCtxs.get(altInfo.altLabel), altActionST);
        CodeBlockForAlt alt = primaryAltsCode.get(i);
        alt.insertOp(0, altAction);
    }
    // Insert code to set ctx.stop after primary block and before op * loop
    ST 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
    ST 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 ctx if there was an alt label
    for (int i = 0; i < opAltsCode.size(); i++) {
        ST 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.containsKey("isListLabel")) {
            altActionST.add("isListLabel", altInfo.isListLabel);
        } else if (altInfo.isListLabel) {
            delegate.getGenerator().tool.errMgr.toolError(ErrorType.CODE_TEMPLATE_ARG_ISSUE, templateName, "isListLabel");
        }
        Action altAction = new Action(delegate, function.altLabelCtxs.get(altInfo.altLabel), altActionST);
        CodeBlockForAlt alt = opAltsCode.get(i);
        alt.insertOp(0, altAction);
    }
}
Also used : GrammarAST(org.antlr.v4.tool.ast.GrammarAST) ActionAST(org.antlr.v4.tool.ast.ActionAST) BlockAST(org.antlr.v4.tool.ast.BlockAST) ST(org.stringtemplate.v4.ST) PredAST(org.antlr.v4.tool.ast.PredAST) Action(org.antlr.v4.codegen.model.Action) SrcOp(org.antlr.v4.codegen.model.SrcOp) Choice(org.antlr.v4.codegen.model.Choice) STGroup(org.stringtemplate.v4.STGroup) ArrayList(java.util.ArrayList) StarBlock(org.antlr.v4.codegen.model.StarBlock) CodeBlockForOuterMostAlt(org.antlr.v4.codegen.model.CodeBlockForOuterMostAlt) CodeBlockForAlt(org.antlr.v4.codegen.model.CodeBlockForAlt) AltBlock(org.antlr.v4.codegen.model.AltBlock) LeftRecursiveRuleAltInfo(org.antlr.v4.analysis.LeftRecursiveRuleAltInfo)

Aggregations

LeftRecursiveRule (org.antlr.v4.tool.LeftRecursiveRule)16 Rule (org.antlr.v4.tool.Rule)14 GrammarAST (org.antlr.v4.tool.ast.GrammarAST)12 Grammar (org.antlr.v4.tool.Grammar)8 ActionAST (org.antlr.v4.tool.ast.ActionAST)8 LexerGrammar (org.antlr.v4.tool.LexerGrammar)6 Test (org.junit.Test)6 ArrayList (java.util.ArrayList)4 Action (org.antlr.v4.codegen.model.Action)4 BlockAST (org.antlr.v4.tool.ast.BlockAST)4 PredAST (org.antlr.v4.tool.ast.PredAST)4 RuleAST (org.antlr.v4.tool.ast.RuleAST)4 HashMap (java.util.HashMap)2 LinkedHashMap (java.util.LinkedHashMap)2 RecognitionException (org.antlr.runtime.RecognitionException)2 LeftRecursiveRuleAltInfo (org.antlr.v4.analysis.LeftRecursiveRuleAltInfo)2 AltBlock (org.antlr.v4.codegen.model.AltBlock)2 Choice (org.antlr.v4.codegen.model.Choice)2 CodeBlockForAlt (org.antlr.v4.codegen.model.CodeBlockForAlt)2 CodeBlockForOuterMostAlt (org.antlr.v4.codegen.model.CodeBlockForOuterMostAlt)2