Index: EcnlProtoTool/trunk/mruby-1.3.0/mrbgems/mruby-compiler/core/parse.y
===================================================================
--- EcnlProtoTool/trunk/mruby-1.2.0/mrbgems/mruby-compiler/core/parse.y	(revision 270)
+++ EcnlProtoTool/trunk/mruby-1.3.0/mrbgems/mruby-compiler/core/parse.y	(revision 331)
@@ -23,10 +23,10 @@
 #include <stdlib.h>
 #include <string.h>
-#include "mruby.h"
-#include "mruby/compile.h"
-#include "mruby/proc.h"
-#include "mruby/error.h"
+#include <mruby.h>
+#include <mruby/compile.h>
+#include <mruby/proc.h>
+#include <mruby/error.h>
+#include <mruby/throw.h>
 #include "node.h"
-#include "mruby/throw.h"
 
 #define YYLEX_PARAM p
@@ -42,4 +42,5 @@
 static void yywarning(parser_state *p, const char *s);
 static void backref_error(parser_state *p, node *n);
+static void void_expr_error(parser_state *p, node *n);
 static void tokadd(parser_state *p, int32_t c);
 
@@ -73,4 +74,6 @@
 #define sym(x) ((mrb_sym)(intptr_t)(x))
 #define nsym(x) ((node*)(intptr_t)(x))
+#define nint(x) ((node*)(intptr_t)(x))
+#define intn(x) ((int)(intptr_t)(x))
 
 static inline mrb_sym
@@ -309,4 +312,10 @@
 }
 
+static node*
+new_mod_rescue(parser_state *p, node *body, node *resq)
+{
+  return new_rescue(p, body, list1(list3(0, 0, resq)), 0);
+}
+
 /* (:ensure body ensure) */
 static node*
@@ -348,4 +357,5 @@
 new_if(parser_state *p, node *a, node *b, node *c)
 {
+  void_expr_error(p, a);
   return list4((node*)NODE_IF, a, b, c);
 }
@@ -355,4 +365,5 @@
 new_unless(parser_state *p, node *a, node *b, node *c)
 {
+  void_expr_error(p, a);
   return list4((node*)NODE_IF, a, c, b);
 }
@@ -362,4 +373,5 @@
 new_while(parser_state *p, node *a, node *b)
 {
+  void_expr_error(p, a);
   return cons((node*)NODE_WHILE, cons(a, b));
 }
@@ -369,4 +381,5 @@
 new_until(parser_state *p, node *a, node *b)
 {
+  void_expr_error(p, a);
   return cons((node*)NODE_UNTIL, cons(a, b));
 }
@@ -376,4 +389,5 @@
 new_for(parser_state *p, node *v, node *o, node *b)
 {
+  void_expr_error(p, o);
   return list4((node*)NODE_FOR, v, o, b);
 }
@@ -386,4 +400,5 @@
   node *n2 = n;
 
+  void_expr_error(p, a);
   while (n2->cdr) {
     n2 = n2->cdr;
@@ -409,7 +424,8 @@
 /* (:call a b c) */
 static node*
-new_call(parser_state *p, node *a, mrb_sym b, node *c)
-{
-  node *n = list4((node*)NODE_CALL, a, nsym(b), c);
+new_call(parser_state *p, node *a, mrb_sym b, node *c, int pass)
+{
+  node *n = list4(nint(pass?NODE_CALL:NODE_SCALL), a, nsym(b), c);
+  void_expr_error(p, a);
   NODE_LINENO(n, a);
   return n;
@@ -507,4 +523,5 @@
 new_colon2(parser_state *p, node *b, mrb_sym c)
 {
+  void_expr_error(p, b);
   return cons((node*)NODE_COLON2, cons(b, nsym(c)));
 }
@@ -614,4 +631,5 @@
 new_class(parser_state *p, node *c, node *s, node *b)
 {
+  void_expr_error(p, s);
   return list4((node*)NODE_CLASS, c, s, cons(locals_node(p), b));
 }
@@ -621,4 +639,5 @@
 new_sclass(parser_state *p, node *o, node *b)
 {
+  void_expr_error(p, o);
   return list3((node*)NODE_SCLASS, o, cons(locals_node(p), b));
 }
@@ -642,4 +661,5 @@
 new_sdef(parser_state *p, node *o, mrb_sym m, node *a, node *b)
 {
+  void_expr_error(p, o);
   return list6((node*)NODE_SDEF, o, nsym(m), locals_node(p), a, b);
 }
@@ -694,4 +714,5 @@
 new_asgn(parser_state *p, node *a, node *b)
 {
+  void_expr_error(p, b);
   return cons((node*)NODE_ASGN, cons(a, b));
 }
@@ -701,4 +722,5 @@
 new_masgn(parser_state *p, node *a, node *b)
 {
+  void_expr_error(p, b);
   return cons((node*)NODE_MASGN, cons(a, b));
 }
@@ -708,4 +730,5 @@
 new_op_asgn(parser_state *p, node *a, mrb_sym op, node *b)
 {
+  void_expr_error(p, b);
   return list4((node*)NODE_OP_ASGN, a, nsym(op), b);
 }
@@ -715,5 +738,5 @@
 new_int(parser_state *p, const char *s, int base)
 {
-  return list3((node*)NODE_INT, (node*)strdup(s), (node*)(intptr_t)base);
+  return list3((node*)NODE_INT, (node*)strdup(s), nint(base));
 }
 
@@ -729,5 +752,5 @@
 new_str(parser_state *p, const char *s, int len)
 {
-  return cons((node*)NODE_STR, cons((node*)strndup(s, len), (node*)(intptr_t)len));
+  return cons((node*)NODE_STR, cons((node*)strndup(s, len), nint(len)));
 }
 
@@ -743,5 +766,5 @@
 new_xstr(parser_state *p, const char *s, int len)
 {
-  return cons((node*)NODE_XSTR, cons((node*)strndup(s, len), (node*)(intptr_t)len));
+  return cons((node*)NODE_XSTR, cons((node*)strndup(s, len), nint(len)));
 }
 
@@ -760,5 +783,5 @@
 }
 
-/* (:str . (a . a)) */
+/* (:regx . (s . (opt . enc))) */
 static node*
 new_regx(parser_state *p, const char *p1, const char* p2, const char* p3)
@@ -767,5 +790,5 @@
 }
 
-/* (:dregx . a) */
+/* (:dregx . (a . b)) */
 static node*
 new_dregx(parser_state *p, node *a, node *b)
@@ -778,5 +801,5 @@
 new_back_ref(parser_state *p, int n)
 {
-  return cons((node*)NODE_BACK_REF, (node*)(intptr_t)n);
+  return cons((node*)NODE_BACK_REF, nint(n));
 }
 
@@ -785,5 +808,5 @@
 new_nth_ref(parser_state *p, int n)
 {
-  return cons((node*)NODE_NTH_REF, (node*)(intptr_t)n);
+  return cons((node*)NODE_NTH_REF, nint(n));
 }
 
@@ -827,5 +850,6 @@
 call_uni_op(parser_state *p, node *recv, const char *m)
 {
-  return new_call(p, recv, intern_cstr(m), 0);
+  void_expr_error(p, recv);
+  return new_call(p, recv, intern_cstr(m), 0, 1);
 }
 
@@ -834,5 +858,5 @@
 call_bin_op(parser_state *p, node *recv, const char *m, node *arg1)
 {
-  return new_call(p, recv, intern_cstr(m), list1(list1(arg1)));
+  return new_call(p, recv, intern_cstr(m), list1(list1(arg1)), 1);
 }
 
@@ -853,12 +877,15 @@
   node *n;
 
-  if (a->car == (node*)NODE_SUPER ||
-      a->car == (node*)NODE_ZSUPER) {
+  switch ((enum node_type)intn(a->car)) {
+  case NODE_SUPER:
+  case NODE_ZSUPER:
     if (!a->cdr) a->cdr = cons(0, b);
     else {
       args_with_block(p, a->cdr, b);
     }
-  }
-  else {
+    break;
+  case NODE_CALL:
+  case NODE_FCALL:
+  case NODE_SCALL:
     n = a->cdr->cdr->cdr;
     if (!n->car) n->car = cons(0, b);
@@ -866,4 +893,7 @@
       args_with_block(p, n->car, b);
     }
+    break;
+  default:
+    break;
   }
 }
@@ -895,5 +925,5 @@
 assignable(parser_state *p, node *lhs)
 {
-  if ((int)(intptr_t)lhs->car == NODE_LVAR) {
+  if (intn(lhs->car) == NODE_LVAR) {
     local_add(p, sym(lhs->cdr));
   }
@@ -905,5 +935,5 @@
   node *n;
 
-  if ((int)(intptr_t)lhs->car == NODE_LVAR) {
+  if (intn(lhs->car) == NODE_LVAR) {
     if (!local_var_p(p, sym(lhs->cdr))) {
       n = new_fcall(p, sym(lhs->cdr), 0);
@@ -921,5 +951,5 @@
 new_strterm(parser_state *p, string_type type, int term, int paren)
 {
-  return cons((node*)(intptr_t)type, cons((node*)0, cons((node*)(intptr_t)paren, (node*)(intptr_t)term)));
+  return cons(nint(type), cons((node*)0, cons(nint(paren), nint(term))));
 }
 
@@ -1002,8 +1032,8 @@
   else {
     /* next heredoc */
-    p->lex_strterm->car = (node*)(intptr_t)parsing_heredoc_inf(p)->type;
-  }
-}
-#define is_strterm_type(p,str_func) ((int)(intptr_t)((p)->lex_strterm->car) & (str_func))
+    p->lex_strterm->car = nint(parsing_heredoc_inf(p)->type);
+  }
+}
+#define is_strterm_type(p,str_func) (intn((p)->lex_strterm->car) & (str_func))
 
 /* xxx ----------------------------- */
@@ -1077,5 +1107,5 @@
 %token <id>  tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tLABEL
 %token <nd>  tINTEGER tFLOAT tCHAR tXSTRING tREGEXP
-%token <nd>  tSTRING tSTRING_PART tSTRING_MID
+%token <nd>  tSTRING tSTRING_PART tSTRING_MID tLABEL_END
 %token <nd>  tNTH_REF tBACK_REF
 %token <num> tREGEXP_END
@@ -1085,10 +1115,10 @@
 %type <nd> top_compstmt top_stmts top_stmt
 %type <nd> bodystmt compstmt stmts stmt expr arg primary command command_call method_call
-%type <nd> expr_value arg_value primary_value
+%type <nd> expr_value arg_rhs primary_value
 %type <nd> if_tail opt_else case_body cases opt_rescue exc_list exc_var opt_ensure
 %type <nd> args call_args opt_call_args
 %type <nd> paren_args opt_paren_args variable
 %type <nd> command_args aref_args opt_block_arg block_arg var_ref var_lhs
-%type <nd> command_asgn mrhs superclass block_call block_command
+%type <nd> command_asgn command_rhs mrhs superclass block_call block_command
 %type <nd> f_block_optarg f_block_opt
 %type <nd> f_arglist f_args f_arg f_arg_item f_optarg f_marg f_marg_list f_margs
@@ -1101,4 +1131,5 @@
 %type <id> cname fname op f_rest_arg f_block_arg opt_f_block_arg f_norm_arg f_opt_asgn
 %type <nd> heredoc words symbols
+%type <num> call_op call_op2     /* 0:'&.', 1:'.', 2:'::' */
 
 %token tUPLUS             /* unary+ */
@@ -1129,4 +1160,5 @@
 %token tAMPER             /* & */
 %token tLAMBDA            /* -> */
+%token tANDDOT            /* &. */
 %token tSYMBEG tREGEXP_BEG tWORDS_BEG tSYMBOLS_BEG
 %token tSTRING_BEG tXSTRING_BEG tSTRING_DVAR tLAMBEG
@@ -1292,9 +1324,9 @@
                 | stmt modifier_rescue stmt
                     {
-                      $$ = new_rescue(p, $1, list1(list3(0, 0, $3)), 0);
+                      $$ = new_mod_rescue(p, $1, $3);
                     }
                 | keyword_END '{' compstmt '}'
                     {
-                      yyerror(p, "END not suported");
+                      yyerror(p, "END not supported");
                       $$ = new_postexe(p, $3);
                     }
@@ -1304,19 +1336,38 @@
                       $$ = new_masgn(p, $1, $3);
                     }
-                | var_lhs tOP_ASGN command_call
+                | lhs '=' mrhs
+                    {
+                      $$ = new_asgn(p, $1, new_array(p, $3));
+                    }
+                | mlhs '=' arg
+                    {
+                      $$ = new_masgn(p, $1, $3);
+                    }
+                | mlhs '=' mrhs
+                    {
+                      $$ = new_masgn(p, $1, new_array(p, $3));
+                    }
+                | expr
+                ;
+
+command_asgn    : lhs '=' command_rhs
+                    {
+                      $$ = new_asgn(p, $1, $3);
+                    }
+                | var_lhs tOP_ASGN command_rhs
                     {
                       $$ = new_op_asgn(p, $1, $2, $3);
                     }
-                | primary_value '[' opt_call_args rbracket tOP_ASGN command_call
-                    {
-                      $$ = new_op_asgn(p, new_call(p, $1, intern("[]",2), $3), $5, $6);
-                    }
-                | primary_value '.' tIDENTIFIER tOP_ASGN command_call
-                    {
-                      $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5);
-                    }
-                | primary_value '.' tCONSTANT tOP_ASGN command_call
-                    {
-                      $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5);
+                | primary_value '[' opt_call_args rbracket tOP_ASGN command_rhs
+                    {
+                      $$ = new_op_asgn(p, new_call(p, $1, intern("[]",2), $3, '.'), $5, $6);
+                    }
+                | primary_value call_op tIDENTIFIER tOP_ASGN command_rhs
+                    {
+                      $$ = new_op_asgn(p, new_call(p, $1, $3, 0, $2), $4, $5);
+                    }
+                | primary_value call_op tCONSTANT tOP_ASGN command_rhs
+                    {
+                      $$ = new_op_asgn(p, new_call(p, $1, $3, 0, $2), $4, $5);
                     }
                 | primary_value tCOLON2 tCONSTANT tOP_ASGN command_call
@@ -1325,36 +1376,21 @@
                       $$ = 0;
                     }
-                | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call
-                    {
-                      $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5);
-                    }
-                | backref tOP_ASGN command_call
+                | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_rhs
+                    {
+                      $$ = new_op_asgn(p, new_call(p, $1, $3, 0, tCOLON2), $4, $5);
+                    }
+                | backref tOP_ASGN command_rhs
                     {
                       backref_error(p, $1);
                       $$ = new_begin(p, 0);
                     }
-                | lhs '=' mrhs
-                    {
-                      $$ = new_asgn(p, $1, new_array(p, $3));
-                    }
-                | mlhs '=' arg_value
-                    {
-                      $$ = new_masgn(p, $1, $3);
-                    }
-                | mlhs '=' mrhs
-                    {
-                      $$ = new_masgn(p, $1, new_array(p, $3));
-                    }
-                | expr
-                ;
-
-command_asgn    : lhs '=' command_call
-                    {
-                      $$ = new_asgn(p, $1, $3);
-                    }
-                | lhs '=' command_asgn
-                    {
-                      $$ = new_asgn(p, $1, $3);
-                    }
+		;
+
+command_rhs     : command_call   %prec tOP_ASGN
+                | command_call modifier_rescue stmt
+                    {
+                      $$ = new_mod_rescue(p, $1, $3);
+                    }
+                | command_asgn
                 ;
 
@@ -1383,5 +1419,7 @@
                     {
                       if (!$1) $$ = new_nil(p);
-                      else $$ = $1;
+                      else {
+                        $$ = $1;
+                      }
                     }
                 ;
@@ -1392,5 +1430,8 @@
 
 block_command   : block_call
-                | block_call dot_or_colon operation2 command_args
+                | block_call call_op2 operation2 command_args
+                    {
+                      $$ = new_call(p, $1, $3, $4, $2);
+                    }
                 ;
 
@@ -1417,21 +1458,21 @@
                       $$ = new_fcall(p, $1, $2);
                     }
-                | primary_value '.' operation2 command_args     %prec tLOWEST
-                    {
-                      $$ = new_call(p, $1, $3, $4);
-                    }
-                | primary_value '.' operation2 command_args cmd_brace_block
+                | primary_value call_op operation2 command_args     %prec tLOWEST
+                    {
+                      $$ = new_call(p, $1, $3, $4, $2);
+                    }
+                | primary_value call_op operation2 command_args cmd_brace_block
                     {
                       args_with_block(p, $4, $5);
-                      $$ = new_call(p, $1, $3, $4);
+                      $$ = new_call(p, $1, $3, $4, $2);
                    }
                 | primary_value tCOLON2 operation2 command_args %prec tLOWEST
                     {
-                      $$ = new_call(p, $1, $3, $4);
+                      $$ = new_call(p, $1, $3, $4, tCOLON2);
                     }
                 | primary_value tCOLON2 operation2 command_args cmd_brace_block
                     {
                       args_with_block(p, $4, $5);
-                      $$ = new_call(p, $1, $3, $4);
+                      $$ = new_call(p, $1, $3, $4, tCOLON2);
                     }
                 | keyword_super command_args
@@ -1549,17 +1590,17 @@
                 | primary_value '[' opt_call_args rbracket
                     {
-                      $$ = new_call(p, $1, intern("[]",2), $3);
-                    }
-                | primary_value '.' tIDENTIFIER
-                    {
-                      $$ = new_call(p, $1, $3, 0);
+                      $$ = new_call(p, $1, intern("[]",2), $3, '.');
+                    }
+                | primary_value call_op tIDENTIFIER
+                    {
+                      $$ = new_call(p, $1, $3, 0, $2);
                     }
                 | primary_value tCOLON2 tIDENTIFIER
                     {
-                      $$ = new_call(p, $1, $3, 0);
-                    }
-                | primary_value '.' tCONSTANT
-                    {
-                      $$ = new_call(p, $1, $3, 0);
+                      $$ = new_call(p, $1, $3, 0, tCOLON2);
+                    }
+                | primary_value call_op tCONSTANT
+                    {
+                      $$ = new_call(p, $1, $3, 0, $2);
                     }
                 | primary_value tCOLON2 tCONSTANT
@@ -1588,17 +1629,17 @@
                 | primary_value '[' opt_call_args rbracket
                     {
-                      $$ = new_call(p, $1, intern("[]",2), $3);
-                    }
-                | primary_value '.' tIDENTIFIER
-                    {
-                      $$ = new_call(p, $1, $3, 0);
+                      $$ = new_call(p, $1, intern("[]",2), $3, '.');
+                    }
+                | primary_value call_op tIDENTIFIER
+                    {
+                      $$ = new_call(p, $1, $3, 0, $2);
                     }
                 | primary_value tCOLON2 tIDENTIFIER
                     {
-                      $$ = new_call(p, $1, $3, 0);
-                    }
-                | primary_value '.' tCONSTANT
-                    {
-                      $$ = new_call(p, $1, $3, 0);
+                      $$ = new_call(p, $1, $3, 0, tCOLON2);
+                    }
+                | primary_value call_op tCONSTANT
+                    {
+                      $$ = new_call(p, $1, $3, 0, $2);
                     }
                 | primary_value tCOLON2 tCONSTANT
@@ -1638,4 +1679,5 @@
                 | primary_value tCOLON2 cname
                     {
+                      void_expr_error(p, $1);
                       $$ = cons($1, nsym($3));
                     }
@@ -1716,47 +1758,39 @@
                 ;
 
-arg             : lhs '=' arg
+arg             : lhs '=' arg_rhs
                     {
                       $$ = new_asgn(p, $1, $3);
                     }
-                | lhs '=' arg modifier_rescue arg
-                    {
-                      $$ = new_asgn(p, $1, new_rescue(p, $3, list1(list3(0, 0, $5)), 0));
-                    }
-                | var_lhs tOP_ASGN arg
+                | var_lhs tOP_ASGN arg_rhs
                     {
                       $$ = new_op_asgn(p, $1, $2, $3);
                     }
-                | var_lhs tOP_ASGN arg modifier_rescue arg
-                    {
-                      $$ = new_op_asgn(p, $1, $2, new_rescue(p, $3, list1(list3(0, 0, $5)), 0));
-                    }
-                | primary_value '[' opt_call_args rbracket tOP_ASGN arg
-                    {
-                      $$ = new_op_asgn(p, new_call(p, $1, intern("[]",2), $3), $5, $6);
-                    }
-                | primary_value '.' tIDENTIFIER tOP_ASGN arg
-                    {
-                      $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5);
-                    }
-                | primary_value '.' tCONSTANT tOP_ASGN arg
-                    {
-                      $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5);
-                    }
-                | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg
-                    {
-                      $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5);
-                    }
-                | primary_value tCOLON2 tCONSTANT tOP_ASGN arg
+                | primary_value '[' opt_call_args rbracket tOP_ASGN arg_rhs
+                    {
+                      $$ = new_op_asgn(p, new_call(p, $1, intern("[]",2), $3, '.'), $5, $6);
+                    }
+                | primary_value call_op tIDENTIFIER tOP_ASGN arg_rhs
+                    {
+                      $$ = new_op_asgn(p, new_call(p, $1, $3, 0, $2), $4, $5);
+                    }
+                | primary_value call_op tCONSTANT tOP_ASGN arg_rhs
+                    {
+                      $$ = new_op_asgn(p, new_call(p, $1, $3, 0, $2), $4, $5);
+                    }
+                | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg_rhs
+                    {
+                      $$ = new_op_asgn(p, new_call(p, $1, $3, 0, tCOLON2), $4, $5);
+                    }
+                | primary_value tCOLON2 tCONSTANT tOP_ASGN arg_rhs
                     {
                       yyerror(p, "constant re-assignment");
                       $$ = new_begin(p, 0);
                     }
-                | tCOLON3 tCONSTANT tOP_ASGN arg
+                | tCOLON3 tCONSTANT tOP_ASGN arg_rhs
                     {
                       yyerror(p, "constant re-assignment");
                       $$ = new_begin(p, 0);
                     }
-                | backref tOP_ASGN arg
+                | backref tOP_ASGN arg_rhs
                     {
                       backref_error(p, $1);
@@ -1897,11 +1931,4 @@
                 ;
 
-arg_value       : arg
-                    {
-                      $$ = $1;
-                      if (!$$) $$ = new_nil(p);
-                    }
-                ;
-
 aref_args       : none
                 | args trailer
@@ -1910,5 +1937,5 @@
                       NODE_LINENO($$, $1);
                     }
-                | args ',' assocs trailer
+                | args comma assocs trailer
                     {
                       $$ = push($1, new_hash(p, $3));
@@ -1918,4 +1945,16 @@
                       $$ = cons(new_hash(p, $1), 0);
                       NODE_LINENO($$, $1);
+                    }
+                ;
+
+arg_rhs         : arg %prec tOP_ASGN
+                    {
+                      $$ = $1;
+                    }
+                | arg modifier_rescue arg
+                    {
+                      void_expr_error(p, $1);
+                      void_expr_error(p, $3);
+                      $$ = new_mod_rescue(p, $1, $3);
                     }
                 ;
@@ -1938,5 +1977,5 @@
                       NODE_LINENO($$, $1);
                     }
-                | args ',' assocs ','
+                | args comma assocs ','
                     {
                       $$ = cons(push($1, new_hash(p, $3)), 0);
@@ -1952,4 +1991,5 @@
 call_args       : command
                     {
+                      void_expr_error(p, $1);
                       $$ = cons(list1($1), 0);
                       NODE_LINENO($$, $1);
@@ -1965,5 +2005,5 @@
                       NODE_LINENO($$, $1);
                     }
-                | args ',' assocs opt_block_arg
+                | args comma assocs opt_block_arg
                     {
                       $$ = cons(push($1, new_hash(p, $3)), $4);
@@ -1988,5 +2028,5 @@
                 ;
 
-block_arg       : tAMPER arg_value
+block_arg       : tAMPER arg
                     {
                       $$ = new_block_arg(p, $2);
@@ -1994,5 +2034,5 @@
                 ;
 
-opt_block_arg   : ',' block_arg
+opt_block_arg   : comma block_arg
                     {
                       $$ = $2;
@@ -2004,42 +2044,45 @@
                 ;
 
-args            : arg_value
-                    {
+comma           : ','
+                | ','  heredoc_bodies
+                ;
+
+args            : arg
+                    {
+                      void_expr_error(p, $1);
                       $$ = cons($1, 0);
                       NODE_LINENO($$, $1);
                     }
-                | tSTAR arg_value
-                    {
+                | tSTAR arg
+                    {
+                      void_expr_error(p, $2);
                       $$ = cons(new_splat(p, $2), 0);
                       NODE_LINENO($$, $2);
                     }
-                | args ',' arg_value
-                    {
+                | args comma arg
+                    {
+                      void_expr_error(p, $3);
                       $$ = push($1, $3);
                     }
-                | args ',' tSTAR arg_value
-                    {
+                | args comma tSTAR arg
+                    {
+                      void_expr_error(p, $4);
                       $$ = push($1, new_splat(p, $4));
                     }
-                | args ',' heredoc_bodies arg_value
-                    {
-                      $$ = push($1, $4);
-                    }
-                | args ',' heredoc_bodies tSTAR arg_value
-                    {
-                      $$ = push($1, new_splat(p, $5));
-                    }
-                ;
-
-mrhs            : args ',' arg_value
-                    {
+                ;
+
+mrhs            : args comma arg
+                    {
+                      void_expr_error(p, $3);
                       $$ = push($1, $3);
                     }
-                | args ',' tSTAR arg_value
-                    {
+                | args comma tSTAR arg
+                    {
+                      void_expr_error(p, $4);
                       $$ = push($1, new_splat(p, $4));
                     }
-                | tSTAR arg_value
-                    {
+                | tSTAR arg
+                    {
+                      void_expr_error(p, $2);
                       $$ = list1(new_splat(p, $2));
                     }
@@ -2073,5 +2116,5 @@
                       p->cmdarg_stack = 0;
                     }
-                  expr {p->lstate = EXPR_ENDARG;} rparen
+                  stmt {p->lstate = EXPR_ENDARG;} rparen
                     {
                       p->cmdarg_stack = $<stack>2;
@@ -2080,5 +2123,5 @@
                 | tLPAREN_ARG {p->lstate = EXPR_ENDARG;} rparen
                     {
-                      $$ = 0;
+                      $$ = new_nil(p);
                     }
                 | tLPAREN compstmt ')'
@@ -2108,15 +2151,7 @@
                       $$ = new_return(p, 0);
                     }
-                | keyword_yield '(' call_args rparen
-                    {
-                      $$ = new_yield(p, $3);
-                    }
-                | keyword_yield '(' rparen
-                    {
-                      $$ = new_yield(p, 0);
-                    }
-                | keyword_yield
-                    {
-                      $$ = new_yield(p, 0);
+                | keyword_yield opt_paren_args
+                    {
+                      $$ = new_yield(p, $2);
                     }
                 | keyword_not '(' expr rparen
@@ -2229,5 +2264,5 @@
                   term
                     {
-                      $<nd>$ = cons(local_switch(p), (node*)(intptr_t)p->in_single);
+                      $<nd>$ = cons(local_switch(p), nint(p->in_single));
                       p->in_single = 0;
                     }
@@ -2239,5 +2274,5 @@
                       local_resume(p, $<nd>6->car);
                       p->in_def = $<num>4;
-                      p->in_single = (int)(intptr_t)$<nd>6->cdr;
+                      p->in_single = intn($<nd>6->cdr);
                     }
                 | keyword_module
@@ -2433,5 +2468,5 @@
                 | f_arg ','
                     {
-                      $$ = new_args(p, $1, 0, 1, 0, 0);
+                      $$ = new_args(p, $1, 0, 0, 0, 0);
                     }
                 | f_arg ',' f_rest_arg ',' f_arg opt_f_block_arg
@@ -2561,16 +2596,16 @@
                       $$ = $1;
                     }
-                | block_call dot_or_colon operation2 opt_paren_args
-                    {
-                      $$ = new_call(p, $1, $3, $4);
-                    }
-                | block_call dot_or_colon operation2 opt_paren_args brace_block
-                    {
-                      $$ = new_call(p, $1, $3, $4);
+                | block_call call_op2 operation2 opt_paren_args
+                    {
+                      $$ = new_call(p, $1, $3, $4, $2);
+                    }
+                | block_call call_op2 operation2 opt_paren_args brace_block
+                    {
+                      $$ = new_call(p, $1, $3, $4, $2);
                       call_with_block(p, $$, $5);
                     }
-                | block_call dot_or_colon operation2 command_args do_block
-                    {
-                      $$ = new_call(p, $1, $3, $4);
+                | block_call call_op2 operation2 command_args do_block
+                    {
+                      $$ = new_call(p, $1, $3, $4, $2);
                       call_with_block(p, $$, $5);
                     }
@@ -2581,23 +2616,23 @@
                       $$ = new_fcall(p, $1, $2);
                     }
-                | primary_value '.' operation2 opt_paren_args
-                    {
-                      $$ = new_call(p, $1, $3, $4);
+                | primary_value call_op operation2 opt_paren_args
+                    {
+                      $$ = new_call(p, $1, $3, $4, $2);
                     }
                 | primary_value tCOLON2 operation2 paren_args
                     {
-                      $$ = new_call(p, $1, $3, $4);
+                      $$ = new_call(p, $1, $3, $4, tCOLON2);
                     }
                 | primary_value tCOLON2 operation3
                     {
-                      $$ = new_call(p, $1, $3, 0);
-                    }
-                | primary_value '.' paren_args
-                    {
-                      $$ = new_call(p, $1, intern("call",4), $3);
+                      $$ = new_call(p, $1, $3, 0, tCOLON2);
+                    }
+                | primary_value call_op paren_args
+                    {
+                      $$ = new_call(p, $1, intern("call",4), $3, $2);
                     }
                 | primary_value tCOLON2 paren_args
                     {
-                      $$ = new_call(p, $1, intern("call",4), $3);
+                      $$ = new_call(p, $1, intern("call",4), $3, tCOLON2);
                     }
                 | keyword_super paren_args
@@ -2611,5 +2646,5 @@
                 | primary_value '[' opt_call_args rbracket
                     {
-                      $$ = new_call(p, $1, intern("[]",2), $3);
+                      $$ = new_call(p, $1, intern("[]",2), $3, '.');
                     }
                 ;
@@ -2671,5 +2706,5 @@
                 ;
 
-exc_list        : arg_value
+exc_list        : arg
                     {
                         $$ = list1($1);
@@ -2766,8 +2801,4 @@
                 ;
 
-opt_heredoc_bodies : /* none */
-                   | heredoc_bodies
-                   ;
-
 heredoc_bodies  : heredoc_body
                 | heredoc_bodies heredoc_body
@@ -2825,5 +2856,5 @@
                       $$ = new_sym(p, $1);
                     }
-                | tSYMBEG tSTRING_BEG string_interp tSTRING
+                | tSYMBEG tSTRING_BEG string_rep tSTRING
                     {
                       p->lstate = EXPR_END;
@@ -2925,8 +2956,9 @@
                 | keyword__FILE__
                     {
-                      if (!p->filename) {
-                        p->filename = "(null)";
+                      const char *fn = p->filename;
+                      if (!fn) {
+                        fn = "(null)";
                       }
-                      $$ = new_str(p, p->filename, strlen(p->filename));
+                      $$ = new_str(p, fn, strlen(fn));
                     }
                 | keyword__LINE__
@@ -2955,5 +2987,5 @@
                     {
                       $$ = $3;
-                    } /* 
+                    } /*
                 | error term
                     {
@@ -3098,6 +3130,7 @@
                 ;
 
-f_opt           : f_opt_asgn arg_value
-                    {
+f_opt           : f_opt_asgn arg
+                    {
+                      void_expr_error(p, $2);
                       $$ = cons(nsym($1), $2);
                     }
@@ -3106,4 +3139,5 @@
 f_block_opt     : f_opt_asgn primary_value
                     {
+                      void_expr_error(p, $2);
                       $$ = cons(nsym($1), $2);
                     }
@@ -3179,5 +3213,5 @@
                       }
                       else {
-                        switch ((enum node_type)(int)(intptr_t)$3->car) {
+                        switch ((enum node_type)intn($3->car)) {
                         case NODE_STR:
                         case NODE_DSTR:
@@ -3216,11 +3250,29 @@
                 ;
 
-assoc           : arg_value tASSOC arg_value
-                    {
+assoc           : arg tASSOC arg
+                    {
+                      void_expr_error(p, $1);
+                      void_expr_error(p, $3);
                       $$ = cons($1, $3);
                     }
-                | tLABEL arg_value
-                    {
+                | tLABEL arg
+                    {
+                      void_expr_error(p, $2);
                       $$ = cons(new_sym(p, $1), $2);
+                    }
+                | tLABEL_END arg
+                    {
+                      void_expr_error(p, $2);
+                      $$ = cons(new_sym(p, new_strsym(p, $1)), $2);
+                    }
+                | tSTRING_BEG tLABEL_END arg
+                    {
+                      void_expr_error(p, $3);
+                      $$ = cons(new_sym(p, new_strsym(p, $2)), $3);
+                    }
+                | tSTRING_BEG string_rep tLABEL_END arg
+                    {
+                      void_expr_error(p, $4);
+                      $$ = cons(new_dsym(p, push($2, $3)), $4);
                     }
                 ;
@@ -3246,4 +3298,21 @@
                 ;
 
+call_op         : '.'
+                    {
+                      $$ = '.';
+                    }
+                | tANDDOT
+                    {
+                      $$ = 0;
+                    }
+                ;
+
+call_op2        : call_op
+                | tCOLON2
+                    {
+                      $$ = tCOLON2;
+                    }
+                ;
+
 opt_terms       : /* none */
                 | terms
@@ -3262,9 +3331,10 @@
 trailer         : /* none */
                 | nl
-                | ','
+                | comma
                 ;
 
 term            : ';' {yyerrok;}
                 | nl
+                | heredoc_body
                 ;
 
@@ -3274,8 +3344,8 @@
                       p->column = 0;
                     }
-                  opt_heredoc_bodies
+                ;
 
 terms           : term
-                | terms ';' {yyerrok;}
+                | terms term
                 ;
 
@@ -3286,5 +3356,5 @@
                 ;
 %%
-#define yylval  (*((YYSTYPE*)(p->ylval)))
+#define pylval  (*((YYSTYPE*)(p->ylval)))
 
 static void
@@ -3374,5 +3444,5 @@
 
   if (c == NODE_NTH_REF) {
-    yyerror_i(p, "can't set variable $%d", (int)(intptr_t)n->cdr);
+    yyerror_i(p, "can't set variable $%" MRB_PRId, (mrb_int)(intptr_t)n->cdr);
   }
   else if (c == NODE_BACK_REF) {
@@ -3381,4 +3451,37 @@
   else {
     mrb_bug(p->mrb, "Internal error in backref_error() : n=>car == %S", mrb_fixnum_value(c));
+  }
+}
+
+static void
+void_expr_error(parser_state *p, node *n)
+{
+  int c;
+
+  if (n == NULL) return;
+  c = (int)(intptr_t)n->car;
+  switch (c) {
+  case NODE_BREAK:
+  case NODE_RETURN:
+  case NODE_NEXT:
+  case NODE_REDO:
+  case NODE_RETRY:
+    yyerror(p, "void value expression");
+    break;
+  case NODE_AND:
+  case NODE_OR:
+    void_expr_error(p, n->cdr->car);
+    void_expr_error(p, n->cdr->cdr);
+    break;
+  case NODE_BEGIN:
+    if (n->cdr) {
+      while (n->cdr) {
+        n = n->cdr;
+      }
+      void_expr_error(p, n->car);
+    }
+    break;
+  default:
+    break;
   }
 }
@@ -3469,4 +3572,5 @@
     c0 = nextc(p);
     if (c0 == -1) return c0;    /* do not skip partial EOF */
+    if (c0 >= 0) --p->column;
     list = push(list, (node*)(intptr_t)c0);
   } while(n--);
@@ -3517,5 +3621,5 @@
     for (;;) {
       c = nextc(p);
-      if (c < 0) return c;
+      if (c < 0) return FALSE;
       if (c == '\n') {
         p->lineno++;
@@ -3547,5 +3651,10 @@
 newtok(parser_state *p)
 {
-  p->bidx = 0;
+  if (p->tokbuf != p->buf) {
+    mrb_free(p->mrb, p->tokbuf);
+    p->tokbuf = p->buf;
+    p->tsiz = MRB_PARSER_TOKBUF_SIZE;
+  }
+  p->tidx = 0;
   return p->column - 1;
 }
@@ -3555,5 +3664,5 @@
 {
   char utf8[4];
-  unsigned len;
+  int i, len;
 
   /* mrb_assert(-0x10FFFF <= c && c <= 0xFF); */
@@ -3589,9 +3698,20 @@
     }
   }
-  if (p->bidx+len <= MRB_PARSER_BUF_SIZE) {
-    unsigned i;
-    for (i = 0; i < len; i++) {
-      p->buf[p->bidx++] = utf8[i];
-    }
+  if (p->tidx+len >= p->tsiz) {
+    if (p->tsiz >= MRB_PARSER_TOKBUF_MAX) {
+      p->tidx += len;
+      return;
+    }
+    p->tsiz *= 2;
+    if (p->tokbuf == p->buf) {
+      p->tokbuf = (char*)mrb_malloc(p->mrb, p->tsiz);
+      memcpy(p->tokbuf, p->buf, MRB_PARSER_TOKBUF_SIZE);
+    }
+    else {
+      p->tokbuf = (char*)mrb_realloc(p->mrb, p->tokbuf, p->tsiz);
+    }
+  }
+  for (i = 0; i < len; i++) {
+    p->tokbuf[p->tidx++] = utf8[i];
   }
 }
@@ -3600,5 +3720,5 @@
 toklast(parser_state *p)
 {
-  return p->buf[p->bidx-1];
+  return p->tokbuf[p->tidx-1];
 }
 
@@ -3606,11 +3726,9 @@
 tokfix(parser_state *p)
 {
-  int i = p->bidx, imax = MRB_PARSER_BUF_SIZE - 1;
-
-  if (i > imax) {
-    i = imax;
+  if (p->tidx >= MRB_PARSER_TOKBUF_MAX) {
+    p->tidx = MRB_PARSER_TOKBUF_MAX-1;
     yyerror(p, "string too long (truncated)");
   }
-  p->buf[i] = '\0';
+  p->tokbuf[p->tidx] = '\0';
 }
 
@@ -3618,5 +3736,5 @@
 tok(parser_state *p)
 {
-  return p->buf;
+  return p->tokbuf;
 }
 
@@ -3624,5 +3742,5 @@
 toklen(parser_state *p)
 {
-  return p->bidx;
+  return p->tidx;
 }
 
@@ -3667,4 +3785,42 @@
 
   return retval;
+}
+
+static int32_t
+read_escape_unicode(parser_state *p, int limit)
+{
+  int32_t c;
+  int buf[9];
+  int i;
+
+  /* Look for opening brace */
+  i = 0;
+  buf[0] = nextc(p);
+  if (buf[0] < 0) goto eof;
+  if (ISXDIGIT(buf[0])) {
+    /* \uxxxx form */
+    for (i=1; i<limit; i++) {
+      buf[i] = nextc(p);
+      if (buf[i] < 0) goto eof;
+      if (!ISXDIGIT(buf[i])) {
+        pushback(p, buf[i]);
+        break;
+      }
+    }
+  }
+  else {
+    pushback(p, buf[0]);
+  }
+  c = scan_hex(buf, i, &i);
+  if (i == 0) {
+  eof:
+    yyerror(p, "Invalid escape character syntax");
+    return -1;
+  }
+  if (c < 0 || c > 0x10FFFF || (c & 0xFFFFF800) == 0xD800) {
+    yyerror(p, "Invalid Unicode code point");
+    return -1;
+  }
+  return c;
 }
 
@@ -3741,51 +3897,15 @@
 
   case 'u':     /* Unicode */
-  {
-    int buf[9];
-    int i;
-
-    /* Look for opening brace */
-    i = 0;
-    buf[0] = nextc(p);
-    if (buf[0] < 0) goto eof;
-    if (buf[0] == '{') {
+    if (peek(p, '{')) {
       /* \u{xxxxxxxx} form */
-      for (i=0; i<9; i++) {
-        buf[i] = nextc(p);
-        if (buf[i] < 0) goto eof;
-        if (buf[i] == '}') {
-          break;
-        }
-        else if (!ISXDIGIT(buf[i])) {
-          yyerror(p, "Invalid escape character syntax");
-          pushback(p, buf[i]);
-          return 0;
-        }
-      }
-    }
-    else if (ISXDIGIT(buf[0])) {
-      /* \uxxxx form */
-      for (i=1; i<4; i++) {
-        buf[i] = nextc(p);
-        if (buf[i] < 0) goto eof;
-        if (!ISXDIGIT(buf[i])) {
-          pushback(p, buf[i]);
-          break;
-        }
-      }
+      nextc(p);
+      c = read_escape_unicode(p, 8);
+      if (c < 0) return 0;
+      if (nextc(p) != '}') goto eof;
     }
     else {
-      pushback(p, buf[0]);
-    }
-    c = scan_hex(buf, i, &i);
-    if (i == 0) {
-      yyerror(p, "Invalid escape character syntax");
-      return 0;
-    }
-    if (c < 0 || c > 0x10FFFF || (c & 0xFFFFF800) == 0xD800) {
-      yyerror(p, "Invalid Unicode code point");
-      return 0;
-    }
-  }
+      c = read_escape_unicode(p, 4);
+      if (c < 0) return 0;
+    }
   return -c;
 
@@ -3845,5 +3965,8 @@
   int end = (intptr_t)p->lex_strterm->cdr->cdr->cdr;
   parser_heredoc_info *hinf = (type & STR_FUNC_HEREDOC) ? parsing_heredoc_inf(p) : NULL;
-
+  int cmd_state = p->cmd_start;
+
+  if (beg == 0) beg = -3;       /* should never happen */
+  if (end == 0) end = -3;
   newtok(p);
   while ((c = nextc(p)) != end || nest_level != 0) {
@@ -3867,5 +3990,10 @@
         }
         if ((len-1 == hinf->term_len) && (strncmp(s, hinf->term, len-1) == 0)) {
-          return tHEREDOC_END;
+          if (c < 0) {
+            p->parsing_heredoc = NULL;
+          }
+          else {
+            return tHEREDOC_END;
+          }
         }
       }
@@ -3876,5 +4004,5 @@
         return 0;
       }
-      yylval.nd = new_str(p, tok(p), toklen(p));
+      pylval.nd = new_str(p, tok(p), toklen(p));
       return tHD_STRING_MID;
     }
@@ -3908,4 +4036,18 @@
           tokadd(p, c);
         }
+        else if (c == 'u' && peek(p, '{')) {
+          /* \u{xxxx xxxx xxxx} form */
+          nextc(p);
+          while (1) {
+            do c = nextc(p); while (ISSPACE(c));
+            if (c == '}') break;
+            pushback(p, c);
+            c = read_escape_unicode(p, 8);
+            if (c < 0) break;
+            tokadd(p, -c);
+          }
+          if (hinf)
+            hinf->line_head = FALSE;
+        }
         else {
           pushback(p, c);
@@ -3935,5 +4077,5 @@
         p->lstate = EXPR_BEG;
         p->cmd_start = TRUE;
-        yylval.nd = new_str(p, tok(p), toklen(p));
+        pylval.nd = new_str(p, tok(p), toklen(p));
         if (hinf) {
           hinf->line_head = FALSE;
@@ -3965,7 +4107,11 @@
         pushback(p, c);
         tokfix(p);
-        yylval.nd = new_str(p, tok(p), toklen(p));
+        pylval.nd = new_str(p, tok(p), toklen(p));
         return tSTRING_MID;
       }
+    }
+    if (c == '\n') {
+      p->lineno++;
+      p->column = 0;
     }
     tokadd(p, c);
@@ -3977,5 +4123,5 @@
 
   if (type & STR_FUNC_XQUOTE) {
-    yylval.nd = new_xstr(p, tok(p), toklen(p));
+    pylval.nd = new_xstr(p, tok(p), toklen(p));
     return tXSTRING;
   }
@@ -4019,18 +4165,27 @@
     if (flag > flags) {
       dup = strndup(flags, (size_t)(flag - flags));
-    } else {
+    }
+    else {
       dup = NULL;
     }
     if (enc) {
       encp = strndup(&enc, 1);
-    } else {
+    }
+    else {
       encp = NULL;
     }
-    yylval.nd = new_regx(p, s, dup, encp);
+    pylval.nd = new_regx(p, s, dup, encp);
 
     return tREGEXP;
   }
-
-  yylval.nd = new_str(p, tok(p), toklen(p));
+  pylval.nd = new_str(p, tok(p), toklen(p));
+  if (IS_LABEL_POSSIBLE()) {
+    if (IS_LABEL_SUFFIX(0)) {
+      p->lstate = EXPR_BEG;
+      nextc(p);
+      return tLABEL_END;
+    }
+  }
+
   return tSTRING;
 }
@@ -4102,5 +4257,5 @@
   p->lstate = EXPR_END;
 
-  yylval.nd = newnode;
+  pylval.nd = newnode;
   return tHEREDOC_BEG;
 }
@@ -4206,5 +4361,5 @@
     if ((c = nextc(p)) == '*') {
       if ((c = nextc(p)) == '=') {
-        yylval.id = intern("**",2);
+        pylval.id = intern("**",2);
         p->lstate = EXPR_BEG;
         return tOP_ASGN;
@@ -4215,5 +4370,5 @@
     else {
       if (c == '=') {
-        yylval.id = intern_c('*');
+        pylval.id = intern_c('*');
         p->lstate = EXPR_BEG;
         return tOP_ASGN;
@@ -4331,5 +4486,5 @@
     if (c == '<') {
       if ((c = nextc(p)) == '=') {
-        yylval.id = intern("<<",2);
+        pylval.id = intern("<<",2);
         p->lstate = EXPR_BEG;
         return tOP_ASGN;
@@ -4353,5 +4508,5 @@
     if (c == '>') {
       if ((c = nextc(p)) == '=') {
-        yylval.id = intern(">>",2);
+        pylval.id = intern(">>",2);
         p->lstate = EXPR_BEG;
         return tOP_ASGN;
@@ -4450,5 +4605,5 @@
     }
     tokfix(p);
-    yylval.nd = new_str(p, tok(p), toklen(p));
+    pylval.nd = new_str(p, tok(p), toklen(p));
     p->lstate = EXPR_END;
     return tCHAR;
@@ -4458,5 +4613,5 @@
       p->lstate = EXPR_BEG;
       if ((c = nextc(p)) == '=') {
-        yylval.id = intern("&&",2);
+        pylval.id = intern("&&",2);
         p->lstate = EXPR_BEG;
         return tOP_ASGN;
@@ -4465,6 +4620,10 @@
       return tANDOP;
     }
+    else if (c == '.') {
+      p->lstate = EXPR_DOT;
+      return tANDDOT;
+    }
     else if (c == '=') {
-      yylval.id = intern_c('&');
+      pylval.id = intern_c('&');
       p->lstate = EXPR_BEG;
       return tOP_ASGN;
@@ -4493,5 +4652,5 @@
       p->lstate = EXPR_BEG;
       if ((c = nextc(p)) == '=') {
-        yylval.id = intern("||",2);
+        pylval.id = intern("||",2);
         p->lstate = EXPR_BEG;
         return tOP_ASGN;
@@ -4501,5 +4660,5 @@
     }
     if (c == '=') {
-      yylval.id = intern_c('|');
+      pylval.id = intern_c('|');
       p->lstate = EXPR_BEG;
       return tOP_ASGN;
@@ -4525,5 +4684,5 @@
     }
     if (c == '=') {
-      yylval.id = intern_c('+');
+      pylval.id = intern_c('+');
       p->lstate = EXPR_BEG;
       return tOP_ASGN;
@@ -4553,5 +4712,5 @@
     }
     if (c == '=') {
-      yylval.id = intern_c('-');
+      pylval.id = intern_c('-');
       p->lstate = EXPR_BEG;
       return tOP_ASGN;
@@ -4627,5 +4786,5 @@
         }
         else if (nondigit) goto trailing_uc;
-        yylval.nd = new_int(p, tok(p), 16);
+        pylval.nd = new_int(p, tok(p), 16);
         return tINTEGER;
       }
@@ -4651,5 +4810,5 @@
         }
         else if (nondigit) goto trailing_uc;
-        yylval.nd = new_int(p, tok(p), 2);
+        pylval.nd = new_int(p, tok(p), 2);
         return tINTEGER;
       }
@@ -4675,5 +4834,5 @@
         }
         else if (nondigit) goto trailing_uc;
-        yylval.nd = new_int(p, tok(p), 10);
+        pylval.nd = new_int(p, tok(p), 10);
         return tINTEGER;
       }
@@ -4708,5 +4867,5 @@
           tokfix(p);
           if (nondigit) goto trailing_uc;
-          yylval.nd = new_int(p, tok(p), 8);
+          pylval.nd = new_int(p, tok(p), 8);
           return tINTEGER;
         }
@@ -4725,5 +4884,5 @@
       else {
         pushback(p, c);
-        yylval.nd = new_int(p, "0", 10);
+        pylval.nd = new_int(p, "0", 10);
         return tINTEGER;
       }
@@ -4801,5 +4960,5 @@
 
       errno = 0;
-      d = strtod(tok(p), &endp);
+      d = mrb_float_read(tok(p), &endp);
       if (d == 0 && endp == tok(p)) {
         yywarning_s(p, "corrupted float value %s", tok(p));
@@ -4809,8 +4968,8 @@
         errno = 0;
       }
-      yylval.nd = new_float(p, tok(p));
+      pylval.nd = new_float(p, tok(p));
       return tFLOAT;
     }
-    yylval.nd = new_int(p, tok(p), 10);
+    pylval.nd = new_int(p, tok(p), 10);
     return tINTEGER;
   }
@@ -4854,5 +5013,5 @@
     }
     if ((c = nextc(p)) == '=') {
-      yylval.id = intern_c('/');
+      pylval.id = intern_c('/');
       p->lstate = EXPR_BEG;
       return tOP_ASGN;
@@ -4873,5 +5032,5 @@
   case '^':
     if ((c = nextc(p)) == '=') {
-      yylval.id = intern_c('^');
+      pylval.id = intern_c('^');
       p->lstate = EXPR_BEG;
       return tOP_ASGN;
@@ -5047,5 +5206,5 @@
     }
     if ((c = nextc(p)) == '=') {
-      yylval.id = intern_c('%');
+      pylval.id = intern_c('%');
       p->lstate = EXPR_BEG;
       return tOP_ASGN;
@@ -5101,5 +5260,5 @@
       tokadd(p, c);
       tokfix(p);
-      yylval.id = intern_cstr(tok(p));
+      pylval.id = intern_cstr(tok(p));
       return tGVAR;
 
@@ -5111,5 +5270,5 @@
       gvar:
       tokfix(p);
-      yylval.id = intern_cstr(tok(p));
+      pylval.id = intern_cstr(tok(p));
       return tGVAR;
 
@@ -5123,5 +5282,5 @@
         goto gvar;
       }
-      yylval.nd = new_back_ref(p, c);
+      pylval.nd = new_back_ref(p, c);
       return tBACK_REF;
 
@@ -5142,5 +5301,5 @@
           return 0;
         }
-        yylval.nd = new_nth_ref(p, (int)n);
+        pylval.nd = new_nth_ref(p, (int)n);
       }
       return tNTH_REF;
@@ -5166,5 +5325,5 @@
       }
       if (c < 0) {
-        if (p->bidx == 1) {
+        if (p->tidx == 1) {
           yyerror(p, "incomplete instance variable syntax");
         }
@@ -5175,5 +5334,5 @@
       }
       else if (isdigit(c)) {
-        if (p->bidx == 1) {
+        if (p->tidx == 1) {
           yyerror_i(p, "'@%c' is not allowed as an instance variable name", c);
         }
@@ -5270,5 +5429,5 @@
           nextc(p);
           tokfix(p);
-          yylval.id = intern_cstr(tok(p));
+          pylval.id = intern_cstr(tok(p));
           return tLABEL;
         }
@@ -5281,8 +5440,8 @@
         if (kw) {
           enum mrb_lex_state_enum state = p->lstate;
-          yylval.num = p->lineno;
+          pylval.num = p->lineno;
           p->lstate = kw->state;
           if (state == EXPR_FNAME) {
-            yylval.id = intern_cstr(kw->name);
+            pylval.id = intern_cstr(kw->name);
             return kw->id[0];
           }
@@ -5331,5 +5490,5 @@
       mrb_sym ident = intern_cstr(tok(p));
 
-      yylval.id = ident;
+      pylval.id = ident;
 #if 0
       if (last_state != EXPR_DOT && islower(tok(p)[0]) && lvar_defined(ident)) {
@@ -5396,8 +5555,9 @@
 mrb_parser_parse(parser_state *p, mrbc_context *c)
 {
-  struct mrb_jmpbuf buf;
-  p->jmp = &buf;
+  struct mrb_jmpbuf buf1;
+  p->jmp = &buf1;
 
   MRB_TRY(p->jmp) {
+    int n;
 
     p->cmd_start = TRUE;
@@ -5407,5 +5567,25 @@
 
     parser_init_cxt(p, c);
-    yyparse(p);
+
+    if (p->mrb->jmp) {
+      n = yyparse(p);
+    }
+    else {
+      struct mrb_jmpbuf buf2;
+
+      p->mrb->jmp = &buf2;
+      MRB_TRY(p->mrb->jmp) {
+        n = yyparse(p);
+      }
+      MRB_CATCH(p->mrb->jmp) {
+        p->nerr++;
+      }
+      MRB_END_EXC(p->mrb->jmp);
+      p->mrb->jmp = 0;
+    }
+    if (n != 0 || p->nerr > 0) {
+      p->tree = 0;
+      return;
+    }
     if (!p->tree) {
       p->tree = new_nil(p);
@@ -5415,5 +5595,4 @@
       mrb_parser_dump(p->mrb, p->tree, 0);
     }
-
   }
   MRB_CATCH(p->jmp) {
@@ -5443,5 +5622,5 @@
 
   p->s = p->send = NULL;
-#ifndef MRB_DISBLE_STDIO
+#ifndef MRB_DISABLE_STDIO
   p->f = NULL;
 #endif
@@ -5456,4 +5635,6 @@
   yydebug = 1;
 #endif
+  p->tsiz = MRB_PARSER_TOKBUF_SIZE;
+  p->tokbuf = p->buf;
 
   p->lex_strterm = NULL;
@@ -5470,4 +5651,7 @@
 MRB_API void
 mrb_parser_free(parser_state *p) {
+  if (p->tokbuf != p->buf) {
+    mrb_free(p->mrb, p->tokbuf);
+  }
   mrb_pool_close(p->pool);
 }
@@ -5482,4 +5666,5 @@
 mrbc_context_free(mrb_state *mrb, mrbc_context *cxt)
 {
+  mrb_free(mrb, cxt->filename);
   mrb_free(mrb, cxt->syms);
   mrb_free(mrb, cxt);
@@ -5491,7 +5676,10 @@
   if (s) {
     int len = strlen(s);
-    char *p = (char *)mrb_alloca(mrb, len + 1);
+    char *p = (char *)mrb_malloc(mrb, len + 1);
 
     memcpy(p, s, len + 1);
+    if (c->filename) {
+      mrb_free(mrb, c->filename);
+    }
     c->filename = p;
   }
@@ -5578,6 +5766,6 @@
 }
 
-static mrb_value
-load_exec(mrb_state *mrb, parser_state *p, mrbc_context *c)
+MRB_API mrb_value
+mrb_load_exec(mrb_state *mrb, struct mrb_parser_state *p, mrbc_context *c)
 {
   struct RClass *target = mrb->object_class;
@@ -5601,5 +5789,7 @@
     }
     else {
-      mrb->exc = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, E_SYNTAX_ERROR, "syntax error"));
+      if (mrb->exc == NULL) {
+        mrb->exc = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, E_SYNTAX_ERROR, "syntax error"));
+      }
       mrb_parser_free(p);
       return mrb_undef_value();
@@ -5609,5 +5799,7 @@
   mrb_parser_free(p);
   if (proc == NULL) {
-    mrb->exc = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, E_SCRIPT_ERROR, "codegen error"));
+    if (mrb->exc == NULL) {
+      mrb->exc = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, E_SCRIPT_ERROR, "codegen error"));
+    }
     return mrb_undef_value();
   }
@@ -5629,5 +5821,5 @@
     mrb->c->ci->target_class = target;
   }
-  v = mrb_toplevel_run_keep(mrb, proc, keep);
+  v = mrb_top_run(mrb, proc, mrb_top_self(mrb), keep);
   if (mrb->exc) return mrb_nil_value();
   return v;
@@ -5638,5 +5830,5 @@
 mrb_load_file_cxt(mrb_state *mrb, FILE *f, mrbc_context *c)
 {
-  return load_exec(mrb, mrb_parse_file(mrb, f, c), c);
+  return mrb_load_exec(mrb, mrb_parse_file(mrb, f, c), c);
 }
 
@@ -5651,5 +5843,5 @@
 mrb_load_nstring_cxt(mrb_state *mrb, const char *s, int len, mrbc_context *c)
 {
-  return load_exec(mrb, mrb_parse_nstring(mrb, s, len, c), c);
+  return mrb_load_exec(mrb, mrb_parse_nstring(mrb, s, len, c), c);
 }
 
@@ -5805,8 +5997,7 @@
         dump_recur(mrb, n->car, offset+2);
       }
-      n = n->cdr;
-      if (n) {
+      if (n->cdr) {
         dump_prefix(n, offset+1);
-        printf("blk=&%s\n", mrb_sym2name(mrb, sym(n)));
+        printf("blk=&%s\n", mrb_sym2name(mrb, sym(n->cdr)));
       }
     }
@@ -5946,5 +6137,15 @@
   case NODE_FCALL:
   case NODE_CALL:
-    printf("NODE_CALL:\n");
+  case NODE_SCALL:
+    switch (nodetype) {
+    case NODE_FCALL:
+      printf("NODE_FCALL:\n"); break;
+    case NODE_CALL:
+      printf("NODE_CALL(.):\n"); break;
+    case NODE_SCALL:
+      printf("NODE_SCALL(&.):\n"); break;
+    default:
+      break;
+    }
     mrb_parser_dump(mrb, tree->car, offset+1);
     dump_prefix(tree, offset+1);
@@ -6154,5 +6355,5 @@
 
   case NODE_NTH_REF:
-    printf("NODE_NTH_REF: $%d\n", (int)(intptr_t)tree);
+    printf("NODE_NTH_REF: $%" MRB_PRId "\n", (mrb_int)(intptr_t)tree);
     break;
 
@@ -6206,10 +6407,17 @@
     dump_prefix(tree, offset);
     printf("tail: %s\n", (char*)tree->cdr->cdr->car);
-    dump_prefix(tree, offset);
-    printf("opt: %s\n", (char*)tree->cdr->cdr->cdr);
+    if (tree->cdr->cdr->cdr->car) {
+      dump_prefix(tree, offset);
+      printf("opt: %s\n", (char*)tree->cdr->cdr->cdr->car);
+    }
+    if (tree->cdr->cdr->cdr->cdr) {
+      dump_prefix(tree, offset);
+      printf("enc: %s\n", (char*)tree->cdr->cdr->cdr->cdr);
+    }
     break;
 
   case NODE_SYM:
-    printf("NODE_SYM :%s\n", mrb_sym2name(mrb, sym(tree)));
+    printf("NODE_SYM :%s (%d)\n", mrb_sym2name(mrb, sym(tree)),
+           (int)(intptr_t)tree);
     break;
 
@@ -6425,6 +6633,6 @@
 
   case NODE_HEREDOC:
-    printf("NODE_HEREDOC:\n");
-    mrb_parser_dump(mrb, ((parser_heredoc_info*)tree)->doc, offset+1);
+    printf("NODE_HEREDOC (<<%s):\n", ((parser_heredoc_info*)tree)->term);
+    dump_recur(mrb, ((parser_heredoc_info*)tree)->doc, offset+1);
     break;
 
