function(item, separator, preserveFirstSeparator) {
    const result = [];

    if (this.token == separator) {
      if (preserveFirstSeparator) result.push(null);
      this.next();
    }

    if (typeof item === "function") {
      do {
        result.push(item.apply(this, []));
        if (this.token != separator) {
          break;
        }
      } while (this.next().token != this.EOF);
    } else {
      if (this.expect(item)) {
        result.push(this.text());
      } else {
        return [];
      }
      while (this.next().token != this.EOF) {
        if (this.token != separator) break;
        // trim current separator & check item
        if (this.next().token != item) break;
        result.push(this.text());
      }
    }
    return result;
  }
function(item, separator, preserveFirstSeparator) {
    const result = [];

    if (this.token == separator) {
      if (preserveFirstSeparator) result.push(null);
      this.next();
    }

    if (typeof item === "function") {
      do {
        result.push(item.apply(this, []));
        if (this.token != separator) {
          break;
        }
      } while (this.next().token != this.EOF);
    } else {
      if (this.expect(item)) {
        result.push(this.text());
      } else {
        return [];
      }
      while (this.next().token != this.EOF) {
        if (this.token != separator) break;
        
        if (this.next().token != item) break;
        result.push(this.text());
      }
    }
    return result;
  }
function ( item , separator , preserveFirstSeparator ) { const result = [ ] ; if ( this . token == separator ) { if ( preserveFirstSeparator ) result . push ( null ) ; this . next ( ) ; } if ( typeof item === "function" ) { do { result . push ( item . apply ( this , [ ] ) ) ; if ( this . token != separator ) { break ; } } while ( this . next ( ) . token != this . EOF ) ; } else { if ( this . expect ( item ) ) { result . push ( this . text ( ) ) ; } else { return [ ] ; } while ( this . next ( ) . token != this . EOF ) { if ( this . token != separator ) break ; // trim current separator & check item if ( this . next ( ) . token != item ) break ; result . push ( this . text ( ) ) ; } } return result ; }
Helper : reads a list of tokens / sample : T_STRING ',' T_STRING ...
```ebnf
list ::= separator? ( item separator )* item
```
Helper : reads a list of tokens / sample : T_STRING T_STRING ... ebnf list :: = separator? ( item separator ) * item