docs: protected AstNode parseCreateFunctionStatement( DdlTokenStream tokens,
                                                      AstNode parentNode ) throws ParsingException {
          assert tokens != null;
          assert parentNode != null;
  
          markStartOfStatement(tokens);
  
          /* ----------------------------------------------------------------------
              CREATE [ OR REPLACE ] FUNCTION [ schema. ] function_name
                [ ( parameter_declaration [, parameter_declaration] ) 
                ]
                RETURN datatype
                [ { invoker_rights_clause
                  | DETERMINISTIC
                  | parallel_enable_clause
                  | result_cache_clause
                  }...
                ]
                { { AGGREGATE | PIPELINED }
                  USING [ schema. ] implementation_type
                | [ PIPELINED ] { IS | AS } { [ declare_section ] body | call_spec }
                } ;
              
              parameter_declaration = parameter_name [ IN | { { OUT | { IN OUT }} [ NOCOPY ] } ] datatype [ { := | DEFAULT } expression ]
          ---------------------------------------------------------------------- */
  
          boolean isReplace = tokens.canConsume(STMT_CREATE_OR_REPLACE_FUNCTION);
  
          tokens.canConsume(STMT_CREATE_FUNCTION);
  
          String name = parseName(tokens);
  
          AstNode node = nodeFactory().node(name, parentNode, TYPE_CREATE_FUNCTION_STATEMENT);
  
          if (isReplace) {
              // TODO: SET isReplace = TRUE to node (possibly a cnd mixin of "replaceable"
          }
  
          boolean ok = parseParameters(tokens, node);
  
          if (ok) {
              if (tokens.canConsume("RETURN")) {
                  DataType dType = getDatatypeParser().parse(tokens);
                  if (dType != null) {
                      getDatatypeParser().setPropertiesOnNode(node, dType);
                  }
              }
          }
  
          parseUntilFwdSlash(tokens, false);
  
          tokens.canConsume("/");
  
          markEndOfStatement(tokens, node);
  
          return node;
      }