/// <summary> /// Appends a regular expression representation of the language described by the node to a given string builder, /// adding brackets if the parent operation has higher priority. /// </summary> /// <param name="resultBuilder">The string builder.</param> /// <param name="parentType">The type of the parent node.</param> /// <param name="formattingSettings">The formatting settings used for conversion from an automaton to a string.</param> /// <param name="useCache">Whether the value caching should be used (see <see cref="AppendToString(StringBuilder, RegexpFormattingSettings, bool)"/>).</param> /// <returns>Returns true if successful, false otherwise.</returns> private bool AppendRegexpWithBrackets( StringBuilder resultBuilder, RegexpTreeNodeType parentType, RegexpFormattingSettings formattingSettings, bool useCache) { Debug.Assert(formattingSettings != null, "A valid formatting settings description must be provided."); bool addBrackets = this.Type < parentType && !(formattingSettings.PutOptionalInSquareBrackets && this.IsOptional()); if (addBrackets) { resultBuilder.Append('('); } if (!this.AppendToString(resultBuilder, formattingSettings, useCache)) { return(false); } if (addBrackets) { resultBuilder.Append(')'); } return(true); }
/// <summary> /// Initializes a new instance of the <see cref="RegexpAutomatonFormat"/> class. /// </summary> /// <param name="formattingSettings">The formatting settings used for conversion from an automaton to a string.</param> public RegexpAutomatonFormat(RegexpFormattingSettings formattingSettings) { Argument.CheckIfNotNull(formattingSettings, "formattingSettings"); this.FormattingSettings = formattingSettings; }
/// <summary> /// Returns a string representation of the language described by the node. /// </summary> /// <param name="resultBuilder">The string builder to append to.</param> /// <param name="formattingSettings">The formatting settings used for conversion from an automaton to a string.</param> /// <param name="useCache">Whether the value caching should be used.</param> /// <returns>False if the max length was reached, true otherwise.</returns> /// <remarks> /// Value caching must be used with care: once cached, a value would never be invalidated. /// That is why this method should be called with value caching only on those nodes that have already been simplified. /// <see cref="SimplifyUnion"/> uses this method in exactly this way. /// </remarks> private bool AppendToString(StringBuilder resultBuilder, RegexpFormattingSettings formattingSettings, bool useCache) { Debug.Assert(formattingSettings != null, "Valid formatting settings must be provided."); Debug.Assert(!useCache || this.simplified, "Caching must not be used for non-simplified nodes."); int lengthAtStart = resultBuilder.Length; if (lengthAtStart > formattingSettings.TruncationLength) { return(false); } if (useCache && this.toStringVerboseCached != null && formattingSettings.Equals(VerboseFormattingSettings)) { resultBuilder.Append(this.toStringVerboseCached); return(true); } ////var resultBuilder = new StringBuilder(); switch (this.Type) { case RegexpTreeNodeType.Empty: break; case RegexpTreeNodeType.Nothing: resultBuilder.Append('Ø'); break; case RegexpTreeNodeType.ElementSet: if (typeof(TElement) == typeof(string)) { resultBuilder.Append("<"); if (this.elementSet is DiscreteChar) { ((DiscreteChar)(object)this.elementSet).AppendToString(resultBuilder); } else { var stringForm = this.elementSet.ToString(); ////if (stringForm.Contains('?')) stringForm = "?"; resultBuilder.Append(stringForm); } resultBuilder.Append(">"); } else { if (this.elementSet.IsPointMass) { if (this.elementSet is DiscreteChar) { var dc = (DiscreteChar)(object)this.elementSet; dc.AppendRegex(resultBuilder); } else { resultBuilder.Append(this.elementSet.Point); } } else if (this.elementSet.IsUniform() || formattingSettings.IgnoreElementDistributionDetails) { resultBuilder.Append(formattingSettings.ShowAnyElementAsQuestionMark ? '?' : '.'); } else { if (this.elementSet is DiscreteChar) { var dc = (DiscreteChar)(object)this.elementSet; dc.AppendRegex(resultBuilder); } else { // not a discrete char... What to do here? resultBuilder.Append(this.elementSet); } } } break; case RegexpTreeNodeType.Union: bool withSquareBrackets = formattingSettings.PutOptionalInSquareBrackets && this.IsOptional(); if (withSquareBrackets) { resultBuilder.Append('['); } bool hasPrevious = false; for (int i = 0; i < this.children.Count; ++i) { if (!withSquareBrackets || this.children[i].Type != RegexpTreeNodeType.Empty) { if (hasPrevious) { resultBuilder.Append('|'); } if (!this.children[i].AppendRegexpWithBrackets(resultBuilder, RegexpTreeNodeType.Union, formattingSettings, useCache)) { return(false); } hasPrevious = true; } } if (withSquareBrackets) { resultBuilder.Append(']'); } break; case RegexpTreeNodeType.Concat: for (int i = 0; i < this.children.Count; ++i) { if (!this.children[i].AppendRegexpWithBrackets(resultBuilder, RegexpTreeNodeType.Concat, formattingSettings, useCache)) { return(false); } } break; case RegexpTreeNodeType.Star: if (!this.children[0].AppendRegexpWithBrackets(resultBuilder, RegexpTreeNodeType.Star, formattingSettings, useCache)) { return(false); } resultBuilder.Append(formattingSettings.UseLazyQuantifier ? "*?" : "*"); break; default: Debug.Fail("Unhandled operation!"); break; } if (useCache && formattingSettings.Equals(VerboseFormattingSettings)) { //// this.toStringVerboseCached = resultBuilder.ToString(lengthAtStart, resultBuilder.Length-lengthAtStart); } return(true); }
/// <summary> /// Returns a string representation of the language described by the node. /// </summary> /// <param name="builder">The string builder to append to.</param> /// <param name="formattingSettings">The formatting settings used for conversion from an automaton to a string.</param> /// <returns>False if the string was truncated.</returns> public bool AppendToString(StringBuilder builder, RegexpFormattingSettings formattingSettings) { Argument.CheckIfNotNull(formattingSettings, "formattingSettings"); return(this.AppendToString(builder, formattingSettings, false)); }