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; } } //method
//Check if there is an action already in state for this term; if yes, and it is Conditional action, // then simply add an extra conditional entry to it. If an action does not exist, or it is not conditional, // create new conditional action for this term. private void AddConditionalEntry(ParserState state, BnfTerm term, ConditionalEntry entry) { ParserAction oldAction; ConditionalParserAction condAction = null; if (state.Actions.TryGetValue(term, out oldAction)) condAction = oldAction as ConditionalParserAction; if (condAction == null) { //there's no old action, or it is not conditional; create new conditional action condAction = new ConditionalParserAction(); condAction.DefaultAction = oldAction; state.Actions[term] = condAction; } condAction.ConditionalEntries.Add(entry); if (condAction.DefaultAction == null) condAction.DefaultAction = FindDefaultAction(state, term); if (condAction.DefaultAction == null) //if still no action, then use the cond. action as default. condAction.DefaultAction = entry.Action; }