private void CreateReduceActions() { foreach (var state in Data.States) { var stateData = state.BuilderData; if (stateData.ShiftItems.Count == 0 && stateData.ReduceItems.Count == 1) { state.DefaultReduceAction = ParserAction.CreateReduce(stateData.ReduceItems.First().Core.Production); continue; } //now create actions foreach (var item in state.BuilderData.ReduceItems) { //create actions foreach (var lkh in item.Lookaheads) { if (state.Actions.ContainsKey(lkh)) { continue; } state.Actions[lkh] = ParserAction.CreateReduce(item.Core.Production); } } //foreach item } //foreach state }
}//method private void CreateDefaultActionsForConflicts(ParserState state, BnfTermSet shiftReduceConflicts, BnfTermSet reduceReduceConflicts) { var stateData = state.BuilderData; //Create default actions for these conflicts. For shift-reduce, default action is shift, and shift action already // exist for all shifts from the state, so we don't need to do anything. For reduce-reduce create reduce actions // for the first reduce item (whatever comes first in the set). foreach (var conflict in reduceReduceConflicts) { var reduceItems = stateData.ReduceItems.SelectByLookahead(conflict); var action = ParserAction.CreateReduce(reduceItems.First().Core.Production); state.Actions[conflict] = action; } //Update ResolvedConflicts and Conflicts sets stateData.ResolvedConflicts.UnionWith(shiftReduceConflicts); stateData.ResolvedConflicts.UnionWith(reduceReduceConflicts); stateData.Conflicts.ExceptWith(stateData.ResolvedConflicts); }
private bool TryResolveConflictByHints(ParserState state, BnfTerm conflict) { var stateData = state.BuilderData; //reduce hints var reduceItems = stateData.ReduceItems.SelectByLookahead(conflict); foreach (var reduceItem in reduceItems) { if (reduceItem.Core.Hints != null) { foreach (var hint in reduceItem.Core.Hints) { if (hint.HintType == HintType.ResolveToReduce) { var newAction = ParserAction.CreateReduce(reduceItem.Core.Production); state.Actions[conflict] = newAction; //replace/add reduce action return(true); } } } } //Shift hints var shiftItems = stateData.ShiftItems.SelectByCurrent(conflict); foreach (var shiftItem in shiftItems) { if (shiftItem.Core.Hints != null) { foreach (var hint in shiftItem.Core.Hints) { if (hint.HintType == HintType.ResolveToShift) { //shift action is already there return(true); } } } } //code hints // first prepare data for conflict action: reduceProduction (for possible reduce) and newState (for possible shift) var reduceProduction = reduceItems.First().Core.Production; //take first of reduce productions ParserState newState = (state.Actions.ContainsKey(conflict) ? state.Actions[conflict].NewState : null); // Get all items that might contain hints; first take all shift items and reduce items in conflict; // we should also add lookahead sources of reduce items. Lookahead source is an LR item that produces the lookahead, // so if it contains a code hint right before the lookahead term, then it applies to this conflict as well. var allItems = new LRItemList(); allItems.AddRange(shiftItems); foreach (var reduceItem in reduceItems) { allItems.Add(reduceItem); allItems.AddRange(reduceItem.ReducedLookaheadSources); } // Scan all items and try to find hint with resolution type Code foreach (var item in allItems) { if (item.Core.Hints != null) { foreach (var hint in item.Core.Hints) { if (hint.HintType == HintType.ResolveInCode) { //found hint with resolution type "code" - this is instruction to use custom code here to resolve the conflict // create new ConflictAction and place it into Actions table var newAction = ParserAction.CreateCodeAction(newState, reduceProduction); state.Actions[conflict] = newAction; //replace/add reduce action return(true); } } } } return(false); }
//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