/**
         * <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 virtual void SetAltASTPointers(LeftRecursiveRule r, RuleAST t)
        {
            //System.Console.WriteLine("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.Count; i++)
            {
                LeftRecursiveRuleAltInfo altInfo = r.recPrimaryAlts[i];
                altInfo.altAST = (AltAST)primaryBlk.GetChild(i);
                altInfo.altAST.leftRecursiveAltInfo         = altInfo;
                altInfo.originalAltAST.leftRecursiveAltInfo = altInfo;
                //altInfo.originalAltAST.Parent = altInfo.altAST.Parent;
                //System.Console.WriteLine(altInfo.altAST.ToStringTree());
            }
            for (int i = 0; i < r.recOpAlts.Count; 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.Console.WriteLine(altInfo.altAST.ToStringTree());
            }
        }
        public override void FinishRule(RuleAST rule, GrammarAST ID, GrammarAST block)
        {
            if (rule.IsLexerRule())
            {
                return;
            }
            BlockAST   blk   = (BlockAST)rule.GetFirstChildWithType(BLOCK);
            int        nalts = blk.ChildCount;
            GrammarAST idAST = (GrammarAST)rule.GetChild(0);

            for (int i = 0; i < nalts; i++)
            {
                AltAST altAST = (AltAST)blk.GetChild(i);
                if (altAST.altLabel != null)
                {
                    string altLabel = altAST.altLabel.Text;
                    // first check that label doesn't conflict with a rule
                    // label X or x can't be rule x.
                    Rule r;
                    if (ruleCollector.rules.TryGetValue(Utils.Decapitalize(altLabel), out r) && r != null)
                    {
                        g.tool.errMgr.GrammarError(ErrorType.ALT_LABEL_CONFLICTS_WITH_RULE,
                                                   g.fileName, altAST.altLabel.Token,
                                                   altLabel,
                                                   r.name);
                    }
                    // Now verify that label X or x doesn't conflict with label
                    // in another rule. altLabelToRuleName has both X and x mapped.
                    string prevRuleForLabel;
                    if (ruleCollector.altLabelToRuleName.TryGetValue(altLabel, out prevRuleForLabel) && prevRuleForLabel != null && !prevRuleForLabel.Equals(rule.GetRuleName()))
                    {
                        g.tool.errMgr.GrammarError(ErrorType.ALT_LABEL_REDEF,
                                                   g.fileName, altAST.altLabel.Token,
                                                   altLabel,
                                                   rule.GetRuleName(),
                                                   prevRuleForLabel);
                    }
                }
            }
            IList <GrammarAST> altLabels;
            int numAltLabels = 0;

            if (ruleCollector.ruleToAltLabels.TryGetValue(rule.GetRuleName(), out altLabels) && altLabels != null)
            {
                numAltLabels = altLabels.Count;
            }
            if (numAltLabels > 0 && nalts != numAltLabels)
            {
                g.tool.errMgr.GrammarError(ErrorType.RULE_WITH_TOO_FEW_ALT_LABELS,
                                           g.fileName, idAST.Token, rule.GetRuleName());
            }
        }