private void PropagateLookaheads() { LRItemList currentList = new LRItemList(); //first collect all items foreach (ParserState state in Data.States) { currentList.AddRange(state.Items); } //Main loop - propagate until done while (currentList.Count > 0) { LRItemList newList = new LRItemList(); foreach (LRItem item in currentList) { if (item.NewLookaheads.Count == 0) { continue; } int oldCount = item.Lookaheads.Count; item.Lookaheads.AddRange(item.NewLookaheads); if (item.Lookaheads.Count != oldCount) { foreach (LRItem targetItem in item.PropagateTargets) { targetItem.NewLookaheads.AddRange(item.NewLookaheads); newList.Add(targetItem); } //foreach targetItem } //if item.NewLookaheads.Clear(); } //foreach item currentList = newList; } //while } //method
private void PropagateLookaheads() { LRItemList currentList = new LRItemList(); _data.States.ForEach(state => currentList.AddRange(state.Items)); while (currentList.Count > 0) { LRItemList newList = new LRItemList(); foreach (LRItem item in currentList) { if (item.NewLookaheads.Count == 0) { continue; } int oldCount = item.Lookaheads.Count; item.Lookaheads.AddRange(item.NewLookaheads); if (item.Lookaheads.Count != oldCount) { foreach (LRItem targetItem in item.PropagateTargets) { targetItem.NewLookaheads.AddRange(item.NewLookaheads); newList.Add(targetItem); } } item.NewLookaheads.Clear(); } currentList = newList; } }
} //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; } } }
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; }
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; } }
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); }
private void PropagateLookaheads() { LRItemList currentList = new LRItemList(); _data.States.ForEach(state => currentList.AddRange(state.Items)); while (currentList.Count > 0) { LRItemList newList = new LRItemList(); foreach (LRItem item in currentList) { if (item.NewLookaheads.Count == 0) continue; int oldCount = item.Lookaheads.Count; item.Lookaheads.AddRange(item.NewLookaheads); if (item.Lookaheads.Count != oldCount) { foreach (LRItem targetItem in item.PropagateTargets) { targetItem.NewLookaheads.AddRange(item.NewLookaheads); newList.Add(targetItem); } } item.NewLookaheads.Clear(); } currentList = newList; } }
}//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]; // If the ReduceProduction was clear, then use the default production following the hints if (args.ReduceProduction == null) args.ReduceProduction = item.Core.Production; 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; } }
} //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; } }