/** * 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; ProductionPattern pattern; 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); }
/** * 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); } }
/** * 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); }
/** * 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))); } }
/** * 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; for (int i = 0; i < elem.MaxCount; i++) { string pr = Enum.GetName(typeof(SyntaxConstants), elem.GetId()); if (i < elem.MinCount || IsNext(elem)) { if (elem.IsToken()) { child = NextToken(elem.Id); EnterNode(child); AddNode(node, ExitNode(child)); if (ExitNode(child) != null) { production.AddRecursiveProduction("Enter: " + pr + "\n"); } production.AddProductionCode(elem.GetId()); production.AddProductionState("Enter: " + pr + "\n"); } else { pr = pr.Substring(5); production.AddRecursiveProduction("Enter: <" + pr + ">\n"); production.AddProductionCode(elem.GetId()); production.AddProductionState("Enter: <" + pr + ">\n"); child = ParsePattern(GetPattern(elem.Id)); AddNode(node, child); } } else { pr = pr.Substring(5); production.AddRecursiveProduction("Enter: NULL <" + pr + ">\n"); production.AddProductionState("NULL"); production.AddProductionCode(elem.GetId()); break; } } }
/** * 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()); }
/** * 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); }