示例#1
0
        private List <GrammarItem> Closure(List <GrammarItem> items)
        {
            List <GrammarItem> I = new List <GrammarItem>();

            I.AddRange(items);

            for (int i = 0; i < I.Count; i++)
            {
                var item = I[i];
                if (item.IsHightlightAfterFinalEntry)
                {
                    continue;
                }
                if (item.HighlightedEntry.IsTerminal)
                {
                    continue;
                }

                var nt = item.HighlightedEntry as NonTerminal;

                var afterHighlight = item.EntriesAfterHighlight;
                foreach (var l in item.Lookaheads)
                {
                    ProductionEntry[] afterPlusLookahead = new ProductionEntry[afterHighlight.Length + 1];
                    Array.Copy(afterHighlight, afterPlusLookahead, afterHighlight.Length);
                    afterPlusLookahead[^ 1] = l;
示例#2
0
        private void SetAction(ParserState state, ProductionEntry key, ParserAction newAction)
        {
            if (key is NonTerminal nt)
            {
                Console.WriteLine();
            }

            if (state.Action.ContainsKey(key.ID))
            {
                var oldAction = state.Action[key.ID];
                if (oldAction.ToString() == newAction.ToString())
                {
                    return;
                }

                if (!(oldAction is AcceptAction) && !(newAction is AcceptAction))
                {
                    if (oldAction.Name != newAction.Name)
                    {
                        //Shift/Reduce Conflict
                        ShiftAction  shiftAction  = (oldAction.Name == "shift" ? oldAction : newAction) as ShiftAction;
                        ReduceAction reduceAction = (oldAction.Name == "shift" ? newAction : oldAction) as ReduceAction;

                        var prod = reduceAction.Production;
                        var term = key as Terminal;

                        //Resolve based on precedence and associativity
                        if (prod.Precendece > term.Precedence ||
                            (prod.Precendece == term.Precedence && prod.Associatvity == OperatorAssociativity.Left))
                        {
                            state.Action[key.ID] = reduceAction;
                        }
                        else
                        {
                            state.Action[key.ID] = shiftAction;
                        }

                        return;
                    }
                    else if (newAction is ReduceAction)
                    {
                        //Reduce/Reduce conflict
                        var newProd = (newAction as ReduceAction).Production;
                        var oldProd = (oldAction as ReduceAction).Production;

                        bool newFirst = false;

                        if (newProd.Lhs != oldProd.Lhs)
                        {
                            //Find the NonTerminal to appear first
                            newFirst = newProd.Lhs.ID < oldProd.Lhs.ID;
                        }
                        else
                        {
                            //Find the production to appear first
                            foreach (var p in newProd.Lhs.Productions)
                            {
                                if (p != newProd && p != oldProd)
                                {
                                    continue;
                                }
                                if (p == newProd)
                                {
                                    newFirst = true;
                                }
                                break;
                            }
                        }

                        //Resolve based on first appearance
                        if (newFirst)
                        {
                            state.Action[key.ID] = newAction;
                        }

                        return;
                    }
                    else
                    {
                        throw new Exception($"Conflict in state {state} on entry {key}. Cannot resolve shift/shift conflict.");
                    }
                }
            }

            state.Action[key.ID] = newAction;
        }