docs: public static ExpressionTree parse(final String expression,
                                       final List<String> metric_queries,
                                       final TSQuery data_query) {
      if (expression == null || expression.isEmpty()) {
        throw new IllegalArgumentException("Expression may not be null or empty");
      }
      if (expression.indexOf('(') == -1 || expression.indexOf(')') == -1) {
        throw new IllegalArgumentException("Invalid Expression: " + expression);
      }
  
      final ExpressionReader reader = new ExpressionReader(expression.toCharArray());
      // consume any whitespace ahead of the expression
      reader.skipWhitespaces();
  
      final String function_name = reader.readFuncName();
      final Expression root_expression = ExpressionFactory.getByName(function_name);
  
      final ExpressionTree root = new ExpressionTree(root_expression, data_query);
      reader.skipWhitespaces();
      
      if (reader.peek() == '(') {
        reader.next();
        parse(reader, metric_queries, root, data_query);
      }
  
      return root;
    }