Search in sources :

Example 1 with GrammarTransformPipeline

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

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 (Tuple2<GrammarAST, String> pair : leftRecursiveRuleWalker.leftRecursiveRuleRefLabels) {
        GrammarAST labelNode = pair.getItem1();
        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 2 with GrammarTransformPipeline

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

the class Tool method process.

/**
 * To process a grammar, we load all of its imported grammars into
 *		subordinate grammar objects. Then we merge the imported rules
 *		into the root grammar. If a root grammar is a combined grammar,
 *		we have to extract the implicit lexer. Once all this is done, we
 *		process the lexer first, if present, and then the parser grammar
 */
public void process(Grammar g, boolean gencode) {
    g.loadImportedGrammars();
    GrammarTransformPipeline transform = new GrammarTransformPipeline(g, this);
    transform.process();
    LexerGrammar lexerg;
    GrammarRootAST lexerAST;
    if (g.ast != null && g.ast.grammarType == ANTLRParser.COMBINED && !g.ast.hasErrors) {
        // alters g.ast
        lexerAST = transform.extractImplicitLexer(g);
        if (lexerAST != null) {
            if (grammarOptions != null) {
                lexerAST.cmdLineOptions = grammarOptions;
            }
            lexerg = new LexerGrammar(this, lexerAST);
            lexerg.fileName = g.fileName;
            lexerg.originalGrammar = g;
            g.implicitLexer = lexerg;
            lexerg.implicitLexerOwner = g;
            processNonCombinedGrammar(lexerg, gencode);
        // System.out.println("lexer tokens="+lexerg.tokenNameToTypeMap);
        // System.out.println("lexer strings="+lexerg.stringLiteralToTypeMap);
        }
    }
    if (g.implicitLexer != null)
        g.importVocab(g.implicitLexer);
    // System.out.println("tokens="+g.tokenNameToTypeMap);
    // System.out.println("strings="+g.stringLiteralToTypeMap);
    processNonCombinedGrammar(g, gencode);
}
Also used : GrammarTransformPipeline(org.antlr.v4.tool.GrammarTransformPipeline) GrammarRootAST(org.antlr.v4.tool.ast.GrammarRootAST) LexerGrammar(org.antlr.v4.tool.LexerGrammar)

Example 3 with GrammarTransformPipeline

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

the class Tool method process.

/**
 * To process a grammar, we load all of its imported grammars into
 *		subordinate grammar objects. Then we merge the imported rules
 *		into the root grammar. If a root grammar is a combined grammar,
 *		we have to extract the implicit lexer. Once all this is done, we
 *		process the lexer first, if present, and then the parser grammar
 */
public void process(Grammar g, boolean gencode) {
    g.loadImportedGrammars();
    GrammarTransformPipeline transform = new GrammarTransformPipeline(g, this);
    transform.process();
    LexerGrammar lexerg;
    GrammarRootAST lexerAST;
    if (g.ast != null && g.ast.grammarType == ANTLRParser.COMBINED && !g.ast.hasErrors) {
        // alters g.ast
        lexerAST = transform.extractImplicitLexer(g);
        if (lexerAST != null) {
            if (grammarOptions != null) {
                lexerAST.cmdLineOptions = grammarOptions;
            }
            lexerg = new LexerGrammar(this, lexerAST);
            lexerg.fileName = g.fileName;
            lexerg.originalGrammar = g;
            g.implicitLexer = lexerg;
            lexerg.implicitLexerOwner = g;
            int prevErrors = errMgr.getNumErrors();
            processNonCombinedGrammar(lexerg, gencode);
            if (errMgr.getNumErrors() > prevErrors) {
                return;
            }
        // System.out.println("lexer tokens="+lexerg.tokenNameToTypeMap);
        // System.out.println("lexer strings="+lexerg.stringLiteralToTypeMap);
        }
    }
    if (g.implicitLexer != null)
        g.importVocab(g.implicitLexer);
    // System.out.println("tokens="+g.tokenNameToTypeMap);
    // System.out.println("strings="+g.stringLiteralToTypeMap);
    processNonCombinedGrammar(g, gencode);
}
Also used : GrammarTransformPipeline(org.antlr.v4.tool.GrammarTransformPipeline) GrammarRootAST(org.antlr.v4.tool.ast.GrammarRootAST) LexerGrammar(org.antlr.v4.tool.LexerGrammar)

Example 4 with GrammarTransformPipeline

use of org.antlr.v4.tool.GrammarTransformPipeline 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)

Aggregations

GrammarTransformPipeline (org.antlr.v4.tool.GrammarTransformPipeline)4 RecognitionException (org.antlr.runtime.RecognitionException)2 BasicSemanticChecks (org.antlr.v4.semantics.BasicSemanticChecks)2 RuleCollector (org.antlr.v4.semantics.RuleCollector)2 LabelElementPair (org.antlr.v4.tool.LabelElementPair)2 LexerGrammar (org.antlr.v4.tool.LexerGrammar)2 ActionAST (org.antlr.v4.tool.ast.ActionAST)2 GrammarAST (org.antlr.v4.tool.ast.GrammarAST)2 GrammarRootAST (org.antlr.v4.tool.ast.GrammarRootAST)2 RuleAST (org.antlr.v4.tool.ast.RuleAST)2