diff --git a/mysql-test/r/parser_stack.result b/mysql-test/r/parser_stack.result
new file mode 100644
index 0000000000000000000000000000000000000000..a0040fc6ae6b6e15b9ad57d6125de4b1a490d471
--- /dev/null
+++ b/mysql-test/r/parser_stack.result
@@ -0,0 +1,306 @@
+use test;
+SELECT
+((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
+((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
+((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
+1
+))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
+))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
+))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
+;
+1
+1
+prepare stmt from
+"
+SELECT
+((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
+((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
+((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
+1
+))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
+))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
+))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
+"
+;
+execute stmt;
+1
+1
+drop view if exists view_overflow;
+CREATE VIEW view_overflow AS
+SELECT
+((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
+((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
+((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
+1
+))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
+))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
+))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
+;
+SELECT * from view_overflow;
+1
+1
+drop view view_overflow;
+drop procedure if exists proc_overflow;
+CREATE PROCEDURE proc_overflow()
+BEGIN
+BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+select 1;
+select 2;
+select 3;
+END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+END $$
+call proc_overflow();
+1
+1
+2
+2
+3
+3
+drop procedure proc_overflow;
+drop function if exists func_overflow;
+create function func_overflow() returns int
+BEGIN
+DECLARE x int default 0;
+BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+SET x=x+1;
+SET x=x+2;
+SET x=x+3;
+END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+return x;
+END $$
+select func_overflow();
+func_overflow()
+6
+drop function func_overflow;
+drop table if exists table_overflow;
+create table table_overflow(a int, b int);
+create trigger trigger_overflow before insert on table_overflow
+for each row
+BEGIN
+BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+SET NEW.b := NEW.a;
+SET NEW.b := NEW.b + 1;
+SET NEW.b := NEW.b + 2;
+SET NEW.b := NEW.b + 3;
+END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+END $$
+insert into table_overflow set a=10;
+insert into table_overflow set a=20;
+select * from table_overflow;
+a	b
+10	16
+20	26
+drop table table_overflow;
+drop procedure if exists proc_35577;
+CREATE PROCEDURE proc_35577()
+BEGIN
+DECLARE z_done INT DEFAULT 0;
+DECLARE t_done VARCHAR(5000);
+outer_loop: LOOP
+IF t_done=1  THEN
+LEAVE outer_loop;
+END IF;
+inner_block:BEGIN
+DECLARE z_done INT DEFAULT  0;
+SET z_done = 0;
+inner_loop: LOOP
+IF z_done=1  THEN
+LEAVE inner_loop;
+END IF;
+IF (t_done = 'a') THEN
+IF (t_done <> 0) THEN
+IF ( t_done > 0) THEN
+IF (t_done = 'a') THEN
+SET t_done = 'a';
+ELSEIF (t_done = 'a') THEN
+SET t_done = 'a';
+ELSEIF(t_done = 'a') THEN
+SET t_done = 'a';
+ELSEIF(t_done = 'a') THEN
+SET t_done = 'a';
+ELSEIF(t_done = 'a') THEN
+SET t_done = 'a';
+ELSEIF(t_done = 'a') THEN
+SET t_done = 'a';
+ELSEIF(t_done = 'a') THEN
+SET t_done = 'a';
+ELSEIF(t_done = 'a') THEN
+SET t_done = 'a';
+END IF;
+END IF;
+END IF;
+END IF;
+END LOOP inner_loop;
+END inner_block;
+END LOOP outer_loop;
+END $$
+drop procedure proc_35577;
+drop procedure if exists p_37269;
+create procedure p_37269()
+begin
+declare done int default 0;
+declare varb int default 0;
+declare vara int default 0;
+repeat
+select now();
+until done end repeat;
+while varb do
+select now();
+begin
+select now();
+repeat
+select now();
+until done end repeat;
+if vara then 
+select now();
+repeat
+select now();
+loop
+select now();
+end loop;
+repeat
+select now();
+label1: while varb do
+select now();
+end while label1;
+if vara then 
+select now();
+repeat
+select now();
+until done end repeat;
+begin
+select now();
+while varb do
+select now();
+label1: while varb do
+select now();
+end while label1;
+if vara then 
+select now();
+while varb do
+select now();
+loop
+select now();
+end loop;
+repeat
+select now();
+loop
+select now();
+while varb do
+select now();
+end while;
+repeat
+select now();
+label1: loop
+select now();
+if vara then 
+select now();
+end if;
+end loop label1;
+until done end repeat;
+end loop;
+until done end repeat;
+end while;
+end if;
+end while;
+end;
+end if;
+until done end repeat;
+until done end repeat;
+end if;
+end;
+end while;
+end $$
+drop procedure p_37269;
+drop procedure if exists p_37228;
+create procedure p_37228 ()
+BEGIN
+DECLARE v INT DEFAULT 123;
+IF (v > 1) THEN SET v = 1; 
+ELSEIF (v < 10) THEN SET v = 10;
+ELSEIF (v < 11) THEN SET v = 11;
+ELSEIF (v < 12) THEN SET v = 12;
+ELSEIF (v < 13) THEN SET v = 13;
+ELSEIF (v < 14) THEN SET v = 14;
+ELSEIF (v < 15) THEN SET v = 15;
+ELSEIF (v < 16) THEN SET v = 16;
+ELSEIF (v < 17) THEN SET v = 17;
+ELSEIF (v < 18) THEN SET v = 18;
+ELSEIF (v < 19) THEN SET v = 19;
+ELSEIF (v < 20) THEN SET v = 20;
+ELSEIF (v < 21) THEN SET v = 21;
+ELSEIF (v < 22) THEN SET v = 22;
+ELSEIF (v < 23) THEN SET v = 23;
+ELSEIF (v < 24) THEN SET v = 24;
+ELSEIF (v < 25) THEN SET v = 25;
+ELSEIF (v < 26) THEN SET v = 26;
+ELSEIF (v < 27) THEN SET v = 27;
+ELSEIF (v < 28) THEN SET v = 28;
+ELSEIF (v < 29) THEN SET v = 29;
+ELSEIF (v < 30) THEN SET v = 30;
+ELSEIF (v < 31) THEN SET v = 31;
+ELSEIF (v < 32) THEN SET v = 32;
+ELSEIF (v < 33) THEN SET v = 33;
+ELSEIF (v < 34) THEN SET v = 34;
+ELSEIF (v < 35) THEN SET v = 35;
+ELSEIF (v < 36) THEN SET v = 36;
+ELSEIF (v < 37) THEN SET v = 37;
+ELSEIF (v < 38) THEN SET v = 38;
+ELSEIF (v < 39) THEN SET v = 39;
+END IF;
+END $$
+drop procedure p_37228;
diff --git a/mysql-test/t/parser_stack.test b/mysql-test/t/parser_stack.test
new file mode 100644
index 0000000000000000000000000000000000000000..3330ef418330016b035d4c89dd024310f5570eb9
--- /dev/null
+++ b/mysql-test/t/parser_stack.test
@@ -0,0 +1,402 @@
+# Copyright (C) 2008 Sun Microsystems, Inc
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+#
+# These tests are designed to cause an internal parser stack overflow,
+# and trigger my_yyoverflow().
+#
+
+use test;
+
+SELECT
+((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
+((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
+((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
+1
+))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
+))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
+))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
+;
+
+prepare stmt from
+"
+SELECT
+((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
+((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
+((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
+1
+))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
+))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
+))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
+"
+;
+
+execute stmt;
+
+--disable_warnings
+drop view if exists view_overflow;
+--enable_warnings
+
+CREATE VIEW view_overflow AS
+SELECT
+((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
+((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
+((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
+1
+))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
+))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
+))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
+;
+
+SELECT * from view_overflow;
+
+drop view view_overflow;
+
+--disable_warnings
+drop procedure if exists proc_overflow;
+--enable_warnings
+
+delimiter $$;
+
+CREATE PROCEDURE proc_overflow()
+BEGIN
+
+  BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+  BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+  BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+  BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+  BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+  BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+  BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+  BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+  BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+  BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+
+  select 1;
+  select 2;
+  select 3;
+
+  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+
+END $$
+
+delimiter ;$$
+
+call proc_overflow();
+
+drop procedure proc_overflow;
+
+--disable_warnings
+drop function if exists func_overflow;
+--enable_warnings
+
+delimiter $$;
+
+create function func_overflow() returns int
+BEGIN
+  DECLARE x int default 0;
+
+  BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+  BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+  BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+  BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+  BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+  BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+  BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+  BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+  BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+  BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+
+  SET x=x+1;
+  SET x=x+2;
+  SET x=x+3;
+
+  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+
+  return x;
+END $$
+
+delimiter ;$$
+
+select func_overflow();
+
+drop function func_overflow;
+
+--disable_warnings
+drop table if exists table_overflow;
+--enable_warnings
+
+create table table_overflow(a int, b int);
+
+delimiter $$;
+
+create trigger trigger_overflow before insert on table_overflow
+for each row
+BEGIN
+
+  BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+  BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+  BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+  BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+  BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+  BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+  BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+  BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+  BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+  BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN
+
+  SET NEW.b := NEW.a;
+  SET NEW.b := NEW.b + 1;
+  SET NEW.b := NEW.b + 2;
+  SET NEW.b := NEW.b + 3;
+
+  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;  END;
+
+END $$
+
+delimiter ;$$
+
+insert into table_overflow set a=10;
+insert into table_overflow set a=20;
+select * from table_overflow;
+
+drop table table_overflow;
+
+--disable_warnings
+drop procedure if exists proc_35577;
+--enable_warnings
+
+delimiter $$;
+
+CREATE PROCEDURE proc_35577()
+BEGIN
+  DECLARE z_done INT DEFAULT 0;
+  DECLARE t_done VARCHAR(5000);
+  outer_loop: LOOP
+    IF t_done=1  THEN
+      LEAVE outer_loop;
+    END IF;
+
+    inner_block:BEGIN
+      DECLARE z_done INT DEFAULT  0;
+      SET z_done = 0;
+      inner_loop: LOOP
+        IF z_done=1  THEN
+          LEAVE inner_loop;
+        END IF;
+        IF (t_done = 'a') THEN
+          IF (t_done <> 0) THEN
+            IF ( t_done > 0) THEN
+              IF (t_done = 'a') THEN
+                SET t_done = 'a';
+              ELSEIF (t_done = 'a') THEN
+                SET t_done = 'a';
+              ELSEIF(t_done = 'a') THEN
+                SET t_done = 'a';
+              ELSEIF(t_done = 'a') THEN
+                SET t_done = 'a';
+              ELSEIF(t_done = 'a') THEN
+                SET t_done = 'a';
+              ELSEIF(t_done = 'a') THEN
+                SET t_done = 'a';
+              ELSEIF(t_done = 'a') THEN
+                SET t_done = 'a';
+              ELSEIF(t_done = 'a') THEN
+                SET t_done = 'a';
+              END IF;
+            END IF;
+          END IF;
+        END IF;
+      END LOOP inner_loop;
+    END inner_block;
+  END LOOP outer_loop;
+END $$
+
+delimiter ;$$
+
+drop procedure proc_35577;
+
+#
+# Bug#37269 (parser crash when creating stored procedure)
+#
+
+--disable_warnings
+drop procedure if exists p_37269;
+--enable_warnings
+
+delimiter $$;
+
+create procedure p_37269()
+begin
+  declare done int default 0;
+  declare varb int default 0;
+  declare vara int default 0;
+
+  repeat
+    select now();
+  until done end repeat;
+  while varb do
+    select now();
+    begin
+      select now();
+      repeat
+        select now();
+      until done end repeat;
+      if vara then 
+        select now();
+        repeat
+          select now();
+          loop
+            select now();
+          end loop;
+          repeat
+            select now();
+            label1: while varb do
+              select now();
+            end while label1;
+            if vara then 
+              select now();
+              repeat
+                select now();
+              until done end repeat;
+              begin
+                select now();
+                while varb do
+                  select now();
+                  label1: while varb do
+                    select now();
+                  end while label1;
+                  if vara then 
+                    select now();
+                    while varb do
+                      select now();
+                      loop
+                        select now();
+                      end loop;
+                      repeat
+                        select now();
+                        loop
+                          select now();
+                          while varb do
+                            select now();
+                          end while;
+                          repeat
+                            select now();
+                            label1: loop
+                              select now();
+                              if vara then 
+                                select now();
+                              end if;
+                            end loop label1;
+                          until done end repeat;
+                        end loop;
+                      until done end repeat;
+                    end while;
+                  end if;
+                end while;
+              end;
+            end if;
+          until done end repeat;
+        until done end repeat;
+      end if;
+    end;
+  end while;
+end $$
+
+delimiter ;$$
+
+drop procedure p_37269;
+
+#
+# Bug#37228 (Sever crashes when creating stored procedure with more than
+#            10 IF/ELSEIF)
+#
+
+--disable_warnings
+drop procedure if exists p_37228;
+--enable_warnings
+
+delimiter $$;
+
+create procedure p_37228 ()
+BEGIN
+  DECLARE v INT DEFAULT 123;
+
+  IF (v > 1) THEN SET v = 1; 
+  ELSEIF (v < 10) THEN SET v = 10;
+  ELSEIF (v < 11) THEN SET v = 11;
+  ELSEIF (v < 12) THEN SET v = 12;
+  ELSEIF (v < 13) THEN SET v = 13;
+  ELSEIF (v < 14) THEN SET v = 14;
+  ELSEIF (v < 15) THEN SET v = 15;
+  ELSEIF (v < 16) THEN SET v = 16;
+  ELSEIF (v < 17) THEN SET v = 17;
+  ELSEIF (v < 18) THEN SET v = 18;
+  ELSEIF (v < 19) THEN SET v = 19;
+  ELSEIF (v < 20) THEN SET v = 20;
+  ELSEIF (v < 21) THEN SET v = 21;
+  ELSEIF (v < 22) THEN SET v = 22;
+  ELSEIF (v < 23) THEN SET v = 23;
+  ELSEIF (v < 24) THEN SET v = 24;
+  ELSEIF (v < 25) THEN SET v = 25;
+  ELSEIF (v < 26) THEN SET v = 26;
+  ELSEIF (v < 27) THEN SET v = 27;
+  ELSEIF (v < 28) THEN SET v = 28;
+  ELSEIF (v < 29) THEN SET v = 29;
+  ELSEIF (v < 30) THEN SET v = 30;
+  ELSEIF (v < 31) THEN SET v = 31;
+  ELSEIF (v < 32) THEN SET v = 32;
+  ELSEIF (v < 33) THEN SET v = 33;
+  ELSEIF (v < 34) THEN SET v = 34;
+  ELSEIF (v < 35) THEN SET v = 35;
+  ELSEIF (v < 36) THEN SET v = 36;
+  ELSEIF (v < 37) THEN SET v = 37;
+  ELSEIF (v < 38) THEN SET v = 38;
+  ELSEIF (v < 39) THEN SET v = 39;
+  END IF;
+END $$
+
+delimiter ;$$
+
+drop procedure p_37228;
+
+
diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc
index dd47b8dd91613c7bb03555efa82770db88a2820c..ea3c9f17e2374e6f59d7758599af4da9b7dcb03e 100644
--- a/sql/event_data_objects.cc
+++ b/sql/event_data_objects.cc
@@ -1439,10 +1439,10 @@ Event_job_data::execute(THD *thd, bool drop)
   thd->query_length= sp_sql.length();
 
   {
-    Lex_input_stream lip(thd, thd->query, thd->query_length);
+    Parser_state parser_state(thd, thd->query, thd->query_length);
     lex_start(thd);
 
-    if (parse_sql(thd, &lip, creation_ctx))
+    if (parse_sql(thd, & parser_state, creation_ctx))
     {
       sql_print_error("Event Scheduler: "
                       "%serror during compilation of %s.%s",
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 0060e7873e1ae52894d12e1e4b95c25d1ba1b8c3..88aba4c9662983cef44d72a9246f170f71f5be9a 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -44,6 +44,8 @@
 #include "sql_plugin.h"
 #include "scheduler.h"
 
+class Parser_state;
+
 /**
   Query type constants.
 
@@ -804,8 +806,8 @@ bool check_string_char_length(LEX_STRING *str, const char *err_msg,
 bool test_if_data_home_dir(const char *dir);
 
 bool parse_sql(THD *thd,
-               class Lex_input_stream *lip,
-               class Object_creation_ctx *creation_ctx);
+               Parser_state *parser_state,
+               Object_creation_ctx *creation_ctx);
 
 enum enum_mysql_completiontype {
   ROLLBACK_RELEASE=-2, ROLLBACK=1,  ROLLBACK_AND_CHAIN=7,
diff --git a/sql/sp.cc b/sql/sp.cc
index a1e5e1291ae92dac807e64039d2a8baf5047045c..cc5459928577a76a91fcb56326b30c41ebf3c387 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -617,12 +617,12 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
   thd->spcont= NULL;
 
   {
-    Lex_input_stream lip(thd, defstr.c_ptr(), defstr.length());
+    Parser_state parser_state(thd, defstr.c_ptr(), defstr.length());
 
     lex_start(thd);
 
     thd->push_internal_handler(&warning_handler);
-    ret= parse_sql(thd, &lip, creation_ctx) || newlex.sphead == NULL;
+    ret= parse_sql(thd, & parser_state, creation_ctx) || newlex.sphead == NULL;
     thd->pop_internal_handler();
 
     /*
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index c450c9dd25dfe07fe3a8820edd7417f183f07e12..92dcafa7aa80f1d2689951ba6514f5c1e6806d04 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -627,14 +627,14 @@ void
 sp_head::set_body_start(THD *thd, const char *begin_ptr)
 {
   m_body_begin= begin_ptr;
-  thd->m_lip->body_utf8_start(thd, begin_ptr);
+  thd->m_parser_state->m_lip.body_utf8_start(thd, begin_ptr);
 }
 
 
 void
 sp_head::set_stmt_end(THD *thd)
 {
-  Lex_input_stream *lip= thd->m_lip; /* shortcut */
+  Lex_input_stream *lip= & thd->m_parser_state->m_lip; /* shortcut */
   const char *end_ptr= lip->get_cpp_ptr(); /* shortcut */
 
   /* Make the string of parameters. */
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index b54aea9442436ed9a920c76761035cd8e647fd08..691b176e59d3485665f857da6c83db0c2ca764aa 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -529,7 +529,7 @@ THD::THD()
    bootstrap(0),
    derived_tables_processing(FALSE),
    spcont(NULL),
-   m_lip(NULL)
+   m_parser_state(NULL)
 {
   ulong tmp;
 
diff --git a/sql/sql_class.h b/sql/sql_class.h
index a86b4d36d00ded4183eeb61f7db3cfe35320880a..9e0272b889183ae442d85001ce39575f4db239cb 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -75,7 +75,7 @@ class Load_log_event;
 class Slave_log_event;
 class sp_rcontext;
 class sp_cache;
-class Lex_input_stream;
+class Parser_state;
 class Rows_log_event;
 
 enum enum_enable_or_disable { LEAVE_AS_IS, ENABLE, DISABLE };
@@ -1771,13 +1771,11 @@ class THD :public Statement,
   } binlog_evt_union;
 
   /**
-    Character input stream consumed by the lexical analyser,
-    used during parsing.
-    Note that since the parser is not re-entrant, we keep only one input
-    stream here. This member is valid only when executing code during parsing,
-    and may point to invalid memory after that.
+    Internal parser state.
+    Note that since the parser is not re-entrant, we keep only one parser
+    state here. This member is valid only when executing code during parsing.
   */
-  Lex_input_stream *m_lip;
+  Parser_state *m_parser_state;
 
 #ifdef WITH_PARTITION_STORAGE_ENGINE
   partition_info *work_part_info;
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 64c2a911313c3d4344105b68c872a40210cd97d1..1822176f00a102d246f91f621109feeef33b36be 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -371,13 +371,6 @@ void lex_end(LEX *lex)
 {
   DBUG_ENTER("lex_end");
   DBUG_PRINT("enter", ("lex: 0x%lx", (long) lex));
-  if (lex->yacc_yyss)
-  {
-    my_free(lex->yacc_yyss, MYF(0));
-    my_free(lex->yacc_yyvs, MYF(0));
-    lex->yacc_yyss= 0;
-    lex->yacc_yyvs= 0;
-  }
 
   /* release used plugins */
   plugin_unlock_list(0, (plugin_ref*)lex->plugins.buffer, 
@@ -387,6 +380,14 @@ void lex_end(LEX *lex)
   DBUG_VOID_RETURN;
 }
 
+Yacc_state::~Yacc_state()
+{
+  if (yacc_yyss)
+  {
+    my_free(yacc_yyss, MYF(0));
+    my_free(yacc_yyvs, MYF(0));
+  }
+}
 
 static int find_keyword(Lex_input_stream *lip, uint len, bool function)
 {
@@ -726,7 +727,7 @@ int MYSQLlex(void *arg, void *yythd)
   uint length;
   enum my_lex_states state;
   THD *thd= (THD *)yythd;
-  Lex_input_stream *lip= thd->m_lip;
+  Lex_input_stream *lip= & thd->m_parser_state->m_lip;
   LEX *lex= thd->lex;
   YYSTYPE *yylval=(YYSTYPE*) arg;
   CHARSET_INFO *cs= thd->charset();
@@ -2128,7 +2129,7 @@ void Query_tables_list::destroy_query_tables_list()
 */
 
 st_lex::st_lex()
-  :result(0), yacc_yyss(0), yacc_yyvs(0),
+  :result(0),
    sql_command(SQLCOM_END), option_type(OPT_DEFAULT), is_lex_started(0)
 {
 
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 443c85b48543c20dce4f1ac745908a141ae5fc11..5af22a895a73340518b3b1fb9851e6cb2d79cd1f 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -1513,7 +1513,6 @@ typedef struct st_lex : public Query_tables_list
   LEX_STRING comment, ident;
   LEX_USER *grant_user;
   XID *xid;
-  uchar* yacc_yyss, *yacc_yyvs;
   THD *thd;
 
   /* maintain a list of used plugins for this LEX */
@@ -1847,6 +1846,59 @@ typedef struct st_lex : public Query_tables_list
   }
 } LEX;
 
+
+/**
+  The internal state of the syntax parser.
+  This object is only available during parsing,
+  and is private to the syntax parser implementation (sql_yacc.yy).
+*/
+class Yacc_state
+{
+public:
+  Yacc_state()
+    : yacc_yyss(NULL), yacc_yyvs(NULL)
+  {}
+
+  ~Yacc_state();
+
+  /**
+    Bison internal state stack, yyss, when dynamically allocated using
+    my_yyoverflow().
+  */
+  uchar *yacc_yyss;
+
+  /**
+    Bison internal semantic value stack, yyvs, when dynamically allocated using
+    my_yyoverflow().
+  */
+  uchar *yacc_yyvs;
+
+  /*
+    TODO: move more attributes from the LEX structure here.
+  */
+};
+
+/**
+  Internal state of the parser.
+  The complete state consist of:
+  - state data used during lexical parsing,
+  - state data used during syntactic parsing.
+*/
+class Parser_state
+{
+public:
+  Parser_state(THD *thd, const char* buff, unsigned int length)
+    : m_lip(thd, buff, length), m_yacc()
+  {}
+
+  ~Parser_state()
+  {}
+
+  Lex_input_stream m_lip;
+  Yacc_state m_yacc;
+};
+
+
 struct st_lex_local: public st_lex
 {
   static void *operator new(size_t size) throw()
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 349e92b00d36d708d677ae74c7905ad96c2bbf56..14b14106925a6b10e888f79f979e799da3159996 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -5323,29 +5323,35 @@ bool check_stack_overrun(THD *thd, long margin,
 
 bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, ulong *yystacksize)
 {
-  LEX	*lex= current_thd->lex;
+  Yacc_state *state= & current_thd->m_parser_state->m_yacc;
   ulong old_info=0;
+  DBUG_ASSERT(state);
   if ((uint) *yystacksize >= MY_YACC_MAX)
     return 1;
-  if (!lex->yacc_yyvs)
+  if (!state->yacc_yyvs)
     old_info= *yystacksize;
   *yystacksize= set_zone((*yystacksize)*2,MY_YACC_INIT,MY_YACC_MAX);
-  if (!(lex->yacc_yyvs= (uchar*)
-	my_realloc(lex->yacc_yyvs,
-		   *yystacksize*sizeof(**yyvs),
-		   MYF(MY_ALLOW_ZERO_PTR | MY_FREE_ON_ERROR))) ||
-      !(lex->yacc_yyss= (uchar*)
-	my_realloc(lex->yacc_yyss,
-		   *yystacksize*sizeof(**yyss),
-		   MYF(MY_ALLOW_ZERO_PTR | MY_FREE_ON_ERROR))))
+  if (!(state->yacc_yyvs= (uchar*)
+        my_realloc(state->yacc_yyvs,
+                   *yystacksize*sizeof(**yyvs),
+                   MYF(MY_ALLOW_ZERO_PTR | MY_FREE_ON_ERROR))) ||
+      !(state->yacc_yyss= (uchar*)
+        my_realloc(state->yacc_yyss,
+                   *yystacksize*sizeof(**yyss),
+                   MYF(MY_ALLOW_ZERO_PTR | MY_FREE_ON_ERROR))))
     return 1;
   if (old_info)
-  {						// Copy old info from stack
-    memcpy(lex->yacc_yyss, (uchar*) *yyss, old_info*sizeof(**yyss));
-    memcpy(lex->yacc_yyvs, (uchar*) *yyvs, old_info*sizeof(**yyvs));
+  {
+    /*
+      Only copy the old stack on the first call to my_yyoverflow(),
+      when replacing a static stack (YYINITDEPTH) by a dynamic stack.
+      For subsequent calls, my_realloc already did preserve the old stack.
+    */
+    memcpy(state->yacc_yyss, *yyss, old_info*sizeof(**yyss));
+    memcpy(state->yacc_yyvs, *yyvs, old_info*sizeof(**yyvs));
   }
-  *yyss=(short*) lex->yacc_yyss;
-  *yyvs=(YYSTYPE*) lex->yacc_yyvs;
+  *yyss= (short*) state->yacc_yyss;
+  *yyvs= (YYSTYPE*) state->yacc_yyvs;
   return 0;
 }
 
@@ -5609,10 +5615,10 @@ void mysql_parse(THD *thd, const char *inBuf, uint length,
     sp_cache_flush_obsolete(&thd->sp_proc_cache);
     sp_cache_flush_obsolete(&thd->sp_func_cache);
 
-    Lex_input_stream lip(thd, inBuf, length);
+    Parser_state parser_state(thd, inBuf, length);
 
-    bool err= parse_sql(thd, &lip, NULL);
-    *found_semicolon= lip.found_semicolon;
+    bool err= parse_sql(thd, & parser_state, NULL);
+    *found_semicolon= parser_state.m_lip.found_semicolon;
 
     if (!err)
     {
@@ -5697,11 +5703,11 @@ bool mysql_test_parse_for_slave(THD *thd, char *inBuf, uint length)
   bool error= 0;
   DBUG_ENTER("mysql_test_parse_for_slave");
 
-  Lex_input_stream lip(thd, inBuf, length);
+  Parser_state parser_state(thd, inBuf, length);
   lex_start(thd);
   mysql_reset_thd_for_next_command(thd);
 
-  if (!parse_sql(thd, &lip, NULL) &&
+  if (!parse_sql(thd, & parser_state, NULL) &&
       all_tables_not_ok(thd,(TABLE_LIST*) lex->select_lex.table_list.first))
     error= 1;                  /* Ignore question */
   thd->end_statement();
@@ -6740,7 +6746,7 @@ bool check_simple_select()
   if (lex->current_select != &lex->select_lex)
   {
     char command[80];
-    Lex_input_stream *lip= thd->m_lip;
+    Lex_input_stream *lip= & thd->m_parser_state->m_lip;
     strmake(command, lip->yylval->symbol.str,
 	    min(lip->yylval->symbol.length, sizeof(command)-1));
     my_error(ER_CANT_USE_OPTION_HERE, MYF(0), command);
@@ -7417,7 +7423,7 @@ extern int MYSQLparse(void *thd); // from sql_yacc.cc
   instead of MYSQLparse().
 
   @param thd Thread context.
-  @param lip Lexer context.
+  @param parser_state Parser state.
   @param creation_ctx Object creation context.
 
   @return Error status.
@@ -7426,10 +7432,10 @@ extern int MYSQLparse(void *thd); // from sql_yacc.cc
 */
 
 bool parse_sql(THD *thd,
-               Lex_input_stream *lip,
+               Parser_state *parser_state,
                Object_creation_ctx *creation_ctx)
 {
-  DBUG_ASSERT(thd->m_lip == NULL);
+  DBUG_ASSERT(thd->m_parser_state == NULL);
 
   /* Backup creation context. */
 
@@ -7438,9 +7444,9 @@ bool parse_sql(THD *thd,
   if (creation_ctx)
     backup_ctx= creation_ctx->set_n_backup(thd);
 
-  /* Set Lex_input_stream. */
+  /* Set parser state. */
 
-  thd->m_lip= lip;
+  thd->m_parser_state= parser_state;
 
   /* Parse the query. */
 
@@ -7451,9 +7457,9 @@ bool parse_sql(THD *thd,
   DBUG_ASSERT(!mysql_parse_status ||
               mysql_parse_status && thd->is_error());
 
-  /* Reset Lex_input_stream. */
+  /* Reset parser state. */
 
-  thd->m_lip= NULL;
+  thd->m_parser_state= NULL;
 
   /* Restore creation context. */
 
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index 037da87be7f8ebada542019509294d43c5450fd5..121ee3c22b46be9036996d9ab531521aa1285ea0 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -3767,7 +3767,7 @@ bool mysql_unpack_partition(THD *thd,
   thd->lex= &lex;
   thd->variables.character_set_client= system_charset_info;
 
-  Lex_input_stream lip(thd, part_buf, part_info_len);
+  Parser_state parser_state(thd, part_buf, part_info_len);
 
   lex_start(thd);
   *work_part_info_used= false;
@@ -3797,7 +3797,7 @@ bool mysql_unpack_partition(THD *thd,
   lex.part_info->part_state= part_state;
   lex.part_info->part_state_len= part_state_len;
   DBUG_PRINT("info", ("Parse: %s", part_buf));
-  if (parse_sql(thd, &lip, NULL))
+  if (parse_sql(thd, & parser_state, NULL))
   {
     thd->free_items();
     goto end;
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 16e4812655ef5e0a9237305daf41e41888edee2d..7fcc374e3f3b70c1b95554639740dca1646c6df0 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -3017,11 +3017,11 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
   old_stmt_arena= thd->stmt_arena;
   thd->stmt_arena= this;
 
-  Lex_input_stream lip(thd, thd->query, thd->query_length);
-  lip.stmt_prepare_mode= TRUE;
+  Parser_state parser_state(thd, thd->query, thd->query_length);
+  parser_state.m_lip.stmt_prepare_mode= TRUE;
   lex_start(thd);
 
-  error= parse_sql(thd, &lip, NULL) ||
+  error= parse_sql(thd, & parser_state, NULL) ||
          thd->is_error() ||
          init_param_array(this);
 
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index d426904e4b23ebbba86cdc65f9545fb9f1c08d5d..32389bde44c9dc0097195a83ebe25e3804bdef16 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -1287,7 +1287,9 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
 
         thd->variables.sql_mode= (ulong)*trg_sql_mode;
 
-        Lex_input_stream lip(thd, trg_create_str->str, trg_create_str->length);
+        Parser_state parser_state(thd,
+                                  trg_create_str->str,
+                                  trg_create_str->length);
 
         Trigger_creation_ctx *creation_ctx=
           Trigger_creation_ctx::create(thd,
@@ -1300,7 +1302,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
         lex_start(thd);
         thd->spcont= NULL;
 
-        if (parse_sql(thd, &lip, creation_ctx))
+        if (parse_sql(thd, & parser_state, creation_ctx))
         {
           /* Currently sphead is always deleted in case of a parse error */
           DBUG_ASSERT(lex.sphead == 0);
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index a654721de3754451b47aedabf6c29ce6418154f8..12b2adf4f1329eed2dec00fd2d8fd034e0de4600 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -1147,9 +1147,9 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
     char old_db_buf[NAME_LEN+1];
     LEX_STRING old_db= { old_db_buf, sizeof(old_db_buf) };
     bool dbchanged;
-    Lex_input_stream lip(thd,
-                         table->select_stmt.str,
-                         table->select_stmt.length);
+    Parser_state parser_state(thd,
+                              table->select_stmt.str,
+                              table->select_stmt.length);
 
     /* 
       Use view db name as thread default database, in order to ensure
@@ -1193,7 +1193,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
 
     /* Parse the query. */
 
-    parse_status= parse_sql(thd, &lip, table->view_creation_ctx);
+    parse_status= parse_sql(thd, & parser_state, table->view_creation_ctx);
 
     /* Restore environment. */
 
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 3652fe8d6b446a1869c6c0533abc8eb46df9e531..ccd64c249603c4b15fe24f62ffaef641a5da5303 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -28,6 +28,7 @@
 #define YYPARSE_PARAM yythd
 #define YYLEX_PARAM yythd
 #define YYTHD ((THD *)yythd)
+#define YYLIP (& YYTHD->m_parser_state->m_lip)
 
 #define MYSQL_YACC
 #define YYINITDEPTH 100
@@ -121,7 +122,7 @@ const LEX_STRING null_lex_str= {0,0};
 void my_parse_error(const char *s)
 {
   THD *thd= current_thd;
-  Lex_input_stream *lip= thd->m_lip;
+  Lex_input_stream *lip= & thd->m_parser_state->m_lip;
 
   const char *yytext= lip->get_tok_start();
   /* Push an error into the error stack */
@@ -1356,11 +1357,11 @@ query:
               MYSQL_YYABORT;
             }
             thd->lex->sql_command= SQLCOM_EMPTY_QUERY;
-            thd->m_lip->found_semicolon= NULL;
+            YYLIP->found_semicolon= NULL;
           }
         | verb_clause
           {
-            Lex_input_stream *lip = YYTHD->m_lip;
+            Lex_input_stream *lip = YYLIP;
 
             if ((YYTHD->client_capabilities & CLIENT_MULTI_QUERIES) &&
                 ! lip->stmt_prepare_mode &&
@@ -1386,7 +1387,7 @@ query:
         | verb_clause END_OF_INPUT
           {
             /* Single query, not terminated. */
-            YYTHD->m_lip->found_semicolon= NULL;
+            YYLIP->found_semicolon= NULL;
           }
         ;
 
@@ -1917,7 +1918,7 @@ ev_sql_stmt:
           {
             THD *thd= YYTHD;
             LEX *lex= thd->lex;
-            Lex_input_stream *lip= thd->m_lip;
+            Lex_input_stream *lip= YYLIP;
 
             /*
               This stops the following :
@@ -2574,7 +2575,7 @@ sp_proc_stmt_statement:
           {
             THD *thd= YYTHD;
             LEX *lex= thd->lex;
-            Lex_input_stream *lip= thd->m_lip;
+            Lex_input_stream *lip= YYLIP;
 
             lex->sphead->reset_lex(thd);
             lex->sphead->m_tmp_query= lip->get_tok_start();
@@ -2583,7 +2584,7 @@ sp_proc_stmt_statement:
           {
             THD *thd= YYTHD;
             LEX *lex= thd->lex;
-            Lex_input_stream *lip= thd->m_lip;
+            Lex_input_stream *lip= YYLIP;
             sp_head *sp= lex->sphead;
 
             sp->m_flags|= sp_get_flags_for_command(lex);
@@ -6455,17 +6456,13 @@ select_item:
 
 remember_name:
           {
-            THD *thd= YYTHD;
-            Lex_input_stream *lip= thd->m_lip;
-            $$= (char*) lip->get_cpp_tok_start();
+            $$= (char*) YYLIP->get_cpp_tok_start();
           }
         ;
 
 remember_end:
           {
-            THD *thd= YYTHD;
-            Lex_input_stream *lip= thd->m_lip;
-            $$= (char*) lip->get_cpp_tok_end();
+            $$= (char*) YYLIP->get_cpp_tok_end();
           }
         ;
 
@@ -9645,7 +9642,7 @@ load:
           {
             THD *thd= YYTHD;
             LEX *lex= thd->lex;
-            Lex_input_stream *lip= thd->m_lip;
+            Lex_input_stream *lip= YYLIP;
 
             if (lex->sphead)
             {
@@ -9686,10 +9683,7 @@ load_data:
           }
           opt_duplicate INTO
           {
-            THD *thd= YYTHD;
-            LEX *lex= thd->lex;
-            Lex_input_stream *lip= thd->m_lip;
-            lex->fname_end= lip->get_ptr();
+            Lex->fname_end= YYLIP->get_ptr();
           }
           TABLE_SYM table_ident
           {
@@ -9924,7 +9918,7 @@ param_marker:
           {
             THD *thd= YYTHD;
             LEX *lex= thd->lex;
-            Lex_input_stream *lip= thd->m_lip;
+            Lex_input_stream *lip= YYLIP;
             Item_param *item;
             if (! lex->parsing_options.allows_variable)
             {
@@ -9956,7 +9950,7 @@ literal:
         | NULL_SYM
           {
             $$ = new Item_null();
-            YYTHD->m_lip->next_state=MY_LEX_OPERATOR_OR_IDENT;
+            YYLIP->next_state= MY_LEX_OPERATOR_OR_IDENT;
           }
         | FALSE_SYM { $$= new Item_int((char*) "FALSE",0,1); }
         | TRUE_SYM { $$= new Item_int((char*) "TRUE",1,1); }
@@ -10086,7 +10080,7 @@ simple_ident:
           {
             THD *thd= YYTHD;
             LEX *lex= thd->lex;
-            Lex_input_stream *lip= thd->m_lip;
+            Lex_input_stream *lip= YYLIP;
             sp_variable_t *spv;
             sp_pcontext *spc = lex->spcont;
             if (spc && (spv = spc->find_variable(&$1)))
@@ -10776,7 +10770,7 @@ option_type_value:
           {
             THD *thd= YYTHD;
             LEX *lex= thd->lex;
-            Lex_input_stream *lip= thd->m_lip;
+            Lex_input_stream *lip= YYLIP;
 
             if (lex->sphead)
             {
@@ -10807,7 +10801,7 @@ option_type_value:
           {
             THD *thd= YYTHD;
             LEX *lex= thd->lex;
-            Lex_input_stream *lip= thd->m_lip;
+            Lex_input_stream *lip= YYLIP;
 
             if (lex->sphead)
             {
@@ -12076,19 +12070,17 @@ view_select:
           {
             THD *thd= YYTHD;
             LEX *lex= Lex;
-            Lex_input_stream *lip= thd->m_lip;
             lex->parsing_options.allows_variable= FALSE;
             lex->parsing_options.allows_select_into= FALSE;
             lex->parsing_options.allows_select_procedure= FALSE;
             lex->parsing_options.allows_derived= FALSE;
-            lex->create_view_select.str= (char *) lip->get_cpp_ptr();
+            lex->create_view_select.str= (char *) YYLIP->get_cpp_ptr();
           }
           view_select_aux view_check_option
           {
             THD *thd= YYTHD;
             LEX *lex= Lex;
-            Lex_input_stream *lip= thd->m_lip;
-            uint len= lip->get_cpp_ptr() - lex->create_view_select.str;
+            uint len= YYLIP->get_cpp_ptr() - lex->create_view_select.str;
             void *create_view_select= thd->memdup(lex->create_view_select.str, len);
             lex->create_view_select.length= len;
             lex->create_view_select.str= (char *) create_view_select;
@@ -12131,26 +12123,20 @@ trigger_tail:
           ON
           remember_name /* $7 */
           { /* $8 */
-            THD *thd= YYTHD;
-            LEX *lex= thd->lex;
-            Lex_input_stream *lip= thd->m_lip;
-            lex->raw_trg_on_table_name_begin= lip->get_tok_start();
+            Lex->raw_trg_on_table_name_begin= YYLIP->get_tok_start();
           }
           table_ident /* $9 */
           FOR_SYM
           remember_name /* $11 */
           { /* $12 */
-            THD *thd= YYTHD;
-            LEX *lex= thd->lex;
-            Lex_input_stream *lip= thd->m_lip;
-            lex->raw_trg_on_table_name_end= lip->get_tok_start();
+            Lex->raw_trg_on_table_name_end= YYLIP->get_tok_start();
           }
           EACH_SYM
           ROW_SYM
           { /* $15 */
             THD *thd= YYTHD;
             LEX *lex= thd->lex;
-            Lex_input_stream *lip= thd->m_lip;
+            Lex_input_stream *lip= YYLIP;
             sp_head *sp;
 
             if (lex->sphead)
@@ -12254,7 +12240,7 @@ sf_tail:
           { /* $5 */
             THD *thd= YYTHD;
             LEX *lex= thd->lex;
-            Lex_input_stream *lip= thd->m_lip;
+            Lex_input_stream *lip= YYLIP;
             sp_head *sp;
             const char* tmp_param_begin;
 
@@ -12282,11 +12268,7 @@ sf_tail:
           sp_fdparam_list /* $6 */
           ')' /* $7 */
           { /* $8 */
-            THD *thd= YYTHD;
-            LEX *lex= thd->lex;
-            Lex_input_stream *lip= thd->m_lip;
-
-            lex->sphead->m_param_end= lip->get_cpp_tok_start();
+            Lex->sphead->m_param_end= YYLIP->get_cpp_tok_start();
           }
           RETURNS_SYM /* $9 */
           { /* $10 */
@@ -12323,7 +12305,7 @@ sf_tail:
           { /* $14 */
             THD *thd= YYTHD;
             LEX *lex= thd->lex;
-            Lex_input_stream *lip= thd->m_lip;
+            Lex_input_stream *lip= YYLIP;
 
             lex->sphead->m_chistics= &lex->sp_chistics;
             lex->sphead->set_body_start(thd, lip->get_cpp_tok_start());
@@ -12408,33 +12390,28 @@ sp_tail:
           }
           '('
           {
-            THD *thd= YYTHD;
-            LEX *lex= thd->lex;
-            Lex_input_stream *lip= thd->m_lip;
             const char* tmp_param_begin;
 
-            tmp_param_begin= lip->get_cpp_tok_start();
+            tmp_param_begin= YYLIP->get_cpp_tok_start();
             tmp_param_begin++;
-            lex->sphead->m_param_begin= tmp_param_begin;
+            Lex->sphead->m_param_begin= tmp_param_begin;
           }
           sp_pdparam_list
           ')'
           {
             THD *thd= YYTHD;
             LEX *lex= thd->lex;
-            Lex_input_stream *lip= thd->m_lip;
 
-            lex->sphead->m_param_end= lip->get_cpp_tok_start();
+            lex->sphead->m_param_end= YYLIP->get_cpp_tok_start();
             bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
           }
           sp_c_chistics
           {
             THD *thd= YYTHD;
             LEX *lex= thd->lex;
-            Lex_input_stream *lip= thd->m_lip;
 
             lex->sphead->m_chistics= &lex->sp_chistics;
-            lex->sphead->set_body_start(thd, lip->get_cpp_tok_start());
+            lex->sphead->set_body_start(thd, YYLIP->get_cpp_tok_start());
           }
           sp_proc_stmt
           {