Search in sources :

Example 1 with LabelElementPair

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

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

the class SymbolChecks method checkForLabelConflicts.

/**
 * Make sure a label doesn't conflict with another symbol.
 * Labels must not conflict with: rules, tokens, scope names,
 * return values, parameters, and rule-scope dynamic attributes
 * defined in surrounding rule.  Also they must have same type
 * for repeated defs.
 */
public void checkForLabelConflicts(Collection<Rule> rules) {
    for (Rule r : rules) {
        checkForAttributeConflicts(r);
        Map<String, LabelElementPair> labelNameSpace = new HashMap<String, LabelElementPair>();
        for (int i = 1; i <= r.numberOfAlts; i++) {
            Alternative a = r.alt[i];
            for (List<LabelElementPair> pairs : a.labelDefs.values()) {
                if (r.hasAltSpecificContexts()) {
                    // Collect labelName-labeledRules map for rule with alternative labels.
                    Map<String, List<LabelElementPair>> labelPairs = new HashMap<String, List<LabelElementPair>>();
                    for (LabelElementPair p : pairs) {
                        String labelName = findAltLabelName(p.label);
                        if (labelName != null) {
                            List<LabelElementPair> list;
                            if (labelPairs.containsKey(labelName)) {
                                list = labelPairs.get(labelName);
                            } else {
                                list = new ArrayList<LabelElementPair>();
                                labelPairs.put(labelName, list);
                            }
                            list.add(p);
                        }
                    }
                    for (List<LabelElementPair> internalPairs : labelPairs.values()) {
                        labelNameSpace.clear();
                        checkLabelPairs(r, labelNameSpace, internalPairs);
                    }
                } else {
                    checkLabelPairs(r, labelNameSpace, pairs);
                }
            }
        }
    }
}
Also used : Alternative(org.antlr.v4.tool.Alternative) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) List(java.util.List) Rule(org.antlr.v4.tool.Rule) LeftRecursiveRule(org.antlr.v4.tool.LeftRecursiveRule) LabelElementPair(org.antlr.v4.tool.LabelElementPair)

Example 3 with LabelElementPair

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

the class SymbolChecks method checkLabelPairs.

private void checkLabelPairs(Rule r, Map<String, LabelElementPair> labelNameSpace, List<LabelElementPair> pairs) {
    for (LabelElementPair p : pairs) {
        checkForLabelConflict(r, p.label);
        String name = p.label.getText();
        LabelElementPair prev = labelNameSpace.get(name);
        if (prev == null) {
            labelNameSpace.put(name, p);
        } else {
            checkForTypeMismatch(r, prev, p);
        }
    }
}
Also used : LabelElementPair(org.antlr.v4.tool.LabelElementPair)

Example 4 with LabelElementPair

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

the class SymbolCollector method label.

@Override
public void label(GrammarAST op, GrammarAST ID, GrammarAST element) {
    LabelElementPair lp = new LabelElementPair(g, ID, element, op.getType());
    currentRule.alt[currentOuterAltNumber].labelDefs.map(ID.getText(), lp);
}
Also used : LabelElementPair(org.antlr.v4.tool.LabelElementPair)

Example 5 with LabelElementPair

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

the class SymbolChecks method checkLabelPairs.

private void checkLabelPairs(Rule r, Map<String, LabelElementPair> labelNameSpace, List<LabelElementPair> pairs) {
    for (LabelElementPair p : pairs) {
        checkForLabelConflict(r, p.label);
        String name = p.label.getText();
        LabelElementPair prev = labelNameSpace.get(name);
        if (prev == null) {
            labelNameSpace.put(name, p);
        } else {
            checkForTypeMismatch(r, prev, p);
        }
    }
}
Also used : LabelElementPair(org.antlr.v4.tool.LabelElementPair)

Aggregations

LabelElementPair (org.antlr.v4.tool.LabelElementPair)8 ArrayList (java.util.ArrayList)2 HashMap (java.util.HashMap)2 List (java.util.List)2 RecognitionException (org.antlr.runtime.RecognitionException)2 BasicSemanticChecks (org.antlr.v4.semantics.BasicSemanticChecks)2 RuleCollector (org.antlr.v4.semantics.RuleCollector)2 Alternative (org.antlr.v4.tool.Alternative)2 GrammarTransformPipeline (org.antlr.v4.tool.GrammarTransformPipeline)2 LeftRecursiveRule (org.antlr.v4.tool.LeftRecursiveRule)2 Rule (org.antlr.v4.tool.Rule)2 ActionAST (org.antlr.v4.tool.ast.ActionAST)2 GrammarAST (org.antlr.v4.tool.ast.GrammarAST)2 RuleAST (org.antlr.v4.tool.ast.RuleAST)2