Пример #1
0
        /*
         * Initial condition: we have state S with conflicts on lookaheads in Sc.Conflicts.
         * Each reduce item Ir in S has a set of lookahead sources Ir.ReducedLookaheadSources.
         * Our goal is to a create non-canonical state ncState with proper lookaheds, create jumps to this state
         * on jump lookaheads from S to ncState, remove these jump lookaheads from lookahead sets of reduce items
         * and replace them with non-canonical non-terminal lookaheads.
         * 1. Compute all jump lookaheads jL and non-canonical lookaheads ncL for state Sc.
         * 2. Collect relevant lookahead sources in lkhSources set. For each lookahead source lkhSrc in all reduce items,
         * if lkhSrc.Current.Firsts includes a jump lookahead in jL, include it into lkhSources.
         * 3. Collect item cores for non-canonical state into ncCores. For each production Prod in productions
         * of current non-terminal of all items in lkhSources, if Prod.Firsts contains a jump lookahead, then add initial LR0 item of Prod
         * to ncCores.
         * 4. Add to ncCores all shift items in state Sc that have Current term in jump lookaheads. We need to include
         * such shift items from original state into non-canonical state to allow proper resolution of shift-reduce
         * conflicts. We let shift items in current state "compete" with possible reductions to non-canonical lookaheads
         * inside non-canonical state.
         * 5. Create (or find existing) non-canonical state Sn from ncCores.
         * 6. Assign lookbacks to items in ncState. For each item Src in lkhSources, for each production Prod
         * in Src.Current.Productions, if Prod.DirectFirsts contains jump lookahead, then:
         * find LR item I in Sn with I.Core == Prod.LR0Items[0]; do the following: I.Lookbacks.Add(Src.Transition).
         * 7. For state S for each reduce item I adjust I.Lookaheads:  remove jump lookaheads from I.Lookaheads,
         *   and add those non-canonical lookaheads that are in I.AllLookaheads
         */
        //TODO: one thing to look at - see if all items in ncState should lead to reduce item in some state.
        //     There may be items (most likely top ones, expansions of original reduced lookahead) that never get
        //     to full reduce, because we switch back to canonical state on reduction of some "child" non-terminal and
        //     continue through canonical states from there.
        //     So we don't need to generate target transition states for these items (unreachable states).
        //     The main trouble is that unreachable state may introduce conflicts that in fact are never realized.
        #endregion
        private void SwitchStateToNLalrLookaheads(ParserState state)
        {
            //1. Compute minimal (most expanded) non-canonical lookaheads that resolve all conflicts
            ComputeStateNonCanonicalLookaheads(state);
            var stateData = state.BuilderData;
            //2. Collect reduced lookahead sources and non-terminal lookaheads
            var lkhSources = new LRItemSet();
            var ntSet      = new NonTerminalSet(); //All non-terminals in current positions of lkhSources

            foreach (var reduceItem in stateData.ReduceItems)
            {
                foreach (var lkhSource in reduceItem.ReducedLookaheadSources)
                {
                    var ntLkh = lkhSource.Core.Current as NonTerminal;
                    if (ntLkh == null)
                    {
                        continue;
                    }
                    if (!ntLkh.Firsts.Overlaps(stateData.JumpLookaheads))
                    {
                        continue;
                    }
                    lkhSources.Add(lkhSource);
                    ntSet.Add(ntLkh);
                }
            }
            //2. Collect core set for non-canonical state
            var ncCoreSet = new LR0ItemSet();

            foreach (var ntLkh in ntSet)
            {
                foreach (var prod in ntLkh.Productions)
                {
                    if (prod.Firsts.Overlaps(stateData.JumpLookaheads))
                    {
                        ncCoreSet.Add(prod.LR0Items[0]);
                    }
                }
            }
            //4. Add shift items
            foreach (var shiftItem in stateData.ShiftItems)
            {
                if (stateData.JumpLookaheads.Contains(shiftItem.Core.Current))
                {
                    ncCoreSet.Add(shiftItem.Core);
                }
            }
            //5. Find or create non-canonical state
            var  oldStateCount = Data.States.Count;
            var  ncState       = FindOrCreateState(ncCoreSet, "SN"); //if not found, state is created and added to state list and state hash
            bool ncStateIsNew  = Data.States.Count > oldStateCount;

            stateData.JumpTarget = ncState;
            //6. Setup appropriate lookbacks in items in ncState;
            // first set lookbacks for items originated from lookaheads of reduce items in original state.
            foreach (var lkhSource in lkhSources)
            {
                var ntLkh = lkhSource.Core.Current as NonTerminal;
                foreach (var prod in ntLkh.Productions)
                {
                    if (prod.Firsts.Overlaps(stateData.JumpLookaheads))
                    {
                        var ncItem = ncState.BuilderData.AllItems.FindByCore(prod.LR0Items[0]);
                        ncItem.Lookbacks.Add(lkhSource.Transition);
                    } //if
                }
            }         //foreach lkhSource
            //Now items orginated from shift items in original state in step 4 above
            // just copy lookbacks
            foreach (var shiftItem in stateData.ShiftItems)
            {
                if (stateData.JumpLookaheads.Contains(shiftItem.Core.Current))
                {
                    var ncItem = ncState.BuilderData.ShiftItems.FindByCore(shiftItem.Core);
                    shiftItem.ShiftedItem = ncItem;
                    ncItem.Lookbacks.UnionWith(shiftItem.Lookbacks);
                    if (ncItem.Transition != null)
                    {
                        ncItem.Transition.Include(shiftItem.Transition.Includes);
                    }
                }
            }
            PropagateLookbacksAndTransitionsThruShifts(ncState);
            //7. Adjust reduce items lookaheads in original state
            foreach (var reduceItem in stateData.ReduceItems)
            {
                foreach (var jumpLkh in stateData.JumpLookaheads)
                {
                    if (reduceItem.Lookaheads.Contains(jumpLkh))
                    {
                        reduceItem.Lookaheads.Remove(jumpLkh);
                    }
                }
                foreach (var ncLkh in stateData.NonCanonicalLookaheads)
                {
                    if (reduceItem.AllLookaheads.Contains(ncLkh))
                    {
                        reduceItem.Lookaheads.Add(ncLkh);
                    }
                }
            }//foreach reduceItem
            // 8. Create jump action to non-canonical state, remove shifts on jump lookaheads
            state.JumpAction = ParserAction.CreateJump(ncState);
            foreach (var jumpTerm in state.BuilderData.JumpLookaheads)
            {
                if (state.Actions.ContainsKey(jumpTerm))
                {
                    state.Actions.Remove(jumpTerm);
                }
            }
            //9. Complete generating states
            state.BuilderData.Conflicts.ExceptWith(state.BuilderData.JumpLookaheads);
        }//method