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; } } }
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))); } }