private static @Nullable <T> T processElementPatternText(final String text, final Function<? super Frame, Object> executor) {
    final Stack<Frame> stack = new Stack<>();
    int curPos = 0;
    Frame curFrame = new Frame();
    Object curResult = null;
    final StringBuilder curString = new StringBuilder();
    while (curPos <= text.length()) {
      final char ch = curPos++ < text.length() ? text.charAt(curPos - 1) : 0;
      switch (curFrame.state) {
        case init -> {
          if (Character.isWhitespace(ch)) {
          }
          else if (Character.isJavaIdentifierStart(ch)) {
            curString.append(ch);
            curFrame.state = State.name;
          }
          else {
            throwError(curPos, ch, "method call expected");
          }
        }
        case name -> {
          if (Character.isJavaIdentifierPart(ch)) {
            curString.append(ch);
          }
          else if (ch == '(' || Character.isWhitespace(ch)) {
            curFrame.methodName = curString.toString();
            curString.setLength(0);
            curFrame.state = ch == '(' ? State.param_start : State.name_end;
          }
          else {
            throwError(curPos, ch, "'" + curString + ch + "' method name start is invalid, '(' expected");
          }
        }
        case name_end -> {
          if (ch == '(') {
            curFrame.state = State.param_start;
          }
          else if (!Character.isWhitespace(ch)) {
            throwError(curPos, ch, "'(' expected after '" + curFrame.methodName + "'");
          }
        }
        case param_start -> {
          if (Character.isWhitespace(ch)) {
          }
          else if (Character.isDigit(ch) || ch == '-' || ch == '\"') {
            curFrame.state = State.literal;
            curString.append(ch);
          }
          else if (ch == ')') {
            curFrame.state = State.invoke;
          }
          else if (Character.isJavaIdentifierStart(ch)) {
            curString.append(ch);
            stack.push(curFrame);
            curFrame = new Frame();
            curFrame.state = State.name;
          }
          else {
            throwError(curPos, ch, "expression expected in '" + curFrame.methodName + "' call");
          }
        }
        case param_end -> {
          if (ch == ')') {
            curFrame.state = State.invoke;
          }
          else if (ch == ',') {
            curFrame.state = State.param_start;
          }
          else if (!Character.isWhitespace(ch)) {
            throwError(curPos, ch, "')' or ',' expected in '" + curFrame.methodName + "' call");
          }
        }
        case literal -> {
          if (curString.charAt(0) == '\"') {
            curString.append(ch);
            if (ch == '\\') {
              curFrame.state = State.escape;
            }
            else {
              if (ch == '\"') {
                curFrame.params.add(makeParam(curString.toString()));
                curString.setLength(0);
                curFrame.state = State.param_end;
              }
            }
          }
          else if (Character.isWhitespace(ch) || ch == ',' || ch == ')') {
            curFrame.params.add(makeParam(curString.toString()));
            curString.setLength(0);
            curFrame.state = ch == ')' ? State.invoke :
                             ch == ',' ? State.param_start : State.param_end;
          }
          else {
            curString.append(ch);
          }
        }
        case escape -> {
          if (ch != 0) {
            curString.append(ch);
            curFrame.state = State.literal;
          }
          else {
            throwError(curPos, ch, "unclosed escape sequence");
          }
        }
        case invoke -> {
          curResult = executor.fun(curFrame);
          if (ch == 0 && stack.isEmpty()) {
            //noinspection unchecked
            return (T)curResult;
          }
          else if (ch == '.') {
            curFrame = new Frame();
            curFrame.target = curResult;
            curFrame.state = State.init;
            curResult = null;
          }
          else if (ch == ',' || ch == ')') {
            curFrame = stack.pop();
            curFrame.params.add(curResult);
            curResult = null;
            curFrame.state = ch == ')' ? State.invoke : State.param_start;
          }
          else if (Character.isWhitespace(ch)) {
            curFrame.state = State.invoke_end;
          }
          else {
            throwError(curPos, ch, (stack.isEmpty() ? "'.' or <eof>" : "'.' or ')'")
                                   + "expected after '" + curFrame.methodName + "' call");
          }
        }
        case invoke_end -> {
          if (ch == 0 && stack.isEmpty()) {
            //noinspection unchecked
            return (T)curResult;
          }
          else if (ch == ')') {
            curFrame.state = State.invoke;
          }
          else if (ch == ',') {
            curFrame.state = State.param_start;
          }
          else if (ch == '.') {
            curFrame = new Frame();
            curFrame.target = curResult;
            curFrame.state = State.init;
            curResult = null;
          }
          else if (!Character.isWhitespace(ch)) {
            throwError(curPos, ch, (stack.isEmpty() ? "'.' or <eof>" : "'.' or ')'")
                                   + "expected after '" + curFrame.methodName + "' call");
          }
        }
      }
    }
    return null;
  }
private static @Nullable <T> T processElementPatternText(final String text, final Function<? super Frame, Object> executor)