Exemple #1
0
  public static Map<Integer, Interval> getStateToGrammarRegionMap(
      GrammarRootAST ast, IntervalSet grammarTokenTypes) {
    Map<Integer, Interval> stateToGrammarRegionMap = new HashMap<Integer, Interval>();
    if (ast == null) return stateToGrammarRegionMap;

    List<GrammarAST> nodes = ast.getNodesWithType(grammarTokenTypes);
    for (GrammarAST n : nodes) {
      if (n.atnState != null) {
        Interval tokenRegion = Interval.of(n.getTokenStartIndex(), n.getTokenStopIndex());
        org.antlr.runtime.tree.Tree ruleNode = null;
        // RULEs, BLOCKs of transformed recursive rules point to original token interval
        switch (n.getType()) {
          case ANTLRParser.RULE:
            ruleNode = n;
            break;
          case ANTLRParser.BLOCK:
          case ANTLRParser.CLOSURE:
            ruleNode = n.getAncestor(ANTLRParser.RULE);
            break;
        }
        if (ruleNode instanceof RuleAST) {
          String ruleName = ((RuleAST) ruleNode).getRuleName();
          Rule r = ast.g.getRule(ruleName);
          if (r instanceof LeftRecursiveRule) {
            RuleAST originalAST = ((LeftRecursiveRule) r).getOriginalAST();
            tokenRegion =
                Interval.of(originalAST.getTokenStartIndex(), originalAST.getTokenStopIndex());
          }
        }
        stateToGrammarRegionMap.put(n.atnState.stateNumber, tokenRegion);
      }
    }
    return stateToGrammarRegionMap;
  }
 @Test
 public void testAplusSingleAltHasPlusASTPointingAtLoopBackState() throws Exception {
   Grammar g =
       new Grammar(
           "parser grammar P;\n"
               + "s : a B ;\n"
               + // (RULE a (BLOCK (ALT (+ (BLOCK (ALT A))))))
               "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());
 }
 /**
  *
  *
  * <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 >= $_p}? '*' (= b e) {$v = $a.v * $b.v;})
  * 			(ALT {6 >= $_p}? '+' (= b e) {$v = $a.v + $b.v;})
  * 			(ALT {3 >= $_p}? '++') (ALT {2 >= $_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);
   BlockAST opsBlk = (BlockAST) mainAlt.getChild(1).getChild(0); // (* BLOCK ...)
   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());
   }
 }
  /** 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) {
      isLeftRec = false; // didn't match; oh well
    }
    if (!isLeftRec) return false;

    // replace old rule's AST
    GrammarAST RULES = (GrammarAST) ast.getFirstChildWithType(ANTLRParser.RULES);
    String newRuleText = leftRecursiveRuleWalker.getArtificialOpPrecRule();
    //		System.out.println("created: "+newRuleText);
    RuleAST t = parseArtificialRule(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.prefixAlts);
    r.recPrimaryAlts.addAll(leftRecursiveRuleWalker.otherAlts);
    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.tool.errMgr);
      r.args.type = AttributeDict.DictType.ARG;
      r.args.ast = arg;
      arg.resolver = r.alt[1]; // todo: isn't this Rule or something?
    }

    // define labels on recursive rule refs we delete; they don't point to nodes of course
    // 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;
  }