示例#1
0
        static string ActionToString(ParserAction action)
        {
            string result = null;
            Shift  shift  = action as Shift;

            if (shift != null)
            {
                return("shift, and go to state " + StateRef(shift.next.num));
            }
            Reduce reduce = action as Reduce;

            if (reduce != null)
            {
                return(String.Format(CultureInfo.InvariantCulture, "reduce using {0} ({1}{2})",
                                     ProductionRef(reduce.item.production.num),
                                     (reduce.item.production.rhs.Count == 0 ? "Erasing " : ""),
                                     reduce.item.production.lhs));
            }
            return(result);
        }
        internal void BuildParseTable()
        {
            foreach (AutomatonState state in states)
            {               //
                // Add shift actions ...
                // This makes shift the default action for all
                // terminal transitions. This is modified as required,
                // later in this foreach state loop.
                //
                foreach (Terminal t in state.terminalTransitions)
                {
                    state.parseTable[t] = new Shift(state.Goto[t]);
                }

                // Add reduce actions ...
                foreach (ProductionItem item in state.allItems)
                {
                    if (item.isReduction())
                    {
                        // Accept on everything
                        if (item.production == grammar.rootProduction)
                        {
                            foreach (Terminal t in grammar.terminals.Values)
                            {
                                state.parseTable[t] = new Reduce(item);
                            }
                        }

                        foreach (Terminal t in item.LA)
                        {
                            // possible conflict with existing action
                            if (state.parseTable.ContainsKey(t))
                            {
                                Reduce       reduceAction;
                                ParserAction other = state.parseTable[t];
                                Production   iProd = item.production;
                                if ((reduceAction = other as Reduce) != null)
                                {
                                    Production oProd = reduceAction.item.production;

                                    // Choose in favour of production listed first in the grammar
                                    if (oProd.num > iProd.num)
                                    {
                                        state.parseTable[t] = new Reduce(item);
                                    }

                                    string p1   = String.Format(CultureInfo.InvariantCulture, " Reduce {0}:\t{1}", oProd.num, oProd.ToString());
                                    string p2   = String.Format(CultureInfo.InvariantCulture, " Reduce {0}:\t{1}", iProd.num, iProd.ToString());
                                    int    chsn = (oProd.num > iProd.num ? iProd.num : oProd.num);
                                    grammar.conflicts.Add(new ReduceReduceConflict(t, p1, p2, chsn, state));
                                    if (GPCG.Verbose)
                                    {
                                        Console.Error.WriteLine(
                                            "Reduce/Reduce conflict in state {0} on symbol {1}",
                                            state.num,
                                            t.ToString());
                                        Console.Error.WriteLine(p1);
                                        Console.Error.WriteLine(p2);
                                    }
                                    else
                                    {
                                        Console.Error.WriteLine("Reduce/Reduce conflict, state {0}: {1} vs {2} on {3}",
                                                                state.num, iProd.num, oProd.num, t);
                                    }
                                }
                                else
                                {
                                    if (iProd.prec != null && t.prec != null)
                                    {
                                        if (iProd.prec.prec > t.prec.prec)
                                        {
                                            //
                                            //  Production iProd has precedence over t, so Reduce.
                                            //
                                            state.parseTable[t] = new Reduce(item);   // No shift/Reduce warning.
                                        }
                                        else if (iProd.prec.prec == t.prec.prec)
                                        {
                                            //
                                            //  Precedence is equal, so use associativity to decide.
                                            //
                                            if (t.prec.type == PrecType.left)
                                            {
                                                //
                                                // For %left tokens reduce the left subexpression.
                                                //
                                                state.parseTable[t] = new Reduce(item);
                                            }
                                            else if (t.prec.type == PrecType.nonassoc)   // && iProd.RightmostTerminal() == t) {
                                            // What is the correct semantics here?
                                            // If %nonassoc x y, is E x E y E an error?
                                            // The YACC spec seems to imply, but not explictly state,
                                            // that x,y are non-associative AS A GROUP
                                            // rather than just individually non-associative.
                                            //
                                            // For %nonassoc tokens disallow the shift action, and force
                                            // lookahead just in case this state has an LR0 Reduce action.
                                            //
                                            {
                                                state.parseTable.Remove(t);
                                                state.ForceLookahead = true;
                                            }
                                            // else t.prec.type == PrecType.right, so Shift.
                                        }
                                        // else iProd.prec.prec < t.proc.prec, so Shift anyway.
                                    }
                                    else    // Need to issue a Shift/Reduce warning message.
                                    {
                                        AutomatonState next = ((Shift)other).next;
                                        string         p1   = String.Format(CultureInfo.InvariantCulture, " Shift \"{0}\":\tState-{1} -> State-{2}", t, state.num, next.num);
                                        string         p2   = String.Format(CultureInfo.InvariantCulture, " Reduce {0}:\t{1}", iProd.num, iProd.ToString());
                                        grammar.conflicts.Add(new ShiftReduceConflict(t, p1, p2, state, next));
                                        if (GPCG.Verbose)
                                        {
                                            Console.Error.WriteLine("Shift/Reduce conflict");
                                            Console.Error.WriteLine(p1);
                                            Console.Error.WriteLine(p2);
                                        }
                                        else
                                        {
                                            Console.Error.WriteLine("Shift/Reduce conflict, state {0} on {1}", state.num, t);
                                        }
                                    }
                                }
                            }
                            else
                            {
                                state.parseTable[t] = new Reduce(item);
                            }
                        }
                    }
                }
            }
        }