示例#1
0
        public static ParseGraph ConstructGraph(Config config)
        {
            var productions = ExtractProductions(config);
            var provider    = new SegmentSetProvider(productions);

            return(ConstructGraph(config, provider));
        }
示例#2
0
        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));
        }
示例#3
0
        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()));
        }
示例#4
0
        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));
                        }
                    }
                }
            }
        }