public override void Apply(LanguageData language, LRItem owner) { var state = owner.State; var allConflicts = state.BuilderData.Conflicts; if (allConflicts.Count == 0) { return; } //Find all conflicts that can be resolved by operator precedence // SL does not support Find extension, so we do it with explicit loop var operConflicts = new List <Terminal>(); foreach (var c in allConflicts) { if (c.Flags.IsSet(TermFlags.IsOperator)) { operConflicts.Add(c); } } foreach (var conflict in operConflicts) { var newState = state.BuilderData.GetNextState(conflict); var reduceItems = state.BuilderData.ReduceItems.SelectByLookahead(conflict).ToList(); if (newState == null || reduceItems.Count != 1) { continue; // this cannot be fixed by precedence } state.Actions[conflict] = new PrecedenceBasedParserAction(conflict, newState, reduceItems[0].Core.Production); allConflicts.Remove(conflict); } //foreach conflict }
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]); } }
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)) { return; //nothing to do } //Current term for shift item (hint owner) is a conflict - resolve it with shift action var newState = owner.ShiftedItem.State; var shiftAction = new ShiftParserAction(owner); state.Actions[currTerm] = shiftAction; conflicts.Remove(currTerm); return; case PreferredActionType.Reduce: if (!owner.Core.IsFinal) { return; //we take care of reduce items only here } //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; } //switch } //method
/// <summary> Gives a chance to a custom code in hint to interfere in parser automaton construction.</summary> /// <param name="language">The LanguageData instance.</param> /// <param name="owner">The LRItem that "owns" the hint. </param> /// <remarks> /// The most common purpose of this method (it's overrides) is to resolve the conflicts /// by adding specific actions into State.Actions dictionary. /// The owner parameter represents the position in the grammar expression where the hint /// is found. The parser state is available through owner.State property. /// </remarks> public virtual void Apply(LanguageData language, LRItem owner) { // owner.State -- the parser state // owner.State.BuilderData.Conflicts -- as set of conflict terminals // owner.State.Actions -- a dictionary of actions in the current state. }