示例#1
0
        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));
                }
            }
        }
示例#2
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));
                        }
                    }
                }
            }
        }
示例#3
0
        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);
        }