/** * Checks a production pattern for completeness. If some rule * in the pattern referenced an production pattern not added * to this parser, a parser creation exception will be thrown. * * @param pattern the production pattern to check * * @throws ParserCreationException if the pattern referenced a * pattern not added to this parser */ private void CheckPattern(ProductionPattern pattern) { for (int i = 0; i < pattern.Count; i++) { CheckAlternative(pattern.Name, pattern[i]); } }
/** * 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); }
/** * 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)); } }
/** * 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; int i; buffer.Append(prod.Name); buffer.Append(" ("); buffer.Append(prod.Id); buffer.Append(") "); for (i = 0; i < buffer.Length; i++) { indent.Append(" "); } buffer.Append("= "); indent.Append("| "); for (i = 0; i < prod.Count; i++) { if (i > 0) { buffer.Append(indent); } buffer.Append(ToString(prod[i])); buffer.Append("\n"); } for (i = 0; i < prod.Count; 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(tokenizer)); buffer.Append("\n"); } } return(buffer.ToString()); }
/** * Parses a production pattern. A parse tree node may or may * not be created depending on the analyzer callbacks. * * @param pattern the production pattern to parse * * @return the parse tree node created, or null * * @throws ParseException if the input couldn't be parsed * correctly */ private Node ParsePattern(ProductionPattern pattern) { ProductionPatternAlternative alt; ProductionPatternAlternative defaultAlt; defaultAlt = pattern.DefaultAlternative; for (int i = 0; i < pattern.Count; i++) { alt = pattern[i]; if (defaultAlt != alt && IsNext(alt)) { return(ParseAlternative(alt)); } } if (defaultAlt == null || !IsNext(defaultAlt)) { ThrowParseException(FindUnion(pattern)); } return(ParseAlternative(defaultAlt)); }
/** * 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); }
/** * Adds a new production pattern to the parser. The first pattern * added is assumed to be the starting point in the grammar. The * patterns added may be validated to some extent. * * @param pattern the pattern to add * * @throws ParserCreationException if the pattern couldn't be * added correctly to the parser */ public virtual void AddPattern(ProductionPattern pattern) { if (pattern.Count <= 0) { throw new ParserCreationException( ParserCreationException.ErrorType.INVALID_PRODUCTION, pattern.Name, "no production alternatives are present (must have at " + "least one)"); } if (patternIds.ContainsKey(pattern.Id)) { throw new ParserCreationException( ParserCreationException.ErrorType.INVALID_PRODUCTION, pattern.Name, "another pattern with the same id (" + pattern.Id + ") has already been added"); } patterns.Add(pattern); patternIds.Add(pattern.Id, pattern); SetInitialized(false); }
/** * Adds a new production pattern to the parser. The pattern * will be added last in the list. The first pattern added is * assumed to be the starting point in the grammar. The * pattern will be validated against the grammar type to some * extent. * * @param pattern the pattern to add * * @throws ParserCreationException if the pattern couldn't be * added correctly to the parser */ public override void AddPattern(ProductionPattern pattern) { // Check for empty matches if (pattern.IsMatchingEmpty()) { throw new ParserCreationException( ParserCreationException.ErrorType.INVALID_PRODUCTION, pattern.Name, "zero elements can be matched (minimum is one)"); } // Check for left-recusive patterns if (pattern.IsLeftRecursive()) { throw new ParserCreationException( ParserCreationException.ErrorType.INVALID_PRODUCTION, pattern.Name, "left recursive patterns are not allowed"); } // Add pattern base.AddPattern(pattern); }
/** * Creates a new production node. * * @param pattern the production pattern */ public Production(ProductionPattern pattern) { this.pattern = pattern; this.children = new ArrayList(); }
/** * Changes the production pattern containing this alternative. * This method should only be called by the production pattern * class. * * @param pattern the new production pattern */ internal void SetPattern(ProductionPattern pattern) { this.pattern = pattern; }
/** * 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); } }
/** * Factory method to create a new production node. This method * can be overridden to provide other production implementations * than the default one. * * @param pattern the production pattern * * @return the new production node * * */ protected virtual Production NewProduction(ProductionPattern pattern) { return(analyzer.NewProduction(pattern)); }
/** * Factory method to create a new production node. This method * can be overridden to provide other production implementations * than the default one. * * @param pattern the production pattern * * @return the new production node * */ public virtual Production NewProduction(ProductionPattern pattern) { return(new Production(pattern)); }