Esempio n. 1
0
        public bool TryUnionLookahead(ParseItem item, SegmentSet lookahead)
        {
            if (item == null)
            {
                throw new ArgumentNullException(nameof(item));
            }
            if (lookahead == null)
            {
                throw new ArgumentNullException(nameof(lookahead));
            }

            var index = IndexOf(_items, item);

            if (index < 0)
            {
                throw new ArgumentException("item not in this set", nameof(item));
            }

            var existing = _lookahead[index];

            if (existing == null)
            {
                _lookahead[index] = lookahead;
                return(true);
            }
            else if (!existing.IsSupersetOf(lookahead))
            {
                _lookahead[index] = existing.Union(lookahead);
                return(true);
            }
            else
            {
                return(false);
            }
        }
Esempio n. 2
0
        public void SubtractLookaheads(SegmentSet lookahead)
        {
            if (lookahead == null)
            {
                throw new ArgumentNullException(nameof(lookahead));
            }

            for (var i = 0; i < _lookahead.Length; i++)
            {
                _lookahead[i] = _lookahead[i].Subtract(lookahead);
            }
        }
Esempio n. 3
0
        static SegmentSet ExtractInitialSegments(Dictionary <Segment, Production[]> productions)
        {
            var list = new List <Segment>();

            foreach (var pair in productions)
            {
                if (pair.Key.IsInitial)
                {
                    list.Add(pair.Key);
                }
            }

            return(list.Count == 0 ? SegmentSet.EmptySet : SegmentSet.New(list));
        }
Esempio n. 4
0
        public void SetLookahead(ParseItem item, SegmentSet lookahead)
        {
            if (item == null)
            {
                throw new ArgumentNullException(nameof(item));
            }

            var index = IndexOf(_items, item);

            if (index < 0)
            {
                throw new ArgumentException("item not in this set", nameof(item));
            }
            _lookahead[index] = lookahead;
        }
Esempio n. 5
0
        static void Append(StringBuilder builder, ParseItem item, SegmentSet lookahead)
        {
            if (builder == null)
            {
                throw new ArgumentNullException(nameof(builder));
            }

            builder.Append("[");
            item.Production.Target.AppendTo(builder);
            builder.Append(" ->");

            for (var i = 0; i < item.Position; i++)
            {
                builder.Append(' ');
                item.Production.Segments[i].AppendTo(builder);
            }

            builder.Append(" \u2022");

            for (var i = item.Position; i < item.Production.Segments.Length; i++)
            {
                builder.Append(' ');
                item.Production.Segments[i].AppendTo(builder);
            }

            if (lookahead != null)
            {
                using (var enumerator = lookahead.GetEnumerator())
                {
                    if (enumerator.MoveNext())
                    {
                        builder.Append(", ");
                        enumerator.Current.AppendTo(builder);

                        while (enumerator.MoveNext())
                        {
                            builder.Append("/");
                            enumerator.Current.AppendTo(builder);
                        }
                    }
                }
            }

            builder.Append("]");
        }
Esempio n. 6
0
        static SegmentSet[] ExtractFollowSets(Production prod, Dictionary <Segment, SegmentSet> firstsSet)
        {
            var sets = new SegmentSet[prod.Segments.Length];

            if (prod.Segments.Length > 0)
            {
                var trailing = SegmentSet.EpsilonSet;

                for (var i = sets.Length - 1; i > 0; i--)
                {
                    sets[i] = trailing;

                    var seg = prod.Segments[i];

                    if (seg.IsTerminal)
                    {
                        trailing = SegmentSet.New(new Segment[] { seg });
                    }
                    else
                    {
                        if (firstsSet.TryGetValue(seg, out var set))
                        {
                            if (set.ContainsSegment(null))
                            {
                                trailing = trailing.Union(set.Subtract(SegmentSet.EpsilonSet));
                            }
                            else
                            {
                                trailing = set;
                            }
                        }
                    }
                }

                sets[0] = trailing;
            }

            return(sets);
        }
Esempio n. 7
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));
                }
            }
        }
Esempio n. 8
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));
                        }
                    }
                }
            }
        }
Esempio n. 9
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);
        }
Esempio n. 10
0
 ParseItemSet(ParseItem[] items)
 {
     _items     = items;
     _hash      = CalculateHash(items);
     _lookahead = new SegmentSet[items.Length];
 }