void StripImpossibleLookAheads() { var segments = new List <Segment>(); foreach (var state in _graph.Graph.States) { segments.Clear(); foreach (var transition in state.ToTransitions) { if (!transition.Label.IsTerminal) { continue; } segments.Add(transition.Label); } if (segments.Count > 0) { state.Label.SubtractLookaheads(SegmentSet.New(segments)); } } }
static void PopulateLookaheads(SegmentSetProvider provider, Graph graph) { var pending = new Queue <KeyValuePair <Graph.State, ParseItem> >(); var eofSet = SegmentSet.New(new Segment[] { Segment.EOF }); foreach (var state in graph.StartStates) { foreach (var item in state.Label) { if (item.Production.Target.IsInitial) { state.Label.SetLookahead(item, eofSet); pending.Enqueue(new KeyValuePair <Graph.State, ParseItem>(state, item)); } } } while (pending.Count > 0) { var pair = pending.Dequeue(); var thisState = pair.Key; var thisItem = pair.Value; var thisLookahead = thisState.Label.GetLookahead(thisItem); var next = thisItem.Production.Segments[thisItem.Position]; foreach (var transition in thisState.ToTransitions) { if (transition.Label != next) { continue; } var nextItem = thisItem.NextItem(); if (transition.ToState.Label.TryUnionLookahead(nextItem, thisLookahead) && nextItem.Position != nextItem.Production.Segments.Length) { pending.Enqueue(new KeyValuePair <Graph.State, ParseItem>(transition.ToState, nextItem)); } break; } if (!next.IsTerminal) { var follow = provider.GetFollowSets(thisItem.Production, thisItem.Position); if (follow.ContainsSegment(null)) { follow = thisLookahead.Union(follow.Subtract(SegmentSet.EpsilonSet)); } foreach (var nextItem in thisState.Label) { if (nextItem.Position != 0) { continue; } if (nextItem.Production.Target != next) { continue; } if (thisState.Label.TryUnionLookahead(nextItem, follow) && nextItem.Position != nextItem.Production.Segments.Length) { pending.Enqueue(new KeyValuePair <Graph.State, ParseItem>(thisState, nextItem)); } } } } }
static Dictionary <Segment, SegmentSet> ExtractFirstsSet(Dictionary <Segment, Production[]> productions) { var changed = true; var result = new Dictionary <Segment, SegmentSet>(); while (changed) { changed = false; foreach (var nonTerminal in productions) { if (!result.TryGetValue(nonTerminal.Key, out var firsts)) { firsts = SegmentSet.EmptySet; } for (var i = 0; i < nonTerminal.Value.Length; i++) { var production = nonTerminal.Value[i]; var containsEmpty = true; for (var k = 0; k < production.Segments.Length; k++) { SegmentSet set; SegmentSet segmentsToAdd; var pSegment = production.Segments[k]; if (pSegment.IsTerminal) { segmentsToAdd = set = SegmentSet.New(new Segment[] { pSegment }); } else if (result.TryGetValue(pSegment, out set)) { segmentsToAdd = set.Subtract(SegmentSet.EpsilonSet); } else { segmentsToAdd = set = SegmentSet.EmptySet; } if (!firsts.IsSupersetOf(segmentsToAdd)) { firsts = firsts.Union(segmentsToAdd); changed = true; } if (!set.ContainsSegment(null)) { containsEmpty = false; break; } } if (containsEmpty && !firsts.ContainsSegment(null)) { firsts = firsts.Union(SegmentSet.EpsilonSet); changed = true; } } result[nonTerminal.Key] = firsts; } } return(result); }