//Create reduce actions for states with a single reduce item (and no shifts) private void CreateRemainingReduceActions() { foreach (var state in _data.States) { if (state.DefaultAction != null) { continue; } var stateData = state.BuilderData; if (stateData.ShiftItems.Count == 0 && stateData.ReduceItems.Count == 1) { state.DefaultAction = ReduceParserAction.Create(stateData.ReduceItems.First().Core.Production); continue; //next state; if we have default reduce action, we don't need to fill actions dictionary for lookaheads } //create actions foreach (var item in state.BuilderData.ReduceItems) { var action = ReduceParserAction.Create(item.Core.Production); foreach (var lkh in item.Lookaheads) { if (state.Actions.ContainsKey(lkh)) { continue; } state.Actions[lkh] = action; } } //foreach item } //foreach state }
public PrecedenceBasedParserAction(BnfTerm shiftTerm, ParserState newShiftState, Production reduceProduction) { _reduceAction = new ReduceParserAction(reduceProduction); var reduceEntry = new ConditionalEntry(CheckMustReduce, _reduceAction, "(Precedence comparison)"); ConditionalEntries.Add(reduceEntry); DefaultAction = _shiftAction = new ShiftParserAction(shiftTerm, newShiftState); }
} //method //Resolve to default actions private void HandleUnresolvedConflicts() { foreach (var state in _data.States) { if (state.BuilderData.Conflicts.Count == 0) { continue; } var shiftReduceConflicts = state.BuilderData.GetShiftReduceConflicts(); var reduceReduceConflicts = state.BuilderData.GetReduceReduceConflicts(); var stateData = state.BuilderData; if (shiftReduceConflicts.Count > 0) { _language.Errors.Add(GrammarErrorLevel.Conflict, state, Resources.ErrSRConflict, state, shiftReduceConflicts.ToString()); } if (reduceReduceConflicts.Count > 0) { _language.Errors.Add(GrammarErrorLevel.Conflict, state, Resources.ErrRRConflict, state, reduceReduceConflicts.ToString()); } //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, only report it //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 firstProd = reduceItems.First().Core.Production; var action = new ReduceParserAction(firstProd); state.Actions[conflict] = action; } //stateData.Conflicts.Clear(); -- do not clear them, let the set keep the auto-resolved conflicts, may find more use for this later } }
public override void Apply(LanguageData language, LRItem owner) { var state = owner.State; var conflicts = state.BuilderData.Conflicts; if (conflicts.Count == 0) { return; } switch (_actionType) { case PreferredActionType.Shift: var currTerm = owner.Core.Current as Terminal; if (currTerm == null || !conflicts.Contains(currTerm)) { //nothing to do return; } //Current term for shift item (hint owner) is a conflict - resolve it with shift action var shiftAction = new ShiftParserAction(owner); state.Actions[currTerm] = shiftAction; conflicts.Remove(currTerm); return; case PreferredActionType.Reduce: if (!owner.Core.IsFinal) { //we take care of reduce items only here return; } //we have a reduce item with "Reduce" hint. Check if any of lookaheads are in conflict ReduceParserAction reduceAction = null; foreach (var lkhead in owner.Lookaheads) { if (conflicts.Contains(lkhead)) { if (reduceAction == null) { reduceAction = new ReduceParserAction(owner.Core.Production); } state.Actions[lkhead] = reduceAction; conflicts.Remove(lkhead); } } return; default: throw new ArgumentOutOfRangeException(); } }
public CustomParserAction(LanguageData language, ParserState state, ExecuteActionMethod executeRef) { Language = language; State = state; ExecuteRef = executeRef ?? throw new ArgumentNullException(nameof(executeRef)); Conflicts.UnionWith(state.BuilderData.Conflicts); // Create default shift and reduce actions foreach (var shiftItem in state.BuilderData.ShiftItems) { ShiftActions.Add(new ShiftParserAction(shiftItem)); } foreach (var item in state.BuilderData.ReduceItems) { ReduceActions.Add(ReduceParserAction.Create(item.Core.Production)); } }
//Find an LR item without hints compatible with term (either shift on term or reduce with term as lookahead); // this item without hints would become our default. We assume that other items have hints, and when conditions // on all these hints fail, we chose this remaining item without hints. private static ParserAction FindDefaultAction(ParserState state, BnfTerm term) { //First check reduce items var reduceItems = state.BuilderData.ReduceItems.SelectByLookahead(term as Terminal); foreach (var item in reduceItems) { if (item.Core.Hints.Count == 0) { return(ReduceParserAction.Create(item.Core.Production)); } } var shiftItem = state.BuilderData.ShiftItems.SelectByCurrent(term).FirstOrDefault(); if (shiftItem != null) { return(new ShiftParserAction(shiftItem)); } //if everything failed, returned first reduce item return(null); }
//Resolve to default actions private void HandleUnresolvedConflicts() { foreach (var state in _data.States) { if (state.BuilderData.Conflicts.Count == 0) continue; var shiftReduceConflicts = state.BuilderData.GetShiftReduceConflicts(); var reduceReduceConflicts = state.BuilderData.GetReduceReduceConflicts(); var stateData = state.BuilderData; if (shiftReduceConflicts.Count > 0) _language.Errors.Add(GrammarErrorLevel.Conflict, state, Resources.ErrSRConflict, state, shiftReduceConflicts.ToString()); if (reduceReduceConflicts.Count > 0) _language.Errors.Add(GrammarErrorLevel.Conflict, state, Resources.ErrRRConflict, state, reduceReduceConflicts.ToString()); //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, only report it //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 firstProd = reduceItems.First().Core.Production; var action = new ReduceParserAction(firstProd); state.Actions[conflict] = action; } //stateData.Conflicts.Clear(); -- do not clear them, let the set keep the auto-resolved conflicts, may find more use for this later } }
public override void Apply(LanguageData language, LRItem owner) { var state = owner.State; if (!state.BuilderData.IsInadequate) { return; //the state is adequate, we don't need to do anything } var conflicts = state.BuilderData.Conflicts; // Note that we remove lookaheads from the state conflicts set at the end of this method - to let parser builder know // that this conflict is taken care of. // On the other hand we may call this method multiple times for different LRItems if we have multiple hints in the same state. // Since we remove lookahead from conflicts on the first call, on the consequitive calls it will not be a conflict - // but we still need to add a new conditional entry to a conditional parser action for this lookahead. // Thus we process the lookahead anyway, even if it is not a conflict. // if (conflicts.Count == 0) return; -- this is a wrong thing to do switch (_actionType) { case PreferredActionType.Reduce: if (!owner.Core.IsFinal) { return; } //it is reduce action; find lookaheads in conflict var lkhs = owner.Lookaheads; if (lkhs.Count == 0) { return; //if no conflicts then nothing to do } var reduceAction = new ReduceParserAction(owner.Core.Production); var reduceCondEntry = new ConditionalParserAction.ConditionalEntry(CheckCondition, reduceAction, _description); foreach (var lkh in lkhs) { AddConditionalEntry(state, lkh, reduceCondEntry); if (conflicts.Contains(lkh)) { conflicts.Remove(lkh); } } break; case PreferredActionType.Shift: var curr = owner.Core.Current as Terminal; if (curr == null) { return; //it is either reduce item, or curr is a NonTerminal - we cannot shift it } var shiftAction = new ShiftParserAction(owner); var shiftCondEntry = new ConditionalParserAction.ConditionalEntry(CheckCondition, shiftAction, _description); AddConditionalEntry(state, curr, shiftCondEntry); if (conflicts.Contains(curr)) { conflicts.Remove(curr); } break; default: throw new ArgumentOutOfRangeException(); } }