//* // * Calculates the look-aheads needed for the specified pattern // * alternative. This method attempts to resolve any conflicts in // * optional elements by recalculating look-aheads for referenced // * productions. // * // * @param alt the production pattern alternative // * @param pos the pattern element position // * // * @throws ParserCreationException if the look-ahead set couldn't // * be determined due to inherent ambiguities // private void CalculateLookAhead(ProductionPatternAlternative alt, int pos) { ProductionPattern pattern = default(ProductionPattern); ProductionPatternElement elem = default(ProductionPatternElement); LookAheadSet first = default(LookAheadSet); LookAheadSet follow = default(LookAheadSet); LookAheadSet conflicts = default(LookAheadSet); LookAheadSet previous = new LookAheadSet(0); string location = null; int length = 1; // Check trivial cases if (pos >= alt.Count) { return; } // Check for non-optional element pattern = alt.Pattern; elem = alt[pos]; if (elem.MinCount == elem.MaxCount) { CalculateLookAhead(alt, pos + 1); return; } // Calculate simple look-aheads first = FindLookAhead(elem, 1, new CallStack(), null); follow = FindLookAhead(alt, 1, pos + 1, new CallStack(), null); // Resolve conflicts location = "at position " + (pos + 1); conflicts = FindConflicts(pattern.Name, location, first, follow); while (conflicts.Size() > 0) { length += 1; conflicts.AddAll(previous); first = FindLookAhead(elem, length, new CallStack(), conflicts); follow = FindLookAhead(alt, length, pos + 1, new CallStack(), conflicts); first = first.CreateCombination(follow); elem.LookAhead = first; if (first.Intersects(conflicts)) { first = first.CreateIntersection(conflicts); ThrowAmbiguityException(pattern.Name, location, first); } previous = conflicts; conflicts = FindConflicts(pattern.Name, location, first, follow); } // Check remaining elements CalculateLookAhead(alt, pos + 1); }
//* // * Finds the look-ahead set for a production pattern alternative. // * The pattern position and maximum look-ahead length must be // * specified. It is also possible to specify a look-ahead set // * filter, which will make sure that unnecessary token sequences // * will be avoided. // * // * @param alt the production pattern alternative // * @param length the maximum look-ahead length // * @param pos the pattern element position // * @param stack the call stack used for loop detection // * @param filter the look-ahead set filter // * // * @return the look-ahead set for the pattern alternative // * // * @throws ParserCreationException if an infinite loop was found // * in the grammar // private LookAheadSet FindLookAhead(ProductionPatternAlternative alt, int length, int pos, CallStack stack, LookAheadSet filter) { LookAheadSet first = default(LookAheadSet); LookAheadSet follow = default(LookAheadSet); LookAheadSet overlaps = default(LookAheadSet); // Check trivial cases if (length <= 0 || pos >= alt.Count) { return(new LookAheadSet(0)); } // Find look-ahead for this element first = FindLookAhead(alt[pos], length, stack, filter); if (alt[pos].MinCount == 0) { first.AddEmpty(); } // Find remaining look-ahead if (filter == null) { length -= first.GetMinLength(); if (length > 0) { follow = FindLookAhead(alt, length, pos + 1, stack, null); first = first.CreateCombination(follow); } } else if (filter.IsOverlap(first)) { overlaps = first.CreateOverlaps(filter); length -= overlaps.GetMinLength(); filter = filter.CreateFilter(overlaps); follow = FindLookAhead(alt, length, pos + 1, stack, filter); first.RemoveAll(overlaps); first.AddAll(overlaps.CreateCombination(follow)); } return(first); }
//* // * Finds the look-ahead set for a production pattern element. The // * maximum look-ahead length must be specified. This method takes // * the element repeats into consideration when creating the // * look-ahead set, but does NOT include an empty sequence even if // * the minimum count is zero (0). It is also possible to specify a // * look-ahead set filter, which will make sure that unnecessary // * token sequences will be avoided. // * // * @param elem the production pattern element // * @param length the maximum look-ahead length // * @param stack the call stack used for loop detection // * @param filter the look-ahead set filter // * // * @return the look-ahead set for the pattern element // * // * @throws ParserCreationException if an infinite loop was found // * in the grammar // private LookAheadSet FindLookAhead(ProductionPatternElement elem, int length, CallStack stack, LookAheadSet filter) { LookAheadSet result = default(LookAheadSet); LookAheadSet first = default(LookAheadSet); LookAheadSet follow = default(LookAheadSet); int max = 0; // Find initial element look-ahead first = FindLookAhead(elem, length, 0, stack, filter); result = new LookAheadSet(length); result.AddAll(first); if (filter == null || !filter.IsOverlap(result)) { return(result); } // Handle element repetitions if (elem.MaxCount == Int32.MaxValue) { first = first.CreateRepetitive(); } max = elem.MaxCount; if (length < max) { max = length; } for (int i = 1; i <= max - 1; i++) { first = first.CreateOverlaps(filter); if (first.Size() <= 0 || first.GetMinLength() >= length) { break; // TODO: might not be correct. Was : Exit For } follow = FindLookAhead(elem, length, 0, stack, filter.CreateFilter(first)); first = first.CreateCombination(follow); result.AddAll(first); } return(result); }