public override void Apply(LanguageData language, Construction.LRItem owner) { //Create custom action and put it into state.Actions table var state = owner.State; var action = new CustomParserAction(language, state, _executeMethod); if (_previewMethod != null) { _previewMethod(action); } if (!state.BuilderData.IsInadequate) // adequate state, with a single possible action which is DefaultAction { state.DefaultAction = action; } else if (owner.Core.Current != null) //shift action { state.Actions[owner.Core.Current] = action; } else { foreach (var lkh in owner.Lookaheads) { state.Actions[lkh] = action; } } //We consider all conflicts handled by the action state.BuilderData.Conflicts.Clear(); } //method
public override void Apply(LanguageData language, Construction.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 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 head 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 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 ConditionalEntry(CheckCondition, shiftAction, _description); AddConditionalEntry(state, curr, shiftCondEntry); if (conflicts.Contains(curr)) { conflicts.Remove(curr); } break; } }//method
public override void Apply(LanguageData language, Construction.LRItem owner) { //Check that owner is not final - we can imply precedence only in shift context var curr = owner.Core.Current; if (curr == null) { return; } //mark the state, to make sure we do stuff in Term_Shifting event handler only in appropriate states owner.State.CustomFlags |= ImpliedPrecedenceCustomFlag; curr.Shifting += Term_Shifting; }
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
public ShiftParserAction(Construction.LRItem item) : this(item.Core.Current, item.ShiftedItem.State) { }
} //method private void ResolveConflictByHints(ParserState state, Terminal conflict) { var stateData = state.BuilderData; //reduce hints var reduceItems = stateData.ReduceItems.SelectByLookahead(conflict); foreach (var reduceItem in reduceItems) { if (reduceItem.Core.Hints.Find(h => h.HintType == HintType.ResolveToReduce) != null) { state.Actions[conflict] = new ParserAction(ParserActionType.Reduce, null, reduceItem.Core.Production); state.BuilderData.ResolvedConflicts.Add(conflict); return; } } //shift hints var shiftItems = stateData.ShiftItems.SelectByCurrent(conflict); foreach (var shiftItem in shiftItems) { if (shiftItem.Core.Hints.Find(h => h.HintType == HintType.ResolveToShift) != null) { //shift action is already there state.BuilderData.ResolvedConflicts.Add(conflict); return; } } //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; var allItems = new LRItemList(); allItems.AddRange(state.BuilderData.ShiftItems.SelectByCurrent(conflict)); allItems.AddRange(state.BuilderData.ReduceItems.SelectByLookahead(conflict)); // Scan all items and try to find hint with resolution type Code foreach (var item in allItems) { if (item.Core.Hints.Find(h => h.HintType == HintType.ResolveInCode) != null) { state.Actions[conflict] = new ParserAction(ParserActionType.Code, newState, reduceProduction); state.BuilderData.ResolvedConflicts.Add(conflict); return; } } //custom hints // find custom grammar hints and build custom conflict resolver var customHints = new List <CustomGrammarHint>(); var hintItems = new Dictionary <CustomGrammarHint, LRItem>(); LRItem defaultItem = null; // the first item with no hints foreach (var item in allItems) { var hints = item.Core.Hints.OfType <CustomGrammarHint>(); foreach (var hint in hints) { customHints.Add(hint); hintItems[hint] = item; } if (defaultItem == null && !hints.Any()) { defaultItem = item; } } // if there are custom hints, build conflict resolver if (customHints.Count > 0) { state.Actions[conflict] = new ParserAction(newState, reduceProduction, args => { // examine all custom hints and select the first production that matched foreach (var customHint in customHints) { if (customHint.Match(args)) { var item = hintItems[customHint]; args.ReduceProduction = item.Core.Production; args.Result = customHint.Action; return; } } // no hints matched, select default LRItem if (defaultItem != null) { args.ReduceProduction = defaultItem.Core.Production; args.Result = args.NewShiftState != null ? ParserActionType.Shift : ParserActionType.Reduce; return; } // prefer Reduce if Shift operation is not available args.Result = args.NewShiftState != null ? ParserActionType.Shift : ParserActionType.Reduce; // TODO: figure out what to do next }); state.BuilderData.ResolvedConflicts.Add(conflict); return; } }