//* // * Parses a production pattern element. All nodes parsed may // * or may not be added to the parse tree node specified, // * depending on the analyzer callbacks. // * // * @param node the production parse tree node // * @param elem the production pattern element to parse // * // * @throws ParseException if the input couldn't be parsed // * correctly // private void ParseElement(Production node, ProductionPatternElement elem) { Node child = default(Node); for (int i = 0; i <= elem.MaxCount - 1; i++) { if (i < elem.MinCount || IsNext(elem)) { if (elem.IsToken()) { child = NextToken(elem.Id); EnterNode(child); AddNode(node, ExitNode(child)); } else { child = ParsePattern(GetPattern(elem.Id)); AddNode(node, child); } } else { break; // TODO: might not be correct. Was : Exit For } } }
//* // * Checks a production pattern element for completeness. If // * the element references a production pattern not added to // * this parser, a parser creation exception will be thrown. // * // * @param name the name of the pattern being checked // * @param elem the production pattern element to check // * // * @throws ParserCreationException if the element referenced a // * pattern not added to this parser // private void CheckElement(string name, ProductionPatternElement elem) { if (elem.IsProduction() && GetPattern(elem.Id) == null) { throw new ParserCreationException(ParserCreationException.ErrorType.INVALID_PRODUCTION, name, "an undefined production pattern id (" + elem.Id + ") is referenced"); } }
//* // * Adds a production pattern element to this alternative. The // * multiplicity values in the element will be overridden with // * the specified values. The element is appended to the end of // * the element list. // * // * @param elem the production pattern element // * @param min the minimum number of occurancies // * @param max the maximum number of occurancies, or // * -1 for infinite // public void AddElement(ProductionPatternElement elem, int min, int max) { if (elem.IsToken()) { AddToken(elem.Id, min, max); } else { AddProduction(elem.Id, min, max); } }
//* // * Returns the minimum number of elements needed to satisfy // * this alternative. The value returned is the sum of all the // * elements minimum count. // * // * @return the minimum number of elements // public int GetMinElementCount() { ProductionPatternElement elem = default(ProductionPatternElement); int min = 0; for (int i = 0; i <= elements.Count - 1; i++) { elem = (ProductionPatternElement)elements[i]; min += elem.MinCount; } return(min); }
//* // * 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 this object is equal to another. This method only // * returns true for another identical production pattern // * element. // * // * @param obj the object to compare with // * // * @return true if the object is identical to this one, or // * false otherwise // public override bool Equals(object obj) { ProductionPatternElement elem = default(ProductionPatternElement); if (obj is ProductionPatternElement) { elem = (ProductionPatternElement)obj; return(this.token == elem.token && this.m_id == elem.Id && this.min == elem.min && this.max == elem.max); } else { return(false); } }
//* // * 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))); } }
//* // * Checks if this alternative is recursive on the right-hand side. // * This method checks all the possible right side elements and // * returns true if the pattern itself is among them. // * // * @return true if the alternative is right side recursive, or // * false otherwise // public bool IsRightRecursive() { ProductionPatternElement elem = default(ProductionPatternElement); for (int i = elements.Count - 1; i >= 0; i += -1) { elem = (ProductionPatternElement)elements[i]; if (elem.Id == m_pattern.Id) { return(true); } else if (elem.MinCount > 0) { break; // TODO: might not be correct. Was : Exit For } } return(false); }
//* // * Returns the maximum number of elements needed to satisfy // * this alternative. The value returned is the sum of all the // * elements maximum count. // * // * @return the maximum number of elements // public int GetMaxElementCount() { ProductionPatternElement elem = default(ProductionPatternElement); int max = 0; for (int i = 0; i <= elements.Count - 1; i++) { elem = (ProductionPatternElement)elements[i]; if (elem.MaxCount >= Int32.MaxValue) { return(Int32.MaxValue); } else { max += elem.MaxCount; } } return(max); }
//* // * 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 a string representation of a production pattern // * element. // * // * @param elem the production pattern element // * // * @return a detailed string representation of the element // private string ToString(ProductionPatternElement elem) { StringBuilder buffer = new StringBuilder(); int min = elem.MinCount; int max = elem.MaxCount; if (min == 0 && max == 1) { buffer.Append("["); } if (elem.IsToken()) { buffer.Append(GetTokenDescription(elem.Id)); } else { buffer.Append(GetPattern(elem.Id).Name); } if (min == 0 && max == 1) { buffer.Append("]"); } else if (min == 0 && max == Int32.MaxValue) { buffer.Append("*"); } else if (min == 1 && max == Int32.MaxValue) { buffer.Append("+"); } else if (min != 1 || max != 1) { buffer.Append("{"); buffer.Append(min); buffer.Append(","); buffer.Append(max); buffer.Append("}"); } return(buffer.ToString()); }
//* // * 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); }
//* // * Adds a production pattern element to this alternative. The // * element is appended to the end of the element list. // * // * @param elem the production pattern element // public void AddElement(ProductionPatternElement elem) { elements.Add(elem); }