/**
 * Copyright (C) 2014 Glayzzle (BSD3 License)
 * @authors https://github.com/glayzzle/php-parser/graphs/contributors
 * @url http://glayzzle.com
 */

module.exports = function(api, tokens, EOF) {
  return {
    read_while: function() {
      this.expect('(').next();
      var cond = this.read_expr();
      this.expect(')').next();
      // @todo ':' inner_statement_list T_ENDWHILE ';'
      var body = this.read_statement();
      return ['while', cond, body];
    }
    ,read_do: function() {
      var body = this.read_statement();
      this.expect(tokens.T_WHILE).next().expect('(').next();
      var cond = this.read_expr();
      this.expect(')').next().expect(';').next();
      return ['do', cond, body];
    }
    ,read_for: function() {
      this.expect('(').next();
      var expr1 = null, expr2 = null, expr3 = null;
      if (this.token !== ';') {
        expr1 = this.read_list(this.read_expr, ',');
        this.expect(';').next();
      } else {
        this.next();
      }
      if (this.token !== ';') {
        expr2 = this.read_list(this.read_expr, ',');
        this.expect(';').next();
      } else {
        this.next();
      }
      if (this.token !== ')') {
        expr3 = this.read_list(this.read_expr, ',');
        this.expect(')').next();
      } else {
        this.next();
      } 
      var body = this.read_statement();
      // @todo ':' inner_statement_list T_ENDFOR ';'
      return ['for', expr1, expr2, expr3, body];
    }
    ,read_foreach: function() {
      this.expect('(').next();
      var expr = this.read_expr();
      this.expect(tokens.T_AS).next();
      // @todo handle list() + & 
      var item = this.read_variable();
      var key = false;
      if (this.token === tokens.T_DOUBLE_ARROW) {
        key = item;
        item = this.next().read_variable();
      }
      this.expect(')').next();
      var body = this.read_statement();
      // @todo ':' inner_statement_list T_ENDFOREACH ';'
      return ['foreach', expr, key, item, body];
    }
  };
};
@@ -1457,32 +1457,176 @@
 3, body%5D;%0A    %7D%0A
+    /**%0A     * %3Cebnf%3E%0A     * foreach ::= '(' expr T_AS foreach_variable (T_DOUBLE_ARROW foreach_variable)? ')' statement%0A     * %3C/ebnf%3E%0A     */%0A
     ,read_foreac
@@ -1633,32 +1633,32 @@
 h: function() %7B%0A
-
       this.expec
@@ -1750,42 +1750,8 @@
 ();%0A
-      // @todo handle list() + & %0A
     
@@ -1769,24 +1769,32 @@
 = this.read_
+foreach_
 variable();%0A
@@ -1791,27 +1791,26 @@
 riable()
-;
+, 
 %0A      
-var
+ 
  key = f
@@ -1917,16 +1917,24 @@
 ().read_
+foreach_
 variable
@@ -2069,24 +2069,24 @@
 FOREACH ';'%0A
-
       return
@@ -2128,15 +2128,620 @@
 ;%0A    %7D%0A
+    /**%0A     * %3Cebnf%3E%0A     * foreach_variable = ('&'? variable) %7C (T_LIST '(' assignment_list ')')%0A     * %3C/ebnf%3E%0A     */%0A    ,read_foreach_variable: function() %7B%0A        if (this.token === '&') %7B%0A          return %5B'byref', this.next().read_variable()%5D;%0A        %7D else if (this.token === tokens.T_LIST) %7B%0A          this.next().expect('(').next();%0A          var assignList = this.read_assignment_list();%0A          this.expect(')').next();%0A          return %5B%0A            'list', %0A            assignList,%0A            false%0A          %5D;%0A        %7D else %7B%0A          return this.read_variable();%0A        %7D%0A    %7D%0A
   %7D;%0A%7D;

fix foreach variable implementation (compliant with php lexer)