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); } }
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); } }
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)); }
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; }
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("]"); }
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); }
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)); } } }
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)); } } } } }
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); }
ParseItemSet(ParseItem[] items) { _items = items; _hash = CalculateHash(items); _lookahead = new SegmentSet[items.Length]; }