static ParseItemSet Closure(SegmentSetProvider provider, ParseItemSet kernelItems) { var lookup = new Dictionary <ParseItem, bool>(); var itemsToAdd = new Queue <ParseItem>(); EnqueueRange(itemsToAdd, kernelItems); while (itemsToAdd.Count > 0) { var item = itemsToAdd.Dequeue(); var production = item.Production; if (!lookup.ContainsKey(item)) { lookup.Add(item, true); if (item.Position < production.Segments.Length) { var next = production.Segments[item.Position]; if (!next.IsTerminal) { EnqueueRange(itemsToAdd, provider.CreateParseItems(next)); } } } } return(ParseItemSet.New(lookup.Keys)); }
static ParseGraph ConstructGraph(Config config, SegmentSetProvider provider) { var graphBuilder = new Graph.Builder(); var map = new Dictionary <ParseItemSet, Graph.State>(); var queue = new Queue <Graph.State>(); var startStates = new List <Graph.State>(); var topLevelSegments = new List <Segment>(); foreach (var segment in provider.InitialSegments) { var initialKernel = ParseItemSet.New(provider.CreateParseItems(segment)); var initialState = graphBuilder.NewState(true, Closure(provider, initialKernel)); map.Add(initialKernel, initialState); queue.Enqueue(initialState); startStates.Add(initialState); topLevelSegments.Add(new Segment(segment.Name, false)); } while (queue.Count > 0) { var fromState = queue.Dequeue(); foreach (var pair in fromState.Label.GetTransitionKernels()) { if (!map.TryGetValue(pair.Value, out var toState)) { toState = graphBuilder.NewState(false, Closure(provider, pair.Value)); map.Add(pair.Value, toState); queue.Enqueue(toState); } graphBuilder.AddTransition(fromState, toState, pair.Key); } } var graph = graphBuilder.Graph; PopulateLookaheads(provider, graph); ParseGraphOptimiser.Optimise(config, graphBuilder); return(new ParseGraph(graph, topLevelSegments.ToArray(), startStates.ToArray())); }