예제 #1
0
        }//method

        /* Detecting conflicts that cannot be resolved by tail wrapping
         *   1. Shift-reduce conflicts. If inadequate state S has shift item based on the same core as source
         *       of one of reduced lookaheads of reduce item, then the conflict is unresolvable -
         *       no wrapping of lookahead would resolve ambiguity
         *   2. Reduce-reduce conflict. If reduce items in inadequate state have reduced lookaheads
         *      with sources having the same core (LR0 item) then we have unresolvable conflict. Wrapping of the item tail would produce
         *      the same new non-terminal as lookahead in both conflicting reduce items.
         */
        private void DetectConflictsUnresolvableByRestructuring(ParserState state)
        {
            //compute R-R and S-R conflicting lookaheads
            var rrConflicts     = new BnfTermSet();
            var srConflicts     = new BnfTermSet();
            var conflictSources = new LR0ItemSet();

            foreach (var conflict in state.BuilderData.Conflicts)
            {
                var nonConflictingSourceCores = new LR0ItemSet();
                foreach (var reduceItem in state.BuilderData.ReduceItems)
                {
                    foreach (var source in reduceItem.ReducedLookaheadSources)
                    {
                        if (source.Core.Current != conflict)
                        {
                            continue;
                        }
                        if (state.BuilderData.Cores.Contains(source.Core)) //we have unresolvable shift-reduce
                        {
                            srConflicts.Add(source.Core.Current);
                            conflictSources.Add(source.Core);
                        }
                        else if (nonConflictingSourceCores.Contains(source.Core)) //unresolvable reduce-reduce
                        {
                            rrConflicts.Add(source.Core.Current);
                            conflictSources.Add(source.Core);
                        }
                        else
                        {
                            nonConflictingSourceCores.Add(source.Core);
                        }
                    } //foreach source
                }     //foreach item
            }         //foreach conflict
            if (srConflicts.Count > 0)
            {
                ReportParseConflicts("Ambiguous grammar, unresolvable shift-reduce conflicts.", state, srConflicts);
            }
            if (rrConflicts.Count > 0)
            {
                ReportParseConflicts("Ambiguous grammar, unresolvable reduce-reduce conflicts.", state, rrConflicts);
            }
            //create default actions and remove them from conflict list, so we don't deal with them anymore
            CreateDefaultActionsForConflicts(state, srConflicts, rrConflicts);
        } // method
        private void CreateInitialState()
        {
            //there is always just one initial production "Root' -> .Root", and we're interested in LR item at 0 index
            var iniItemSet = new LR0ItemSet();

            iniItemSet.Add(_language.GrammarData.AugmentedRoot.Productions[0].LR0Items[0]);
            Data.InitialState = CreateState(iniItemSet, "S");
        }
예제 #3
0
 private ParserState CreateInitialState(NonTerminal augmentedRoot) {
   //for an augmented root there is an initial production "Root' -> .Root"; so we need the LR0 item at 0 index
   var iniItemSet = new LR0ItemSet();
   iniItemSet.Add(augmentedRoot.Productions[0].LR0Items[0]);
   var initialState = FindOrCreateState(iniItemSet);
   var rootNt = augmentedRoot.Productions[0].RValues[0] as NonTerminal; 
   Data.InitialStates[rootNt] = initialState; 
   return initialState;
 }
예제 #4
0
        private TransitionList  CreateLookbackTransitions(LRItemSet sourceItems)
        {
            var newTransitions = new TransitionList();
            //Build set of initial cores - this is optimization for performance
            //We need to find all initial items in all states that shift into one of sourceItems
            // Each such initial item would have the core from the "initial" cores set that we build from source items.
            var iniCores = new LR0ItemSet();

            foreach (var sourceItem in sourceItems)
            {
                iniCores.Add(sourceItem.Core.Production.LR0Items[0]);
            }
            //find
            foreach (var state in _data.States)
            {
                foreach (var iniItem in state.BuilderData.InitialItems)
                {
                    if (!iniCores.Contains(iniItem.Core))
                    {
                        continue;
                    }
                    var        iniItemNt = iniItem.Core.Production.LValue; // iniItem's non-terminal (left side of production)
                    Transition lookback  = null;                           // local var for lookback - transition over iniItemNt
                    var        currItem  = iniItem;                        // iniItem is initial item for all currItem's in the shift chain.
                    while (currItem != null)
                    {
                        if (sourceItems.Contains(currItem))
                        {
                            // We create transitions lazily, only when we actually need them. Check if we have iniItem's transition
                            // in local variable; if not, get it from state's transitions table; if not found, create it.
                            if (lookback == null && !state.BuilderData.Transitions.TryGetValue(iniItemNt, out lookback))
                            {
                                lookback = new Transition(state, iniItemNt);
                                newTransitions.Add(lookback);
                            }
                            //Now for currItem, either add trans to Lookbacks, or "include" it into currItem.Transition
                            // We need lookbacks ONLY for final items; for non-Final items we need proper Include lists on transitions
                            if (currItem.Core.IsFinal)
                            {
                                currItem.Lookbacks.Add(lookback);
                            }
                            else // if (currItem.Transition != null)
                                 // Note: looks like checking for currItem.Transition is redundant - currItem is either:
                                 //    - Final - always the case for the first run of this method;
                                 //    - it has a transition after the first run, due to the way we select sourceItems list
                                 //       in SelectNewItemsThatNeedLookback (by transitions)
                            {
                                currItem.Transition.Include(lookback);
                            }
                        }//if
                        //move to next item
                        currItem = currItem.ShiftedItem;
                    } //while
                }     //foreach iniItem
            }         //foreach state
            return(newTransitions);
        }
        public LR0ItemSet GetCores()
        {
            var result = new LR0ItemSet();

            foreach (var item in this)
            {
                result.Add(item.Core);
            }
            return(result);
        }
예제 #6
0
        private ParserState CreateInitialState(NonTerminal augmentedRoot)
        {
            //for an augmented root there is an initial production "Root' -> .Root"; so we need the LR0 item at 0 index
            var iniItemSet = new LR0ItemSet();

            iniItemSet.Add(augmentedRoot.Productions[0].LR0Items[0]);
            var initialState = FindOrCreateState(iniItemSet);
            var rootNt       = augmentedRoot.Productions[0].RValues[0] as NonTerminal;

            _data.InitialStates[rootNt] = initialState;
            return(initialState);
        }
예제 #7
0
        private TransitionList  CreateLookbackTransitions(LRItemSet sourceItems)
        {
            var newTransitions = new TransitionList();
            //Build set of initial cores - this is optimization for performance
            //We need to find all initial items in all states that shift into one of sourceItems
            // Each such initial item would have the core from the "initial" cores set that we build from source items.
            var iniCores = new LR0ItemSet();

            foreach (var sourceItem in sourceItems)
            {
                iniCores.Add(sourceItem.Core.Production.LR0Items[0]);
            }
            //find
            foreach (var state in Data.States)
            {
                foreach (var iniItem in state.BuilderData.InitialItems)
                {
                    if (!iniCores.Contains(iniItem.Core))
                    {
                        continue;
                    }
                    var currItem = iniItem;
                    while (currItem != null)
                    {
                        if (sourceItems.Contains(currItem))
                        {
                            //iniItem is initial item for currItem (one of source items)
                            // check if transition for iniItem's non-terminal exists
                            var        ntLeft = iniItem.Core.Production.LValue;
                            Transition trans;
                            if (!state.BuilderData.Transitions.TryGetValue(ntLeft, out trans))
                            {
                                trans = new Transition(iniItem.State, iniItem.Core.Production.LValue);
                                newTransitions.Add(trans);
                            }
                            //Now for currItem, either add trans to Lookbackbacks, or "include" it into currItem.Transition
                            if (currItem.Core.IsFinal)
                            {
                                currItem.Lookbacks.Add(trans);
                            }
                            else if (currItem.Transition != null)
                            {
                                currItem.Transition.Include(trans);
                            }
                        }//if
                        //move to next items
                        currItem = currItem.ShiftedItem;
                    } //while
                }     //foreach iniItem
            }         //foreach state
            return(newTransitions);
        }
예제 #8
0
        public LR0ItemSet GetShiftedCores()
        {
            var result = new LR0ItemSet();

            foreach (var item in this)
            {
                if (item.Core.ShiftedItem != null)
                {
                    result.Add(item.Core.ShiftedItem);
                }
            }
            return(result);
        }
예제 #9
0
        public void AddItem(LR0Item core)
        {
            //Check if a core had been already added. If yes, simply return
            if (!AllCores.Add(core))
            {
                return;
            }
            //Create new item, add it to AllItems, InitialItems, ReduceItems or ShiftItems
            var item = new LRItem(State, core);

            AllItems.Add(item);
            if (item.Core.IsFinal)
            {
                ReduceItems.Add(item);
            }
            else
            {
                ShiftItems.Add(item);
            }
            if (item.Core.IsInitial)
            {
                InitialItems.Add(item);
            }
            if (core.IsFinal)
            {
                return;
            }
            //Add current term to ShiftTerms
            if (!ShiftTerms.Add(core.Current))
            {
                return;
            }
            if (core.Current is Terminal)
            {
                ShiftTerminals.Add(core.Current as Terminal);
            }
            //If current term (core.Current) is a new non-terminal, expand it
            var currNt = core.Current as NonTerminal;

            if (currNt == null)
            {
                return;
            }
            foreach (var prod in currNt.Productions)
            {
                AddItem(prod.LR0Items[0]);
            }
        }//method
        }//method

        public void AddItem(LRItem item)
        {
            if (AllItems.Contains(item))
            {
                return;
            }
            AllItems.Add(item);
            Cores.Add(item.Core);
            if (item.Core.IsFinal)
            {
                ReduceItems.Add(item);
            }
            else
            {
                ShiftItems.Add(item);
                ShiftTerms.Add(item.Core.Current);
            }
        }
예제 #11
0
 private void CreateInitialState()
 {
     //there is always just one initial production "Root' -> .Root", and we're interested in LR item at 0 index
       var iniItemSet = new LR0ItemSet();
       iniItemSet.Add(_language.GrammarData.AugmentedRoot.Productions[0].LR0Items[0]);
       Data.InitialState = CreateState(iniItemSet, "S");
 }
    /*
    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
    }//method

    /* Detecting conflicts that cannot be resolved by tail wrapping 
         1. Shift-reduce conflicts. If inadequate state S has shift item based on the same core as source 
             of one of reduced lookaheads of reduce item, then the conflict is unresolvable - 
             no wrapping of lookahead would resolve ambiguity
         2. Reduce-reduce conflict. If reduce items in inadequate state have reduced lookaheads 
            with sources having the same core (LR0 item) then we have unresolvable conflict. Wrapping of the item tail would produce
            the same new non-terminal as lookahead in both conflicting reduce items. 
    */
    private void DetectConflictsUnresolvableByRestructuring(ParserState state) {
      //compute R-R and S-R conflicting lookaheads
      var rrConflicts = new BnfTermSet();
      var srConflicts = new BnfTermSet();
      var conflictSources = new LR0ItemSet();
      foreach (var conflict in state.BuilderData.Conflicts) {
        var nonConflictingSourceCores = new LR0ItemSet();
        foreach (var reduceItem in state.BuilderData.ReduceItems) {
          foreach (var source in reduceItem.ReducedLookaheadSources) {
            if (source.Core.Current != conflict) continue;
            if (state.BuilderData.Cores.Contains(source.Core)) {  //we have unresolvable shift-reduce
              srConflicts.Add(source.Core.Current);
              conflictSources.Add(source.Core);
            } else if (nonConflictingSourceCores.Contains(source.Core)) {        //unresolvable reduce-reduce
              rrConflicts.Add(source.Core.Current);
              conflictSources.Add(source.Core);
            } else
              nonConflictingSourceCores.Add(source.Core);
          }//foreach source
        }//foreach item
      }//foreach conflict
      if (srConflicts.Count > 0)
        ReportParseConflicts("Ambiguous grammar, unresolvable shift-reduce conflicts.", state, srConflicts);
      if (rrConflicts.Count > 0)
        ReportParseConflicts("Ambiguous grammar, unresolvable reduce-reduce conflicts.", state, rrConflicts);
      //create default actions and remove them from conflict list, so we don't deal with them anymore
      CreateDefaultActionsForConflicts(state, srConflicts, rrConflicts); 
    } // method
예제 #14
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
예제 #15
0
 private TransitionList CreateLookbackTransitions(LRItemSet sourceItems)
 {
     var newTransitions = new TransitionList();
       //Build set of initial cores - this is optimization for performance
       //We need to find all initial items in all states that shift into one of sourceItems
       // Each such initial item would have the core from the "initial" cores set that we build from source items.
       var iniCores = new LR0ItemSet();
       foreach(var sourceItem in sourceItems)
     iniCores.Add(sourceItem.Core.Production.LR0Items[0]);
       //find
       foreach(var state in Data.States) {
     foreach(var iniItem in state.BuilderData.InitialItems) {
       if (!iniCores.Contains(iniItem.Core)) continue;
       var iniItemNt = iniItem.Core.Production.LValue; // iniItem's non-terminal (left side of production)
       Transition lookback = null; // local var for lookback - transition over iniItemNt
       var currItem = iniItem; // iniItem is initial item for all currItem's in the shift chain.
       while (currItem != null) {
     if(sourceItems.Contains(currItem)) {
       // We create transitions lazily, only when we actually need them. Check if we have iniItem's transition
       // in local variable; if not, get it from state's transitions table; if not found, create it.
       if(lookback == null && !state.BuilderData.Transitions.TryGetValue(iniItemNt, out lookback)) {
         lookback = new Transition(state, iniItemNt);
         newTransitions.Add(lookback);
       }
       //Now for currItem, either add trans to Lookbacks, or "include" it into currItem.Transition
       // We need lookbacks ONLY for final items; for non-Final items we need proper Include lists on transitions
       if (currItem.Core.IsFinal)
         currItem.Lookbacks.Add(lookback);
       else // if (currItem.Transition != null)
         // Note: looks like checking for currItem.Transition is redundant - currItem is either:
         //    - Final - always the case for the first run of this method;
         //    - it has a transition after the first run, due to the way we select sourceItems list
         //       in SelectNewItemsThatNeedLookback (by transitions)
         currItem.Transition.Include(lookback);
     }//if
     //move to next item
     currItem = currItem.ShiftedItem;
       }//while
     }//foreach iniItem
       }//foreach state
       return newTransitions;
 }
예제 #16
0
 private TransitionList  CreateLookbackTransitions(LRItemSet sourceItems) {
   var newTransitions = new TransitionList();
   //Build set of initial cores - this is optimization for performance
   //We need to find all initial items in all states that shift into one of sourceItems
   // Each such initial item would have the core from the "initial" cores set that we build from source items.
   var iniCores = new LR0ItemSet();
   foreach(var sourceItem in sourceItems)
     iniCores.Add(sourceItem.Core.Production.LR0Items[0]);
   //find 
   foreach(var state in Data.States) {
     foreach(var iniItem in state.BuilderData.InitialItems) {
       if (!iniCores.Contains(iniItem.Core)) continue; 
       var currItem = iniItem;
       while(currItem != null) {
         if(sourceItems.Contains(currItem)) {
           //iniItem is initial item for currItem (one of source items) 
           // check if transition for iniItem's non-terminal exists
           var ntLeft = iniItem.Core.Production.LValue;
           Transition trans; 
           if(!state.BuilderData.Transitions.TryGetValue(ntLeft, out trans)) {
             trans = new Transition(iniItem.State, iniItem.Core.Production.LValue);
             newTransitions.Add(trans);
           }
           //Now for currItem, either add trans to Lookbackbacks, or "include" it into currItem.Transition
           if(currItem.Core.IsFinal)
             currItem.Lookbacks.Add(trans);
           else if(currItem.Transition != null)
             currItem.Transition.Include(trans);
         }//if 
         //move to next items
         currItem = currItem.ShiftedItem;
       }//while
     }//foreach iniItem
   }//foreach state
   return newTransitions;
 }
예제 #17
0
        //Detect conflicts that cannot be handled by non-canonical NLALR method directly, by may be fixed by grammar transformation
        private void DetectNlalrFixableConflicts(ParserState state)
        {
            var stateData = state.BuilderData;
            //compute R-R and S-R conflicting lookaheads
            var reduceLkhds = new BnfTermSet();
            var rrConflicts = new BnfTermSet();
            var srConflicts = new BnfTermSet();

            foreach (var reduceItem in state.BuilderData.ReduceItems)
            {
                foreach (var lkh in reduceItem.ReducedLookaheads)
                {
                    if (stateData.ShiftTerms.Contains(lkh))
                    {
                        if (!lkh.IsSet(TermOptions.UsePrecedence))
                        {
                            srConflicts.Add(lkh); //S-R conflict
                        }
                    }
                    else if (reduceLkhds.Contains(lkh))
                    {
                        rrConflicts.Add(lkh); //R-R conflict
                    }
                    reduceLkhds.Add(lkh);
                } //foreach lkh
            }     //foreach item
            if (srConflicts.Count == 0 && rrConflicts.Count == 0)
            {
                return;
            }
            //Collect all cores to recommend for adding WrapTail hint.
            var allConflicts = new BnfTermSet();

            allConflicts.UnionWith(srConflicts);
            allConflicts.UnionWith(rrConflicts);
            foreach (var conflict in allConflicts)
            {
                var conflictingShiftItems = state.BuilderData.ShiftItems.SelectByCurrent(conflict);
                foreach (var item in conflictingShiftItems)
                {
                    if (!item.Core.IsInitial) //only non-initial
                    {
                        _coresToAddWrapTailHint.Add(item.Core);
                    }
                }
                foreach (var reduceItem in state.BuilderData.ReduceItems)
                {
                    var conflictingSources = reduceItem.ReducedLookaheadSources.SelectByCurrent(conflict);
                    foreach (var source in conflictingSources)
                    {
                        _coresToAddWrapTailHint.Add(source.Core);
                    }
                }
            }
            //still report them as conflicts
            ReportParseConflicts(state, srConflicts, rrConflicts);
            //create default actions and remove conflicts from list so we don't deal with them anymore
            foreach (var conflict in rrConflicts)
            {
                var reduceItems = stateData.ReduceItems.SelectByReducedLookahead(conflict);
                var action      = ParserAction.CreateReduce(reduceItems.First().Core.Production);
                state.Actions[conflict] = action;
            }
            //Update ResolvedConflicts and Conflicts sets
            stateData.ResolvedConflicts.UnionWith(srConflicts);
            stateData.ResolvedConflicts.UnionWith(rrConflicts);
            stateData.Conflicts.ExceptWith(stateData.ResolvedConflicts);
        }//method