}//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"); }
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; }
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); }
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); }
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); }
public LR0ItemSet GetShiftedCores() { var result = new LR0ItemSet(); foreach (var item in this) { if (item.Core.ShiftedItem != null) { result.Add(item.Core.ShiftedItem); } } return(result); }
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); } }
/* 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
/* * 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
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; }
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; }
//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