private static RTree ParseStdGroup(RevgexStringReader inp, GroupSet groups) { string name = null; var id = -1; if (inp.Peek() == ':') { name = ParseGroupName(inp); } if (name != null) { if (!groups.Add(name)) { throw Error(inp, $"Group name {name} is already used."); } } else { groups.Add(id = groups.GetNextId()); } var body = ParseGroupBody(inp, groups); if (name != null) { groups.Specify(name, new RGroup(body)); return(new RNamedGroupRef(name, LookupQuantifier(inp))); } else { groups.Specify(id, new RGroup(body)); return(new RGroupRef(id, LookupQuantifier(inp))); } }
private static RTree ParseDelimitedSequence(RevgexStringReader inp, GroupSet groups) { var type = inp.Read(); // '"' or ' var delimiter = ""; while (true) { if (inp.Peek() == -1) { throw Error(inp, "Incomplete delimiter specification."); } else if (inp.Peek() == ';') { inp.Read(); break; } else if (inp.Peek() == '\\') { inp.Read(); if (inp.Peek() < 0) { throw Error(inp, "Incomplete delimiter specification."); } delimiter += inp.Read(); } else { delimiter += inp.Read(); } } var quantifier = LookupQuantifier(inp); var body = ParseGroupBody(inp, groups); return(new RDelimitedSequence(quantifier, delimiter, type == '\'', body)); }
private static RTree[] ParseGroupBody(RevgexStringReader inp, GroupSet groups) { var alternatives = new List <List <RTree> > { new List <RTree>() }; while (true) { switch (inp.Peek()) { case -1: throw Error(inp, "Missing ')'."); case '|': inp.Read(); alternatives.Add(new List <RTree>()); break; case ')': inp.Read(); return(alternatives.Count == 1 ? alternatives[0].ToArray() : new RTree[] { new RAlternation(alternatives.Select(a => new RGroup(a.ToArray())).ToArray()) }); default: alternatives[alternatives.Count - 1].Add(ParseSingleSubtree(inp, groups)); break; } } }
public Revgex(string str, bool ignoreLineEndings = false, bool ignoreWhitespace = false, bool allowPredefinedGroups = true) { groups = str.Length == 0 ? new GroupSet() : Parser.Parse(str.Replace("\r\n", "\n").Replace('\r', '\n'), ignoreLineEndings, ignoreWhitespace, allowPredefinedGroups); tree = groups.Get(0) ?? REmpty.Instance; }
public override void Generate(GroupSet groups, Random rand, StringBuilder sb, int recursionDepth, int repetitionLimit) { if (recursionDepth >= Revgex.MaxRecursion) { return; } sb.Append(Value = GenerateValue(groups, rand, recursionDepth, repetitionLimit)); }
private static RTree ParseModifier(RevgexStringReader inp, GroupSet groups) { inp.Read(); // '!' var type = ParseModifierType(inp); var body = ParseGroupBody(inp, groups); return(new RModifier(type, body)); }
private static RTree ParseValueReference(RevgexStringReader inp, GroupSet groups) { inp.Read(); // '$' var c = inp.Peek(); if (c >= '0' && c <= '9') { var groupId = inp.Read() - '0'; c = inp.Peek(); if (c >= '0' && c <= '9') { groupId = groupId * 10 + (inp.Read() - '0'); } if (groupId == 0) { throw Error(inp, "Value backreference to the entire patternt (zero-th group) is not allowed."); } if (groups.Get(groupId) == null) { throw Error(inp, "Invalid group backreference."); } return(new RGroupValueRef(groupId, LookupQuantifier(inp))); } switch (c) { case -1: throw Error(inp, "Incomplete group value backreference."); case ':': var groupName = ParseGroupName(inp); if (groups.Get(groupName) == null) { throw Error(inp, "Invalid named group value backreference."); } return(new RNamedGroupValueRef(groupName, LookupQuantifier(inp))); case '(': inp.Read(); var groupId = 0; c = inp.Peek(); do { if (c < '0' || c > '9') { throw Error(inp, "Invalid group value backreference."); } groupId = groupId * 10 + (inp.Read() - '0'); } while ((c = inp.Peek()) != ')'); inp.Read(); // ')' if (groups.Get(groupId) == null) { throw Error(inp, "Invalid group value backreference."); } return(new RGroupValueRef(groupId, LookupQuantifier(inp))); default: throw Error(inp, "Invalid group value backreference."); } }
public override void Generate(GroupSet groups, Random rand, StringBuilder sb, int recursionDepth, int repetitionLimit) { if (possibleChars.Length == 0) { return; } var c = Quantifier.GetQuantity(rand, repetitionLimit); for (var i = 0; i < c; ++i) { sb.Append(possibleChars[rand.Next(possibleChars.Length)]); } }
protected virtual string GenerateValue(GroupSet groups, Random rand, int recursionDepth, int repetitionLimit) { if (branches.Length == 0) { return(""); } var sb2 = new StringBuilder(); foreach (var b in branches) { b.Generate(groups, rand, sb2, recursionDepth + 1, repetitionLimit); } return(sb2.ToString()); }
private static RTree ParseControlGroup(RevgexStringReader inp, GroupSet groups) { inp.Read(); // '?' switch (inp.Peek()) { case -1: throw Error(inp, "Incomplete control group."); case ':': // non-capturing group inp.Read(); return(new RGroup(ParseGroupBody(inp, groups))); default: throw Error(inp, "Invalid control group."); } }
// equivalent to Generate if no value was generated yet public void RecallLastValue(GroupSet groups, Random rand, StringBuilder sb, int recursionDepth, int repetitionLimit) { if (branches.Length == 0) { return; } if (recursionDepth >= Revgex.MaxRecursion) { return; } if (Value != null) { sb.Append(Value); } else { sb.Append(Value = GenerateValue(groups, rand, recursionDepth, repetitionLimit)); } }
private static GroupSet Parse(RevgexStringReader inp, bool allowPredefinedGroups) { var groups = new GroupSet(); if (allowPredefinedGroups) { groups.Add(":maleName", PredefinedGroups.MaleName); groups.Add(":femaleName", PredefinedGroups.FemaleName); groups.Add(":surname", PredefinedGroups.Surname); groups.Add(":byte", PredefinedGroups.Byte); groups.Add(":int", PredefinedGroups.Int); groups.Add(":uint", PredefinedGroups.UnsignedInt); groups.Add(":usPhone", PredefinedGroups.USPhone); groups.Add(":mailSuffix", PredefinedGroups.MailSuffix); groups.Add(":passwd", PredefinedGroups.Password); } groups.Add(0); var alternatives = new List <List <RTree> > { new List <RTree>() }; while (inp.Peek() >= 0) { if (inp.Peek() == '|') { inp.Read(); alternatives.Add(new List <RTree>()); } else { alternatives[alternatives.Count - 1].Add(ParseSingleSubtree(inp, groups)); } } groups.Specify(0, alternatives.Count == 1 ? new RGroup(alternatives[0].ToArray()) : new RGroup(new RAlternation(alternatives.Select(a => new RGroup(a.ToArray())).ToArray()))); return(groups); }
private static RTree ParseAnyGroup(RevgexStringReader inp, GroupSet groups) { inp.Read(); // '(' switch (inp.Peek()) { case -1: throw Error(inp, "Missing ')'."); case '!': return(ParseModifier(inp, groups)); case '?': return(ParseControlGroup(inp, groups)); case '\'': case '"': return(ParseDelimitedSequence(inp, groups)); default: return(ParseStdGroup(inp, groups)); } }
public override void Generate(GroupSet groups, Random rand, StringBuilder sb, int recursionDepth, int repetitionLimit) { if (branches.Length == 0) { return; } if (recursionDepth >= Revgex.MaxRecursion) { return; } var c = quantifier.GetQuantity(rand, repetitionLimit); if (@fixed) { Value = GenerateValue(groups, rand, recursionDepth, repetitionLimit); for (var i = 0; i < c; ++i) { if (i > 0) { sb.Append(delimiter); } sb.Append(Value); } } else { for (var i = 0; i < c; ++i) { if (i > 0) { sb.Append(delimiter); } base.Generate(groups, rand, sb, recursionDepth, repetitionLimit); } } }
private static RTree ParseSingleSubtree(RevgexStringReader inp, GroupSet groups) { var buffer = ""; while (true) { switch (inp.Peek()) { case -1: return(buffer.Length > 0 ? new RFixedString(buffer, QuantifierOne.Instance) : REmpty.Instance); case '(': return(buffer.Length > 0 ? new RFixedString(buffer, QuantifierOne.Instance) : ParseAnyGroup(inp, groups)); case ')': return(buffer.Length > 0 ? new RFixedString(buffer, QuantifierOne.Instance) : throw Error(inp, "Unexpected right parenthesis.")); case '*': case '+': case '{': case '?': if (buffer.Length > 0) { if (buffer.Length == 1) { return(new RFixedString(buffer, LookupQuantifier(inp))); } inp.UnreadEscaped(); return(new RFixedString(buffer.Substring(0, buffer.Length - 1), LookupQuantifier(inp))); } throw Error(inp, $"Unexpected character {inp.Peek()}."); case '\\': if (TryParseSimpleEscapeSequence(inp, out var ch)) { buffer += ch; continue; } return(buffer.Length > 0 ? new RFixedString(buffer, QuantifierOne.Instance) : ParseEscapeSequence(inp, groups)); case '$': return(buffer.Length > 0 ? new RFixedString(buffer, QuantifierOne.Instance) : ParseValueReference(inp, groups)); case '.': if (buffer.Length > 0) { return(new RFixedString(buffer, QuantifierOne.Instance)); } else { inp.Read(); return(RChar.Dot(LookupQuantifier(inp))); } case '[': return(buffer.Length > 0 ? new RFixedString(buffer, QuantifierOne.Instance) : ParseCharSet(inp)); case '|': return(buffer.Length > 0 ? new RFixedString(buffer, QuantifierOne.Instance) : REmpty.Instance); default: buffer += inp.Read(); continue; } } }
public override void Generate(GroupSet groups, Random rand, StringBuilder sb, int recursionDepth, int repetitionLimit) { }
protected override string GenerateValue(GroupSet groups, Random rand, int recursionDepth, int repetitionLimit) => set.Length == 0 ? "" : rand.Item(set);
private static RTree ParseEscapeSequence(RevgexStringReader inp, GroupSet groups) { inp.Read(); // '\' var c = inp.Peek(); if (c >= '0' && c <= '9') { var groupId = inp.Read() - '0'; c = inp.Peek(); if (c >= '0' && c <= '9') { groupId = groupId * 10 + (inp.Read() - '0'); } if (groupId == 0) { throw Error(inp, "Backreference to the entire patternt (zero-th group) is not allowed."); } if (groups.Get(groupId) == null) { throw Error(inp, "Invalid group backreference."); } return(new RGroupRef(groupId, LookupQuantifier(inp))); } switch (c) { case -1: throw Error(inp, "Incomplete escape sequence."); case ':': var groupName = ParseGroupName(inp); if (groups.Get(groupName) == null) { throw Error(inp, "Invalid named group backreference."); } return(new RNamedGroupRef(groupName, LookupQuantifier(inp))); case '(': inp.Read(); var groupId = 0; c = inp.Peek(); do { if (c < '0' || c > '9') { throw Error(inp, "Invalid group backreference."); } groupId = groupId * 10 + (inp.Read() - '0'); } while ((c = inp.Peek()) != ')'); inp.Read(); // ')' if (groups.Get(groupId) == null) { throw Error(inp, "Invalid group backreference."); } return(new RGroupRef(groupId, LookupQuantifier(inp))); case 'w': inp.Read(); return(RChar.w(LookupQuantifier(inp))); case 'W': inp.Read(); return(RChar.W(LookupQuantifier(inp))); case 's': inp.Read(); return(RChar.s(LookupQuantifier(inp))); case 'S': inp.Read(); return(RChar.S(LookupQuantifier(inp))); case 'd': inp.Read(); return(RChar.d(LookupQuantifier(inp))); case 'D': inp.Read(); return(RChar.D(LookupQuantifier(inp))); default: return(new RFixedString(inp.Read().ToString(), LookupQuantifier(inp))); } }