//* // * Removes all the token sequences from a specified set. Only // * sequences already in this set will be removed. // * // * @param set the set to remove from // public void RemoveAll(LookAheadSet @set) { for (int i = 0; i <= @set.elements.Count - 1; i++) { Remove((Sequence)@set.elements[i]); } }
//* // * Creates a new look-ahead set filter. The filter will contain // * all sequences from this set, possibly left trimmed by each one // * of the sequences in the specified set. // * // * @param set the look-ahead set to trim with // * // * @return a new look-ahead set filter // public LookAheadSet CreateFilter(LookAheadSet @set) { LookAheadSet result = new LookAheadSet(maxLength); Sequence first = default(Sequence); Sequence second = default(Sequence); // Handle special cases if (this.Size() <= 0 || @set.Size() <= 0) { return(this); } for (int i = 0; i <= elements.Count - 1; i++) { // Create combinations first = (Sequence)elements[i]; for (int j = 0; j <= @set.elements.Count - 1; j++) { second = (Sequence)@set.elements[j]; if (first.StartsWith(second)) { result.Add(first.Subsequence(second.Length())); } } } return(result); }
//* // * Checks if another look-ahead set has an overlapping token // * sequence. An overlapping token sequence is a token sequence // * that is identical to another sequence, but for the length. // * I.e. one of the two sequences may be longer than the other. // * // * @param set the look-ahead set to check // * // * @return true if there is some token sequence that overlaps, or // * false otherwise // public bool IsOverlap(LookAheadSet @set) { for (int i = 0; i <= elements.Count - 1; i++) { if (@set.IsOverlap((Sequence)elements[i])) { return(true); } } return(false); }
//* // * Returns a look-ahead set with all conflicts between two // * look-ahead sets. // * // * @param pattern the pattern name being analyzed // * @param location the pattern location // * @param set1 the first look-ahead set // * @param set2 the second look-ahead set // * // * @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(string pattern, string location, LookAheadSet set1, LookAheadSet set2) { LookAheadSet result = default(LookAheadSet); result = set1.CreateIntersection(set2); if (result.IsRepetitive()) { ThrowAmbiguityException(pattern, location, result); } return(result); }
//* // * Checks if some token sequence is present in both this set // * and a specified one. // * // * @param set the look-ahead set to compare with // * // * @return true if the look-ahead sets intersect, or // * false otherwise // public bool Intersects(LookAheadSet @set) { for (int i = 0; i <= elements.Count - 1; i++) { if (@set.Contains((Sequence)elements[i])) { return(true); } } return(false); }
//* // * 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); }
//* // * Checks if the next tokens match a production pattern. The // * pattern look-ahead set will be used if existing, otherwise // * this method returns false. // * // * @param pattern the pattern to check // * // * @return true if the next tokens match, or // * false otherwise // private bool IsNext(ProductionPattern pattern) { LookAheadSet @set = pattern.LookAhead; if (@set == null) { return(false); } else { return(@set.IsNext(this)); } }
//* // * Checks if the next tokens match a production pattern // * alternative. The pattern alternative look-ahead set will be // * used if existing, otherwise this method returns false. // * // * @param alt the pattern alternative to check // * // * @return true if the next tokens match, or // * false otherwise // private bool IsNext(ProductionPatternAlternative alt) { LookAheadSet @set = alt.LookAhead; if (@set == null) { return(false); } else { return(@set.IsNext(this)); } }
//* // * Creates a new look-ahead set with overlaps from another. All // * token sequences in this set that overlaps with the other set // * will be added to the new look-ahead set. // * // * @param set the look-ahead set to check with // * // * @return a new look-ahead set containing the overlaps // public LookAheadSet CreateOverlaps(LookAheadSet @set) { LookAheadSet result = new LookAheadSet(maxLength); Sequence seq = default(Sequence); for (int i = 0; i <= elements.Count - 1; i++) { seq = (Sequence)elements[i]; if (@set.IsOverlap(seq)) { result.Add(seq); } } return(result); }
//* // * Throws a parser creation exception for an ambiguity. The // * specified look-ahead set contains the token conflicts to be // * reported. // * // * @param pattern the production pattern name // * @param location the production pattern location, or null // * @param set the look-ahead set with conflicts // * // * @throws ParserCreationException always thrown by this method // private void ThrowAmbiguityException(string pattern, string location, LookAheadSet @set) { ArrayList list = new ArrayList(); int[] initials = null; // Find next token descriptions initials = @set.GetInitialTokens(); for (int i = 0; i <= initials.Length - 1; i++) { list.Add(GetTokenDescription(initials[i])); } // Create exception throw new ParserCreationException(ParserCreationException.ErrorType.INHERENT_AMBIGUITY, pattern, location, list); }
//* // * Creates a new look-ahead set that is the result of reading // * the specified token. The new look-ahead set will contain // * the rest of all the token sequences that started with the // * specified token. // * // * @param token the token to read // * // * @return a new look-ahead set containing the remaining tokens // public LookAheadSet CreateNextSet(int token) { LookAheadSet result = new LookAheadSet(maxLength - 1); Sequence seq = default(Sequence); object value = null; for (int i = 0; i <= elements.Count - 1; i++) { seq = (Sequence)elements[i]; value = seq.GetToken(0); if (value != null && token == (int)value) { result.Add(seq.Subsequence(1)); } } return(result); }
//* // * Checks if the next tokens match a production pattern // * element. If the element has a look-ahead set it will be // * used, otherwise the look-ahead set of the referenced // * production or token will be used. // * // * @param elem the pattern element to check // * // * @return true if the next tokens match, or // * false otherwise // private bool IsNext(ProductionPatternElement elem) { LookAheadSet @set = elem.LookAhead; if (@set != null) { return(@set.IsNext(this)); } else if (elem.IsToken()) { return(elem.IsMatch(PeekToken(0))); } else { return(IsNext(GetPattern(elem.Id))); } }
//* // * Creates a new identical look-ahead set, except for the // * repeat flag being set in each token sequence. // * // * @return a new repetitive look-ahead set // public LookAheadSet CreateRepetitive() { LookAheadSet result = new LookAheadSet(maxLength); Sequence seq = default(Sequence); for (int i = 0; i <= elements.Count - 1; i++) { seq = (Sequence)elements[i]; if (seq.IsRepetitive()) { result.Add(seq); } else { result.Add(new Sequence(true, seq)); } } return(result); }
//* // * Returns a string representation of a production pattern. // * // * @param prod the production pattern // * // * @return a detailed string representation of the pattern // private string ToString(ProductionPattern prod) { StringBuilder buffer = new StringBuilder(); StringBuilder indent = new StringBuilder(); LookAheadSet @set = default(LookAheadSet); int i = 0; buffer.Append(prod.Name); buffer.Append(" ("); buffer.Append(prod.Id); buffer.Append(") "); for (i = 0; i <= buffer.Length - 1; i++) { indent.Append(" "); } buffer.Append("= "); indent.Append("| "); for (i = 0; i <= prod.Count - 1; i++) { if (i > 0) { buffer.Append(indent); } buffer.Append(ToString(prod[i])); buffer.Append("" + Convert.ToChar(10) + ""); } for (i = 0; i <= prod.Count - 1; i++) { @set = prod[i].LookAhead; if (@set.GetMaxLength() > 1) { buffer.Append("Using "); buffer.Append(@set.GetMaxLength()); buffer.Append(" token look-ahead for alternative "); buffer.Append(i + 1); buffer.Append(": "); buffer.Append(@set.ToString(m_tokenizer)); buffer.Append("" + Convert.ToChar(10) + ""); } } return(buffer.ToString()); }
//* // * 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); }
//* // * 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 = default(LookAheadSet); LookAheadSet set2 = default(LookAheadSet); for (int i = 0; i <= pattern.Count - 1; i++) { set1 = pattern[i].LookAhead; for (int j = 0; j <= i - 1; 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 intersection of // * this set with another set. The token sequences in the net // * set will only have the repeat flag set if it was set in // * both the identical token sequences. // * // * @param set the set to intersect with // * // * @return a new look-ahead set containing the intersection // public LookAheadSet CreateIntersection(LookAheadSet @set) { LookAheadSet result = new LookAheadSet(maxLength); Sequence seq1 = default(Sequence); Sequence seq2 = default(Sequence); for (int i = 0; i <= elements.Count - 1; i++) { seq1 = (Sequence)elements[i]; seq2 = @set.FindSequence(seq1); if (seq2 != null && seq1.IsRepetitive()) { result.Add(seq2); } else if (seq2 != null) { result.Add(seq1); } } 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 = 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); }
//* // * 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 = default(LookAheadSet); int length = 0; int i = 0; for (i = 0; i <= pattern.Count - 1; i++) { result = pattern[i].LookAhead; if (result.GetMaxLength() > length) { length = result.GetMaxLength(); } } result = new LookAheadSet(length); for (i = 0; i <= pattern.Count - 1; i++) { result.AddAll(pattern[i].LookAhead); } return(result); }
//* // * Finds the look-ahead set for a production pattern element. The // * maximum look-ahead length must be specified. This method does // * NOT take the element repeat into consideration when creating // * the look-ahead set. 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 dummy a parameter to distinguish the method // * @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, int dummy, CallStack stack, LookAheadSet filter) { LookAheadSet result = default(LookAheadSet); ProductionPattern pattern = default(ProductionPattern); if (elem.IsToken()) { result = new LookAheadSet(length); result.Add(elem.Id); } else { pattern = GetPattern(elem.Id); result = FindLookAhead(pattern, length, stack, filter); if (stack.Contains(pattern.Name)) { result = result.CreateRepetitive(); } } 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 = default(Sequence); Sequence second = default(Sequence); // Handle special cases if (this.Size() <= 0) { return(@set); } else if (@set.Size() <= 0) { return(this); } for (int i = 0; i <= elements.Count - 1; i++) { // Create combinations 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 - 1; j++) { second = (Sequence)@set.elements[j]; result.Add(first.Concat(maxLength, second)); } } } return(result); }
//* // * 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 = default(LookAheadSet); LookAheadSet temp = default(LookAheadSet); // 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 - 1; i++) { temp = FindLookAhead(pattern[i], length, 0, stack, filter); result.AddAll(temp); } stack.Pop(); return(result); }
//* // * Throws a parse exception that matches the specified look-ahead // * set. This method will take into account any initial matching // * tokens in the look-ahead set. // * // * @param set the look-ahead set to match // * // * @throws ParseException always thrown by this method // private void ThrowParseException(LookAheadSet @set) { Token token = default(Token); ArrayList list = new ArrayList(); int[] initials = null; // Read tokens until mismatch while (@set.IsNext(this, 1)) { @set = @set.CreateNextSet(NextToken().Id); } // Find next token descriptions initials = @set.GetInitialTokens(); for (int i = 0; i <= initials.Length - 1; i++) { list.Add(GetTokenDescription(initials[i])); } // Create exception token = NextToken(); throw new ParseException(ParseException.ErrorType.UNEXPECTED_TOKEN, token.ToShortString(), list, token.StartLine, token.StartColumn); }
//* // * 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 = default(ProductionPatternAlternative); LookAheadSet result = default(LookAheadSet); LookAheadSet[] alternatives = null; LookAheadSet conflicts = default(LookAheadSet); LookAheadSet previous = new LookAheadSet(0); int length = 1; int i = 0; 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 - 1; 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 += 1; stack.Clear(); stack.Push(pattern.Name, length); conflicts.AddAll(previous); for (i = 0; i <= pattern.Count - 1; 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 (!object.ReferenceEquals(pattern.DefaultAlternative, alt)) { result = alternatives[i].CreateIntersection(conflicts); ThrowAmbiguityException(pattern.Name, null, result); } } } previous = conflicts; conflicts = FindConflicts(pattern, length); } for (i = 0; i <= pattern.Count - 1; i++) { // Resolve conflicts inside rules CalculateLookAhead(pattern[i], 0); } }
//* // * Creates a duplicate look-ahead set, possibly with a // * different maximum length. // * // * @param maxLength the maximum token sequence length // * @param set the look-ahead set to copy // public LookAheadSet(int maxLength, LookAheadSet @set) : this(maxLength) { AddAll(@set); }