whole_func_string: function() {
      const result = this.node("class");
      const flag = this.read_class_scope();
      // graceful mode : ignore token & go next
      if (this.token !== this.tok.T_CLASS) {
        this.error(this.tok.T_CLASS);
        this.next();
        return null;
      }
      this.next().expect(this.tok.T_STRING);
      let propName = this.node("identifier");
      const name = this.text();
      this.next();
      propName = propName(name);
      let propExtends = null;
      if (this.token == this.tok.T_EXTENDS) {
        propExtends = this.next().read_namespace_name();
      }
      let propImplements = null;
      if (this.token == this.tok.T_IMPLEMENTS) {
        propImplements = this.next().read_name_list();
      }
      this.expect("{");
      const body = this.next().read_class_body();
      return result(propName, propExtends, propImplements, body, flag);
    }
func_code_string: function() {
      const result = this.node("class");
      const flag = this.read_class_scope();
      // graceful mode : ignore token & go next
      if (this.token !== this.tok.T_CLASS) {
        this.error(this.tok.T_CLASS);
        this.next();
        return null;
      }
      this.next().expect(this.tok.T_STRING);
      let propName = this.node("identifier");
      const name = this.text();
      this.next();
      propName = propName(name);
      let propExtends = null;
      if (this.token == this.tok.T_EXTENDS) {
        propExtends = this.next().read_namespace_name();
      }
      let propImplements = null;
      if (this.token == this.tok.T_IMPLEMENTS) {
        propImplements = this.next().read_name_list();
      }
      this.expect("{");
      const body = this.next().read_class_body();
      return result(propName, propExtends, propImplements, body, flag);
    }
func_documentation_string: reading a class
  ```ebnf
  class ::= class_scope? T_CLASS T_STRING (T_EXTENDS NAMESPACE_NAME)? (T_IMPLEMENTS (NAMESPACE_NAME ',')* NAMESPACE_NAME)? '{' CLASS_BODY '}'
  ```