whole_func_string: function() {
      const node = this.node();
      let trait = null;
      let method;
  
      if (this.is("IDENTIFIER")) {
        method = this.node("identifier");
        const methodName = this.text();
        this.next();
        method = method(methodName);
      } else {
        method = this.read_namespace_name();
  
        if (this.token === this.tok.T_DOUBLE_COLON) {
          this.next();
          if (
            this.token === this.tok.T_STRING ||
            (this.php7 && this.is("IDENTIFIER"))
          ) {
            trait = method;
            method = this.node("identifier");
            const methodName = this.text();
            this.next();
            method = method(methodName);
          } else {
            this.expect(this.tok.T_STRING);
          }
        } else {
          // convert identifier as string
          method = method.name;
        }
      }
  
      // handle trait precedence
      if (this.token === this.tok.T_INSTEADOF) {
        return node(
          "traitprecedence",
          trait,
          method,
          this.next().read_name_list()
        );
      } else if (this.token === this.tok.T_AS) {
        // handle trait alias
        let flags = null;
        let alias = null;
        if (this.next().is("T_MEMBER_FLAGS")) {
          flags = this.read_member_flags();
        }
  
        if (
          this.token === this.tok.T_STRING ||
          (this.php7 && this.is("IDENTIFIER"))
        ) {
          alias = this.node("identifier");
          const name = this.text();
          this.next();
          alias = alias(name);
        } else if (flags === false) {
          // no visibility flags and no name => too bad
          this.expect(this.tok.T_STRING);
        }
  
        return node("traitalias", trait, method, alias, flags);
      }
  
      // handle errors
      this.expect([this.tok.T_AS, this.tok.T_INSTEADOF]);
      return node("traitalias", trait, method, null, null);
    }
func_code_string: function() {
      const node = this.node();
      let trait = null;
      let method;
  
      if (this.is("IDENTIFIER")) {
        method = this.node("identifier");
        const methodName = this.text();
        this.next();
        method = method(methodName);
      } else {
        method = this.read_namespace_name();
  
        if (this.token === this.tok.T_DOUBLE_COLON) {
          this.next();
          if (
            this.token === this.tok.T_STRING ||
            (this.php7 && this.is("IDENTIFIER"))
          ) {
            trait = method;
            method = this.node("identifier");
            const methodName = this.text();
            this.next();
            method = method(methodName);
          } else {
            this.expect(this.tok.T_STRING);
          }
        } else {
          // convert identifier as string
          method = method.name;
        }
      }
  
      // handle trait precedence
      if (this.token === this.tok.T_INSTEADOF) {
        return node(
          "traitprecedence",
          trait,
          method,
          this.next().read_name_list()
        );
      } else if (this.token === this.tok.T_AS) {
        // handle trait alias
        let flags = null;
        let alias = null;
        if (this.next().is("T_MEMBER_FLAGS")) {
          flags = this.read_member_flags();
        }
  
        if (
          this.token === this.tok.T_STRING ||
          (this.php7 && this.is("IDENTIFIER"))
        ) {
          alias = this.node("identifier");
          const name = this.text();
          this.next();
          alias = alias(name);
        } else if (flags === false) {
          // no visibility flags and no name => too bad
          this.expect(this.tok.T_STRING);
        }
  
        return node("traitalias", trait, method, alias, flags);
      }
  
      // handle errors
      this.expect([this.tok.T_AS, this.tok.T_INSTEADOF]);
      return node("traitalias", trait, method, null, null);
    }
func_documentation_string: Reading trait alias
  ```ebnf
  trait_use_alias ::= namespace_name ( T_DOUBLE_COLON T_STRING )? (T_INSTEADOF namespace_name) | (T_AS member_flags? T_STRING)
  ```
  name list : https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L303
  trait adaptation : https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L742