Search in sources :

Example 6 with RuleAST

use of org.antlr.v4.tool.ast.RuleAST in project antlr4 by antlr.

the class LeftRecursiveRuleTransformer method parseArtificialRule.

public RuleAST parseArtificialRule(final Grammar g, String ruleText) {
    ANTLRLexer lexer = new ANTLRLexer(new ANTLRStringStream(ruleText));
    GrammarASTAdaptor adaptor = new GrammarASTAdaptor(lexer.getCharStream());
    CommonTokenStream tokens = new CommonTokenStream(lexer);
    lexer.tokens = tokens;
    ToolANTLRParser p = new ToolANTLRParser(tokens, tool);
    p.setTreeAdaptor(adaptor);
    Token ruleStart = null;
    try {
        ParserRuleReturnScope r = p.rule();
        RuleAST tree = (RuleAST) r.getTree();
        ruleStart = (Token) r.getStart();
        GrammarTransformPipeline.setGrammarPtr(g, tree);
        GrammarTransformPipeline.augmentTokensWithOriginalPosition(g, tree);
        return tree;
    } catch (Exception e) {
        tool.errMgr.toolError(ErrorType.INTERNAL_ERROR, e, ruleStart, "error parsing rule created during left-recursion detection: " + ruleText);
    }
    return null;
}
Also used : ANTLRStringStream(org.antlr.runtime.ANTLRStringStream) RuleAST(org.antlr.v4.tool.ast.RuleAST) CommonTokenStream(org.antlr.runtime.CommonTokenStream) ANTLRLexer(org.antlr.v4.parse.ANTLRLexer) GrammarASTAdaptor(org.antlr.v4.parse.GrammarASTAdaptor) Token(org.antlr.runtime.Token) ParserRuleReturnScope(org.antlr.runtime.ParserRuleReturnScope) ToolANTLRParser(org.antlr.v4.parse.ToolANTLRParser) RecognitionException(org.antlr.runtime.RecognitionException)

Example 7 with RuleAST

use of org.antlr.v4.tool.ast.RuleAST in project antlr4 by antlr.

the class TestATNConstruction method testAplusSingleAltHasPlusASTPointingAtLoopBackState.

@Test
public void testAplusSingleAltHasPlusASTPointingAtLoopBackState() throws Exception {
    Grammar g = new Grammar("parser grammar P;\n" + // (RULE a (BLOCK (ALT (+ (BLOCK (ALT A))))))
    "s : a B ;\n" + "a : A+;");
    String expecting = "RuleStart_a_2->PlusBlockStart_8\n" + "PlusBlockStart_8->s7\n" + "s7-A->BlockEnd_9\n" + "BlockEnd_9->PlusLoopBack_10\n" + "PlusLoopBack_10->PlusBlockStart_8\n" + "PlusLoopBack_10->s11\n" + "s11->RuleStop_a_3\n" + "RuleStop_a_3->s5\n";
    checkRuleATN(g, "a", expecting);
    // Get all AST -> ATNState relationships. Make sure loopback is covered when no loop entry decision
    List<GrammarAST> ruleNodes = g.ast.getNodesWithType(ANTLRParser.RULE);
    RuleAST a = (RuleAST) ruleNodes.get(1);
    List<GrammarAST> nodesInRule = a.getNodesWithType(null);
    Map<GrammarAST, ATNState> covered = new LinkedHashMap<GrammarAST, ATNState>();
    for (GrammarAST node : nodesInRule) {
        if (node.atnState != null) {
            covered.put(node, node.atnState);
        }
    }
    assertEquals("{RULE=2, BLOCK=8, +=10, BLOCK=8, A=7}", covered.toString());
}
Also used : RuleAST(org.antlr.v4.tool.ast.RuleAST) GrammarAST(org.antlr.v4.tool.ast.GrammarAST) Grammar(org.antlr.v4.tool.Grammar) LexerGrammar(org.antlr.v4.tool.LexerGrammar) LinkedHashMap(java.util.LinkedHashMap) ATNState(org.antlr.v4.runtime.atn.ATNState) Test(org.junit.Test)

Example 8 with RuleAST

use of org.antlr.v4.tool.ast.RuleAST in project antlr4 by antlr.

the class LeftRecursiveRuleTransformer method setAltASTPointers.

/**
	 * <pre>
	 * (RULE e int _p (returns int v)
	 * 	(BLOCK
	 * 	  (ALT
	 * 		(BLOCK
	 * 			(ALT INT {$v = $INT.int;})
	 * 			(ALT '(' (= x e) ')' {$v = $x.v;})
	 * 			(ALT ID))
	 * 		(* (BLOCK
	 *			(OPTIONS ...)
	 * 			(ALT {7 &gt;= $_p}? '*' (= b e) {$v = $a.v * $b.v;})
	 * 			(ALT {6 &gt;= $_p}? '+' (= b e) {$v = $a.v + $b.v;})
	 * 			(ALT {3 &gt;= $_p}? '++') (ALT {2 &gt;= $_p}? '--'))))))
	 * </pre>
	 */
public void setAltASTPointers(LeftRecursiveRule r, RuleAST t) {
    //		System.out.println("RULE: "+t.toStringTree());
    BlockAST ruleBlk = (BlockAST) t.getFirstChildWithType(ANTLRParser.BLOCK);
    AltAST mainAlt = (AltAST) ruleBlk.getChild(0);
    BlockAST primaryBlk = (BlockAST) mainAlt.getChild(0);
    // (* BLOCK ...)
    BlockAST opsBlk = (BlockAST) mainAlt.getChild(1).getChild(0);
    for (int i = 0; i < r.recPrimaryAlts.size(); i++) {
        LeftRecursiveRuleAltInfo altInfo = r.recPrimaryAlts.get(i);
        altInfo.altAST = (AltAST) primaryBlk.getChild(i);
        altInfo.altAST.leftRecursiveAltInfo = altInfo;
        altInfo.originalAltAST.leftRecursiveAltInfo = altInfo;
    //			altInfo.originalAltAST.parent = altInfo.altAST.parent;
    //			System.out.println(altInfo.altAST.toStringTree());
    }
    for (int i = 0; i < r.recOpAlts.size(); i++) {
        LeftRecursiveRuleAltInfo altInfo = r.recOpAlts.getElement(i);
        altInfo.altAST = (AltAST) opsBlk.getChild(i);
        altInfo.altAST.leftRecursiveAltInfo = altInfo;
        altInfo.originalAltAST.leftRecursiveAltInfo = altInfo;
    //			altInfo.originalAltAST.parent = altInfo.altAST.parent;
    //			System.out.println(altInfo.altAST.toStringTree());
    }
}
Also used : BlockAST(org.antlr.v4.tool.ast.BlockAST) AltAST(org.antlr.v4.tool.ast.AltAST)

Example 9 with RuleAST

use of org.antlr.v4.tool.ast.RuleAST in project antlr4 by antlr.

the class LeftRecursiveRuleTransformer method translateLeftRecursiveRule.

/** Return true if successful */
public boolean translateLeftRecursiveRule(GrammarRootAST ast, LeftRecursiveRule r, String language) {
    //tool.log("grammar", ruleAST.toStringTree());
    GrammarAST prevRuleAST = r.ast;
    String ruleName = prevRuleAST.getChild(0).getText();
    LeftRecursiveRuleAnalyzer leftRecursiveRuleWalker = new LeftRecursiveRuleAnalyzer(prevRuleAST, tool, ruleName, language);
    boolean isLeftRec;
    try {
        //			System.out.println("TESTING ---------------\n"+
        //							   leftRecursiveRuleWalker.text(ruleAST));
        isLeftRec = leftRecursiveRuleWalker.rec_rule();
    } catch (RecognitionException re) {
        // didn't match; oh well
        isLeftRec = false;
    }
    if (!isLeftRec)
        return false;
    // replace old rule's AST; first create text of altered rule
    GrammarAST RULES = (GrammarAST) ast.getFirstChildWithType(ANTLRParser.RULES);
    String newRuleText = leftRecursiveRuleWalker.getArtificialOpPrecRule();
    //		System.out.println("created: "+newRuleText);
    // now parse within the context of the grammar that originally created
    // the AST we are transforming. This could be an imported grammar so
    // we cannot just reference this.g because the role might come from
    // the imported grammar and not the root grammar (this.g)
    RuleAST t = parseArtificialRule(prevRuleAST.g, newRuleText);
    // reuse the name token from the original AST since it refers to the proper source location in the original grammar
    ((GrammarAST) t.getChild(0)).token = ((GrammarAST) prevRuleAST.getChild(0)).getToken();
    // update grammar AST and set rule's AST.
    RULES.setChild(prevRuleAST.getChildIndex(), t);
    r.ast = t;
    // Reduce sets in newly created rule tree
    GrammarTransformPipeline transform = new GrammarTransformPipeline(g, g.tool);
    transform.reduceBlocksToSets(r.ast);
    transform.expandParameterizedLoops(r.ast);
    // Rerun semantic checks on the new rule
    RuleCollector ruleCollector = new RuleCollector(g);
    ruleCollector.visit(t, "rule");
    BasicSemanticChecks basics = new BasicSemanticChecks(g, ruleCollector);
    // disable the assoc element option checks because they are already
    // handled for the pre-transformed rule.
    basics.checkAssocElementOption = false;
    basics.visit(t, "rule");
    // track recursive alt info for codegen
    r.recPrimaryAlts = new ArrayList<LeftRecursiveRuleAltInfo>();
    r.recPrimaryAlts.addAll(leftRecursiveRuleWalker.prefixAndOtherAlts);
    if (r.recPrimaryAlts.isEmpty()) {
        tool.errMgr.grammarError(ErrorType.NO_NON_LR_ALTS, g.fileName, ((GrammarAST) r.ast.getChild(0)).getToken(), r.name);
    }
    r.recOpAlts = new OrderedHashMap<Integer, LeftRecursiveRuleAltInfo>();
    r.recOpAlts.putAll(leftRecursiveRuleWalker.binaryAlts);
    r.recOpAlts.putAll(leftRecursiveRuleWalker.ternaryAlts);
    r.recOpAlts.putAll(leftRecursiveRuleWalker.suffixAlts);
    // walk alt info records and set their altAST to point to appropriate ALT subtree
    // from freshly created AST
    setAltASTPointers(r, t);
    // update Rule to just one alt and add prec alt
    ActionAST arg = (ActionAST) r.ast.getFirstChildWithType(ANTLRParser.ARG_ACTION);
    if (arg != null) {
        r.args = ScopeParser.parseTypedArgList(arg, arg.getText(), g);
        r.args.type = AttributeDict.DictType.ARG;
        r.args.ast = arg;
        // todo: isn't this Rule or something?
        arg.resolver = r.alt[1];
    }
    // these are so $label in action translation works
    for (Pair<GrammarAST, String> pair : leftRecursiveRuleWalker.leftRecursiveRuleRefLabels) {
        GrammarAST labelNode = pair.a;
        GrammarAST labelOpNode = (GrammarAST) labelNode.getParent();
        GrammarAST elementNode = (GrammarAST) labelOpNode.getChild(1);
        LabelElementPair lp = new LabelElementPair(g, labelNode, elementNode, labelOpNode.getType());
        r.alt[1].labelDefs.map(labelNode.getText(), lp);
    }
    // copy to rule from walker
    r.leftRecursiveRuleRefLabels = leftRecursiveRuleWalker.leftRecursiveRuleRefLabels;
    tool.log("grammar", "added: " + t.toStringTree());
    return true;
}
Also used : RuleAST(org.antlr.v4.tool.ast.RuleAST) RuleCollector(org.antlr.v4.semantics.RuleCollector) GrammarAST(org.antlr.v4.tool.ast.GrammarAST) LabelElementPair(org.antlr.v4.tool.LabelElementPair) ActionAST(org.antlr.v4.tool.ast.ActionAST) GrammarTransformPipeline(org.antlr.v4.tool.GrammarTransformPipeline) BasicSemanticChecks(org.antlr.v4.semantics.BasicSemanticChecks) RecognitionException(org.antlr.runtime.RecognitionException)

Example 10 with RuleAST

use of org.antlr.v4.tool.ast.RuleAST in project antlr4 by antlr.

the class Tool method checkForRuleIssues.

/**
	 * Important enough to avoid multiple definitions that we do very early,
	 * right after AST construction. Also check for undefined rules in
	 * parser/lexer to avoid exceptions later. Return true if we find multiple
	 * definitions of the same rule or a reference to an undefined rule or
	 * parser rule ref in lexer rule.
	 */
public boolean checkForRuleIssues(final Grammar g) {
    // check for redefined rules
    GrammarAST RULES = (GrammarAST) g.ast.getFirstChildWithType(ANTLRParser.RULES);
    List<GrammarAST> rules = new ArrayList<GrammarAST>(RULES.getAllChildrenWithType(ANTLRParser.RULE));
    for (GrammarAST mode : g.ast.getAllChildrenWithType(ANTLRParser.MODE)) {
        rules.addAll(mode.getAllChildrenWithType(ANTLRParser.RULE));
    }
    boolean redefinition = false;
    final Map<String, RuleAST> ruleToAST = new HashMap<String, RuleAST>();
    for (GrammarAST r : rules) {
        RuleAST ruleAST = (RuleAST) r;
        GrammarAST ID = (GrammarAST) ruleAST.getChild(0);
        String ruleName = ID.getText();
        RuleAST prev = ruleToAST.get(ruleName);
        if (prev != null) {
            GrammarAST prevChild = (GrammarAST) prev.getChild(0);
            g.tool.errMgr.grammarError(ErrorType.RULE_REDEFINITION, g.fileName, ID.getToken(), ruleName, prevChild.getToken().getLine());
            redefinition = true;
            continue;
        }
        ruleToAST.put(ruleName, ruleAST);
    }
    // check for undefined rules
    class UndefChecker extends GrammarTreeVisitor {

        public boolean badref = false;

        @Override
        public void tokenRef(TerminalAST ref) {
            if ("EOF".equals(ref.getText())) {
                // this is a special predefined reference
                return;
            }
            if (g.isLexer())
                ruleRef(ref, null);
        }

        @Override
        public void ruleRef(GrammarAST ref, ActionAST arg) {
            RuleAST ruleAST = ruleToAST.get(ref.getText());
            String fileName = ref.getToken().getInputStream().getSourceName();
            if (Character.isUpperCase(currentRuleName.charAt(0)) && Character.isLowerCase(ref.getText().charAt(0))) {
                badref = true;
                errMgr.grammarError(ErrorType.PARSER_RULE_REF_IN_LEXER_RULE, fileName, ref.getToken(), ref.getText(), currentRuleName);
            } else if (ruleAST == null) {
                badref = true;
                errMgr.grammarError(ErrorType.UNDEFINED_RULE_REF, fileName, ref.token, ref.getText());
            }
        }

        @Override
        public ErrorManager getErrorManager() {
            return errMgr;
        }
    }
    UndefChecker chk = new UndefChecker();
    chk.visitGrammar(g.ast);
    return redefinition || chk.badref;
}
Also used : RuleAST(org.antlr.v4.tool.ast.RuleAST) HashMap(java.util.HashMap) GrammarTreeVisitor(org.antlr.v4.parse.GrammarTreeVisitor) GrammarAST(org.antlr.v4.tool.ast.GrammarAST) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArrayList(java.util.ArrayList) TerminalAST(org.antlr.v4.tool.ast.TerminalAST) ActionAST(org.antlr.v4.tool.ast.ActionAST)

Aggregations

GrammarAST (org.antlr.v4.tool.ast.GrammarAST)8 RuleAST (org.antlr.v4.tool.ast.RuleAST)7 Rule (org.antlr.v4.tool.Rule)4 LeftRecursiveRule (org.antlr.v4.tool.LeftRecursiveRule)3 ActionAST (org.antlr.v4.tool.ast.ActionAST)3 AltAST (org.antlr.v4.tool.ast.AltAST)3 BlockAST (org.antlr.v4.tool.ast.BlockAST)3 TerminalAST (org.antlr.v4.tool.ast.TerminalAST)3 ArrayList (java.util.ArrayList)2 HashMap (java.util.HashMap)2 LinkedHashMap (java.util.LinkedHashMap)2 CommonToken (org.antlr.runtime.CommonToken)2 RecognitionException (org.antlr.runtime.RecognitionException)2 GrammarASTAdaptor (org.antlr.v4.parse.GrammarASTAdaptor)2 CopyOnWriteArrayList (java.util.concurrent.CopyOnWriteArrayList)1 ANTLRStringStream (org.antlr.runtime.ANTLRStringStream)1 CommonTokenStream (org.antlr.runtime.CommonTokenStream)1 ParserRuleReturnScope (org.antlr.runtime.ParserRuleReturnScope)1 Token (org.antlr.runtime.Token)1 OrderedHashMap (org.antlr.v4.misc.OrderedHashMap)1