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);
   try {
     ParserRuleReturnScope r = p.rule();
     RuleAST tree = (RuleAST) r.getTree();
     GrammarTransformPipeline.setGrammarPtr(g, tree);
     GrammarTransformPipeline.augmentTokensWithOriginalPosition(g, tree);
     return tree;
   } catch (Exception e) {
     tool.errMgr.toolError(
         ErrorType.INTERNAL_ERROR,
         "error parsing rule created during left-recursion detection: " + ruleText,
         e);
   }
   return null;
 }
  /** 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;
  }