예제 #1
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));
        }
예제 #2
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()));
        }
예제 #3
0
        ParseItem[] FindTrivialItems(ParseItemSet set)
        {
            var count  = set.Count;
            var items  = new ParseItem[count];
            var tokens = new Segment[count];
            var write  = 0;

            set.CopyTo(items, 0);

            // Consider only incomplete items.
            for (var i = 0; i < count; i++)
            {
                var item       = items[i];
                var production = item.Production;

                if (item.Position < production.Segments.Length)
                {
                    items[write]  = items[i];
                    tokens[write] = production.Segments[item.Position];
                    write++;
                }
            }

            if (write == 0)
            {
                return(null);
            }

            count = write;
            write = 0;

            Array.Sort(tokens, items, 0, count);

            var duplicate = false;
            var prevToken = tokens[0];
            var prevItem  = items[0];

            // Discard items that share the "next" segment or have a non-trivial action.
            for (var i = 1; i < count; i++)
            {
                var nextToken = tokens[i];
                var nextItem  = items[i];

                if (nextToken == prevToken)
                {
                    duplicate = true;
                }
                else
                {
                    if (duplicate)
                    {
                        duplicate = false;
                    }
                    else if (!prevItem.Production.Target.IsInitial && _trivialLookup[prevItem.Production])
                    {
                        items[write]  = prevItem;
                        tokens[write] = prevToken;
                        write++;
                    }

                    prevToken = nextToken;
                    prevItem  = nextItem;
                }
            }

            if (!duplicate && !prevItem.Production.Target.IsInitial && _trivialLookup[prevItem.Production])
            {
                items[write]  = prevItem;
                tokens[write] = prevToken;
                write++;
            }

            if (write == 0)
            {
                return(null);
            }

            count = write;

            if (count < items.Length)
            {
                Array.Resize(ref items, count);
            }

            return(items);
        }