Exemple #1
0
            public void Action(Expansion e)
            {
                if (e is Sequence)
                {
                    if (e.Parent is Choice || e.Parent is ZeroOrMore ||
                        e.Parent is OneOrMore || e.Parent is ZeroOrOne)
                    {
                        return;
                    }
                    Sequence  seq = (Sequence)e;
                    Lookahead la  = (Lookahead)(seq.Units[0]);
                    if (!la.IsExplicit)
                    {
                        return;
                    }

                    // Create a singleton choice with an empty action.
                    Choice ch = new Choice();
                    ch.Line   = la.Line;
                    ch.Column = la.Column;
                    ch.Parent = seq;
                    Sequence seq1 = new Sequence();
                    seq1.Line   = la.Line;
                    seq1.Column = la.Column;
                    seq1.Parent = ch;
                    seq1.Units.Add(la);
                    la.Parent = seq1;
                    Action act = new Action();
                    act.Line   = la.Line;
                    act.Column = la.Column;
                    act.Parent = seq1;
                    seq1.Units.Add(act);
                    ch.Choices.Add(seq1);
                    if (la.Amount != 0)
                    {
                        if (la.ActionTokens.Count != 0)
                        {
                            CSharpCCErrors.Warning(la,
                                                   "Encountered LOOKAHEAD(...) at a non-choice location.  " +
                                                   "Only semantic lookahead will be considered here.");
                        }
                        else
                        {
                            CSharpCCErrors.Warning(la, "Encountered LOOKAHEAD(...) at a non-choice location.  This will be ignored.");
                        }
                    }
                    // Now we have moved the lookahead into the singleton choice.  Now create
                    // a new dummy lookahead node to replace this one at its original location.
                    Lookahead la1 = new Lookahead();
                    la1.IsExplicit = false;
                    la1.Line       = la.Line;
                    la1.Column     = la.Column;
                    la1.Parent     = seq;
                    // Now set the la_expansion field of la and la1 with a dummy expansion (we use EOF).
                    la.Expansion  = new REndOfFile();
                    la1.Expansion = new REndOfFile();
                    seq.Units[0]  = la1;
                    seq.Units[1]  = ch;
                }
            }
Exemple #2
0
        public void CheckUnmatchability()
        {
            RegularExpression curRE;
            int numStrings = 0;

            for (int i = 0; i < choices.Count; i++)
            {
                if (!(curRE = choices[i]).IsPrivate &&
                    //curRE instanceof RJustName &&
                    curRE.Ordinal > 0 && curRE.Ordinal < Ordinal &&
                    LexGen.lexStates[curRE.Ordinal] == LexGen.lexStates[Ordinal])
                {
                    if (Label != null)
                    {
                        CSharpCCErrors.Warning(this, "Regular Expression choice : " + curRE.Label + " can never be matched as : " + Label);
                    }
                    else
                    {
                        CSharpCCErrors.Warning(this, "Regular Expression choice : " + curRE.Label + " can never be matched as token of kind : " + Ordinal);
                    }
                }

                if (!curRE.IsPrivate && curRE is RStringLiteral)
                {
                    numStrings++;
                }
            }
        }
Exemple #3
0
        public static void ebnfCalc(Expansion exp, Expansion nested)
        {
            // exp is one of OneOrMore, ZeroOrMore, ZeroOrOne
            MatchInfo         m, m1 = null;
            IList <MatchInfo> v, first, follow;
            int la;

            for (la = 1; la <= Options.getOtherAmbiguityCheck(); la++)
            {
                MatchInfo.laLimit = la;
                LookaheadWalk.sizeLimitedMatches = new List <MatchInfo>();
                m = new MatchInfo();
                m.firstFreeLoc = 0;
                v = new List <MatchInfo>();
                v.Add(m);
                LookaheadWalk.considerSemanticLA = !Options.getForceLaCheck();
                LookaheadWalk.genFirstSet(v, nested);
                first = LookaheadWalk.sizeLimitedMatches;
                LookaheadWalk.sizeLimitedMatches = new List <MatchInfo>();
                LookaheadWalk.considerSemanticLA = false;
                LookaheadWalk.genFollowSet(v, exp, Expansion.NextGenerationIndex++);
                follow = LookaheadWalk.sizeLimitedMatches;
                if (la == 1)
                {
                    if (CodeCheck(first))
                    {
                        CSharpCCErrors.Warning(nested,
                                               "CSHARPCODE non-terminal within " + image(exp) +
                                               " construct will force this construct to be entered in favor of " +
                                               "expansions occurring after construct.");
                    }
                }
                if ((m = overlap(first, follow)) == null)
                {
                    break;
                }
                m1 = m;
            }
            if (la > Options.getOtherAmbiguityCheck())
            {
                CSharpCCErrors.Warning("Choice conflict in " + image(exp) + " construct " +
                                       "at line " + exp.Line + ", column " + exp.Column + ".");
                Console.Error.WriteLine("         Expansion nested within construct and expansion following construct");
                Console.Error.WriteLine("         have common prefixes, one of which is: " + image(m1));
                Console.Error.WriteLine("         Consider using a lookahead of " + la + " or more for nested expansion.");
            }
            else if (la > 1)
            {
                CSharpCCErrors.Warning("Choice conflict in " + image(exp) + " construct " +
                                       "at line " + exp.Line + ", column " + exp.Column + ".");
                Console.Error.WriteLine("         Expansion nested within construct and expansion following construct");
                Console.Error.WriteLine("         have common prefixes, one of which is: " + image(m1));
                Console.Error.WriteLine("         Consider using a lookahead of " + la + " for nested expansion.");
            }
        }
 public static void add_token_manager_decls(Token t, IList <Token> decls)
 {
     if (CSharpCCGlobals.token_mgr_decls != null)
     {
         CSharpCCErrors.ParseError(t, "Multiple occurrence of \"TOKEN_MGR_DECLS\".");
     }
     else
     {
         CSharpCCGlobals.token_mgr_decls = decls;
         if (Options.getUserTokenManager())
         {
             CSharpCCErrors.Warning(t, "Ignoring declarations in \"TOKEN_MGR_DECLS\" since option " +
                                    "USER_TOKEN_MANAGER has been set to true.");
         }
     }
 }
Exemple #5
0
        public static void Normalize()
        {
            if (getDebugLookahead() && !getDebugParser())
            {
                if (cmdLineSetting.Contains("DEBUG_PARSER") ||
                    inputFileSetting.Contains("DEBUG_PARSER"))
                {
                    CSharpCCErrors.Warning("True setting of option DEBUG_LOOKAHEAD overrides " +
                                           "false setting of option DEBUG_PARSER.");
                }
                optionValues.Add("DEBUG_PARSER", true);
            }

            // Now set the "GENERATE" options from the supplied (or default) JDK version.

            optionValues["GENERATE_CHAINED_EXCEPTION"] = clrVersionAtLeast(1.1);
            optionValues["GENERATE_GENERICS"]          = clrVersionAtLeast(2.0);
            optionValues["GENERATE_STRING_BUILDER"]    = clrVersionAtLeast(1.1);
        }
Exemple #6
0
        public static void SetInputFileOption(object nameloc, object valueloc, string name, object value)
        {
            string s = name.ToUpper();

            if (!optionValues.ContainsKey(s))
            {
                CSharpCCErrors.Warning(nameloc, "Bad option name \"" + name + "\".  Option setting will be ignored.");
                return;
            }

            object existingValue;

            value = UpgradeValue(name, value);

            if (optionValues.TryGetValue(s, out existingValue))
            {
                if ((existingValue.GetType() != value.GetType()) ||
                    (value is int && ((int)value) <= 0))
                {
                    CSharpCCErrors.Warning(valueloc, "Bad option value \"" + value + "\" for \"" + name + "\".  Option setting will be ignored.");
                    return;
                }

                if (inputFileSetting.Contains(s))
                {
                    CSharpCCErrors.Warning(nameloc, "Duplicate option setting for \"" + name + "\" will be ignored.");
                    return;
                }

                if (cmdLineSetting.Contains(s))
                {
                    if (!existingValue.Equals(value))
                    {
                        CSharpCCErrors.Warning(nameloc, "Command line setting of \"" + name + "\" modifies option value in file.");
                    }
                    return;
                }
            }

            optionValues[s] = value;
            inputFileSetting.Add(s);
        }
Exemple #7
0
        public static void CreateOutputDir(string outputDir)
        {
            if (!Directory.Exists(outputDir))
            {
                CSharpCCErrors.Warning("Output directory \"" + outputDir + "\" does not exist. Creating the directory.");

                if (Directory.CreateDirectory(outputDir) == null)
                {
                    CSharpCCErrors.SemanticError("Cannot create the output directory : " + outputDir);
                    return;
                }
            }

            /*
             * TODO:
             * if (!outputDir.canWrite())
             * {
             *  CSharpCCErrors.SemanticError("Cannot write to the output output directory : \"" + outputDir + "\"");
             *  return;
             * }
             */
        }
        public static void addregexpr(TokenProduction p)
        {
            int ii;

            CSharpCCGlobals.rexprlist.Add(p);
            if (Options.getUserTokenManager())
            {
                if (p.LexStates == null ||
                    p.LexStates.Length != 1 ||
                    !p.LexStates[0].Equals("DEFAULT"))
                {
                    CSharpCCErrors.Warning(p, "Ignoring lexical state specifications since option " +
                                           "USER_TOKEN_MANAGER has been set to true.");
                }
            }
            if (p.LexStates == null)
            {
                return;
            }
            for (int i = 0; i < p.LexStates.Length; i++)
            {
                for (int j = 0; j < i; j++)
                {
                    if (p.LexStates[i].Equals(p.LexStates[j]))
                    {
                        CSharpCCErrors.ParseError(p, "Multiple occurrence of \"" + p.LexStates[i] + "\" in lexical state list.");
                    }
                }
                if (!CSharpCCGlobals.lexstate_S2I.ContainsKey(p.LexStates[i]))
                {
                    ii = nextFreeLexState++;
                    CSharpCCGlobals.lexstate_S2I[p.LexStates[i]]        = ii;
                    CSharpCCGlobals.lexstate_I2S[ii]                    = p.LexStates[i];
                    CSharpCCGlobals.simple_tokens_table[p.LexStates[i]] = new Dictionary <string, IDictionary <string, RegularExpression> >();
                }
            }
        }
Exemple #9
0
        public static void choiceCalc(Choice choice)
        {
            int first = firstChoice(choice);

            // dbl[i] and dbr[i] are lists of size limited matches for choice i
            // of choice.  dbl ignores matches with semantic lookaheads (when force_la_check
            // is false), while dbr ignores semantic lookahead.
            IList <MatchInfo>[] dbl       = new IList <MatchInfo> [choice.Choices.Count];
            IList <MatchInfo>[] dbr       = new IList <MatchInfo> [choice.Choices.Count];
            int[]             minLA       = new int[choice.Choices.Count - 1];
            MatchInfo[]       overlapInfo = new MatchInfo[choice.Choices.Count - 1];
            int[]             other       = new int[choice.Choices.Count - 1];
            MatchInfo         m;
            IList <MatchInfo> v;
            bool overlapDetected;

            for (int la = 1; la <= Options.getChoiceAmbiguityCheck(); la++)
            {
                MatchInfo.laLimit = la;
                LookaheadWalk.considerSemanticLA = !Options.getForceLaCheck();
                for (int i = first; i < choice.Choices.Count - 1; i++)
                {
                    LookaheadWalk.sizeLimitedMatches = new List <MatchInfo>();
                    m = new MatchInfo();
                    m.firstFreeLoc = 0;
                    v = new List <MatchInfo>();
                    v.Add(m);
                    LookaheadWalk.genFirstSet(v, (Expansion)choice.Choices[i]);
                    dbl[i] = LookaheadWalk.sizeLimitedMatches;
                }
                LookaheadWalk.considerSemanticLA = false;
                for (int i = first + 1; i < choice.Choices.Count; i++)
                {
                    LookaheadWalk.sizeLimitedMatches = new List <MatchInfo>();
                    m = new MatchInfo();
                    m.firstFreeLoc = 0;
                    v = new List <MatchInfo>();
                    v.Add(m);
                    LookaheadWalk.genFirstSet(v, (Expansion)choice.Choices[i]);
                    dbr[i] = LookaheadWalk.sizeLimitedMatches;
                }
                if (la == 1)
                {
                    for (int i = first; i < choice.Choices.Count - 1; i++)
                    {
                        Expansion exp = (Expansion)choice.Choices[i];
                        if (Semanticize.EmptyExpansionExists(exp))
                        {
                            CSharpCCErrors.Warning(exp,
                                                   "This choice can expand to the empty token sequence " +
                                                   "and will therefore always be taken in favor of the choices appearing later.");
                            break;
                        }
                        else if (CodeCheck(dbl[i]))
                        {
                            CSharpCCErrors.Warning(exp,
                                                   "CSHARPCODE non-terminal will force this choice to be taken " +
                                                   "in favor of the choices appearing later.");
                            break;
                        }
                    }
                }
                overlapDetected = false;
                for (int i = first; i < choice.Choices.Count - 1; i++)
                {
                    for (int j = i + 1; j < choice.Choices.Count; j++)
                    {
                        if ((m = overlap(dbl[i], dbr[j])) != null)
                        {
                            minLA[i]        = la + 1;
                            overlapInfo[i]  = m;
                            other[i]        = j;
                            overlapDetected = true;
                            break;
                        }
                    }
                }
                if (!overlapDetected)
                {
                    break;
                }
            }
            for (int i = first; i < choice.Choices.Count - 1; i++)
            {
                if (explicitLA((Expansion)choice.Choices[i]) && !Options.getForceLaCheck())
                {
                    continue;
                }
                if (minLA[i] > Options.getChoiceAmbiguityCheck())
                {
                    CSharpCCErrors.Warning("Choice conflict involving two expansions at");
                    Console.Error.Write("         line " + ((Expansion)choice.Choices[i]).Line);
                    Console.Error.Write(", column " + ((Expansion)choice.Choices[i]).Column);
                    Console.Error.Write(" and line " + ((Expansion)choice.Choices[other[i]]).Line);
                    Console.Error.Write(", column " + ((Expansion)choice.Choices[other[i]]).Column);
                    Console.Error.WriteLine(" respectively.");
                    Console.Error.WriteLine("         A common prefix is: " + image(overlapInfo[i]));
                    Console.Error.WriteLine("         Consider using a lookahead of " + minLA[i] + " or more for earlier expansion.");
                }
                else if (minLA[i] > 1)
                {
                    CSharpCCErrors.Warning("Choice conflict involving two expansions at");
                    Console.Error.Write("         line " + ((Expansion)choice.Choices[i]).Line);
                    Console.Error.Write(", column " + ((Expansion)choice.Choices[i]).Column);
                    Console.Error.Write(" and line " + ((Expansion)choice.Choices[other[i]]).Line);
                    Console.Error.Write(", column " + ((Expansion)choice.Choices[other[i]]).Column);
                    Console.Error.WriteLine(" respectively.");
                    Console.Error.WriteLine("         A common prefix is: " + image(overlapInfo[i]));
                    Console.Error.WriteLine("         Consider using a lookahead of " + minLA[i] + " for earlier expansion.");
                }
            }
        }
Exemple #10
0
        public static void start()
        {
            Token t = null;

            keepLineCol = Options.getKeepLineColumn();

            if (CSharpCCErrors.ErrorCount != 0)
            {
                throw new MetaParseException();
            }

            CSharpFiles.GenerateTokenManagerError();
            CSharpFiles.GenerateParseException();
            CSharpFiles.GenerateToken();
            if (Options.getUserTokenManager())
            {
                CSharpFiles.GenerateITokenManager();
            }
            else if (Options.getUserCharStream())
            {
                CSharpFiles.GenerateICharStream();
            }
            else
            {
                if (Options.getUnicodeEscape())
                {
                    CSharpFiles.GenerateUnicodeCharStream();
                }
                else
                {
                    CSharpFiles.GenerateSimpleCharStream();
                }
            }

            try {
                ostr =
                    new StreamWriter(
                        new BufferedStream(
                            new FileStream(Path.Combine(Options.getOutputDirectory().FullName, CSharpCCGlobals.cu_name + "Constants.cs"),
                                           FileMode.OpenOrCreate, FileAccess.Write), 8192));
            } catch (IOException) {
                CSharpCCErrors.SemanticError("Could not open file " + CSharpCCGlobals.cu_name + "Constants.cs for writing.");
                throw new InvalidOperationException();
            }

            List <string> tn = new List <string>(CSharpCCGlobals.ToolNames);

            tn.Add(CSharpCCGlobals.ToolName);
            ostr.WriteLine("/* " + CSharpCCGlobals.GetIdString(tn, CSharpCCGlobals.cu_name + "Constants.cs") + " */");

            bool namespaceInserted = false;

            if (CSharpCCGlobals.cu_to_insertion_point_1.Count != 0 &&
                CSharpCCGlobals.cu_to_insertion_point_1[0].kind == CSharpCCParserConstants.NAMESPACE)
            {
                namespaceInserted = true;
                for (int i = 1; i < CSharpCCGlobals.cu_to_insertion_point_1.Count; i++)
                {
                    if (CSharpCCGlobals.cu_to_insertion_point_1[i].kind == CSharpCCParserConstants.SEMICOLON)
                    {
                        CSharpCCGlobals.PrintTokenSetup(CSharpCCGlobals.cu_to_insertion_point_1[0]);
                        for (int j = 0; j <= i; j++)
                        {
                            t = (CSharpCCGlobals.cu_to_insertion_point_1[j]);
                            if (t.kind != CSharpCCParserConstants.SEMICOLON)
                            {
                                CSharpCCGlobals.PrintToken(t, ostr);
                            }
                        }
                        CSharpCCGlobals.PrintTrailingComments(t, ostr);
                        break;
                    }
                }

                ostr.WriteLine("{");
            }
            ostr.WriteLine("");
            ostr.WriteLine("/// <summary>");
            ostr.WriteLine("/// Token literal values and constants.");
            ostr.WriteLine("/// <summary>");
            if (Options.getSupportClassVisibilityPublic())
            {
                ostr.Write("public ");
            }
            ostr.WriteLine("class " + CSharpCCGlobals.cu_name + "Constants {");
            ostr.WriteLine("");
            ostr.WriteLine("  /// <summary> End of File</summary>");
            ostr.WriteLine("  public const int EOF = 0;");

            foreach (RegularExpression re in CSharpCCGlobals.ordered_named_tokens)
            {
                ostr.WriteLine("  /// <summary>RegularExpression Id.</summary>");
                ostr.WriteLine("  public const int " + re.Label + " = " + re.Ordinal + ";");
            }
            ostr.WriteLine("");
            if (!Options.getUserTokenManager() && Options.getBuildTokenManager())
            {
                for (int i = 0; i < LexGen.lexStateName.Length; i++)
                {
                    ostr.WriteLine("  /// <summary>Lexical state.</summary>");
                    ostr.WriteLine("  public const int " + LexGen.lexStateName[i] + " = " + i + ";");
                }
                ostr.WriteLine("");
            }
            ostr.WriteLine("  /// <summary>Literal token values.</summary>");
            ostr.WriteLine("  public static readonly string[] TokenImage = {");
            ostr.WriteLine("    \"<EOF>\",");

            foreach (TokenProduction tp in CSharpCCGlobals.rexprlist)
            {
                IList <RegExprSpec> respecs = tp.RegexSpecs;
                foreach (RegExprSpec res in respecs)
                {
                    RegularExpression re = res.RegularExpression;
                    if (re is RStringLiteral)
                    {
                        ostr.WriteLine("    \"\\\"" + CSharpCCGlobals.AddEscapes(CSharpCCGlobals.AddEscapes(((RStringLiteral)re).Image)) + "\\\"\",");
                    }
                    else
                    if (!re.Label.Equals(""))
                    {
                        ostr.WriteLine("    \"<" + re.Label + ">\",");
                    }
                    else
                    {
                        if (re.TokenProductionContext.Kind == TokenProduction.TOKEN)
                        {
                            CSharpCCErrors.Warning(re, "Consider giving this non-string token a label for better error reporting.");
                        }
                        ostr.WriteLine("    \"<token of kind " + re.Ordinal + ">\",");
                    }
                }
            }
            ostr.WriteLine("  };");
            ostr.WriteLine("");
            ostr.WriteLine("}");
            if (namespaceInserted)
            {
                ostr.WriteLine("}");
            }
            ostr.Close();
        }
Exemple #11
0
        public static void start()
        {
            if (CSharpCCErrors.ErrorCount != 0)
            {
                throw new MetaParseException();
            }

            if (Options.getLookahead() > 1 && !Options.getForceLaCheck() && Options.getSanityCheck())
            {
                CSharpCCErrors.Warning("Lookahead adequacy checking not being performed since option LOOKAHEAD " +
                                       "is more than 1.  Set option FORCE_LA_CHECK to true to force checking.");
            }

            /*
             * The following walks the entire parse tree to convert all LOOKAHEAD's
             * that are not at choice points (but at beginning of sequences) and converts
             * them to trivial choices.  This way, their semantic lookahead specification
             * can be evaluated during other lookahead evaluations.
             */
            foreach (var production in CSharpCCGlobals.bnfproductions)
            {
                ExpansionTreeWalker.PostOrderWalk(production.Expansion, new LookaheadFixer());
            }

            /*
             * The following loop populates "production_table"
             */
            foreach (var p in CSharpCCGlobals.bnfproductions)
            {
                if (CSharpCCGlobals.production_table.ContainsKey(p.Lhs))
                {
                    CSharpCCErrors.SemanticError(p, p.Lhs + " occurs on the left hand side of more than one production.");
                }
                else
                {
                    CSharpCCGlobals.production_table[p.Lhs] = p;
                }
            }

            /*
             * The following walks the entire parse tree to make sure that all
             * non-terminals on RHS's are defined on the LHS.
             */
            foreach (var production in CSharpCCGlobals.bnfproductions)
            {
                ExpansionTreeWalker.PreOrderWalk(production.Expansion, new ProductionDefinedChecker());
            }

            /*
             * The following loop ensures that all target lexical states are
             * defined.  Also piggybacking on this loop is the detection of
             * <EOF> and <name> in token productions.  After reporting an
             * error, these entries are removed.  Also checked are definitions
             * on inline private regular expressions.
             * This loop works slightly differently when USER_TOKEN_MANAGER
             * is set to true.  In this case, <name> occurrences are OK, while
             * regular expression specs generate a warning.
             */
            foreach (var tp in CSharpCCGlobals.rexprlist)
            {
                IList <RegExprSpec> respecs = tp.RegexSpecs;
                foreach (var res in respecs)
                {
                    if (res.NextState != null)
                    {
                        if (!CSharpCCGlobals.lexstate_S2I.ContainsKey(res.NextState))
                        {
                            CSharpCCErrors.SemanticError(res.NextStateToken,
                                                         "Lexical state \"" + res.NextState +
                                                         "\" has not been defined.");
                        }
                    }
                    if (res.RegularExpression is REndOfFile)
                    {
                        //CSharpCCErrors.SemanticError(res.RegularExpression, "Badly placed <EOF>.");
                        if (tp.LexStates != null)
                        {
                            CSharpCCErrors.SemanticError(res.RegularExpression,
                                                         "EOF action/state change must be specified for all states, " +
                                                         "i.e., <*>TOKEN:.");
                        }
                        if (tp.Kind != TokenProduction.TOKEN)
                        {
                            CSharpCCErrors.SemanticError(res.RegularExpression,
                                                         "EOF action/state change can be specified only in a " +
                                                         "TOKEN specification.");
                        }
                        if (CSharpCCGlobals.nextStateForEof != null ||
                            CSharpCCGlobals.actForEof != null)
                        {
                            CSharpCCErrors.SemanticError(res.RegularExpression, "Duplicate action/state change specification for <EOF>.");
                        }
                        CSharpCCGlobals.actForEof       = res.Action;
                        CSharpCCGlobals.nextStateForEof = res.NextState;
                        prepareToRemove(respecs, res);
                    }
                    else if (tp.IsExplicit && Options.getUserTokenManager())
                    {
                        CSharpCCErrors.Warning(res.RegularExpression,
                                               "Ignoring regular expression specification since " +
                                               "option USER_TOKEN_MANAGER has been set to true.");
                    }
                    else if (tp.IsExplicit && !Options.getUserTokenManager() && res.RegularExpression is RJustName)
                    {
                        CSharpCCErrors.Warning(res.RegularExpression,
                                               "Ignoring free-standing regular expression reference.  " +
                                               "If you really want this, you must give it a different label as <NEWLABEL:<"
                                               + res.RegularExpression.Label + ">>.");
                        prepareToRemove(respecs, res);
                    }
                    else if (!tp.IsExplicit && res.RegularExpression.IsPrivate)
                    {
                        CSharpCCErrors.SemanticError(res.RegularExpression,
                                                     "Private (#) regular expression cannot be defined within " +
                                                     "grammar productions.");
                    }
                }
            }

            removePreparedItems();

            /*
             * The following loop inserts all names of regular expressions into
             * "named_tokens_table" and "ordered_named_tokens".
             * Duplications are flagged as errors.
             */
            foreach (var tp in CSharpCCGlobals.rexprlist)
            {
                IList <RegExprSpec> respecs = tp.RegexSpecs;
                foreach (var res in respecs)
                {
                    if (!(res.RegularExpression is RJustName) &&
                        !String.IsNullOrEmpty(res.RegularExpression.Label))
                    {
                        string s = res.RegularExpression.Label;
                        if (CSharpCCGlobals.named_tokens_table.ContainsKey(s))
                        {
                            CSharpCCErrors.SemanticError(res.RegularExpression, "Multiply defined lexical token name \"" + s + "\".");
                        }
                        else
                        {
                            CSharpCCGlobals.named_tokens_table[s] = res.RegularExpression;
                            CSharpCCGlobals.ordered_named_tokens.Add(res.RegularExpression);
                        }
                        if (CSharpCCGlobals.lexstate_S2I.ContainsKey(s))
                        {
                            CSharpCCErrors.SemanticError(res.RegularExpression,
                                                         "Lexical token name \"" + s + "\" is the same as " +
                                                         "that of a lexical state.");
                        }
                    }
                }
            }

            /*
             * The following code merges multiple uses of the same string in the same
             * lexical state and produces error messages when there are multiple
             * explicit occurrences (outside the BNF) of the string in the same
             * lexical state, or when within BNF occurrences of a string are duplicates
             * of those that occur as non-TOKEN's (SKIP, MORE, SPECIAL_TOKEN) or private
             * regular expressions.  While doing this, this code also numbers all
             * regular expressions (by setting their ordinal values), and populates the
             * table "names_of_tokens".
             */

            CSharpCCGlobals.tokenCount = 1;
            foreach (var tp in CSharpCCGlobals.rexprlist)
            {
                IList <RegExprSpec> respecs = tp.RegexSpecs;
                if (tp.LexStates == null)
                {
                    tp.LexStates = new String[CSharpCCGlobals.lexstate_I2S.Count];
                    int i = 0;
                    foreach (var value in CSharpCCGlobals.lexstate_I2S.Values)
                    {
                        tp.LexStates[i++] = value;
                    }
                }
                var table = new IDictionary <string, IDictionary <string, RegularExpression> > [tp.LexStates.Length];
                for (int i = 0; i < tp.LexStates.Length; i++)
                {
                    IDictionary <string, IDictionary <string, RegularExpression> > toSet;
                    if (CSharpCCGlobals.simple_tokens_table.TryGetValue(tp.LexStates[i], out toSet))
                    {
                        table[i] = toSet;
                    }
                    else
                    {
                        table[i] = null;
                    }
                }

                foreach (var res in respecs)
                {
                    if (res.RegularExpression is RStringLiteral)
                    {
                        RStringLiteral sl = (RStringLiteral)res.RegularExpression;
                        // This loop performs the checks and actions with respect to each lexical state.
                        for (int i = 0; i < table.Length; i++)
                        {
                            // Get table of all case variants of "sl.Image" into table2.
                            IDictionary <string, RegularExpression> table2;
                            if (!table[i].TryGetValue(sl.Image.ToUpper(), out table2))
                            {
                                // There are no case variants of "sl.Image" earlier than the current one.
                                // So go ahead and insert this item.
                                if (sl.Ordinal == 0)
                                {
                                    sl.Ordinal = CSharpCCGlobals.tokenCount++;
                                }
                                table2                       = new Dictionary <string, RegularExpression>();
                                table2[sl.Image]             = sl;
                                table[i][sl.Image.ToUpper()] = table2;
                            }
                            else if (hasIgnoreCase(table2, sl.Image))
                            {
                                // hasIgnoreCase sets "other" if it is found.
                                // Since IGNORE_CASE version exists, current one is useless and bad.
                                if (!sl.TokenProductionContext.IsExplicit)
                                {
                                    // inline BNF string is used earlier with an IGNORE_CASE.
                                    CSharpCCErrors.SemanticError(sl,
                                                                 "String \"" + sl.Image + "\" can never be matched " +
                                                                 "due to presence of more general (IGNORE_CASE) regular expression " +
                                                                 "at line " + other.Line + ", column " + other.Column + ".");
                                }
                                else
                                {
                                    // give the standard error message.
                                    CSharpCCErrors.SemanticError(sl,
                                                                 "Duplicate definition of string token \"" + sl.Image + "\" " +
                                                                 "can never be matched.");
                                }
                            }
                            else if (sl.TokenProductionContext.IgnoreCase)
                            {
                                // This has to be explicit.  A warning needs to be given with respect
                                // to all previous strings.
                                String pos   = "";
                                int    count = 0;
                                foreach (var rexp in table2.Values)
                                {
                                    if (count != 0)
                                    {
                                        pos += ",";
                                    }
                                    pos += " line " + rexp.Line;
                                    count++;
                                }
                                if (count == 1)
                                {
                                    CSharpCCErrors.Warning(sl, "String with IGNORE_CASE is partially superceded by string at" + pos + ".");
                                }
                                else
                                {
                                    CSharpCCErrors.Warning(sl, "String with IGNORE_CASE is partially superceded by strings at" + pos + ".");
                                }
                                // This entry is legitimate.  So insert it.
                                if (sl.Ordinal == 0)
                                {
                                    sl.Ordinal = CSharpCCGlobals.tokenCount++;
                                }

                                table2[sl.Image] = sl;
                                // The above "put" may override an existing entry (that is not IGNORE_CASE) and that's
                                // the desired behavior.
                            }
                            else
                            {
                                // The rest of the cases do not involve IGNORE_CASE.
                                RegularExpression re;
                                if (!table2.TryGetValue(sl.Image, out re))
                                {
                                    if (sl.Ordinal == 0)
                                    {
                                        sl.Ordinal = CSharpCCGlobals.tokenCount++;
                                    }
                                    table2[sl.Image] = sl;
                                }
                                else if (tp.IsExplicit)
                                {
                                    // This is an error even if the first occurrence was implicit.
                                    if (tp.LexStates[i].Equals("DEFAULT"))
                                    {
                                        CSharpCCErrors.SemanticError(sl, "Duplicate definition of string token \"" + sl.Image + "\".");
                                    }
                                    else
                                    {
                                        CSharpCCErrors.SemanticError(sl,
                                                                     "Duplicate definition of string token \"" + sl.Image +
                                                                     "\" in lexical state \"" + tp.LexStates[i] + "\".");
                                    }
                                }
                                else if (re.TokenProductionContext.Kind != TokenProduction.TOKEN)
                                {
                                    CSharpCCErrors.SemanticError(sl,
                                                                 "String token \"" + sl.Image + "\" has been defined as a \"" +
                                                                 TokenProduction.kindImage[re.TokenProductionContext.Kind] + "\" token.");
                                }
                                else if (re.IsPrivate)
                                {
                                    CSharpCCErrors.SemanticError(sl,
                                                                 "String token \"" + sl.Image +
                                                                 "\" has been defined as a private regular expression.");
                                }
                                else
                                {
                                    // This is now a legitimate reference to an existing RStringLiteral.
                                    // So we assign it a number and take it out of "rexprlist".
                                    // Therefore, if all is OK (no errors), then there will be only unequal
                                    // string literals in each lexical state.  Note that the only way
                                    // this can be legal is if this is a string declared inline within the
                                    // BNF.  Hence, it belongs to only one lexical state - namely "DEFAULT".
                                    sl.Ordinal = re.Ordinal;
                                    prepareToRemove(respecs, res);
                                }
                            }
                        }
                    }
                    else if (!(res.RegularExpression is RJustName))
                    {
                        res.RegularExpression.Ordinal = CSharpCCGlobals.tokenCount++;
                    }
                    if (!(res.RegularExpression is RJustName) &&
                        !String.IsNullOrEmpty(res.RegularExpression.Label))
                    {
                        CSharpCCGlobals.names_of_tokens[res.RegularExpression.Ordinal] = res.RegularExpression.Label;
                    }
                    if (!(res.RegularExpression is RJustName))
                    {
                        CSharpCCGlobals.rexps_of_tokens[res.RegularExpression.Ordinal] = res.RegularExpression;
                    }
                }
            }

            removePreparedItems();

            /*
             * The following code performs a tree walk on all regular expressions
             * attaching links to "RJustName"s.  Error messages are given if
             * undeclared names are used, or if "RJustNames" refer to private
             * regular expressions or to regular expressions of any kind other
             * than TOKEN.  In addition, this loop also removes top level
             * "RJustName"s from "rexprlist".
             * This code is not executed if Options.getUserTokenManager() is set to
             * true.  Instead the following block of code is executed.
             */

            if (!Options.getUserTokenManager())
            {
                FixRJustNames frjn = new FixRJustNames();
                foreach (var tp in CSharpCCGlobals.rexprlist)
                {
                    IList <RegExprSpec> respecs = tp.RegexSpecs;
                    foreach (var res in respecs)
                    {
                        frjn.root = res.RegularExpression;
                        ExpansionTreeWalker.PreOrderWalk(res.RegularExpression, frjn);
                        if (res.RegularExpression is RJustName)
                        {
                            prepareToRemove(respecs, res);
                        }
                    }
                }
            }

            removePreparedItems();

            /*
             * The following code is executed only if Options.getUserTokenManager() is
             * set to true.  This code visits all top-level "RJustName"s (ignores
             * "RJustName"s nested within regular expressions).  Since regular expressions
             * are optional in this case, "RJustName"s without corresponding regular
             * expressions are given ordinal values here.  If "RJustName"s refer to
             * a named regular expression, their ordinal values are set to reflect this.
             * All but one "RJustName" node is removed from the lists by the end of
             * execution of this code.
             */

            if (Options.getUserTokenManager())
            {
                foreach (var tp in CSharpCCGlobals.rexprlist)
                {
                    IList <RegExprSpec> respecs = tp.RegexSpecs;
                    foreach (var res in respecs)
                    {
                        if (res.RegularExpression is RJustName)
                        {
                            RJustName         jn = (RJustName)res.RegularExpression;
                            RegularExpression rexp;
                            if (!CSharpCCGlobals.named_tokens_table.TryGetValue(jn.Label, out rexp))
                            {
                                jn.Ordinal = CSharpCCGlobals.tokenCount++;
                                CSharpCCGlobals.named_tokens_table[jn.Label] = jn;
                                CSharpCCGlobals.ordered_named_tokens.Add(jn);
                                CSharpCCGlobals.names_of_tokens[jn.Ordinal] = jn.Label;
                            }
                            else
                            {
                                jn.Ordinal = rexp.Ordinal;
                                prepareToRemove(respecs, res);
                            }
                        }
                    }
                }
            }

            removePreparedItems();

            /*
             * The following code is executed only if Options.getUserTokenManager() is
             * set to true.  This loop labels any unlabeled regular expression and
             * prints a warning that it is doing so.  These labels are added to
             * "ordered_named_tokens" so that they may be generated into the ...Constants
             * file.
             */
            if (Options.getUserTokenManager())
            {
                foreach (var tp in CSharpCCGlobals.rexprlist)
                {
                    IList <RegExprSpec> respecs = tp.RegexSpecs;
                    foreach (var res in respecs)
                    {
                        int ii = res.RegularExpression.Ordinal;
                        if (!CSharpCCGlobals.names_of_tokens.ContainsKey(ii))
                        {
                            CSharpCCErrors.Warning(res.RegularExpression,
                                                   "Unlabeled regular expression cannot be referred to by " +
                                                   "user generated token manager.");
                        }
                    }
                }
            }

            if (CSharpCCErrors.ErrorCount != 0)
            {
                throw new MetaParseException();
            }

            // The following code sets the value of the "emptyPossible" field of NormalProduction
            // nodes.  This field is initialized to false, and then the entire list of
            // productions is processed.  This is repeated as long as at least one item
            // got updated from false to true in the pass.
            bool emptyUpdate = true;

            while (emptyUpdate)
            {
                emptyUpdate = false;
                foreach (var prod in CSharpCCGlobals.bnfproductions)
                {
                    if (EmptyExpansionExists(prod.Expansion))
                    {
                        if (!prod.IsEmptyPossible)
                        {
                            emptyUpdate = prod.IsEmptyPossible = true;
                        }
                    }
                }
            }

            if (Options.getSanityCheck() && CSharpCCErrors.ErrorCount == 0)
            {
                // The following code checks that all ZeroOrMore, ZeroOrOne, and OneOrMore nodes
                // do not contain expansions that can expand to the empty token list.
                foreach (var prod in CSharpCCGlobals.bnfproductions)
                {
                    ExpansionTreeWalker.PreOrderWalk(prod.Expansion, new EmptyChecker());
                }

                // The following code goes through the productions and adds pointers to other
                // productions that it can expand to without consuming any tokens.  Once this is
                // done, a left-recursion check can be performed.
                foreach (var prod in CSharpCCGlobals.bnfproductions)
                {
                    addLeftMost(prod, prod.Expansion);
                }

                // Now the following loop calls a recursive walk routine that searches for
                // actual left recursions.  The way the algorithm is coded, once a node has
                // been determined to participate in a left recursive loop, it is not tried
                // in any other loop.
                foreach (var prod in CSharpCCGlobals.bnfproductions)
                {
                    if (prod.WalkStatus == 0)
                    {
                        prodWalk(prod);
                    }
                }

                // Now we do a similar, but much simpler walk for the regular expression part of
                // the grammar.  Here we are looking for any kind of loop, not just left recursions,
                // so we only need to do the equivalent of the above walk.
                // This is not done if option USER_TOKEN_MANAGER is set to true.
                if (!Options.getUserTokenManager())
                {
                    foreach (var tp in CSharpCCGlobals.rexprlist)
                    {
                        IList <RegExprSpec> respecs = tp.RegexSpecs;
                        foreach (var res in respecs)
                        {
                            RegularExpression rexp = res.RegularExpression;
                            if (rexp.WalkStatus == 0)
                            {
                                rexp.WalkStatus = -1;
                                if (rexpWalk(rexp))
                                {
                                    loopString = "..." + rexp.Label + "... --> " + loopString;
                                    CSharpCCErrors.SemanticError(rexp, "Loop in regular expression detected: \"" + loopString + "\"");
                                }
                                rexp.WalkStatus = 1;
                            }
                        }
                    }
                }

                /*
                 * The following code performs the lookahead ambiguity checking.
                 */
                if (CSharpCCErrors.ErrorCount == 0)
                {
                    foreach (var prod in CSharpCCGlobals.bnfproductions)
                    {
                        ExpansionTreeWalker.PreOrderWalk(prod.Expansion, new LookaheadChecker());
                    }
                }
            } // matches "if (Options.getSanityCheck()) {"

            if (CSharpCCErrors.ErrorCount != 0)
            {
                throw new MetaParseException();
            }
        }