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