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);
  }
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 {
        
        method = method.name;
      }
    }

    
    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) {
      
      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) {
        
        this.expect(this.tok.T_STRING);
      }

      return node("traitalias", trait, method, alias, flags);
    }

    
    this.expect([this.tok.T_AS, this.tok.T_INSTEADOF]);
    return node("traitalias", trait, method, null, null);
  }
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 ) ; }
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
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