/** * Finds the look-ahead set for a production pattern. The 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 pattern the production pattern * @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 production pattern * * @throws ParserCreationException if an infinite loop was found * in the grammar */ private LookAheadSet FindLookAhead(ProductionPattern pattern, int length, CallStack stack, LookAheadSet filter) { LookAheadSet result; LookAheadSet temp; // Check for infinite loop if (stack.Contains(pattern.Name, length)) { throw new ParserCreationException( ParserCreationException.ErrorType.INFINITE_LOOP, pattern.Name, (String)null); } // Find pattern look-ahead stack.Push(pattern.Name, length); result = new LookAheadSet(length); for (int i = 0; i < pattern.Count; i++) { temp = FindLookAhead(pattern[i], length, 0, stack, filter); result.AddAll(temp); } stack.Pop(); return(result); }
/** * 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; LookAheadSet first; LookAheadSet follow; int max; // 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; i++) { first = first.CreateOverlaps(filter); if (first.Size() <= 0 || first.GetMinLength() >= length) { break; } follow = FindLookAhead(elem, length, 0, stack, filter.CreateFilter(first)); first = first.CreateCombination(follow); result.AddAll(first); } return(result); }
/** * Returns the union of all alternative look-ahead sets in a * production pattern. * * @param pattern the production pattern * * @return a unified look-ahead set */ private LookAheadSet FindUnion(ProductionPattern pattern) { LookAheadSet result; int length = 0; int i; for (i = 0; i < pattern.Count; i++) { result = pattern[i].LookAhead; if (result.GetMaxLength() > length) { length = result.GetMaxLength(); } } result = new LookAheadSet(length); for (i = 0; i < pattern.Count; i++) { result.AddAll(pattern[i].LookAhead); } return(result); }
/** * Returns a look-ahead set with all conflics between * alternatives in a production pattern. * * @param pattern the production pattern * @param maxLength the maximum token sequence length * * @return a look-ahead set with the conflicts found * * @throws ParserCreationException if an inherent ambiguity was * found among the look-ahead sets */ private LookAheadSet FindConflicts(ProductionPattern pattern, int maxLength) { LookAheadSet result = new LookAheadSet(maxLength); LookAheadSet set1; LookAheadSet set2; for (int i = 0; i < pattern.Count; i++) { set1 = pattern[i].LookAhead; for (int j = 0; j < i; j++) { set2 = pattern[j].LookAhead; result.AddAll(set1.CreateIntersection(set2)); } } if (result.IsRepetitive()) { ThrowAmbiguityException(pattern.Name, null, result); } return(result); }
/** * Creates a new look-ahead set that is the combination of * this set with another set. The combination is created by * creating new token sequences that consist of appending all * elements from the specified set onto all elements in this * set. This is sometimes referred to as the cartesian * product. * * @param set the set to combine with * * @return a new look-ahead set containing the combination */ public LookAheadSet CreateCombination(LookAheadSet set) { LookAheadSet result = new LookAheadSet(maxLength); Sequence first; Sequence second; // Handle special cases if (this.Size() <= 0) { return(set); } else if (set.Size() <= 0) { return(this); } // Create combinations for (int i = 0; i < elements.Count; i++) { first = (Sequence)elements[i]; if (first.Length() >= maxLength) { result.Add(first); } else if (first.Length() <= 0) { result.AddAll(set); } else { for (int j = 0; j < set.elements.Count; j++) { second = (Sequence)set.elements[j]; result.Add(first.Concat(maxLength, second)); } } } return(result); }
/** * Calculates the look-ahead needed for the specified production * pattern. This method attempts to resolve any conflicts and * stores the results in the pattern look-ahead object. * * @param pattern the production pattern * * @throws ParserCreationException if the look-ahead set couldn't * be determined due to inherent ambiguities */ private void CalculateLookAhead(ProductionPattern pattern) { ProductionPatternAlternative alt; LookAheadSet result; LookAheadSet[] alternatives; LookAheadSet conflicts; LookAheadSet previous = new LookAheadSet(0); int length = 1; int i; CallStack stack = new CallStack(); // Calculate simple look-ahead stack.Push(pattern.Name, 1); result = new LookAheadSet(1); alternatives = new LookAheadSet[pattern.Count]; for (i = 0; i < pattern.Count; i++) { alt = pattern[i]; alternatives[i] = FindLookAhead(alt, 1, 0, stack, null); alt.LookAhead = alternatives[i]; result.AddAll(alternatives[i]); } if (pattern.LookAhead == null) { pattern.LookAhead = result; } conflicts = FindConflicts(pattern, 1); // Resolve conflicts while (conflicts.Size() > 0) { length++; stack.Clear(); stack.Push(pattern.Name, length); conflicts.AddAll(previous); for (i = 0; i < pattern.Count; i++) { alt = pattern[i]; if (alternatives[i].Intersects(conflicts)) { alternatives[i] = FindLookAhead(alt, length, 0, stack, conflicts); alt.LookAhead = alternatives[i]; } if (alternatives[i].Intersects(conflicts)) { if (pattern.DefaultAlternative == null) { pattern.DefaultAlternative = alt; } else if (pattern.DefaultAlternative != alt) { result = alternatives[i].CreateIntersection(conflicts); ThrowAmbiguityException(pattern.Name, null, result); } } } previous = conflicts; conflicts = FindConflicts(pattern, length); } // Resolve conflicts inside rules for (i = 0; i < pattern.Count; i++) { CalculateLookAhead(pattern[i], 0); } }