parse.y


DEFINITIONS

This source file includes following functions.
  1. yyparse
  2. SIGN_EXTEND_CHAR
  3. SIGN_EXTEND_CHAR
  4. yyerror
  5. yycompile
  6. lex_get_str
  7. lex_getline
  8. rb_compile_string
  9. rb_compile_cstr
  10. rb_compile_file
  11. nextc
  12. pushback
  13. newtok
  14. tokadd
  15. read_escape
  16. tokadd_escape
  17. regx_options
  18. tokadd_string
  19. parse_string
  20. heredoc_identifier
  21. heredoc_restore
  22. whole_match_p
  23. here_document
  24. arg_ambiguous
  25. yylex
  26. rb_node_newnode
  27. nodetype
  28. nodeline
  29. newline_node
  30. fixpos
  31. block_append
  32. list_append
  33. list_concat
  34. literal_concat_string
  35. literal_concat_dstr
  36. literal_concat_list
  37. literal_append
  38. literal_concat
  39. call_op
  40. match_gen
  41. gettable
  42. assignable
  43. aryset
  44. rb_id_attrset
  45. attrset
  46. rb_backref_error
  47. arg_concat
  48. arg_add
  49. node_assign
  50. value_expr
  51. void_expr
  52. void_stmts
  53. assign_in_cond
  54. e_option_supplied
  55. warn_unless_e_option
  56. warning_unless_e_option
  57. range_op
  58. cond0
  59. cond
  60. logop
  61. ret_args
  62. arg_blk_pass
  63. arg_prepend
  64. new_call
  65. new_fcall
  66. new_super
  67. local_push
  68. local_pop
  69. local_tbl
  70. local_append
  71. local_cnt
  72. local_id
  73. top_local_init
  74. top_local_setup
  75. dyna_push
  76. dyna_pop
  77. dyna_in_block
  78. ruby_parser_stack_on_heap
  79. rb_gc_mark_parser
  80. rb_parser_append_print
  81. rb_parser_while_loop
  82. Init_sym
  83. internal_id
  84. rb_intern
  85. rb_id2name
  86. symbols_i
  87. rb_sym_all_symbols
  88. rb_is_const_id
  89. rb_is_class_id
  90. rb_is_instance_id
  91. rb_is_local_id
  92. special_local_set
  93. rb_backref_get
  94. rb_backref_set
  95. rb_lastline_get
  96. rb_lastline_set


   1  /**********************************************************************
   2  
   3    parse.y -
   4  
   5    $Author: nobu $
   6    $Date: 2002/09/10 14:38:20 $
   7    created at: Fri May 28 18:02:42 JST 1993
   8  
   9    Copyright (C) 1993-2002 Yukihiro Matsumoto
  10  
  11  **********************************************************************/
  12  
  13  %{
  14  
  15  #define YYDEBUG 1
  16  
  17  #include "ruby.h"
  18  #include "env.h"
  19  #include "intern.h"
  20  #include "node.h"
  21  #include "st.h"
  22  #include <stdio.h>
  23  #include <errno.h>
  24  #include <ctype.h>
  25  
  26  #define yyparse ruby_yyparse
  27  #define yylex ruby_yylex
  28  #define yyerror ruby_yyerror
  29  #define yylval ruby_yylval
  30  #define yychar ruby_yychar
  31  #define yydebug ruby_yydebug
  32  
  33  #define ID_SCOPE_SHIFT 3
  34  #define ID_SCOPE_MASK 0x07
  35  #define ID_LOCAL    0x01
  36  #define ID_INSTANCE 0x02
  37  #define ID_GLOBAL   0x03
  38  #define ID_ATTRSET  0x04
  39  #define ID_CONST    0x05
  40  #define ID_CLASS    0x06
  41  #define ID_JUNK     0x07
  42  #define ID_INTERNAL ID_JUNK
  43  
  44  #define is_notop_id(id) ((id)>LAST_TOKEN)
  45  #define is_local_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_LOCAL)
  46  #define is_global_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_GLOBAL)
  47  #define is_instance_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_INSTANCE)
  48  #define is_attrset_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_ATTRSET)
  49  #define is_const_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CONST)
  50  #define is_class_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CLASS)
  51  
  52  NODE *ruby_eval_tree_begin = 0;
  53  NODE *ruby_eval_tree = 0;
  54  
  55  char *ruby_sourcefile;          /* current source file */
  56  int   ruby_sourceline;          /* current line no. */
  57  
  58  static int yylex();
  59  static int yyerror();
  60  
  61  static enum lex_state {
  62      EXPR_BEG,                   /* ignore newline, +/- is a sign. */
  63      EXPR_END,                   /* newline significant, +/- is a operator. */
  64      EXPR_ARG,                   /* newline significant, +/- is a operator. */
  65      EXPR_CMDARG,                /* newline significant, +/- is a operator. */
  66      EXPR_ENDARG,                /* newline significant, +/- is a operator. */
  67      EXPR_MID,                   /* newline significant, +/- is a operator. */
  68      EXPR_FNAME,                 /* ignore newline, no reserved words. */
  69      EXPR_DOT,                   /* right after `.' or `::', no reserved words. */
  70      EXPR_CLASS,                 /* immediate after `class', no here document. */
  71  } lex_state;
  72  static NODE *lex_strterm;
  73  static int lex_strnest;
  74  
  75  #ifdef HAVE_LONG_LONG
  76  typedef unsigned LONG_LONG stack_type;
  77  #else
  78  typedef unsigned long stack_type;
  79  #endif
  80  
  81  static stack_type cond_stack = 0;
  82  #define COND_PUSH(n) (cond_stack = (cond_stack<<1)|((n)&1))
  83  #define COND_POP() (cond_stack >>= 1)
  84  #define COND_LEXPOP() do {\
  85      int last = COND_P();\
  86      cond_stack >>= 1;\
  87      if (last) cond_stack |= 1;\
  88  } while (0)
  89  #define COND_P() (cond_stack&1)
  90  
  91  static stack_type cmdarg_stack = 0;
  92  #define CMDARG_PUSH(n) (cmdarg_stack = (cmdarg_stack<<1)|((n)&1))
  93  #define CMDARG_POP() (cmdarg_stack >>= 1)
  94  #define CMDARG_LEXPOP() do {\
  95      int last = CMDARG_P();\
  96      cmdarg_stack >>= 1;\
  97      if (last) cmdarg_stack |= 1;\
  98  } while (0)
  99  #define CMDARG_P() (cmdarg_stack&1)
 100  
 101  static int class_nest = 0;
 102  static int in_single = 0;
 103  static int in_def = 0;
 104  static int compile_for_eval = 0;
 105  static ID cur_mid = 0;
 106  static int quoted_term;
 107  #define quoted_term_char ((unsigned char)quoted_term)
 108  #define WHEN_QUOTED_TERM(x) ((quoted_term >= 0) && (x))
 109  #define QUOTED_TERM_P(c) WHEN_QUOTED_TERM((c) == quoted_term_char)
 110  
 111  static NODE *cond();
 112  static NODE *logop();
 113  
 114  static NODE *newline_node();
 115  static void fixpos();
 116  
 117  static int value_expr();
 118  static void void_expr();
 119  static void void_stmts();
 120  
 121  static NODE *block_append();
 122  static NODE *list_append();
 123  static NODE *list_concat();
 124  static NODE *arg_concat();
 125  static NODE *arg_prepend();
 126  static NODE *literal_concat();
 127  static NODE *literal_append();
 128  static NODE *call_op();
 129  static int in_defined = 0;
 130  
 131  static NODE *ret_args();
 132  static NODE *arg_blk_pass();
 133  static NODE *new_call();
 134  static NODE *new_fcall();
 135  static NODE *new_super();
 136  
 137  static NODE *gettable();
 138  static NODE *assignable();
 139  static NODE *aryset();
 140  static NODE *attrset();
 141  static void rb_backref_error();
 142  static NODE *node_assign();
 143  
 144  static NODE *match_gen();
 145  static void local_push();
 146  static void local_pop();
 147  static int  local_append();
 148  static int  local_cnt();
 149  static int  local_id();
 150  static ID  *local_tbl();
 151  static ID   internal_id();
 152  
 153  static struct RVarmap *dyna_push();
 154  static void dyna_pop();
 155  static int dyna_in_block();
 156  
 157  static void top_local_init();
 158  static void top_local_setup();
 159  
 160  #define RE_OPTION_ONCE 0x80
 161  
 162  #define NODE_STRTERM NODE_ZARRAY        /* nothing to gc */
 163  #define NODE_HEREDOC NODE_ARRAY         /* 1, 3 to gc */
 164  #define nd_func u1.id
 165  #define nd_term u2.id
 166  #define nd_paren u3.id
 167  
 168  %}
 169  
 170  %union {
 171      NODE *node;
 172      ID id;
 173      int num;
 174      struct RVarmap *vars;
 175  }
 176  
 177  %token  kCLASS
 178          kMODULE
 179          kDEF
 180          kUNDEF
 181          kBEGIN
 182          kRESCUE
 183          kENSURE
 184          kEND
 185          kIF
 186          kUNLESS
 187          kTHEN
 188          kELSIF
 189          kELSE
 190          kCASE
 191          kWHEN
 192          kWHILE
 193          kUNTIL
 194          kFOR
 195          kBREAK
 196          kNEXT
 197          kREDO
 198          kRETRY
 199          kIN
 200          kDO
 201          kDO_COND
 202          kDO_BLOCK
 203          kRETURN
 204          kYIELD
 205          kSUPER
 206          kSELF
 207          kNIL
 208          kTRUE
 209          kFALSE
 210          kAND
 211          kOR
 212          kNOT
 213          kIF_MOD
 214          kUNLESS_MOD
 215          kWHILE_MOD
 216          kUNTIL_MOD
 217          kRESCUE_MOD
 218          kALIAS
 219          kDEFINED
 220          klBEGIN
 221          klEND
 222          k__LINE__
 223          k__FILE__
 224  
 225  %token <id>   tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR
 226  %token <node> tINTEGER tFLOAT tSTRING_CONTENT
 227  %token <node> tNTH_REF tBACK_REF
 228  %token <num>  tREGEXP_END
 229  
 230  %type <node> singleton strings string string1 xstring regexp
 231  %type <node> string_contents xstring_contents string_content
 232  %type <node> words qwords word_list qword_list word
 233  %type <node> literal numeric
 234  %type <node> bodystmt compstmt stmts stmt expr arg primary command command_call method_call
 235  %type <node> expr_value arg_value primary_value
 236  %type <node> if_tail opt_else case_body cases opt_rescue exc_list exc_var opt_ensure
 237  %type <node> args when_args call_args call_args2 open_args paren_args opt_paren_args
 238  %type <node> command_args aref_args opt_block_arg block_arg var_ref var_lhs
 239  %type <node> mrhs mrhs_basic superclass block_call block_command
 240  %type <node> f_arglist f_args f_optarg f_opt f_block_arg opt_f_block_arg
 241  %type <node> assoc_list assocs assoc undef_list backref string_dvar
 242  %type <node> block_var opt_block_var brace_block do_block lhs none
 243  %type <node> mlhs mlhs_head mlhs_basic mlhs_entry mlhs_item mlhs_node
 244  %type <id>   fitem variable sym symbol operation operation2 operation3
 245  %type <id>   cname fname op f_rest_arg
 246  %type <num>  f_norm_arg f_arg term_push
 247  %token tUPLUS           /* unary+ */
 248  %token tUMINUS          /* unary- */
 249  %token tPOW             /* ** */
 250  %token tCMP             /* <=> */
 251  %token tEQ              /* == */
 252  %token tEQQ             /* === */
 253  %token tNEQ             /* != */
 254  %token tGEQ             /* >= */
 255  %token tLEQ             /* <= */
 256  %token tANDOP tOROP     /* && and || */
 257  %token tMATCH tNMATCH   /* =~ and !~ */
 258  %token tDOT2 tDOT3      /* .. and ... */
 259  %token tAREF tASET      /* [] and []= */
 260  %token tLSHFT tRSHFT    /* << and >> */
 261  %token tCOLON2          /* :: */
 262  %token tCOLON3          /* :: at EXPR_BEG */
 263  %token <id> tOP_ASGN    /* +=, -=  etc. */
 264  %token tASSOC           /* => */
 265  %token tLPAREN          /* ( */
 266  %token tLPAREN_ARG      /* ( */
 267  %token tRPAREN          /* ) */
 268  %token tLBRACK          /* [ */
 269  %token tLBRACE          /* { */
 270  %token tLBRACE_ARG      /* { */
 271  %token tSTAR            /* * */
 272  %token tAMPER           /* & */
 273  %token tSYMBEG tSTRING_BEG tXSTRING_BEG tREGEXP_BEG tWORDS_BEG tQWORDS_BEG
 274  %token tSTRING_DBEG tSTRING_DVAR tSTRING_END
 275  
 276  /*
 277   *      precedence table
 278   */
 279  
 280  %left  kIF_MOD kUNLESS_MOD kWHILE_MOD kUNTIL_MOD kRESCUE_MOD
 281  %left  kOR kAND
 282  %right kNOT
 283  %nonassoc kDEFINED
 284  %right '=' tOP_ASGN
 285  %right '?' ':'
 286  %nonassoc tDOT2 tDOT3
 287  %left  tOROP
 288  %left  tANDOP
 289  %nonassoc  tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
 290  %left  '>' tGEQ '<' tLEQ
 291  %left  '|' '^'
 292  %left  '&'
 293  %left  tLSHFT tRSHFT
 294  %left  '+' '-'
 295  %left  '*' '/' '%'
 296  %right '!' '~' tUPLUS tUMINUS
 297  %right tPOW
 298  
 299  %token LAST_TOKEN
 300  
 301  %%
 302  program         :  {
 303                          lex_state = EXPR_BEG;
 304                          top_local_init();
 305                          if ((VALUE)ruby_class == rb_cObject) class_nest = 0;
 306                          else class_nest = 1;
 307                      }
 308                    compstmt
 309                      {
 310                          if ($2 && !compile_for_eval) {
 311                              /* last expression should not be void */
 312                              if (nd_type($2) != NODE_BLOCK) void_expr($2);
 313                              else {
 314                                  NODE *node = $2;
 315                                  while (node->nd_next) {
 316                                      node = node->nd_next;
 317                                  }
 318                                  void_expr(node->nd_head);
 319                              }
 320                          }
 321                          ruby_eval_tree = block_append(ruby_eval_tree, $2);
 322                          top_local_setup();
 323                          class_nest = 0;
 324                      }
 325                  ;
 326  
 327  bodystmt        : compstmt
 328                    opt_rescue
 329                    opt_else
 330                    opt_ensure
 331                      {
 332                          $$ = $1;
 333                          if ($2) {
 334                              $$ = NEW_RESCUE($1, $2, $3);
 335                          }
 336                          else if ($3) {
 337                              rb_warn("else without rescue is useless");
 338                              $$ = block_append($$, $3);
 339                          }
 340                          if ($4) {
 341                              $$ = NEW_ENSURE($$, $4);
 342                          }
 343                          fixpos($$, $1);
 344                      }
 345                  ;
 346  
 347  compstmt        : stmts opt_terms
 348                      {
 349                          void_stmts($1);
 350                          $$ = $1;
 351                      }
 352                  ;
 353  
 354  stmts           : none
 355                  | stmt
 356                      {
 357                          $$ = newline_node($1);
 358                      }
 359                  | stmts terms stmt
 360                      {
 361                          $$ = block_append($1, newline_node($3));
 362                      }
 363                  | error stmt
 364                      {
 365                          $$ = $2;
 366                      }
 367                  ;
 368  
 369  stmt            : kALIAS fitem {lex_state = EXPR_FNAME;} fitem
 370                      {
 371                          $$ = NEW_ALIAS($2, $4);
 372                      }
 373                  | kALIAS tGVAR tGVAR
 374                      {
 375                          $$ = NEW_VALIAS($2, $3);
 376                      }
 377                  | kALIAS tGVAR tBACK_REF
 378                      {
 379                          char buf[3];
 380  
 381                          sprintf(buf, "$%c", $3->nd_nth);
 382                          $$ = NEW_VALIAS($2, rb_intern(buf));
 383                      }
 384                  | kALIAS tGVAR tNTH_REF
 385                      {
 386                          yyerror("can't make alias for the number variables");
 387                          $$ = 0;
 388                      }
 389                  | kUNDEF undef_list
 390                      {
 391                          $$ = $2;
 392                      }
 393                  | stmt kIF_MOD expr_value
 394                      {
 395                          $$ = NEW_IF(cond($3), $1, 0);
 396                          fixpos($$, $3);
 397                      }
 398                  | stmt kUNLESS_MOD expr_value
 399                      {
 400                          $$ = NEW_UNLESS(cond($3), $1, 0);
 401                          fixpos($$, $3);
 402                      }
 403                  | stmt kWHILE_MOD expr_value
 404                      {
 405                          if ($1 && nd_type($1) == NODE_BEGIN) {
 406                              $$ = NEW_WHILE(cond($3), $1->nd_body, 0);
 407                          }
 408                          else {
 409                              $$ = NEW_WHILE(cond($3), $1, 1);
 410                          }
 411                      }
 412                  | stmt kUNTIL_MOD expr_value
 413                      {
 414                          if ($1 && nd_type($1) == NODE_BEGIN) {
 415                              $$ = NEW_UNTIL(cond($3), $1->nd_body, 0);
 416                          }
 417                          else {
 418                              $$ = NEW_UNTIL(cond($3), $1, 1);
 419                          }
 420                      }
 421                  | stmt kRESCUE_MOD stmt
 422                      {
 423                          $$ = NEW_RESCUE($1, NEW_RESBODY(0,$3,0), 0);
 424                      }
 425                  | klBEGIN
 426                      {
 427                          if (in_def || in_single) {
 428                              yyerror("BEGIN in method");
 429                          }
 430                          local_push(0);
 431                      }
 432                    '{' compstmt '}'
 433                      {
 434                          ruby_eval_tree_begin = block_append(ruby_eval_tree_begin,
 435                                                              NEW_PREEXE($4));
 436                          local_pop();
 437                          $$ = 0;
 438                      }
 439                  | klEND '{' compstmt '}'
 440                      {
 441                          if (compile_for_eval && (in_def || in_single)) {
 442                              yyerror("END in method; use at_exit");
 443                          }
 444  
 445                          $$ = NEW_ITER(0, NEW_POSTEXE(), $3);
 446                      }
 447                  | lhs '=' command_call
 448                      {
 449                          $$ = node_assign($1, $3);
 450                      }
 451                  | mlhs '=' command_call
 452                      {
 453                          value_expr($3);
 454                          $1->nd_value = $3;
 455                          $$ = $1;
 456                      }
 457                  | var_lhs tOP_ASGN command_call
 458                      {
 459                          value_expr($3);
 460                          if ($1) {
 461                              ID vid = $1->nd_vid;
 462                              if ($2 == tOROP) {
 463                                  $1->nd_value = $3;
 464                                  $$ = NEW_OP_ASGN_OR(gettable(vid), $1);
 465                                  if (is_instance_id(vid)) {
 466                                      $$->nd_aid = vid;
 467                                  }
 468                              }
 469                              else if ($2 == tANDOP) {
 470                                  $1->nd_value = $3;
 471                                  $$ = NEW_OP_ASGN_AND(gettable(vid), $1);
 472                              }
 473                              else {
 474                                  $$ = $1;
 475                                  $$->nd_value = call_op(gettable(vid),$2,1,$3);
 476                              }
 477                          }
 478                          else {
 479                              $$ = 0;
 480                          }
 481                      }
 482                  | primary_value '[' aref_args ']' tOP_ASGN command_call
 483                      {
 484                          NODE *args;
 485  
 486                          value_expr($6);
 487                          args = NEW_LIST($6);
 488                          $3 = list_append($3, NEW_NIL());
 489                          list_concat(args, $3);
 490                          if ($5 == tOROP) {
 491                              $5 = 0;
 492                          }
 493                          else if ($5 == tANDOP) {
 494                              $5 = 1;
 495                          }
 496                          $$ = NEW_OP_ASGN1($1, $5, args);
 497                          fixpos($$, $1);
 498                      }
 499                  | primary_value '.' tIDENTIFIER tOP_ASGN command_call
 500                      {
 501                          value_expr($5);
 502                          if ($4 == tOROP) {
 503                              $4 = 0;
 504                          }
 505                          else if ($4 == tANDOP) {
 506                              $4 = 1;
 507                          }
 508                          $$ = NEW_OP_ASGN2($1, $3, $4, $5);
 509                          fixpos($$, $1);
 510                      }
 511                  | primary_value '.' tCONSTANT tOP_ASGN command_call
 512                      {
 513                          value_expr($5);
 514                          if ($4 == tOROP) {
 515                              $4 = 0;
 516                          }
 517                          else if ($4 == tANDOP) {
 518                              $4 = 1;
 519                          }
 520                          $$ = NEW_OP_ASGN2($1, $3, $4, $5);
 521                          fixpos($$, $1);
 522                      }
 523                  | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call
 524                      {
 525                          value_expr($5);
 526                          if ($4 == tOROP) {
 527                              $4 = 0;
 528                          }
 529                          else if ($4 == tANDOP) {
 530                              $4 = 1;
 531                          }
 532                          $$ = NEW_OP_ASGN2($1, $3, $4, $5);
 533                          fixpos($$, $1);
 534                      }
 535                  | backref tOP_ASGN command_call
 536                      {
 537                          rb_backref_error($1);
 538                          $$ = 0;
 539                      }
 540                  | lhs '=' mrhs_basic
 541                      {
 542                          $$ = node_assign($1, NEW_REXPAND($3));
 543                      }
 544                  | mlhs '=' mrhs
 545                      {
 546                          $1->nd_value = $3;
 547                          $$ = $1;
 548                      }
 549                  | expr
 550                  ;
 551  
 552  expr            : kRETURN call_args
 553                      {
 554                          if (!compile_for_eval && !in_def && !in_single)
 555                              yyerror("return appeared outside of method");
 556                          $$ = NEW_RETURN(ret_args($2));
 557                      }
 558                  | kBREAK call_args
 559                      {
 560                          $$ = NEW_BREAK(ret_args($2));
 561                      }
 562                  | kNEXT call_args
 563                      {
 564                          $$ = NEW_NEXT(ret_args($2));
 565                      }
 566                  | command_call
 567                  | expr kAND expr
 568                      {
 569                          $$ = logop(NODE_AND, $1, $3);
 570                      }
 571                  | expr kOR expr
 572                      {
 573                          $$ = logop(NODE_OR, $1, $3);
 574                      }
 575                  | kNOT expr
 576                      {
 577                          $$ = NEW_NOT(cond($2));
 578                      }
 579                  | '!' command_call
 580                      {
 581                          $$ = NEW_NOT(cond($2));
 582                      }
 583                  | arg
 584                  ;
 585  
 586  expr_value      : expr
 587                      {
 588                          value_expr($$);
 589                          $$ = $1;
 590                      }
 591                  ;
 592  
 593  command_call    : command
 594                  | block_command
 595                  ;
 596  
 597  block_command   : block_call
 598                  | block_call '.' operation2 command_args
 599                      {
 600                          $$ = new_call($1, $3, $4);
 601                      }
 602                  | block_call tCOLON2 operation2 command_args
 603                      {
 604                          $$ = new_call($1, $3, $4);
 605                      }
 606                  ;
 607  
 608  command         : operation command_args
 609                      {
 610                          $$ = new_fcall($1, $2);
 611                          fixpos($$, $2);
 612                     }
 613                  | primary_value '.' operation2 command_args
 614                      {
 615                          $$ = new_call($1, $3, $4);
 616                          fixpos($$, $1);
 617                      }
 618                  | primary_value tCOLON2 operation2 command_args
 619                      {
 620                          $$ = new_call($1, $3, $4);
 621                          fixpos($$, $1);
 622                      }
 623                  | kSUPER command_args
 624                      {
 625                          $$ = new_super($2);
 626                          fixpos($$, $2);
 627                      }
 628                  | kYIELD command_args
 629                      {
 630                          $$ = NEW_YIELD(ret_args($2));
 631                          fixpos($$, $2);
 632                      }
 633                  ;
 634  
 635  mlhs            : mlhs_basic
 636                  | tLPAREN mlhs_entry ')'
 637                      {
 638                          $$ = $2;
 639                      }
 640                  ;
 641  
 642  mlhs_entry      : mlhs_basic
 643                  | tLPAREN mlhs_entry ')'
 644                      {
 645                          $$ = NEW_MASGN(NEW_LIST($2), 0);
 646                      }
 647                  ;
 648  
 649  mlhs_basic      : mlhs_head
 650                      {
 651                          $$ = NEW_MASGN($1, 0);
 652                      }
 653                  | mlhs_head mlhs_item
 654                      {
 655                          $$ = NEW_MASGN(list_append($1,$2), 0);
 656                      }
 657                  | mlhs_head tSTAR mlhs_node
 658                      {
 659                          $$ = NEW_MASGN($1, $3);
 660                      }
 661                  | mlhs_head tSTAR
 662                      {
 663                          $$ = NEW_MASGN($1, -1);
 664                      }
 665                  | tSTAR mlhs_node
 666                      {
 667                          $$ = NEW_MASGN(0, $2);
 668                      }
 669                  | tSTAR
 670                      {
 671                          $$ = NEW_MASGN(0, -1);
 672                      }
 673                  ;
 674  
 675  mlhs_item       : mlhs_node
 676                  | tLPAREN mlhs_entry ')'
 677                      {
 678                          $$ = $2;
 679                      }
 680                  ;
 681  
 682  mlhs_head       : mlhs_item ','
 683                      {
 684                          $$ = NEW_LIST($1);
 685                      }
 686                  | mlhs_head mlhs_item ','
 687                      {
 688                          $$ = list_append($1, $2);
 689                      }
 690                  ;
 691  
 692  mlhs_node       : variable
 693                      {
 694                          $$ = assignable($1, 0);
 695                      }
 696                  | primary_value '[' aref_args ']'
 697                      {
 698                          $$ = aryset($1, $3);
 699                      }
 700                  | primary_value '.' tIDENTIFIER
 701                      {
 702                          $$ = attrset($1, $3);
 703                      }
 704                  | primary_value tCOLON2 tIDENTIFIER
 705                      {
 706                          $$ = attrset($1, $3);
 707                      }
 708                  | primary_value '.' tCONSTANT
 709                      {
 710                          $$ = attrset($1, $3);
 711                      }
 712                  | backref
 713                      {
 714                          rb_backref_error($1);
 715                          $$ = 0;
 716                      }
 717                  ;
 718  
 719  lhs             : variable
 720                      {
 721                          $$ = assignable($1, 0);
 722                      }
 723                  | primary_value '[' aref_args ']'
 724                      {
 725                          $$ = aryset($1, $3);
 726                      }
 727                  | primary_value '.' tIDENTIFIER
 728                      {
 729                          $$ = attrset($1, $3);
 730                      }
 731                  | primary_value tCOLON2 tIDENTIFIER
 732                      {
 733                          $$ = attrset($1, $3);
 734                      }
 735                  | primary_value '.' tCONSTANT
 736                      {
 737                          $$ = attrset($1, $3);
 738                      }
 739                  | backref
 740                      {
 741                          rb_backref_error($1);
 742                          $$ = 0;
 743                      }
 744                  ;
 745  
 746  cname           : tIDENTIFIER
 747                      {
 748                          yyerror("class/module name must be CONSTANT");
 749                      }
 750                  | tCONSTANT
 751                  ;
 752  
 753  fname           : tIDENTIFIER
 754                  | tCONSTANT
 755                  | tFID
 756                  | op
 757                      {
 758                          lex_state = EXPR_END;
 759                          $$ = $1;
 760                      }
 761                  | reswords
 762                      {
 763                          lex_state = EXPR_END;
 764                          $$ = $<id>1;
 765                      }
 766                  ;
 767  
 768  fitem           : fname
 769                  | symbol
 770                  ;
 771  
 772  undef_list      : fitem
 773                      {
 774                          $$ = NEW_UNDEF($1);
 775                      }
 776                  | undef_list ',' {lex_state = EXPR_FNAME;} fitem
 777                      {
 778                          $$ = block_append($1, NEW_UNDEF($4));
 779                      }
 780                  ;
 781  
 782  op              : '|'           { $$ = '|'; }
 783                  | '^'           { $$ = '^'; }
 784                  | '&'           { $$ = '&'; }
 785                  | tCMP          { $$ = tCMP; }
 786                  | tEQ           { $$ = tEQ; }
 787                  | tEQQ          { $$ = tEQQ; }
 788                  | tMATCH        { $$ = tMATCH; }
 789                  | '>'           { $$ = '>'; }
 790                  | tGEQ          { $$ = tGEQ; }
 791                  | '<'           { $$ = '<'; }
 792                  | tLEQ          { $$ = tLEQ; }
 793                  | tLSHFT        { $$ = tLSHFT; }
 794                  | tRSHFT        { $$ = tRSHFT; }
 795                  | '+'           { $$ = '+'; }
 796                  | '-'           { $$ = '-'; }
 797                  | '*'           { $$ = '*'; }
 798                  | tSTAR         { $$ = '*'; }
 799                  | '/'           { $$ = '/'; }
 800                  | '%'           { $$ = '%'; }
 801                  | tPOW          { $$ = tPOW; }
 802                  | '~'           { $$ = '~'; }
 803                  | tUPLUS        { $$ = tUPLUS; }
 804                  | tUMINUS       { $$ = tUMINUS; }
 805                  | tAREF         { $$ = tAREF; }
 806                  | tASET         { $$ = tASET; }
 807                  | '`'           { $$ = '`'; }
 808                  ;
 809  
 810  reswords        : k__LINE__ | k__FILE__  | klBEGIN | klEND
 811                  | kALIAS | kAND | kBEGIN | kBREAK | kCASE | kCLASS | kDEF
 812                  | kDEFINED | kDO | kELSE | kELSIF | kEND | kENSURE | kFALSE
 813                  | kFOR | kIF_MOD | kIN | kMODULE | kNEXT | kNIL | kNOT
 814                  | kOR | kREDO | kRESCUE | kRETRY | kRETURN | kSELF | kSUPER
 815                  | kTHEN | kTRUE | kUNDEF | kUNLESS_MOD | kUNTIL_MOD | kWHEN
 816                  | kWHILE_MOD | kYIELD | kRESCUE_MOD
 817                  ;
 818  
 819  arg             : lhs '=' arg
 820                      {
 821                          $$ = node_assign($1, $3);
 822                      }
 823                  | var_lhs tOP_ASGN arg
 824                      {
 825                          value_expr($3);
 826                          if ($1) {
 827                              ID vid = $1->nd_vid;
 828                              if ($2 == tOROP) {
 829                                  $1->nd_value = $3;
 830                                  $$ = NEW_OP_ASGN_OR(gettable(vid), $1);
 831                                  if (is_instance_id(vid)) {
 832                                      $$->nd_aid = vid;
 833                                  }
 834                              }
 835                              else if ($2 == tANDOP) {
 836                                  $1->nd_value = $3;
 837                                  $$ = NEW_OP_ASGN_AND(gettable(vid), $1);
 838                              }
 839                              else {
 840                                  $$ = $1;
 841                                  $$->nd_value = call_op(gettable(vid),$2,1,$3);
 842                              }
 843                          }
 844                          else {
 845                              $$ = 0;
 846                          }
 847                      }
 848                  | primary_value '[' aref_args ']' tOP_ASGN arg
 849                      {
 850                          NODE *args;
 851  
 852                          value_expr($6);
 853                          args = NEW_LIST($6);
 854                          $3 = list_append($3, NEW_NIL());
 855                          list_concat(args, $3);
 856                          if ($5 == tOROP) {
 857                              $5 = 0;
 858                          }
 859                          else if ($5 == tANDOP) {
 860                              $5 = 1;
 861                          }
 862                          $$ = NEW_OP_ASGN1($1, $5, args);
 863                          fixpos($$, $1);
 864                      }
 865                  | primary_value '.' tIDENTIFIER tOP_ASGN arg
 866                      {
 867                          value_expr($5);
 868                          if ($4 == tOROP) {
 869                              $4 = 0;
 870                          }
 871                          else if ($4 == tANDOP) {
 872                              $4 = 1;
 873                          }
 874                          $$ = NEW_OP_ASGN2($1, $3, $4, $5);
 875                          fixpos($$, $1);
 876                      }
 877                  | primary_value '.' tCONSTANT tOP_ASGN arg
 878                      {
 879                          value_expr($5);
 880                          if ($4 == tOROP) {
 881                              $4 = 0;
 882                          }
 883                          else if ($4 == tANDOP) {
 884                              $4 = 1;
 885                          }
 886                          $$ = NEW_OP_ASGN2($1, $3, $4, $5);
 887                          fixpos($$, $1);
 888                      }
 889                  | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg
 890                      {
 891                          value_expr($5);
 892                          if ($4 == tOROP) {
 893                              $4 = 0;
 894                          }
 895                          else if ($4 == tANDOP) {
 896                              $4 = 1;
 897                          }
 898                          $$ = NEW_OP_ASGN2($1, $3, $4, $5);
 899                          fixpos($$, $1);
 900                      }
 901                  | backref tOP_ASGN arg
 902                      {
 903                          rb_backref_error($1);
 904                          $$ = 0;
 905                      }
 906                  | arg tDOT2 arg
 907                      {
 908                          value_expr($1);
 909                          value_expr($3);
 910                          $$ = NEW_DOT2($1, $3);
 911                      }
 912                  | arg tDOT3 arg
 913                      {
 914                          value_expr($1);
 915                          value_expr($3);
 916                          $$ = NEW_DOT3($1, $3);
 917                      }
 918                  | arg '+' arg
 919                      {
 920                          $$ = call_op($1, '+', 1, $3);
 921                      }
 922                  | arg '-' arg
 923                      {
 924                          $$ = call_op($1, '-', 1, $3);
 925                      }
 926                  | arg '*' arg
 927                      {
 928                          $$ = call_op($1, '*', 1, $3);
 929                      }
 930                  | arg '/' arg
 931                      {
 932                          $$ = call_op($1, '/', 1, $3);
 933                      }
 934                  | arg '%' arg
 935                      {
 936                          $$ = call_op($1, '%', 1, $3);
 937                      }
 938                  | arg tPOW arg
 939                      {
 940                          $$ = call_op($1, tPOW, 1, $3);
 941                      }
 942                  | tUPLUS arg
 943                      {
 944                          if ($2 && nd_type($2) == NODE_LIT) {
 945                              $$ = $2;
 946                          }
 947                          else {
 948                              $$ = call_op($2, tUPLUS, 0, 0);
 949                          }
 950                      }
 951                  | tUMINUS arg
 952                      {
 953                          if ($2 && nd_type($2) == NODE_LIT && FIXNUM_P($2->nd_lit)) {
 954                              long i = FIX2LONG($2->nd_lit);
 955  
 956                              $2->nd_lit = LONG2NUM(-i);
 957                              $$ = $2;
 958                          }
 959                          else {
 960                              $$ = call_op($2, tUMINUS, 0, 0);
 961                          }
 962                      }
 963                  | arg '|' arg
 964                      {
 965                          $$ = call_op($1, '|', 1, $3);
 966                      }
 967                  | arg '^' arg
 968                      {
 969                          $$ = call_op($1, '^', 1, $3);
 970                      }
 971                  | arg '&' arg
 972                      {
 973                          $$ = call_op($1, '&', 1, $3);
 974                      }
 975                  | arg tCMP arg
 976                      {
 977                          $$ = call_op($1, tCMP, 1, $3);
 978                      }
 979                  | arg '>' arg
 980                      {
 981                          $$ = call_op($1, '>', 1, $3);
 982                      }
 983                  | arg tGEQ arg
 984                      {
 985                          $$ = call_op($1, tGEQ, 1, $3);
 986                      }
 987                  | arg '<' arg
 988                      {
 989                          $$ = call_op($1, '<', 1, $3);
 990                      }
 991                  | arg tLEQ arg
 992                      {
 993                          $$ = call_op($1, tLEQ, 1, $3);
 994                      }
 995                  | arg tEQ arg
 996                      {
 997                          $$ = call_op($1, tEQ, 1, $3);
 998                      }
 999                  | arg tEQQ arg
1000                      {
1001                          $$ = call_op($1, tEQQ, 1, $3);
1002                      }
1003                  | arg tNEQ arg
1004                      {
1005                          $$ = NEW_NOT(call_op($1, tEQ, 1, $3));
1006                      }
1007                  | arg tMATCH arg
1008                      {
1009                          $$ = match_gen($1, $3);
1010                      }
1011                  | arg tNMATCH arg
1012                      {
1013                          $$ = NEW_NOT(match_gen($1, $3));
1014                      }
1015                  | '!' arg
1016                      {
1017                          $$ = NEW_NOT(cond($2));
1018                      }
1019                  | '~' arg
1020                      {
1021                          $$ = call_op($2, '~', 0, 0);
1022                      }
1023                  | arg tLSHFT arg
1024                      {
1025                          $$ = call_op($1, tLSHFT, 1, $3);
1026                      }
1027                  | arg tRSHFT arg
1028                      {
1029                          $$ = call_op($1, tRSHFT, 1, $3);
1030                      }
1031                  | arg tANDOP arg
1032                      {
1033                          $$ = logop(NODE_AND, $1, $3);
1034                      }
1035                  | arg tOROP arg
1036                      {
1037                          $$ = logop(NODE_OR, $1, $3);
1038                      }
1039                  | kDEFINED opt_nl {in_defined = 1;} arg
1040                      {
1041                          in_defined = 0;
1042                          $$ = NEW_DEFINED($4);
1043                      }
1044                  | arg '?' arg ':' arg
1045                      {
1046                          $$ = NEW_IF(cond($1), $3, $5);
1047                          fixpos($$, $1);
1048                      }
1049                  | primary
1050                      {
1051                          $$ = $1;
1052                      }
1053                  ;
1054  
1055  arg_value       : arg
1056                      {
1057                          value_expr($1);
1058                          $$ = $1;
1059                      }
1060                  ;
1061  
1062  aref_args       : none
1063                  | command opt_nl
1064                      {
1065                          rb_warn("parenthesize argument(s) for future version");
1066                          $$ = NEW_LIST($1);
1067                      }
1068                  | args trailer
1069                      {
1070                          $$ = $1;
1071                      }
1072                  | args ',' tSTAR arg opt_nl
1073                      {
1074                          value_expr($4);
1075                          $$ = arg_concat($1, $4);
1076                      }
1077                  | assocs trailer
1078                      {
1079                          $$ = NEW_LIST(NEW_HASH($1));
1080                      }
1081                  | tSTAR arg opt_nl
1082                      {
1083                          value_expr($2);
1084                          $$ = NEW_RESTARY($2);
1085                      }
1086                  ;
1087  
1088  paren_args      : '(' none ')'
1089                      {
1090                          $$ = $2;
1091                      }
1092                  | '(' call_args opt_nl ')'
1093                      {
1094                          $$ = $2;
1095                      }
1096                  | '(' block_call opt_nl ')'
1097                      {
1098                          rb_warn("parenthesize argument for future version");
1099                          $$ = NEW_LIST($2);
1100                      }
1101                  | '(' args ',' block_call opt_nl ')'
1102                      {
1103                          rb_warn("parenthesize argument for future version");
1104                          $$ = list_append($2, $4);
1105                      }
1106                  ;
1107  
1108  opt_paren_args  : none
1109                  | paren_args
1110                  ;
1111  
1112  call_args       : command
1113                      {
1114                          rb_warn("parenthesize argument(s) for future version");
1115                          $$ = NEW_LIST($1);
1116                      }
1117                  | args opt_block_arg
1118                      {
1119                          $$ = arg_blk_pass($1, $2);
1120                      }
1121                  | args ',' tSTAR arg_value opt_block_arg
1122                      {
1123                          $$ = arg_concat($1, $4);
1124                          $$ = arg_blk_pass($$, $5);
1125                      }
1126                  | assocs opt_block_arg
1127                      {
1128                          $$ = NEW_LIST(NEW_HASH($1));
1129                          $$ = arg_blk_pass($$, $2);
1130                      }
1131                  | assocs ',' tSTAR arg_value opt_block_arg
1132                      {
1133                          $$ = arg_concat(NEW_LIST(NEW_HASH($1)), $4);
1134                          $$ = arg_blk_pass($$, $5);
1135                      }
1136                  | args ',' assocs opt_block_arg
1137                      {
1138                          $$ = list_append($1, NEW_HASH($3));
1139                          $$ = arg_blk_pass($$, $4);
1140                      }
1141                  | args ',' assocs ',' tSTAR arg opt_block_arg
1142                      {
1143                          value_expr($6);
1144                          $$ = arg_concat(list_append($1, NEW_HASH($3)), $6);
1145                          $$ = arg_blk_pass($$, $7);
1146                      }
1147                  | tSTAR arg_value opt_block_arg
1148                      {
1149                          $$ = arg_blk_pass(NEW_RESTARGS($2), $3);
1150                      }
1151                  | block_arg
1152                  ;
1153  
1154  call_args2      : arg_value ',' args opt_block_arg
1155                      {
1156                          $$ = arg_blk_pass(list_concat(NEW_LIST($1),$3), $4);
1157                      }
1158                  | arg_value ',' block_arg
1159                      {
1160                          $$ = arg_blk_pass($1, $3);
1161                      }
1162                  | arg_value ',' tSTAR arg_value opt_block_arg
1163                      {
1164                          $$ = arg_concat(NEW_LIST($1), $4);
1165                          $$ = arg_blk_pass($$, $5);
1166                      }
1167                  | arg_value ',' args ',' tSTAR arg_value opt_block_arg
1168                      {
1169                          $$ = arg_concat(list_concat($1,$3), $6);
1170                          $$ = arg_blk_pass($$, $7);
1171                      }
1172                  | assocs opt_block_arg
1173                      {
1174                          $$ = NEW_LIST(NEW_HASH($1));
1175                          $$ = arg_blk_pass($$, $2);
1176                      }
1177                  | assocs ',' tSTAR arg_value opt_block_arg
1178                      {
1179                          $$ = arg_concat(NEW_LIST(NEW_HASH($1)), $4);
1180                          $$ = arg_blk_pass($$, $5);
1181                      }
1182                  | arg_value ',' assocs opt_block_arg
1183                      {
1184                          $$ = list_append(NEW_LIST($1), NEW_HASH($3));
1185                          $$ = arg_blk_pass($$, $4);
1186                      }
1187                  | arg_value ',' args ',' assocs opt_block_arg
1188                      {
1189                          $$ = list_append(list_concat(NEW_LIST($1),$3), NEW_HASH($5));
1190                          $$ = arg_blk_pass($$, $6);
1191                      }
1192                  | arg_value ',' assocs ',' tSTAR arg_value opt_block_arg
1193                      {
1194                          $$ = arg_concat(list_append(NEW_LIST($1), NEW_HASH($3)), $6);
1195                          $$ = arg_blk_pass($$, $7);
1196                      }
1197                  | arg_value ',' args ',' assocs ',' tSTAR arg_value opt_block_arg
1198                      {
1199                          $$ = arg_concat(list_append(list_concat(NEW_LIST($1), $3), NEW_HASH($5)), $8);
1200                          $$ = arg_blk_pass($$, $9);
1201                      }
1202                  | tSTAR arg_value opt_block_arg
1203                      {
1204                          $$ = arg_blk_pass(NEW_RESTARGS($2), $3);
1205                      }
1206                  | block_arg
1207                  ;
1208  
1209  command_args    :  {
1210                          $<num>$ = cmdarg_stack;
1211                          CMDARG_PUSH(1);
1212                      }
1213                    open_args
1214                      {
1215                          /* CMDARG_POP() */
1216                          cmdarg_stack = $<num>1;
1217                          $$ = $2;
1218                      }
1219                  ;
1220  
1221  open_args       : call_args
1222                  | tLPAREN_ARG  {lex_state = EXPR_ENDARG;} ')'
1223                      {
1224                          rb_warning("%s (...) interpreted as method call",
1225                                     rb_id2name($<id>1));
1226                          $$ = 0;
1227                      }
1228                  | tLPAREN_ARG call_args2 {lex_state = EXPR_ENDARG;} ')'
1229                      {
1230                          rb_warning("%s (...) interpreted as method call",
1231                                     rb_id2name($<id>1));
1232                          $$ = $2;
1233                      }
1234                  ;
1235  
1236  block_arg       : tAMPER arg_value
1237                      {
1238                          $$ = NEW_BLOCK_PASS($2);
1239                      }
1240                  ;
1241  
1242  opt_block_arg   : ',' block_arg
1243                      {
1244                          $$ = $2;
1245                      }
1246                  | none
1247                  ;
1248  
1249  args            : arg_value
1250                      {
1251                          $$ = NEW_LIST($1);
1252                      }
1253                  | args ',' arg_value
1254                      {
1255                          $$ = list_append($1, $3);
1256                      }
1257                  ;
1258  
1259  mrhs            : arg_value
1260                      {
1261                          $$ = $1;
1262                      }
1263                  | mrhs_basic
1264                      {
1265                          $$ = NEW_REXPAND($1);
1266                      }
1267                  ;
1268  
1269  mrhs_basic      : args ',' arg_value
1270                      {
1271                          $$ = list_append($1, $3);
1272                      }
1273                  | args ',' tSTAR arg_value
1274                      {
1275                          $$ = arg_concat($1, $4);
1276                      }
1277                  | tSTAR arg_value
1278                      {
1279                          $$ = $2;
1280                      }
1281                  ;
1282  
1283  primary         : literal
1284                  | strings
1285                  | xstring
1286                  | regexp
1287                  | words
1288                  | qwords
1289                  | var_ref
1290                  | backref
1291                  | tFID
1292                      {
1293                          $$ = NEW_VCALL($1);
1294                      }
1295                  | kBEGIN
1296                    bodystmt
1297                    kEND
1298                      {
1299                          $$ = NEW_BEGIN($2);
1300                      }
1301                  | tLPAREN_ARG expr {lex_state = EXPR_ENDARG;} ')'
1302                      {
1303                          rb_warning("(...) interpreted as grouped expression");
1304                          $$ = $2;
1305                      }
1306                  | tLPAREN compstmt ')'
1307                      {
1308                          $$ = $2;
1309                      }
1310                  | primary_value tCOLON2 tCONSTANT
1311                      {
1312                          $$ = NEW_COLON2($1, $3);
1313                      }
1314                  | tCOLON3 cname
1315                      {
1316                          $$ = NEW_COLON3($2);
1317                      }
1318                  | primary_value '[' aref_args ']'
1319                      {
1320                          $$ = NEW_CALL($1, tAREF, $3);
1321                      }
1322                  | tLBRACK aref_args ']'
1323                      {
1324                          if ($2 == 0) {
1325                              $$ = NEW_ZARRAY(); /* zero length array*/
1326                          }
1327                          else {
1328                              $$ = $2;
1329                          }
1330                      }
1331                  | tLBRACE assoc_list '}'
1332                      {
1333                          $$ = NEW_HASH($2);
1334                      }
1335                  | kRETURN
1336                      {
1337                          if (!compile_for_eval && !in_def && !in_single)
1338                              yyerror("return appeared outside of method");
1339                          $$ = NEW_RETURN(0);
1340                      }
1341                  | kYIELD '(' call_args ')'
1342                      {
1343                          $$ = NEW_YIELD(ret_args($3));
1344                      }
1345                  | kYIELD '(' ')'
1346                      {
1347                          $$ = NEW_YIELD(0);
1348                      }
1349                  | kYIELD
1350                      {
1351                          $$ = NEW_YIELD(0);
1352                      }
1353                  | kDEFINED opt_nl '(' {in_defined = 1;} expr ')'
1354                      {
1355                          in_defined = 0;
1356                          $$ = NEW_DEFINED($5);
1357                      }
1358                  | operation brace_block
1359                      {
1360                          $2->nd_iter = NEW_FCALL($1, 0);
1361                          $$ = $2;
1362                      }
1363                  | method_call
1364                  | method_call brace_block
1365                      {
1366                          if ($1 && nd_type($1) == NODE_BLOCK_PASS) {
1367                              rb_compile_error("both block arg and actual block given");
1368                          }
1369                          $2->nd_iter = $1;
1370                          $$ = $2;
1371                          fixpos($$, $1);
1372                      }
1373                  | kIF expr_value then
1374                    compstmt
1375                    if_tail
1376                    kEND
1377                      {
1378                          $$ = NEW_IF(cond($2), $4, $5);
1379                          fixpos($$, $2);
1380                      }
1381                  | kUNLESS expr_value then
1382                    compstmt
1383                    opt_else
1384                    kEND
1385                      {
1386                          $$ = NEW_UNLESS(cond($2), $4, $5);
1387                          fixpos($$, $2);
1388                      }
1389                  | kWHILE {COND_PUSH(1);} expr_value do {COND_POP();}
1390                    compstmt
1391                    kEND
1392                      {
1393                          $$ = NEW_WHILE(cond($3), $6, 1);
1394                          fixpos($$, $3);
1395                      }
1396                  | kUNTIL {COND_PUSH(1);} expr_value do {COND_POP();} 
1397                    compstmt
1398                    kEND
1399                      {
1400                          $$ = NEW_UNTIL(cond($3), $6, 1);
1401                          fixpos($$, $3);
1402                      }
1403                  | kCASE expr_value opt_terms
1404                    case_body
1405                    kEND
1406                      {
1407                          $$ = NEW_CASE($2, $4);
1408                          fixpos($$, $2);
1409                      }
1410                  | kCASE opt_terms case_body kEND
1411                      {
1412                          $$ = $3;
1413                      }
1414                  | kFOR block_var kIN {COND_PUSH(1);} expr_value do {COND_POP();}
1415                    compstmt
1416                    kEND
1417                      {
1418                          $$ = NEW_FOR($2, $5, $8);
1419                          fixpos($$, $2);
1420                      }
1421                  | kCLASS cname superclass
1422                      {
1423                          if (in_def || in_single)
1424                              yyerror("class definition in method body");
1425                          class_nest++;
1426                          local_push(0);
1427                          $<num>$ = ruby_sourceline;
1428                      }
1429                    bodystmt
1430                    kEND
1431                      {
1432                          $$ = NEW_CLASS($2, $5, $3);
1433                          nd_set_line($$, $<num>4);
1434                          local_pop();
1435                          class_nest--;
1436                      }
1437                  | kCLASS tLSHFT expr
1438                      {
1439                          $<num>$ = in_def;
1440                          in_def = 0;
1441                      }
1442                    term
1443                      {
1444                          $<num>$ = in_single;
1445                          in_single = 0;
1446                          class_nest++;
1447                          local_push(0);
1448                      }
1449                    bodystmt
1450                    kEND
1451                      {
1452                          $$ = NEW_SCLASS($3, $7);
1453                          fixpos($$, $3);
1454                          local_pop();
1455                          class_nest--;
1456                          in_def = $<num>4;
1457                          in_single = $<num>6;
1458                      }
1459                  | kMODULE cname
1460                      {
1461                          if (in_def || in_single)
1462                              yyerror("module definition in method body");
1463                          class_nest++;
1464                          local_push(0);
1465                          $<num>$ = ruby_sourceline;
1466                      }
1467                    bodystmt
1468                    kEND
1469                      {
1470                          $$ = NEW_MODULE($2, $4);
1471                          nd_set_line($$, $<num>3);
1472                          local_pop();
1473                          class_nest--;
1474                      }
1475                  | kDEF fname
1476                      {
1477                          $<id>$ = cur_mid;
1478                          cur_mid = $2;
1479                          in_def++;
1480                          local_push(0);
1481                      }
1482                    f_arglist
1483                    bodystmt
1484                    kEND
1485                      {
1486                          /* NOEX_PRIVATE for toplevel */
1487                          $$ = NEW_DEFN($2, $4, $5, class_nest?NOEX_PUBLIC:NOEX_PRIVATE);
1488                          if (is_attrset_id($2)) $$->nd_noex = NOEX_PUBLIC;
1489                          fixpos($$, $4);
1490                          local_pop();
1491                          in_def--;
1492                          cur_mid = $<id>3;
1493                      }
1494                  | kDEF singleton dot_or_colon {lex_state = EXPR_FNAME;} fname
1495                      {
1496                          in_single++;
1497                          local_push(0);
1498                          lex_state = EXPR_END; /* force for args */
1499                      }
1500                    f_arglist
1501                    bodystmt
1502                    kEND
1503                      {
1504                          $$ = NEW_DEFS($2, $5, $7, $8);
1505                          fixpos($$, $2);
1506                          local_pop();
1507                          in_single--;
1508                      }
1509                  | kBREAK
1510                      {
1511                          $$ = NEW_BREAK(0);
1512                      }
1513                  | kNEXT
1514                      {
1515                          $$ = NEW_NEXT(0);
1516                      }
1517                  | kREDO
1518                      {
1519                          $$ = NEW_REDO();
1520                      }
1521                  | kRETRY
1522                      {
1523                          $$ = NEW_RETRY();
1524                      }
1525                  ;
1526  
1527  primary_value   : primary
1528                      {
1529                          value_expr($1);
1530                          $$ = $1;
1531                      }
1532                  ;
1533  
1534  then            : term
1535                  | kTHEN
1536                  | term kTHEN
1537                  ;
1538  
1539  do              : term
1540                  | kDO_COND
1541                  ;
1542  
1543  if_tail         : opt_else
1544                  | kELSIF expr_value then
1545                    compstmt
1546                    if_tail
1547                      {
1548                          $$ = NEW_IF(cond($2), $4, $5);
1549                          fixpos($$, $2);
1550                      }
1551                  ;
1552  
1553  opt_else        : none
1554                  | kELSE compstmt
1555                      {
1556                          $$ = $2;
1557                      }
1558                  ;
1559  
1560  block_var       : lhs
1561                  | mlhs
1562                  ;
1563  
1564  opt_block_var   : none
1565                  | '|' /* none */ '|'
1566                      {
1567                          $$ = (NODE*)1;
1568                      }
1569                  | tOROP
1570                      {
1571                          $$ = (NODE*)1;
1572                      }
1573                  | '|' block_var '|'
1574                      {
1575                          $$ = $2;
1576                      }
1577                  ;
1578  
1579  do_block        : kDO_BLOCK
1580                      {
1581                          $<vars>$ = dyna_push();
1582                      }
1583                    opt_block_var
1584                    compstmt
1585                    kEND
1586                      {
1587                          $$ = NEW_ITER($3, 0, $4);
1588                          fixpos($$, $3?$3:$4);
1589                          dyna_pop($<vars>2);
1590                      }
1591                  | tLBRACE_ARG {$<vars>$ = dyna_push();}
1592                    opt_block_var
1593                    compstmt
1594                    '}'
1595                      {
1596                          $$ = NEW_ITER($3, 0, $4);
1597                          fixpos($$, $3?$3:$4);
1598                          dyna_pop($<vars>2);
1599                      }
1600  
1601                  ;
1602  
1603  block_call      : command do_block
1604                      {
1605                          if ($1 && nd_type($1) == NODE_BLOCK_PASS) {
1606                              rb_compile_error("both block arg and actual block given");
1607                          }
1608                          $2->nd_iter = $1;
1609                          $$ = $2;
1610                          fixpos($$, $2);
1611                      }
1612                  | block_call '.' operation2 opt_paren_args
1613                      {
1614                          $$ = new_call($1, $3, $4);
1615                      }
1616                  | block_call tCOLON2 operation2 opt_paren_args
1617                      {
1618                          $$ = new_call($1, $3, $4);
1619                      }
1620                  ;
1621  
1622  method_call     : operation paren_args
1623                      {
1624                          $$ = new_fcall($1, $2);
1625                          fixpos($$, $2);
1626                      }
1627                  | primary_value '.' operation2 opt_paren_args
1628                      {
1629                          $$ = new_call($1, $3, $4);
1630                          fixpos($$, $1);
1631                      }
1632                  | primary_value tCOLON2 operation2 paren_args
1633                      {
1634                          $$ = new_call($1, $3, $4);
1635                          fixpos($$, $1);
1636                      }
1637                  | primary_value tCOLON2 operation3
1638                      {
1639                          $$ = new_call($1, $3, 0);
1640                      }
1641                  | kSUPER paren_args
1642                      {
1643                          $$ = new_super($2);
1644                      }
1645                  | kSUPER
1646                      {
1647                          $$ = NEW_ZSUPER();
1648                      }
1649                  ;
1650  
1651  brace_block     : '{'
1652                      {
1653                          $<vars>$ = dyna_push();
1654                      }
1655                    opt_block_var
1656                    compstmt '}'
1657                      {
1658                          $$ = NEW_ITER($3, 0, $4);
1659                          fixpos($$, $4);
1660                          dyna_pop($<vars>2);
1661                      }
1662                  | kDO
1663                      {
1664                          $<vars>$ = dyna_push();
1665                      }
1666                    opt_block_var
1667                    compstmt kEND
1668                      {
1669                          $$ = NEW_ITER($3, 0, $4);
1670                          fixpos($$, $4);
1671                          dyna_pop($<vars>2);
1672                      }
1673                  ;
1674  
1675  case_body       : kWHEN when_args then
1676                    compstmt
1677                    cases
1678                      {
1679                          $$ = NEW_WHEN($2, $4, $5);
1680                      }
1681                  ;
1682  
1683  when_args       : args
1684                  | args ',' tSTAR arg_value
1685                      {
1686                          $$ = list_append($1, NEW_WHEN($4, 0, 0));
1687                      }
1688                  | tSTAR arg_value
1689                      {
1690                          $$ = NEW_LIST(NEW_WHEN($2, 0, 0));
1691                      }
1692                  ;
1693  
1694  cases           : opt_else
1695                  | case_body
1696                  ;
1697  
1698  opt_rescue      : kRESCUE exc_list exc_var then
1699                    compstmt
1700                    opt_rescue
1701                      {
1702                          if ($3) {
1703                              $3 = node_assign($3, NEW_GVAR(rb_intern("$!")));
1704                              $5 = block_append($3, $5);
1705                          }
1706                          $$ = NEW_RESBODY($2, $5, $6);
1707                          fixpos($$, $2?$2:$5);
1708                      }
1709                  | none
1710                  ;
1711  
1712  exc_list        : args
1713                  | none
1714                  ;
1715  
1716  exc_var         : tASSOC lhs
1717                      {
1718                          $$ = $2;
1719                      }
1720                  | none
1721                  ;
1722  
1723  opt_ensure      : kENSURE compstmt
1724                      {
1725                          if ($2)
1726                              $$ = $2;
1727                          else
1728                              /* place holder */
1729                              $$ = NEW_NIL();
1730                      }
1731                  | none
1732                  ;
1733  
1734  literal         : numeric
1735                  | symbol
1736                      {
1737                          $$ = NEW_LIT(ID2SYM($1));
1738                      }
1739                  ;
1740  
1741  strings         : string
1742                      {
1743                          NODE *node = $1;
1744                          if (!node) {
1745                              node = NEW_STR(rb_str_new(0, 0));
1746                          }
1747                          else {
1748                              switch (nd_type(node)) {
1749                                case NODE_STR: case NODE_DSTR:
1750                                  break;
1751                                default:
1752                                  node = rb_node_newnode(NODE_DSTR, rb_str_new(0, 0),
1753                                                         1, NEW_LIST(node));
1754                                  break;
1755                              }
1756                          }
1757                          $$ = node;
1758                      }
1759                  ;
1760  
1761  string          : string1
1762                  | string string1
1763                      {
1764                          $$ = literal_concat($1, $2);
1765                      }
1766                  ;
1767  
1768  string1         : tSTRING_BEG string_contents tSTRING_END
1769                      {
1770                          $$ = $2;
1771                      }
1772                  ;
1773  
1774  xstring         : tXSTRING_BEG xstring_contents tSTRING_END
1775                      {
1776                          NODE *node = $2;
1777                          if (!node) {
1778                              node = NEW_XSTR(rb_str_new(0, 0));
1779                          }
1780                          else {
1781                              switch (nd_type(node)) {
1782                                case NODE_STR:
1783                                  nd_set_type(node, NODE_XSTR);
1784                                  break;
1785                                case NODE_DSTR:
1786                                  nd_set_type(node, NODE_DXSTR);
1787                                  break;
1788                                default:
1789                                  node = rb_node_newnode(NODE_DXSTR, rb_str_new(0, 0),
1790                                                         1, NEW_LIST(node));
1791                                  break;
1792                              }
1793                          }
1794                          $$ = node;
1795                      }
1796                  ;
1797  
1798  regexp          : tREGEXP_BEG xstring_contents tREGEXP_END
1799                      {
1800                          int options = $3;
1801                          NODE *node = $2;
1802                          if (!node) {
1803                              node = NEW_LIT(rb_reg_new("", 0, options & ~RE_OPTION_ONCE));
1804                          }
1805                          else switch (nd_type(node)) {
1806                            case NODE_STR:
1807                              {
1808                                  VALUE src = node->nd_lit;
1809                                  nd_set_type(node, NODE_LIT);
1810                                  node->nd_lit = rb_reg_new(RSTRING(src)->ptr,
1811                                                            RSTRING(src)->len,
1812                                                            options & ~RE_OPTION_ONCE);
1813                              }
1814                              break;
1815                            default:
1816                              node = rb_node_newnode(NODE_DSTR, rb_str_new(0, 0),
1817                                                     1, NEW_LIST(node));
1818                            case NODE_DSTR:
1819                              if (options & RE_OPTION_ONCE) {
1820                                  nd_set_type(node, NODE_DREGX_ONCE);
1821                              }
1822                              else {
1823                                  nd_set_type(node, NODE_DREGX);
1824                              }
1825                              node->nd_cflag = options & ~RE_OPTION_ONCE;
1826                              break;
1827                          }
1828                          $$ = node;
1829                      }
1830                  ;
1831  
1832  words           : tWORDS_BEG ' ' tSTRING_END
1833                      {
1834                          $$ = NEW_ZARRAY();
1835                      }
1836                  | tWORDS_BEG word_list tSTRING_END
1837                      {
1838                          $$ = $2;
1839                      }
1840                  ;
1841  
1842  word_list       : /* none */
1843                      {
1844                          lex_strnest = 0;
1845                          $$ = 0;
1846                      }
1847                  | word_list word ' '
1848                      {
1849                          $$ = list_append($1, $2);
1850                      }
1851                  ;
1852  
1853  word            : string_content
1854                  | word string_content
1855                      {
1856                          $$ = literal_concat($1, $2);
1857                      }
1858                  ;
1859  
1860  qwords          : tQWORDS_BEG ' ' tSTRING_END
1861                      {
1862                          $$ = NEW_ZARRAY();
1863                      }
1864                  | tQWORDS_BEG qword_list tSTRING_END
1865                      {
1866                          $$ = $2;
1867                      }
1868                  ;
1869  
1870  qword_list      : /* none */
1871                      {
1872                          lex_strnest = 0;
1873                          $$ = 0;
1874                      }
1875                  | qword_list tSTRING_CONTENT ' '
1876                      {
1877                          $$ = list_append($1, $2);
1878                      }
1879                  ;
1880  
1881  string_contents : /* none */
1882                      {
1883                          lex_strnest = 0;
1884                          $$ = 0;
1885                      }
1886                  | string_contents string_content
1887                      {
1888                          $$ = literal_concat($1, $2);
1889                      }
1890                  ;
1891  
1892  xstring_contents: /* none */
1893                      {
1894                          lex_strnest = 0;
1895                          $$ = 0;
1896                      }
1897                  | xstring_contents string_content
1898                      {
1899                          $$ = literal_append($1, $2);
1900                      }
1901                  ;
1902  
1903  string_content  : tSTRING_CONTENT
1904                  | tSTRING_DVAR
1905                      {
1906                          $<num>1 = lex_strnest;
1907                          $<node>$ = lex_strterm;
1908                          lex_strterm = 0;
1909                          lex_state = EXPR_BEG;
1910                      }
1911                    string_dvar
1912                      {
1913                          lex_strnest = $<num>1;
1914                          lex_strterm = $<node>2;
1915                          $$ = NEW_EVSTR($3);
1916                      }
1917                  | tSTRING_DBEG term_push
1918                      {
1919                          $<num>1 = lex_strnest;
1920                          $<node>$ = lex_strterm;
1921                          lex_strterm = 0;
1922                          lex_state = EXPR_BEG;
1923                      }
1924                    compstmt '}'
1925                      {
1926                          lex_strnest = $<num>1;
1927                          quoted_term = $2;
1928                          lex_strterm = $<node>3;
1929                          if (($$ = $4) && nd_type($$) == NODE_NEWLINE) {
1930                              $$ = $$->nd_next;
1931                              rb_gc_force_recycle((VALUE)$4);
1932                          }
1933                          $$ = NEW_EVSTR($$);
1934                      }
1935                  ;
1936  
1937  string_dvar     : tGVAR {$$ = NEW_GVAR($1);}
1938                  | tIVAR {$$ = NEW_IVAR($1);}
1939                  | tCVAR {$$ = NEW_CVAR($1);}
1940                  | backref
1941                  ;
1942  
1943  term_push       : /* none */
1944                      {
1945                          if (($$ = quoted_term) == -1 &&
1946                              nd_type(lex_strterm) == NODE_STRTERM &&
1947                              !lex_strterm->nd_paren) {
1948                              quoted_term = lex_strterm->nd_term;
1949                          }
1950                      }
1951                  ;
1952  
1953  symbol          : tSYMBEG sym
1954                      {
1955                          lex_state = EXPR_END;
1956                          $$ = $2;
1957                      }
1958                  ;
1959  
1960  sym             : fname
1961                  | tIVAR
1962                  | tGVAR
1963                  | tCVAR
1964                  ;
1965  
1966  numeric         : tINTEGER
1967                  | tFLOAT
1968                  ;
1969  
1970  variable        : tIDENTIFIER
1971                  | tIVAR
1972                  | tGVAR
1973                  | tCONSTANT
1974                  | tCVAR
1975                  | kNIL {$$ = kNIL;}
1976                  | kSELF {$$ = kSELF;}
1977                  | kTRUE {$$ = kTRUE;}
1978                  | kFALSE {$$ = kFALSE;}
1979                  | k__FILE__ {$$ = k__FILE__;}
1980                  | k__LINE__ {$$ = k__LINE__;}
1981                  ;
1982  
1983  var_ref         : variable
1984                      {
1985                          $$ = gettable($1);
1986                      }
1987                  ;
1988  
1989  var_lhs         : variable
1990                      {
1991                          $$ = assignable($1, 0);
1992                      }
1993                  ;
1994  
1995  backref         : tNTH_REF
1996                  | tBACK_REF
1997                  ;
1998  
1999  superclass      : term
2000                      {
2001                          $$ = 0;
2002                      }
2003                  | '<'
2004                      {
2005                          lex_state = EXPR_BEG;
2006                      }
2007                    expr_value term
2008                      {
2009                          $$ = $3;
2010                      }
2011                  | error term {yyerrok; $$ = 0;}
2012                  ;
2013  
2014  f_arglist       : '(' f_args opt_nl ')'
2015                      {
2016                          $$ = $2;
2017                          lex_state = EXPR_BEG;
2018                      }
2019                  | f_args term
2020                      {
2021                          $$ = $1;
2022                      }
2023                  ;
2024  
2025  f_args          : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg
2026                      {
2027                          $$ = block_append(NEW_ARGS($1, $3, $5), $6);
2028                      }
2029                  | f_arg ',' f_optarg opt_f_block_arg
2030                      {
2031                          $$ = block_append(NEW_ARGS($1, $3, -1), $4);
2032                      }
2033                  | f_arg ',' f_rest_arg opt_f_block_arg
2034                      {
2035                          $$ = block_append(NEW_ARGS($1, 0, $3), $4);
2036                      }
2037                  | f_arg opt_f_block_arg
2038                      {
2039                          $$ = block_append(NEW_ARGS($1, 0, -1), $2);
2040                      }
2041                  | f_optarg ',' f_rest_arg opt_f_block_arg
2042                      {
2043                          $$ = block_append(NEW_ARGS(0, $1, $3), $4);
2044                      }
2045                  | f_optarg opt_f_block_arg
2046                      {
2047                          $$ = block_append(NEW_ARGS(0, $1, -1), $2);
2048                      }
2049                  | f_rest_arg opt_f_block_arg
2050                      {
2051                          $$ = block_append(NEW_ARGS(0, 0, $1), $2);
2052                      }
2053                  | f_block_arg
2054                      {
2055                          $$ = block_append(NEW_ARGS(0, 0, -1), $1);
2056                      }
2057                  | /* none */
2058                      {
2059                          $$ = NEW_ARGS(0, 0, -1);
2060                      }
2061                  ;
2062  
2063  f_norm_arg      : tCONSTANT
2064                      {
2065                          yyerror("formal argument cannot be a constant");
2066                      }
2067                  | tIVAR
2068                      {
2069                          yyerror("formal argument cannot be an instance variable");
2070                      }
2071                  | tGVAR
2072                      {
2073                          yyerror("formal argument cannot be a global variable");
2074                      }
2075                  | tCVAR
2076                      {
2077                          yyerror("formal argument cannot be a class variable");
2078                      }
2079                  | tIDENTIFIER
2080                      {
2081                          if (!is_local_id($1))
2082                              yyerror("formal argument must be local variable");
2083                          else if (local_id($1))
2084                              yyerror("duplicate argument name");
2085                          local_cnt($1);
2086                          $$ = 1;
2087                      }
2088                  ;
2089  
2090  f_arg           : f_norm_arg
2091                  | f_arg ',' f_norm_arg
2092                      {
2093                          $$ += 1;
2094                      }
2095                  ;
2096  
2097  f_opt           : tIDENTIFIER '=' arg_value
2098                      {
2099                          if (!is_local_id($1))
2100                              yyerror("formal argument must be local variable");
2101                          else if (local_id($1))
2102                              yyerror("duplicate optional argument name");
2103                          $$ = assignable($1, $3);
2104                      }
2105                  ;
2106  
2107  f_optarg        : f_opt
2108                      {
2109                          $$ = NEW_BLOCK($1);
2110                          $$->nd_end = $$;
2111                      }
2112                  | f_optarg ',' f_opt
2113                      {
2114                          $$ = block_append($1, $3);
2115                      }
2116                  ;
2117  
2118  f_rest_arg      : tSTAR tIDENTIFIER
2119                      {
2120                          if (!is_local_id($2))
2121                              yyerror("rest argument must be local variable");
2122                          else if (local_id($2))
2123                              yyerror("duplicate rest argument name");
2124                          $$ = local_cnt($2);
2125                      }
2126                  | tSTAR
2127                      {
2128                          $$ = -2;
2129                      }
2130                  ;
2131  
2132  f_block_arg     : tAMPER tIDENTIFIER
2133                      {
2134                          if (!is_local_id($2))
2135                              yyerror("block argument must be local variable");
2136                          else if (local_id($2))
2137                              yyerror("duplicate block argument name");
2138                          $$ = NEW_BLOCK_ARG($2);
2139                      }
2140                  ;
2141  
2142  opt_f_block_arg : ',' f_block_arg
2143                      {
2144                          $$ = $2;
2145                      }
2146                  | none
2147                  ;
2148  
2149  singleton       : var_ref
2150                      {
2151                          if (nd_type($1) == NODE_SELF) {
2152                              $$ = NEW_SELF();
2153                          }
2154                          else {
2155                              $$ = $1;
2156                              value_expr($$);
2157                          }
2158                      }
2159                  | '(' {lex_state = EXPR_BEG;} expr opt_nl ')'
2160                      {
2161                          if ($3 == 0) {
2162                              yyerror("can't define single method for ().");
2163                          }
2164                          else {
2165                              switch (nd_type($3)) {
2166                                case NODE_STR:
2167                                case NODE_DSTR:
2168                                case NODE_XSTR:
2169                                case NODE_DXSTR:
2170                                case NODE_DREGX:
2171                                case NODE_LIT:
2172                                case NODE_ARRAY:
2173                                case NODE_ZARRAY:
2174                                  yyerror("can't define single method for literals");
2175                                default:
2176                                  value_expr($3);
2177                                  break;
2178                              }
2179                          }
2180                          $$ = $3;
2181                      }
2182                  ;
2183  
2184  assoc_list      : none
2185                  | assocs trailer
2186                      {
2187                          $$ = $1;
2188                      }
2189                  | args trailer
2190                      {
2191                          if ($1->nd_alen%2 != 0) {
2192                              yyerror("odd number list for Hash");
2193                          }
2194                          $$ = $1;
2195                      }
2196                  ;
2197  
2198  assocs          : assoc
2199                  | assocs ',' assoc
2200                      {
2201                          $$ = list_concat($1, $3);
2202                      }
2203                  ;
2204  
2205  assoc           : arg_value tASSOC arg_value
2206                      {
2207                          $$ = list_append(NEW_LIST($1), $3);
2208                      }
2209                  ;
2210  
2211  operation       : tIDENTIFIER
2212                  | tCONSTANT
2213                  | tFID
2214                  ;
2215  
2216  operation2      : tIDENTIFIER
2217                  | tCONSTANT
2218                  | tFID
2219                  | op
2220                  ;
2221  
2222  operation3      : tIDENTIFIER
2223                  | tFID
2224                  | op
2225                  ;
2226  
2227  dot_or_colon    : '.'
2228                  | tCOLON2
2229                  ;
2230  
2231  opt_terms       : /* none */
2232                  | terms
2233                  ;
2234  
2235  opt_nl          : /* none */
2236                  | '\n'
2237                  ;
2238  
2239  trailer         : /* none */
2240                  | '\n'
2241                  | ','
2242                  ;
2243  
2244  term            : ';' {yyerrok;}
2245                  | '\n'
2246                  ;
2247  
2248  terms           : term
2249                  | terms ';' {yyerrok;}
2250                  ;
2251  
2252  none            : /* none */ {$$ = 0;}
2253                  ;
2254  %%
2255  #include "regex.h"
2256  #include "util.h"
2257  
2258  /* We remove any previous definition of `SIGN_EXTEND_CHAR',
2259     since ours (we hope) works properly with all combinations of
2260     machines, compilers, `char' and `unsigned char' argument types.
2261     (Per Bothner suggested the basic approach.)  */
2262  #undef SIGN_EXTEND_CHAR
2263  #if __STDC__
2264  # define SIGN_EXTEND_CHAR(c) ((signed char)(c))
2265  #else  /* not __STDC__ */
2266  /* As in Harbison and Steele.  */
2267  # define SIGN_EXTEND_CHAR(c) ((((unsigned char)(c)) ^ 128) - 128)
2268  #endif
2269  #define is_identchar(c) (SIGN_EXTEND_CHAR(c)!=-1&&(ISALNUM(c) || (c) == '_' || ismbchar(c)))
2270  
2271  static char *tokenbuf = NULL;
2272  static int   tokidx, toksiz = 0;
2273  
2274  #define LEAVE_BS 1
2275  
2276  static VALUE (*lex_gets)();     /* gets function */
2277  static VALUE lex_input;         /* non-nil if File */
2278  static VALUE lex_lastline;      /* gc protect */
2279  static char *lex_pbeg;
2280  static char *lex_p;
2281  static char *lex_pend;
2282  
2283  static int
2284  yyerror(msg)
2285      char *msg;
2286  {
2287      char *p, *pe, *buf;
2288      int len, i;
2289  
2290      rb_compile_error("%s", msg);
2291      p = lex_p;
2292      while (lex_pbeg <= p) {
2293          if (*p == '\n') break;
2294          p--;
2295      }
2296      p++;
2297  
2298      pe = lex_p;
2299      while (pe < lex_pend) {
2300          if (*pe == '\n') break;
2301          pe++;
2302      }
2303  
2304      len = pe - p;
2305      if (len > 4) {
2306          buf = ALLOCA_N(char, len+2);
2307          MEMCPY(buf, p, char, len);
2308          buf[len] = '\0';
2309          rb_compile_error_append("%s", buf);
2310  
2311          i = lex_p - p;
2312          p = buf; pe = p + len;
2313  
2314          while (p < pe) {
2315              if (*p != '\t') *p = ' ';
2316              p++;
2317          }
2318          buf[i] = '^';
2319          buf[i+1] = '\0';
2320          rb_compile_error_append("%s", buf);
2321      }
2322  
2323      return 0;
2324  }
2325  
2326  static int heredoc_end;
2327  static int command_start = Qtrue;
2328  
2329  int ruby_in_compile = 0;
2330  int ruby__end__seen;
2331  
2332  static VALUE ruby_debug_lines;
2333  
2334  static NODE*
2335  yycompile(f, line)
2336      char *f;
2337      int line;
2338  {
2339      int n;
2340      NODE *node = 0;
2341      struct RVarmap *vp, *vars = ruby_dyna_vars;
2342  
2343      if (!compile_for_eval && rb_safe_level() == 0 &&
2344          rb_const_defined(rb_cObject, rb_intern("SCRIPT_LINES__"))) {
2345          VALUE hash, fname;
2346  
2347          hash = rb_const_get(rb_cObject, rb_intern("SCRIPT_LINES__"));
2348          if (TYPE(hash) == T_HASH) {
2349              fname = rb_str_new2(f);
2350              ruby_debug_lines = rb_hash_aref(hash, fname);
2351              if (NIL_P(ruby_debug_lines)) {
2352                  ruby_debug_lines = rb_ary_new();
2353                  rb_hash_aset(hash, fname, ruby_debug_lines);
2354              }
2355          }
2356          if (line > 1) {
2357              VALUE str = rb_str_new(0,0);
2358              while (line > 1) {
2359                  rb_ary_push(ruby_debug_lines, str);
2360                  line--;
2361              }
2362          }
2363      }
2364  
2365      ruby__end__seen = 0;
2366      ruby_eval_tree = 0;
2367      heredoc_end = 0;
2368      lex_strterm = 0;
2369      lex_strnest = 0;
2370      quoted_term = -1;
2371      ruby_current_node = 0;
2372      ruby_sourcefile = rb_source_filename(f);
2373      ruby_in_compile = 1;
2374      n = yyparse();
2375      ruby_debug_lines = 0;
2376      compile_for_eval = 0;
2377      ruby_in_compile = 0;
2378      cond_stack = 0;
2379      cmdarg_stack = 0;
2380      command_start = 1;            
2381      class_nest = 0;
2382      in_single = 0;
2383      in_def = 0;
2384      cur_mid = 0;
2385  
2386      vp = ruby_dyna_vars;
2387      ruby_dyna_vars = vars;
2388      lex_strterm = 0;
2389      while (vp && vp != vars) {
2390          struct RVarmap *tmp = vp;
2391          vp = vp->next;
2392          rb_gc_force_recycle((VALUE)tmp);
2393      }
2394      if (n == 0) node = ruby_eval_tree;
2395      return node;
2396  }
2397  
2398  static int lex_gets_ptr;
2399  
2400  static VALUE
2401  lex_get_str(s)
2402      VALUE s;
2403  {
2404      char *beg, *end, *pend;
2405  
2406      beg = RSTRING(s)->ptr;
2407      if (lex_gets_ptr) {
2408          if (RSTRING(s)->len == lex_gets_ptr) return Qnil;
2409          beg += lex_gets_ptr;
2410      }
2411      pend = RSTRING(s)->ptr + RSTRING(s)->len;
2412      end = beg;
2413      while (end < pend) {
2414          if (*end++ == '\n') break;
2415      }
2416      lex_gets_ptr = end - RSTRING(s)->ptr;
2417      return rb_str_new(beg, end - beg);
2418  }
2419  
2420  static VALUE
2421  lex_getline()
2422  {
2423      VALUE line = (*lex_gets)(lex_input);
2424      if (ruby_debug_lines && !NIL_P(line)) {
2425          rb_ary_push(ruby_debug_lines, line);
2426      }
2427      return line;
2428  }
2429  
2430  NODE*
2431  rb_compile_string(f, s, line)
2432      const char *f;
2433      VALUE s;
2434      int line;
2435  {
2436      lex_gets = lex_get_str;
2437      lex_gets_ptr = 0;
2438      lex_input = s;
2439      lex_pbeg = lex_p = lex_pend = 0;
2440      ruby_sourceline = line - 1;
2441      compile_for_eval = ruby_in_eval;
2442  
2443      return yycompile(f, line);
2444  }
2445  
2446  NODE*
2447  rb_compile_cstr(f, s, len, line)
2448      const char *f, *s;
2449      int len, line;
2450  {
2451      return rb_compile_string(f, rb_str_new(s, len), line);
2452  }
2453  
2454  NODE*
2455  rb_compile_file(f, file, start)
2456      const char *f;
2457      VALUE file;
2458      int start;
2459  {
2460      lex_gets = rb_io_gets;
2461      lex_input = file;
2462      lex_pbeg = lex_p = lex_pend = 0;
2463      ruby_sourceline = start - 1;
2464  
2465      return yycompile(f, start);
2466  }
2467  
2468  static inline int
2469  nextc()
2470  {
2471      int c;
2472  
2473      if (lex_p == lex_pend) {
2474          if (lex_input) {
2475              VALUE v = lex_getline();
2476  
2477              if (NIL_P(v)) return -1;
2478              if (heredoc_end > 0) {
2479                  ruby_sourceline = heredoc_end;
2480                  heredoc_end = 0;
2481              }
2482              ruby_sourceline++;
2483              lex_pbeg = lex_p = RSTRING(v)->ptr;
2484              lex_pend = lex_p + RSTRING(v)->len;
2485              lex_lastline = v;
2486          }
2487          else {
2488              lex_lastline = 0;
2489              return -1;
2490          }
2491      }
2492      c = (unsigned char)*lex_p++;
2493      if (c == '\r' && lex_p <= lex_pend && *lex_p == '\n') {
2494          lex_p++;
2495          c = '\n';
2496      }
2497  
2498      return c;
2499  }
2500  
2501  static void
2502  pushback(c)
2503      int c;
2504  {
2505      if (c == -1) return;
2506      lex_p--;
2507  }
2508  
2509  #define peek(c) (lex_p != lex_pend && (c) == *lex_p)
2510  
2511  #define tokfix() (tokenbuf[tokidx]='\0')
2512  #define tok() tokenbuf
2513  #define toklen() tokidx
2514  #define toklast() (tokidx>0?tokenbuf[tokidx-1]:0)
2515  
2516  static char*
2517  newtok()
2518  {
2519      tokidx = 0;
2520      if (!tokenbuf) {
2521          toksiz = 60;
2522          tokenbuf = ALLOC_N(char, 60);
2523      }
2524      if (toksiz > 4096) {
2525          toksiz = 60;
2526          REALLOC_N(tokenbuf, char, 60);
2527      }
2528      return tokenbuf;
2529  }
2530  
2531  static void
2532  tokadd(c)
2533      char c;
2534  {
2535      tokenbuf[tokidx++] = c;
2536      if (tokidx >= toksiz) {
2537          toksiz *= 2;
2538          REALLOC_N(tokenbuf, char, toksiz);
2539      }
2540  }
2541  
2542  static int
2543  read_escape()
2544  {
2545      int c;
2546  
2547      switch (c = nextc()) {
2548        case '\\':        /* Backslash */
2549          return c;
2550  
2551        case 'n': /* newline */
2552          return '\n';
2553  
2554        case 't': /* horizontal tab */
2555          return '\t';
2556  
2557        case 'r': /* carriage-return */
2558          return '\r';
2559  
2560        case 'f': /* form-feed */
2561          return '\f';
2562  
2563        case 'v': /* vertical tab */
2564          return '\13';
2565  
2566        case 'a': /* alarm(bell) */
2567          return '\007';
2568  
2569        case 'e': /* escape */
2570          return 033;
2571  
2572        case '0': case '1': case '2': case '3': /* octal constant */
2573        case '4': case '5': case '6': case '7':
2574          {
2575              int numlen;
2576  
2577              pushback(c);
2578              c = scan_oct(lex_p, 3, &numlen);
2579              lex_p += numlen;
2580          }
2581          return c;
2582  
2583        case 'x': /* hex constant */
2584          {
2585              int numlen;
2586  
2587              c = scan_hex(lex_p, 2, &numlen);
2588              if (numlen == 0) {
2589                  yyerror("Invalid escape character syntax");
2590                  return 0;
2591              }
2592              lex_p += numlen;
2593          }
2594          return c;
2595  
2596        case 'b': /* backspace */
2597          return '\010';
2598  
2599        case 's': /* space */
2600          return ' ';
2601  
2602        case 'M':
2603          if ((c = nextc()) != '-') {
2604              yyerror("Invalid escape character syntax");
2605              pushback(c);
2606              return '\0';
2607          }
2608          if ((c = nextc()) == '\\') {
2609              return read_escape() | 0x80;
2610          }
2611          else if (c == -1) goto eof;
2612          else {
2613              return ((c & 0xff) | 0x80);
2614          }
2615  
2616        case 'C':
2617          if ((c = nextc()) != '-') {
2618              yyerror("Invalid escape character syntax");
2619              pushback(c);
2620              return '\0';
2621          }
2622        case 'c':
2623          if ((c = nextc())== '\\') {
2624              c = read_escape();
2625          }
2626          else if (c == '?')
2627              return 0177;
2628          else if (c == -1) goto eof;
2629          return c & 0x9f;
2630  
2631        eof:
2632        case -1:
2633          yyerror("Invalid escape character syntax");
2634          return '\0';
2635  
2636        default:
2637          return c;
2638      }
2639  }
2640  
2641  static int
2642  tokadd_escape(term)
2643      int term;
2644  {
2645      int c;
2646  
2647      switch (c = nextc()) {
2648        case '\n':
2649          return 0;               /* just ignore */
2650  
2651        case '0': case '1': case '2': case '3': /* octal constant */
2652        case '4': case '5': case '6': case '7':
2653          {
2654              int i;
2655  
2656              tokadd('\\');
2657              tokadd(c);
2658              for (i=0; i<2; i++) {
2659                  c = nextc();
2660                  if (c == -1) goto eof;
2661                  if (c < '0' || '7' < c) {
2662                      pushback(c);
2663                      break;
2664                  }
2665                  tokadd(c);
2666              }
2667          }
2668          return 0;
2669  
2670        case 'x': /* hex constant */
2671          {
2672              int numlen;
2673  
2674              tokadd('\\');
2675              tokadd(c);
2676              scan_hex(lex_p, 2, &numlen);
2677              if (numlen == 0) {
2678                  yyerror("Invalid escape character syntax");
2679                  return -1;
2680              }
2681              while (numlen--)
2682                  tokadd(nextc());
2683          }
2684          return 0;
2685  
2686        case 'M':
2687          if ((c = nextc()) != '-') {
2688              yyerror("Invalid escape character syntax");
2689              pushback(c);
2690              return 0;
2691          }
2692          tokadd('\\'); tokadd('M'); tokadd('-');
2693          goto escaped;
2694  
2695        case 'C':
2696          if ((c = nextc()) != '-') {
2697              yyerror("Invalid escape character syntax");
2698              pushback(c);
2699              return 0;
2700          }
2701          tokadd('\\'); tokadd('C'); tokadd('-');
2702          goto escaped;
2703  
2704        case 'c':
2705          tokadd('\\'); tokadd('c');
2706        escaped:
2707          if ((c = nextc()) == '\\') {
2708              return tokadd_escape(term);
2709          }
2710          else if (c == -1) goto eof;
2711          tokadd(c);
2712          return 0;
2713  
2714        eof:
2715        case -1:
2716          yyerror("Invalid escape character syntax");
2717          return -1;
2718  
2719        default:
2720          if (c != '\\' || c != term)
2721              tokadd('\\');
2722          tokadd(c);
2723      }
2724      return 0;
2725  }
2726  
2727  static int
2728  regx_options()
2729  {
2730      char kcode = 0;
2731      int options = 0;
2732      int c;
2733  
2734      newtok();
2735      while (c = nextc(), ISALPHA(c)) {
2736          switch (c) {
2737            case 'i':
2738              options |= RE_OPTION_IGNORECASE;
2739              break;
2740            case 'x':
2741              options |= RE_OPTION_EXTENDED;
2742              break;
2743            case 'm':
2744              options |= RE_OPTION_MULTILINE;
2745              break;
2746            case 'o':
2747              options |= RE_OPTION_ONCE;
2748              break;
2749            case 'n':
2750              kcode = 16;
2751              break;
2752            case 'e':
2753              kcode = 32;
2754              break;
2755            case 's':
2756              kcode = 48;
2757              break;
2758            case 'u':
2759              kcode = 64;
2760              break;
2761            default:
2762              tokadd(c);
2763              break;
2764          }
2765      }
2766      pushback(c);
2767      if (toklen()) {
2768          tokfix();
2769          rb_compile_error("unknown regexp option%s - %s",
2770                           toklen() > 1 ? "s" : "", tok());
2771      }
2772      return options | kcode;
2773  }
2774  
2775  #define STR_FUNC_ESCAPE 0x01
2776  #define STR_FUNC_EXPAND 0x02
2777  #define STR_FUNC_REGEXP 0x04
2778  #define STR_FUNC_QWORDS 0x08
2779  #define STR_FUNC_INDENT 0x20
2780  
2781  enum string_type {
2782      str_squote = (0),
2783      str_dquote = (STR_FUNC_EXPAND),
2784      str_xquote = (STR_FUNC_ESCAPE|STR_FUNC_EXPAND),
2785      str_regexp = (STR_FUNC_REGEXP|STR_FUNC_ESCAPE|STR_FUNC_EXPAND),
2786      str_sword  = (STR_FUNC_QWORDS),
2787      str_dword  = (STR_FUNC_QWORDS|STR_FUNC_EXPAND),
2788  };
2789  
2790  static int
2791  tokadd_string(func, term, paren)
2792      int func, term, paren;
2793  {
2794      int c;
2795  
2796      while ((c = nextc()) != -1) {
2797          if (paren && c == paren) {
2798              lex_strnest++;
2799          }
2800          else if (c == term) {
2801              if (!lex_strnest) {
2802                  pushback(c);
2803                  break;
2804              }
2805              --lex_strnest;
2806          }
2807          else if ((func & STR_FUNC_EXPAND) && c == '#' && lex_p < lex_pend) {
2808              int c2 = *lex_p;
2809              if (c2 == '$' || c2 == '@' || c2 == '{') {
2810                  pushback(c);
2811                  break;
2812              }
2813          }
2814          else if (c == '\\') {
2815              c = nextc();
2816              if (QUOTED_TERM_P(c)) {
2817                  pushback(c);
2818                  return c;
2819              }
2820              switch (c) {
2821                case '\n':
2822                  continue;
2823  
2824                case '\\':
2825                  if (func & STR_FUNC_ESCAPE) tokadd(c);
2826                  break;
2827  
2828                default:
2829                  if (func & STR_FUNC_REGEXP) {
2830                      pushback(c);
2831                      if (tokadd_escape(term) < 0)
2832                          return -1;
2833                      continue;
2834                  }
2835                  else if (func & STR_FUNC_EXPAND) {
2836                      pushback(c);
2837                      if (func & STR_FUNC_ESCAPE) tokadd('\\');
2838                      c = read_escape();
2839                  }
2840                  else if ((func & STR_FUNC_QWORDS) && ISSPACE(c)) {
2841                      /* ignore backslashed spaces in %w */
2842                  }
2843                  else if (c != term && !(paren && c == paren)) {
2844                      tokadd('\\');
2845                  }
2846              }
2847          }
2848          else if (ismbchar(c)) {
2849              int i, len = mbclen(c)-1;
2850  
2851              for (i = 0; i < len; i++) {
2852                  tokadd(c);
2853                  c = nextc();
2854              }
2855          }
2856          else if ((func & STR_FUNC_QWORDS) && ISSPACE(c)) {
2857              pushback(c);
2858              break;
2859          }
2860          tokadd(c);
2861      }
2862      return c;
2863  }
2864  
2865  #define NEW_STRTERM(func, term, paren) \
2866          rb_node_newnode(NODE_STRTERM, (func), (term), (paren))
2867  
2868  static int
2869  parse_string(quote)
2870      NODE *quote;
2871  {
2872      int func = quote->nd_func;
2873      int term = quote->nd_term;
2874      int paren = quote->nd_paren;
2875      int c, space = 0;
2876  
2877      if (func == -1) return tSTRING_END;
2878      c = nextc();
2879      if ((func & STR_FUNC_QWORDS) && ISSPACE(c)) {
2880          do {c = nextc();} while (ISSPACE(c));
2881          space = 1;
2882      }
2883      if (c == term) {
2884          if (!lex_strnest) {
2885            eos:
2886              if (func & STR_FUNC_QWORDS) {
2887                  quote->nd_func = -1;
2888                  return ' ';
2889              }
2890              if (!(func & STR_FUNC_REGEXP)) return tSTRING_END;
2891              yylval.num = regx_options();
2892              return tREGEXP_END;
2893          }
2894      }
2895      if (c == '\\' && WHEN_QUOTED_TERM(peek(quoted_term_char))) {
2896          if ((c = nextc()) == term) goto eos;
2897      }
2898      if (space) {
2899          pushback(c);
2900          return ' ';
2901      }
2902      newtok();
2903      if ((func & STR_FUNC_EXPAND) && c == '#') {
2904          switch (c = nextc()) {
2905            case '$':
2906            case '@':
2907              pushback(c);
2908              return tSTRING_DVAR;
2909            case '{':
2910              return tSTRING_DBEG;
2911          }
2912          tokadd('#');
2913      }
2914      pushback(c);
2915      if (tokadd_string(func, term, paren) == -1) {
2916          ruby_sourceline = nd_line(quote);
2917          rb_compile_error("unterminated string meets end of file");
2918          return tSTRING_END;
2919      }
2920  
2921      tokfix();
2922      yylval.node = NEW_STR(rb_str_new(tok(), toklen()));
2923      return tSTRING_CONTENT;
2924  }
2925  
2926  static int
2927  heredoc_identifier()
2928  {
2929      int c = nextc(), term, func = 0, len;
2930  
2931      if (c == '-') {
2932          c = nextc();
2933          if (ISSPACE(c)) {
2934              pushback(c);
2935              pushback('-');
2936              return 0;
2937          }
2938          func = STR_FUNC_INDENT;
2939      }
2940      else if (ISSPACE(c)) {
2941        not_heredoc:
2942          pushback(c);
2943          return 0;
2944      }
2945      switch (c) {
2946        case '\'':
2947          func |= str_squote; goto quoted;
2948        case '"':
2949          func |= str_dquote; goto quoted;
2950        case '`':
2951          func |= str_xquote;
2952        quoted:
2953          newtok();
2954          tokadd(func);
2955          term = c;
2956          while ((c = nextc()) != -1 && c != term) {
2957              len = mbclen(c);
2958              do {tokadd(c);} while (--len > 0 && (c = nextc()) != -1);
2959          }
2960          if (c == -1) {
2961              rb_compile_error("unterminated here document identifier");
2962              return 0;
2963          }
2964          break;
2965  
2966        default:
2967          if (!is_identchar(c)) goto not_heredoc;
2968          newtok();
2969          term = '"';
2970          tokadd(func |= str_dquote);
2971          do {
2972              len = mbclen(c);
2973              do {tokadd(c);} while (--len > 0 && (c = nextc()) != -1);
2974          } while ((c = nextc()) != -1 && is_identchar(c));
2975          pushback(c);
2976          break;
2977      }
2978  
2979      tokfix();
2980      len = lex_p - lex_pbeg;
2981      lex_p = lex_pend;
2982      lex_strterm = rb_node_newnode(NODE_HEREDOC,
2983                                    rb_str_new(tok(), toklen()),  /* nd_lit */
2984                                    len,                          /* nd_nth */
2985                                    lex_lastline);                /* nd_orig */
2986      return term == '`' ? tXSTRING_BEG : tSTRING_BEG;
2987  }
2988  
2989  static void
2990  heredoc_restore(here)
2991      NODE *here;
2992  {
2993      VALUE line = here->nd_orig;
2994      lex_lastline = line;
2995      lex_pbeg = RSTRING(line)->ptr;
2996      lex_pend = lex_pbeg + RSTRING(line)->len;
2997      lex_p = lex_pbeg + here->nd_nth;
2998      heredoc_end = ruby_sourceline;
2999      ruby_sourceline = nd_line(here);
3000      rb_gc_force_recycle(here->nd_lit);
3001      rb_gc_force_recycle((VALUE)here);
3002  }
3003  
3004  static int
3005  whole_match_p(eos, len, indent)
3006      char *eos;
3007      int len, indent;
3008  {
3009      char *p = lex_pbeg;
3010  
3011      if (indent) {
3012          while (*p && ISSPACE(*p)) p++;
3013      }
3014      if (strncmp(eos, p, len) == 0) {
3015          if (p[len] == '\n' || p[len] == '\r') return Qtrue;
3016          if (p + len == lex_pend) return Qtrue;
3017      }
3018      return Qfalse;
3019  }
3020  
3021  static int
3022  here_document(here)
3023      NODE *here;
3024  {
3025      int c, func, indent = 0;
3026      char *eos;
3027      long len;
3028      VALUE str = 0, line;
3029  
3030      eos = RSTRING(here->nd_lit)->ptr;
3031      len = RSTRING(here->nd_lit)->len - 1;
3032      indent = (func = *eos++) & STR_FUNC_INDENT;
3033  
3034      if ((c = nextc()) == -1) {
3035        error:
3036          rb_compile_error("can't find string \"%s\" anywhere before EOF", eos);
3037          heredoc_restore(lex_strterm);
3038          lex_strterm = 0;
3039          return 0;
3040      }
3041      if (lex_p - 1 == lex_pbeg && whole_match_p(eos, len, indent)) {
3042          heredoc_restore(lex_strterm);
3043          return tSTRING_END;
3044      }
3045  
3046      if (!(func & STR_FUNC_EXPAND)) {
3047          do {
3048              line = lex_lastline;
3049              if (str)
3050                  rb_str_cat(str, RSTRING(line)->ptr, RSTRING(line)->len);
3051              else
3052                  str = rb_str_new(RSTRING(line)->ptr, RSTRING(line)->len);
3053              lex_p = lex_pend;
3054              if (nextc() == -1) {
3055                  if (str) rb_gc_force_recycle(str);
3056                  goto error;
3057              }
3058          } while (!whole_match_p(eos, len, indent));
3059      }
3060      else {
3061          newtok();
3062          if (c == '#') {
3063              switch (c = nextc()) {
3064                case '$':
3065                case '@':
3066                  pushback(c);
3067                  return tSTRING_DVAR;
3068                case '{':
3069                  return tSTRING_DBEG;
3070              }
3071              tokadd('#');
3072          }
3073          do {
3074              pushback(c);
3075              if ((c = tokadd_string(func, '\n', 0)) == -1) goto error;
3076              if (c != '\n') {
3077                  yylval.node = NEW_STR(rb_str_new(tok(), toklen()));
3078                  return tSTRING_CONTENT;
3079              }
3080              tokadd(nextc());
3081              if ((c = nextc()) == -1) goto error;
3082          } while (!whole_match_p(eos, len, indent));
3083          str = rb_str_new(tok(), toklen());
3084      }
3085      heredoc_restore(lex_strterm);
3086      lex_strterm = NEW_STRTERM(-1, 0, 0);
3087      yylval.node = NEW_STR(str);
3088      return tSTRING_CONTENT;
3089  }
3090  
3091  #include "lex.c"
3092  
3093  static void
3094  arg_ambiguous()
3095  {
3096      rb_warning("ambiguous first argument; make sure");
3097  }
3098  
3099  #if !defined(strtod) && !defined(HAVE_STDLIB_H)
3100  double strtod ();
3101  #endif
3102  
3103  #define IS_ARG() (lex_state == EXPR_ARG || lex_state == EXPR_CMDARG)
3104  
3105  static int
3106  yylex()
3107  {
3108      static ID last_id = 0;
3109      register int c;
3110      int space_seen = 0;
3111      int cmd_state;
3112  
3113      if (lex_strterm) {
3114          int token;
3115          if (nd_type(lex_strterm) == NODE_HEREDOC) {
3116              token = here_document(lex_strterm);
3117              if (token == tSTRING_END) {
3118                  lex_strterm = 0;
3119                  lex_state = EXPR_END;
3120              }
3121          }
3122          else {
3123              token = parse_string(lex_strterm);
3124              if (token == tSTRING_END || token == tREGEXP_END) {
3125                  rb_gc_force_recycle((VALUE)lex_strterm);
3126                  lex_strterm = 0;
3127                  lex_state = EXPR_END;
3128              }
3129          }
3130          return token;
3131      }
3132      cmd_state = command_start;
3133      command_start = Qfalse;
3134    retry:
3135      switch (c = nextc()) {
3136        case '\0':                /* NUL */
3137        case '\004':              /* ^D */
3138        case '\032':              /* ^Z */
3139        case -1:                  /* end of script. */
3140          return 0;
3141  
3142          /* white spaces */
3143        case ' ': case '\t': case '\f': case '\r':
3144        case '\13': /* '\v' */
3145          space_seen++;
3146          goto retry;
3147  
3148        case '#':         /* it's a comment */
3149          while ((c = nextc()) != '\n') {
3150              if (c == -1)
3151                  return 0;
3152          }
3153          /* fall through */
3154        case '\n':
3155          switch (lex_state) {
3156            case EXPR_BEG:
3157            case EXPR_FNAME:
3158            case EXPR_DOT:
3159            case EXPR_CLASS:
3160              goto retry;
3161            default:
3162              break;
3163          }
3164          command_start = Qtrue;
3165          lex_state = EXPR_BEG;
3166          return '\n';
3167  
3168        case '*':
3169          if ((c = nextc()) == '*') {
3170              if ((c = nextc()) == '=') {
3171                  yylval.id = tPOW;
3172                  lex_state = EXPR_BEG;
3173                  return tOP_ASGN;
3174              }
3175              pushback(c);
3176              c = tPOW;
3177          }
3178          else {
3179              if (c == '=') {
3180                  yylval.id = '*';
3181                  lex_state = EXPR_BEG;
3182                  return tOP_ASGN;
3183              }
3184              pushback(c);
3185              if (IS_ARG() && space_seen && !ISSPACE(c)){
3186                  rb_warning("`*' interpreted as argument prefix");
3187                  c = tSTAR;
3188              }
3189              else if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
3190                  c = tSTAR;
3191              }
3192              else {
3193                  c = '*';
3194              }
3195          }
3196          switch (lex_state) {
3197            case EXPR_FNAME: case EXPR_DOT:
3198              lex_state = EXPR_ARG; break;
3199            default:
3200              lex_state = EXPR_BEG; break;
3201          }
3202          return c;
3203  
3204        case '!':
3205          lex_state = EXPR_BEG;
3206          if ((c = nextc()) == '=') {
3207              return tNEQ;
3208          }
3209          if (c == '~') {
3210              return tNMATCH;
3211          }
3212          pushback(c);
3213          return '!';
3214  
3215        case '=':
3216          if (lex_p == lex_pbeg + 1) {
3217              /* skip embedded rd document */
3218              if (strncmp(lex_p, "begin", 5) == 0 && ISSPACE(lex_p[5])) {
3219                  for (;;) {
3220                      lex_p = lex_pend;
3221                      c = nextc();
3222                      if (c == -1) {
3223                          rb_compile_error("embedded document meets end of file");
3224                          return 0;
3225                      }
3226                      if (c != '=') continue;
3227                      if (strncmp(lex_p, "end", 3) == 0 &&
3228                          (lex_p + 3 == lex_pend || ISSPACE(lex_p[3]))) {
3229                          break;
3230                      }
3231                  }
3232                  lex_p = lex_pend;
3233                  goto retry;
3234              }
3235          }
3236  
3237          switch (lex_state) {
3238            case EXPR_FNAME: case EXPR_DOT:
3239              lex_state = EXPR_ARG; break;
3240            default:
3241              lex_state = EXPR_BEG; break;
3242          }
3243          if ((c = nextc()) == '=') {
3244              if ((c = nextc()) == '=') {
3245                  return tEQQ;
3246              }
3247              pushback(c);
3248              return tEQ;
3249          }
3250          if (c == '~') {
3251              return tMATCH;
3252          }
3253          else if (c == '>') {
3254              return tASSOC;
3255          }
3256          pushback(c);
3257          return '=';
3258  
3259        case '<':
3260          c = nextc();
3261          if (c == '<' &&
3262              lex_state != EXPR_END &&
3263              lex_state != EXPR_DOT &&
3264              lex_state != EXPR_ENDARG && 
3265              lex_state != EXPR_CLASS &&
3266              (!IS_ARG() || space_seen)) {
3267              int token = heredoc_identifier();
3268              if (token) return token;
3269          }
3270          switch (lex_state) {
3271            case EXPR_FNAME: case EXPR_DOT:
3272              lex_state = EXPR_ARG; break;
3273            default:
3274              lex_state = EXPR_BEG; break;
3275          }
3276          if (c == '=') {
3277              if ((c = nextc()) == '>') {
3278                  return tCMP;
3279              }
3280              pushback(c);
3281              return tLEQ;
3282          }
3283          if (c == '<') {
3284              if ((c = nextc()) == '=') {
3285                  yylval.id = tLSHFT;
3286                  lex_state = EXPR_BEG;
3287                  return tOP_ASGN;
3288              }
3289              pushback(c);
3290              return tLSHFT;
3291          }
3292          pushback(c);
3293          return '<';
3294  
3295        case '>':
3296          switch (lex_state) {
3297            case EXPR_FNAME: case EXPR_DOT:
3298              lex_state = EXPR_ARG; break;
3299            default:
3300              lex_state = EXPR_BEG; break;
3301          }
3302          if ((c = nextc()) == '=') {
3303              return tGEQ;
3304          }
3305          if (c == '>') {
3306              if ((c = nextc()) == '=') {
3307                  yylval.id = tRSHFT;
3308                  lex_state = EXPR_BEG;
3309                  return tOP_ASGN;
3310              }
3311              pushback(c);
3312              return tRSHFT;
3313          }
3314          pushback(c);
3315          return '>';
3316  
3317        case '"':
3318          lex_strterm = NEW_STRTERM(str_dquote, '"', 0);
3319          return tSTRING_BEG;
3320  
3321        case '`':
3322          if (lex_state == EXPR_FNAME) {
3323              lex_state = EXPR_END;
3324              return c;
3325          }
3326          if (lex_state == EXPR_DOT) {
3327              if (cmd_state)
3328                  lex_state = EXPR_CMDARG;
3329              else
3330                  lex_state = EXPR_ARG;
3331              return c;
3332          }
3333          lex_strterm = NEW_STRTERM(str_xquote, '`', 0);
3334          return tXSTRING_BEG;
3335  
3336        case '\'':
3337          lex_strterm = NEW_STRTERM(str_squote, '\'', 0);
3338          return tSTRING_BEG;
3339  
3340        case '?':
3341          if (lex_state == EXPR_END || lex_state == EXPR_ENDARG) {
3342              lex_state = EXPR_BEG;
3343              return '?';
3344          }
3345          c = nextc();
3346          if (c == -1) {
3347              rb_compile_error("incomplete character syntax");
3348              return 0;
3349          }
3350          if (ISSPACE(c)){
3351              if (!IS_ARG()){
3352                  int c2 = 0;
3353                  switch (c) {
3354                    case ' ':
3355                      c2 = 's';
3356                      break;
3357                    case '\n':
3358                      c2 = 'n';
3359                      break;
3360                    case '\t':
3361                      c2 = 't';
3362                      break;
3363                    case '\v':
3364                      c2 = 'v';
3365                      break;
3366                    case '\r':
3367                      c2 = 'r';
3368                      break;
3369                    case '\f':
3370                      c2 = 'f';
3371                      break;
3372                  }
3373                  if (c2) {
3374                      rb_warn("invalid character syntax; use ?\\%c", c2);
3375                  }
3376              }
3377            ternary:
3378              pushback(c);
3379              lex_state = EXPR_BEG;
3380              return '?';
3381          }
3382          else if (ismbchar(c)) {
3383              rb_warn("multibyte character literal not supported yet; use ?\\%.3o", c);
3384              goto ternary;
3385          }
3386          else if ((ISALNUM(c) || c == '_') && lex_p < lex_pend && is_identchar(*lex_p)) {
3387              goto ternary;
3388          }
3389          else if (c == '\\') {
3390              c = read_escape();
3391          }
3392          c &= 0xff;
3393          lex_state = EXPR_END;
3394          yylval.node = NEW_LIT(INT2FIX(c));
3395          return tINTEGER;
3396  
3397        case '&':
3398          if ((c = nextc()) == '&') {
3399              lex_state = EXPR_BEG;
3400              if ((c = nextc()) == '=') {
3401                  yylval.id = tANDOP;
3402                  lex_state = EXPR_BEG;
3403                  return tOP_ASGN;
3404              }
3405              pushback(c);
3406              return tANDOP;
3407          }
3408          else if (c == '=') {
3409              yylval.id = '&';
3410              lex_state = EXPR_BEG;
3411              return tOP_ASGN;
3412          }
3413          pushback(c);
3414          if (IS_ARG() && space_seen && !ISSPACE(c)){
3415              rb_warning("`&' interpreted as argument prefix");
3416              c = tAMPER;
3417          }
3418          else if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
3419              c = tAMPER;
3420          }
3421          else {
3422              c = '&';
3423          }
3424          switch (lex_state) {
3425            case EXPR_FNAME: case EXPR_DOT:
3426              lex_state = EXPR_ARG; break;
3427            default:
3428              lex_state = EXPR_BEG;
3429          }
3430          return c;
3431  
3432        case '|':
3433          if ((c = nextc()) == '|') {
3434              lex_state = EXPR_BEG;
3435              if ((c = nextc()) == '=') {
3436                  yylval.id = tOROP;
3437                  lex_state = EXPR_BEG;
3438                  return tOP_ASGN;
3439              }
3440              pushback(c);
3441              return tOROP;
3442          }
3443          if (c == '=') {
3444              yylval.id = '|';
3445              lex_state = EXPR_BEG;
3446              return tOP_ASGN;
3447          }
3448          if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
3449              lex_state = EXPR_ARG;
3450          }
3451          else {
3452              lex_state = EXPR_BEG;
3453          }
3454          pushback(c);
3455          return '|';
3456  
3457        case '+':
3458          c = nextc();
3459          if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
3460              lex_state = EXPR_ARG;
3461              if (c == '@') {
3462                  return tUPLUS;
3463              }
3464              pushback(c);
3465              return '+';
3466          }
3467          if (c == '=') {
3468              yylval.id = '+';
3469              lex_state = EXPR_BEG;
3470              return tOP_ASGN;
3471          }
3472          if (lex_state == EXPR_BEG || lex_state == EXPR_MID ||
3473              (IS_ARG() && space_seen && !ISSPACE(c))) {
3474              if (IS_ARG()) arg_ambiguous();
3475              lex_state = EXPR_BEG;
3476              pushback(c);
3477              if (ISDIGIT(c)) {
3478                  c = '+';
3479                  goto start_num;
3480              }
3481              return tUPLUS;
3482          }
3483          lex_state = EXPR_BEG;
3484          pushback(c);
3485          return '+';
3486  
3487        case '-':
3488          c = nextc();
3489          if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
3490              lex_state = EXPR_ARG;
3491              if (c == '@') {
3492                  return tUMINUS;
3493              }
3494              pushback(c);
3495              return '-';
3496          }
3497          if (c == '=') {
3498              yylval.id = '-';
3499              lex_state = EXPR_BEG;
3500              return tOP_ASGN;
3501          }
3502          if (lex_state == EXPR_BEG || lex_state == EXPR_MID ||
3503              (IS_ARG() && space_seen && !ISSPACE(c))) {
3504              if (IS_ARG()) arg_ambiguous();
3505              lex_state = EXPR_BEG;
3506              pushback(c);
3507              if (ISDIGIT(c)) {
3508                  c = '-';
3509                  goto start_num;
3510              }
3511              return tUMINUS;
3512          }
3513          lex_state = EXPR_BEG;
3514          pushback(c);
3515          return '-';
3516  
3517        case '.':
3518          lex_state = EXPR_BEG;
3519          if ((c = nextc()) == '.') {
3520              if ((c = nextc()) == '.') {
3521                  return tDOT3;
3522              }
3523              pushback(c);
3524              return tDOT2;
3525          }
3526          pushback(c);
3527          if (!ISDIGIT(c)) {
3528              lex_state = EXPR_DOT;
3529              return '.';
3530          }
3531          c = '.';
3532          /* fall through */
3533  
3534        start_num:
3535        case '0': case '1': case '2': case '3': case '4':
3536        case '5': case '6': case '7': case '8': case '9':
3537          {
3538              int is_float, seen_point, seen_e, nondigit;
3539  
3540              is_float = seen_point = seen_e = nondigit = 0;
3541              lex_state = EXPR_END;
3542              newtok();
3543              if (c == '-' || c == '+') {
3544                  tokadd(c);
3545                  c = nextc();
3546              }
3547              if (c == '0') {
3548                  int start = toklen();
3549                  c = nextc();
3550                  if (c == 'x' || c == 'X') {
3551                      /* hexadecimal */
3552                      c = nextc();
3553                      if (ISXDIGIT(c)) {
3554                          do {
3555                              if (c == '_') {
3556                                  if (nondigit) break;
3557                                  nondigit = c;
3558                                  continue;
3559                              }
3560                              if (!ISXDIGIT(c)) break;
3561                              nondigit = 0;
3562                              tokadd(c);
3563                          } while (c = nextc());
3564                      }
3565                      pushback(c);
3566                      tokfix();
3567                      if (toklen() == start) {
3568                          yyerror("numeric literal without digits");
3569                      }
3570                      else if (nondigit) goto trailing_uc;
3571                      yylval.node = NEW_LIT(rb_cstr_to_inum(tok(), 16, Qfalse));
3572                      return tINTEGER;
3573                  }
3574                  if (c == 'b' || c == 'B') {
3575                      /* binary */
3576                      c = nextc();
3577                      if (c == '0' || c == '1') {
3578                          do {
3579                              if (c == '_') {
3580                                  if (nondigit) break;
3581                                  nondigit = c;
3582                                  continue;
3583                              }
3584                              if (c != '0' && c != '1') break;
3585                              nondigit = 0;
3586                              tokadd(c);
3587                          } while (c = nextc());
3588                      }
3589                      pushback(c);
3590                      tokfix();
3591                      if (toklen() == start) {
3592                          yyerror("numeric literal without digits");
3593                      }
3594                      else if (nondigit) goto trailing_uc;
3595                      yylval.node = NEW_LIT(rb_cstr_to_inum(tok(), 2, Qfalse));
3596                      return tINTEGER;
3597                  }
3598                  if (c == 'd' || c == 'D') {
3599                      /* decimal */
3600                      c = nextc();
3601                      if (ISDIGIT(c)) {
3602                          do {
3603                              if (c == '_') {
3604                                  if (nondigit) break;
3605                                  nondigit = c;
3606                                  continue;
3607                              }
3608                              if (!ISDIGIT(c)) break;
3609                              nondigit = 0;
3610                              tokadd(c);
3611                          } while (c = nextc());
3612                      }
3613                      pushback(c);
3614                      tokfix();
3615                      if (toklen() == start) {
3616                          yyerror("numeric literal without digits");
3617                      }
3618                      else if (nondigit) goto trailing_uc;
3619                      yylval.node = NEW_LIT(rb_cstr_to_inum(tok(), 10, Qfalse));
3620                      return tINTEGER;
3621                  }
3622                  if (c == '_') {
3623                      /* 0_0 */
3624                      goto octal_number;
3625                  }
3626                  if (c == 'o' || c == 'O') {
3627                      /* prefixed octal */
3628                      c = nextc();
3629                      if (c == '_') {
3630                          yyerror("numeric literal without digits");
3631                      }
3632                  }
3633                  if (c >= '0' && c <= '7') {
3634                      /* octal */
3635                    octal_number:
3636                      do {
3637                          if (c == '_') {
3638                              if (nondigit) break;
3639                              nondigit = c;
3640                              continue;
3641                          }
3642                          if (c < '0' || c > '7') break;
3643                          nondigit = 0;
3644                          tokadd(c);
3645                      } while (c = nextc());
3646                      if (toklen() > start) {
3647                          pushback(c);
3648                          tokfix();
3649                          if (nondigit) goto trailing_uc;
3650                          yylval.node = NEW_LIT(rb_cstr_to_inum(tok(), 8, Qfalse));
3651                          return tINTEGER;
3652                      }
3653                      if (nondigit) {
3654                          pushback(c);
3655                          goto trailing_uc;
3656                      }
3657                  }
3658                  if (c > '7' && c <= '9') {
3659                      yyerror("Illegal octal digit");
3660                  }
3661                  else if (c == '.' || c == 'e' || c == 'E') {
3662                      tokadd('0');
3663                  }
3664                  else {
3665                      pushback(c);
3666                      yylval.node = NEW_LIT(INT2FIX(0));
3667                      return tINTEGER;
3668                  }
3669              }
3670  
3671              for (;;) {
3672                  switch (c) {
3673                    case '0': case '1': case '2': case '3': case '4':
3674                    case '5': case '6': case '7': case '8': case '9':
3675                      nondigit = 0;
3676                      tokadd(c);
3677                      break;
3678  
3679                    case '.':
3680                      if (nondigit) goto trailing_uc;
3681                      if (seen_point || seen_e) {
3682                          goto decode_num;
3683                      }
3684                      else {
3685                          int c0 = nextc();
3686                          if (!ISDIGIT(c0)) {
3687                              pushback(c0);
3688                              goto decode_num;
3689                          }
3690                          c = c0;
3691                      }
3692                      tokadd('.');
3693                      tokadd(c);
3694                      is_float++;
3695                      seen_point++;
3696                      nondigit = 0;
3697                      break;
3698  
3699                    case 'e':
3700                    case 'E':
3701                      if (nondigit) {
3702                          pushback(c);
3703                          c = nondigit;
3704                          goto decode_num;
3705                      }
3706                      if (seen_e) {
3707                          goto decode_num;
3708                      }
3709                      tokadd(c);
3710                      seen_e++;
3711                      is_float++;
3712                      nondigit = c;
3713                      c = nextc();
3714                      if (c != '-' && c != '+') continue;
3715                      tokadd(c);
3716                      nondigit = c;
3717                      break;
3718  
3719                    case '_':     /* `_' in number just ignored */
3720                      if (nondigit) goto decode_num;
3721                      nondigit = c;
3722                      break;
3723  
3724                    default:
3725                      goto decode_num;
3726                  }
3727                  c = nextc();
3728              }
3729  
3730            decode_num:
3731              pushback(c);
3732              tokfix();
3733              if (nondigit) {
3734                  char tmp[30];
3735                trailing_uc:
3736                  sprintf(tmp, "trailing `%c' in number", nondigit);
3737                  yyerror(tmp);
3738              }
3739              if (is_float) {
3740                  double d = strtod(tok(), 0);
3741                  if (errno == ERANGE) {
3742                      rb_warn("Float %s out of range", tok());
3743                      errno = 0;
3744                  }
3745                  yylval.node = NEW_LIT(rb_float_new(d));
3746                  return tFLOAT;
3747              }
3748              yylval.node = NEW_LIT(rb_cstr_to_inum(tok(), 10, Qfalse));
3749              return tINTEGER;
3750          }
3751  
3752        case ']':
3753        case '}':
3754        case ')':
3755          COND_LEXPOP();
3756          CMDARG_LEXPOP();
3757          lex_state = EXPR_END;
3758          return c;
3759  
3760        case ':':
3761          c = nextc();
3762          if (c == ':') {
3763              if (lex_state == EXPR_BEG ||  lex_state == EXPR_MID ||
3764                  (IS_ARG() && space_seen)) {
3765                  lex_state = EXPR_BEG;
3766                  return tCOLON3;
3767              }
3768              lex_state = EXPR_DOT;
3769              return tCOLON2;
3770          }
3771          pushback(c);
3772          if (lex_state == EXPR_END || lex_state == EXPR_ENDARG || ISSPACE(c)) {
3773              lex_state = EXPR_BEG;
3774              return ':';
3775          }
3776          lex_state = EXPR_FNAME;
3777          return tSYMBEG;
3778  
3779        case '/':
3780          if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
3781              lex_strterm = NEW_STRTERM(str_regexp, '/', 0);
3782              return tREGEXP_BEG;
3783          }
3784          if ((c = nextc()) == '=') {
3785              yylval.id = '/';
3786              lex_state = EXPR_BEG;
3787              return tOP_ASGN;
3788          }
3789          pushback(c);
3790          if (IS_ARG() && space_seen) {
3791              if (!ISSPACE(c)) {
3792                  arg_ambiguous();
3793                  lex_strterm = NEW_STRTERM(str_regexp, '/', 0);
3794                  return tREGEXP_BEG;
3795              }
3796          }
3797          switch (lex_state) {
3798            case EXPR_FNAME: case EXPR_DOT:
3799              lex_state = EXPR_ARG; break;
3800            default:
3801              lex_state = EXPR_BEG; break;
3802          }
3803          return '/';
3804  
3805        case '^':
3806          if ((c = nextc()) == '=') {
3807              yylval.id = '^';
3808              lex_state = EXPR_BEG;
3809              return tOP_ASGN;
3810          }
3811          switch (lex_state) {
3812            case EXPR_FNAME: case EXPR_DOT:
3813              lex_state = EXPR_ARG; break;
3814            default:
3815              lex_state = EXPR_BEG; break;
3816          }
3817          pushback(c);
3818          return '^';
3819  
3820        case ';':
3821          command_start = Qtrue;
3822        case ',':
3823          lex_state = EXPR_BEG;
3824          return c;
3825  
3826        case '~':
3827          if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
3828              if ((c = nextc()) != '@') {
3829                  pushback(c);
3830              }
3831          }
3832          switch (lex_state) {
3833            case EXPR_FNAME: case EXPR_DOT:
3834              lex_state = EXPR_ARG; break;
3835            default:
3836              lex_state = EXPR_BEG; break;
3837          }
3838          return '~';
3839  
3840        case '(':
3841          command_start = Qtrue;
3842          if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
3843              c = tLPAREN;
3844          }
3845          else if (space_seen) {
3846              if (lex_state == EXPR_CMDARG) {
3847                  c = tLPAREN_ARG;
3848              }
3849              else if (lex_state == EXPR_ARG) {
3850                  c = tLPAREN_ARG;
3851                  yylval.id = last_id;
3852              }
3853          }
3854          COND_PUSH(0);
3855          CMDARG_PUSH(0);
3856          lex_state = EXPR_BEG;
3857          return c;
3858  
3859        case '[':
3860          if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
3861              lex_state = EXPR_ARG;
3862              if ((c = nextc()) == ']') {
3863                  if ((c = nextc()) == '=') {
3864                      return tASET;
3865                  }
3866                  pushback(c);
3867                  return tAREF;
3868              }
3869              pushback(c);
3870              return '[';
3871          }
3872          else if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
3873              c = tLBRACK;
3874          }
3875          else if (IS_ARG() && space_seen) {
3876              c = tLBRACK;
3877          }
3878          lex_state = EXPR_BEG;
3879          COND_PUSH(0);
3880          CMDARG_PUSH(0);
3881          return c;
3882  
3883        case '{':
3884          if (IS_ARG() || lex_state == EXPR_END)
3885              c = '{';          /* block (primary) */
3886          else if (lex_state == EXPR_ENDARG)
3887              c = tLBRACE_ARG;  /* block (expr) */
3888          else
3889              c = tLBRACE;      /* hash */
3890          COND_PUSH(0);
3891          CMDARG_PUSH(0);
3892          lex_state = EXPR_BEG;
3893          return c;
3894  
3895        case '\\':
3896          c = nextc();
3897          if (c == '\n') {
3898              space_seen = 1;
3899              goto retry; /* skip \\n */
3900          }
3901          pushback(c);
3902          if (QUOTED_TERM_P(c)) {
3903              if (!(quoted_term & (1 << CHAR_BIT))) {
3904                  rb_warn("escaped terminator '%c' inside string interpolation", c);
3905                  quoted_term |= 1 << CHAR_BIT;
3906              }
3907              goto retry;
3908          }
3909          return '\\';
3910  
3911        case '%':
3912          if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
3913              int term;
3914              int paren;
3915  
3916              c = nextc();
3917            quotation:
3918              if (c == '\\' && WHEN_QUOTED_TERM(peek(quoted_term_char))) {
3919                  c = nextc();
3920                  if (!(quoted_term & (1 << CHAR_BIT))) {
3921                      rb_warn("escaped terminator '%s%c' inside string interpolation",
3922                              (c == '\'' ? "\\" : ""), c);
3923                      quoted_term |= 1 << CHAR_BIT;
3924                  }
3925              }
3926              if (!ISALNUM(c)) {
3927                  term = c;
3928                  c = 'Q';
3929              }
3930              else {
3931                  term = nextc();
3932                  if (ISALNUM(term) || ismbchar(term)) {
3933                      yyerror("unknown type of %string");
3934                      return 0;
3935                  }
3936              }
3937              if (c == -1 || term == -1) {
3938                  rb_compile_error("unterminated quoted string meets end of file");
3939                  return 0;
3940              }
3941              paren = term;
3942              if (term == '(') term = ')';
3943              else if (term == '[') term = ']';
3944              else if (term == '{') term = '}';
3945              else if (term == '<') term = '>';
3946              else paren = 0;
3947  
3948              switch (c) {
3949                case 'Q':
3950                  lex_strterm = NEW_STRTERM(str_dquote, term, paren);
3951                  return tSTRING_BEG;
3952  
3953                case 'q':
3954                  lex_strterm = NEW_STRTERM(str_squote, term, paren);
3955                  return tSTRING_BEG;
3956  
3957                case 'W':
3958                  lex_strterm = NEW_STRTERM(str_dquote | STR_FUNC_QWORDS, term, paren);
3959                  do {c = nextc();} while (ISSPACE(c));
3960                  pushback(c);
3961                  return tWORDS_BEG;
3962  
3963                case 'w':
3964                  lex_strterm = NEW_STRTERM(str_squote | STR_FUNC_QWORDS, term, paren);
3965                  do {c = nextc();} while (ISSPACE(c));
3966                  pushback(c);
3967                  return tQWORDS_BEG;
3968  
3969                case 'x':
3970                  lex_strterm = NEW_STRTERM(str_xquote, term, paren);
3971                  return tXSTRING_BEG;
3972  
3973                case 'r':
3974                  lex_strterm = NEW_STRTERM(str_regexp, term, paren);
3975                  return tREGEXP_BEG;
3976  
3977                default:
3978                  yyerror("unknown type of %string");
3979                  return 0;
3980              }
3981          }
3982          if ((c = nextc()) == '=') {
3983              yylval.id = '%';
3984              lex_state = EXPR_BEG;
3985              return tOP_ASGN;
3986          }
3987          if (IS_ARG() && space_seen && !ISSPACE(c)) {
3988              goto quotation;
3989          }
3990          switch (lex_state) {
3991            case EXPR_FNAME: case EXPR_DOT:
3992              lex_state = EXPR_ARG; break;
3993            default:
3994              lex_state = EXPR_BEG; break;
3995          }
3996          pushback(c);
3997          return '%';
3998  
3999        case '$':
4000          lex_state = EXPR_END;
4001          newtok();
4002          c = nextc();
4003          switch (c) {
4004            case '_':             /* $_: last read line string */
4005              c = nextc();
4006              if (is_identchar(c)) {
4007                  tokadd('$');
4008                  tokadd('_');
4009                  break;
4010              }
4011              pushback(c);
4012              c = '_';
4013              /* fall through */
4014            case '~':             /* $~: match-data */
4015              local_cnt(c);
4016              /* fall through */
4017            case '*':             /* $*: argv */
4018            case '$':             /* $$: pid */
4019            case '?':             /* $?: last status */
4020            case '!':             /* $!: error string */
4021            case '@':             /* $@: error position */
4022            case '/':             /* $/: input record separator */
4023            case '\\':            /* $\: output record separator */
4024            case ';':             /* $;: field separator */
4025            case ',':             /* $,: output field separator */
4026            case '.':             /* $.: last read line number */
4027            case '=':             /* $=: ignorecase */
4028            case ':':             /* $:: load path */
4029            case '<':             /* $<: reading filename */
4030            case '>':             /* $>: default output handle */
4031            case '\"':            /* $": already loaded files */
4032              tokadd('$');
4033              tokadd(c);
4034              tokfix();
4035              yylval.id = rb_intern(tok());
4036              return tGVAR;
4037  
4038            case '-':
4039              tokadd('$');
4040              tokadd(c);
4041              c = nextc();
4042              tokadd(c);
4043              tokfix();
4044              yylval.id = rb_intern(tok());
4045              /* xxx shouldn't check if valid option variable */
4046              return tGVAR;
4047  
4048            case '&':             /* $&: last match */
4049            case '`':             /* $`: string before last match */
4050            case '\'':            /* $': string after last match */
4051            case '+':             /* $+: string matches last paren. */
4052              yylval.node = NEW_BACK_REF(c);
4053              return tBACK_REF;
4054  
4055            case '1': case '2': case '3':
4056            case '4': case '5': case '6':
4057            case '7': case '8': case '9':
4058              tokadd('$');
4059              while (ISDIGIT(c)) {
4060                  tokadd(c);
4061                  c = nextc();
4062              }
4063              if (is_identchar(c))
4064                  break;
4065              pushback(c);
4066              tokfix();
4067              yylval.node = NEW_NTH_REF(atoi(tok()+1));
4068              return tNTH_REF;
4069  
4070            default:
4071              if (!is_identchar(c)) {
4072                  pushback(c);
4073                  return '$';
4074              }
4075            case '0':
4076              tokadd('$');
4077          }
4078          break;
4079  
4080        case '@':
4081          c = nextc();
4082          newtok();
4083          tokadd('@');
4084          if (c == '@') {
4085              tokadd('@');
4086              c = nextc();
4087          }
4088          if (ISDIGIT(c)) {
4089              if (tokidx == 1) {
4090                  rb_compile_error("`@%c' is not a valid instance variable name", c);
4091              }
4092              else {
4093                  rb_compile_error("`@@%c' is not a valid class variable name", c);
4094              }
4095          }
4096          if (!is_identchar(c)) {
4097              pushback(c);
4098              return '@';
4099          }
4100          break;
4101  
4102        default:
4103          if (!is_identchar(c) || ISDIGIT(c)) {
4104              rb_compile_error("Invalid char `\\%03o' in expression", c);
4105              goto retry;
4106          }
4107  
4108          newtok();
4109          break;
4110      }
4111  
4112      while (is_identchar(c)) {
4113          tokadd(c);
4114          if (ismbchar(c)) {
4115              int i, len = mbclen(c)-1;
4116  
4117              for (i = 0; i < len; i++) {
4118                  c = nextc();
4119                  tokadd(c);
4120              }
4121          }
4122          c = nextc();
4123      }
4124      if ((c == '!' || c == '?') && is_identchar(tok()[0]) && !peek('=')) {
4125          tokadd(c);
4126      }
4127      else {
4128          pushback(c);
4129      }
4130      tokfix();
4131  
4132      {
4133          int result = 0;
4134  
4135          switch (tok()[0]) {
4136            case '$':
4137              lex_state = EXPR_END;
4138              result = tGVAR;
4139              break;
4140            case '@':
4141              lex_state = EXPR_END;
4142              if (tok()[1] == '@')
4143                  result = tCVAR;
4144              else
4145                  result = tIVAR;
4146              break;
4147  
4148            default:
4149              if (toklast() == '!' || toklast() == '?') {
4150                  result = tFID;
4151              }
4152              else {
4153                  if (lex_state == EXPR_FNAME) {
4154                      if ((c = nextc()) == '=' && !peek('~') && !peek('>') &&
4155                          (!peek('=') || lex_p + 1 < lex_pend && lex_p[1] == '>')) {
4156                          result = tIDENTIFIER;
4157                          tokadd(c);
4158                      }
4159                      else {
4160                          pushback(c);
4161                      }
4162                  }
4163                  if (result == 0 && ISUPPER(tok()[0])) {
4164                      result = tCONSTANT;
4165                  }
4166                  else {
4167                      result = tIDENTIFIER;
4168                  }
4169              }
4170  
4171              if (lex_state != EXPR_DOT) {
4172                  struct kwtable *kw;
4173  
4174                  /* See if it is a reserved word.  */
4175                  kw = rb_reserved_word(tok(), toklen());
4176                  if (kw) {
4177                      enum lex_state state = lex_state;
4178                      lex_state = kw->state;
4179                      if (state == EXPR_FNAME) {
4180                          yylval.id = rb_intern(kw->name);
4181                      }
4182                      if (kw->id[0] == kDO) {
4183                          if (COND_P()) return kDO_COND;
4184                          if (CMDARG_P() && state != EXPR_CMDARG)
4185                              return kDO_BLOCK;
4186                          if (state == EXPR_ENDARG)
4187                              return kDO_BLOCK;
4188                          return kDO;
4189                      }
4190                      if (state == EXPR_BEG)
4191                          return kw->id[0];
4192                      else {
4193                          if (kw->id[0] != kw->id[1])
4194                              lex_state = EXPR_BEG;
4195                          return kw->id[1];
4196                      }
4197                  }
4198              }
4199  
4200              if (lex_state == EXPR_BEG ||
4201                  lex_state == EXPR_MID ||
4202                  lex_state == EXPR_DOT ||
4203                  lex_state == EXPR_ARG ||
4204                  lex_state == EXPR_CMDARG) {
4205                  if (cmd_state)
4206                      lex_state = EXPR_CMDARG;
4207                  else
4208                      lex_state = EXPR_ARG;
4209              }
4210              else {
4211                  lex_state = EXPR_END;
4212              }
4213          }
4214          tokfix();
4215          if (strcmp(tok(), "__END__") == 0 &&
4216              lex_p - lex_pbeg == 7 &&
4217              (lex_pend == lex_p || *lex_p == '\n' || *lex_p == '\r')) {
4218              ruby__end__seen = 1;
4219              lex_lastline = 0;
4220              return -1;
4221          }
4222          last_id = yylval.id = rb_intern(tok());
4223          return result;
4224      }
4225  }
4226  
4227  NODE*
4228  rb_node_newnode(type, a0, a1, a2)
4229      enum node_type type;
4230      NODE *a0, *a1, *a2;
4231  {
4232      NODE *n = (NODE*)rb_newobj();
4233  
4234      n->flags |= T_NODE;
4235      nd_set_type(n, type);
4236      nd_set_line(n, ruby_sourceline);
4237      n->nd_file = ruby_sourcefile;
4238  
4239      n->u1.node = a0;
4240      n->u2.node = a1;
4241      n->u3.node = a2;
4242  
4243      return n;
4244  }
4245  
4246  static enum node_type
4247  nodetype(node)                  /* for debug */
4248      NODE *node;
4249  {
4250      return (enum node_type)nd_type(node);
4251  }
4252  
4253  static int
4254  nodeline(node)
4255      NODE *node;
4256  {
4257      return nd_line(node);
4258  }
4259  
4260  static NODE*
4261  newline_node(node)
4262      NODE *node;
4263  {
4264      NODE *nl = 0;
4265      if (node) {
4266          nl = NEW_NEWLINE(node);
4267          fixpos(nl, node);
4268          nl->nd_nth = nd_line(node);
4269      }
4270      return nl;
4271  }
4272  
4273  static void
4274  fixpos(node, orig)
4275      NODE *node, *orig;
4276  {
4277      if (!node) return;
4278      if (!orig) return;
4279      if (orig == (NODE*)1) return;
4280      node->nd_file = orig->nd_file;
4281      nd_set_line(node, nd_line(orig));
4282  }
4283  
4284  static NODE*
4285  block_append(head, tail)
4286      NODE *head, *tail;
4287  {
4288      NODE *end;
4289  
4290      if (tail == 0) return head;
4291      if (head == 0) return tail;
4292  
4293      if (nd_type(head) != NODE_BLOCK) {
4294          end = NEW_BLOCK(head);
4295          end->nd_end = end;
4296          fixpos(end, head);
4297          head = end;
4298      }
4299      else {
4300          end = head->nd_end;
4301      }
4302  
4303      if (RTEST(ruby_verbose)) {
4304          NODE *nd = end->nd_head;
4305        newline:
4306          switch (nd_type(nd)) {
4307            case NODE_RETURN:
4308            case NODE_BREAK:
4309            case NODE_NEXT:
4310            case NODE_REDO:
4311            case NODE_RETRY:
4312              rb_warning("statement not reached");
4313              break;
4314  
4315          case NODE_NEWLINE:
4316              nd = nd->nd_next;
4317              goto newline;
4318  
4319            default:
4320              break;
4321          }
4322      }
4323  
4324      if (nd_type(tail) != NODE_BLOCK) {
4325          tail = NEW_BLOCK(tail);
4326          tail->nd_end = tail;
4327      }
4328      end->nd_next = tail;
4329      head->nd_end = tail->nd_end;
4330      return head;
4331  }
4332  
4333  /* append item to the list */
4334  static NODE*
4335  list_append(list, item)
4336      NODE *list, *item;
4337  {
4338      NODE *last;
4339  
4340      if (list == 0) return NEW_LIST(item);
4341  
4342      last = list;
4343      while (last->nd_next) {
4344          last = last->nd_next;
4345      }
4346  
4347      last->nd_next = NEW_LIST(item);
4348      list->nd_alen += 1;
4349      return list;
4350  }
4351  
4352  /* concat two lists */
4353  static NODE*
4354  list_concat(head, tail)
4355      NODE *head, *tail;
4356  {
4357      NODE *last;
4358  
4359      last = head;
4360      while (last->nd_next) {
4361          last = last->nd_next;
4362      }
4363  
4364      last->nd_next = tail;
4365      head->nd_alen += tail->nd_alen;
4366  
4367      return head;
4368  }
4369  
4370  static NODE *
4371  literal_concat_string(head, tail, str)
4372      NODE *head, *tail;
4373      VALUE str;
4374  {
4375      NODE *last = head, *last1 = 0, *prev = 0;
4376  
4377      for (;;) {
4378          switch (nd_type(last)) {
4379            case NODE_NEWLINE:
4380              last = last->nd_next;
4381              break;
4382            case NODE_BLOCK:
4383            case NODE_DSTR:
4384              if (!last1) last1 = prev;
4385              prev = last;
4386              while (last->nd_next) {
4387                  last = last->nd_next;
4388              }
4389              last = last->nd_head;
4390              break;
4391            case NODE_STR:
4392              rb_str_concat(last->nd_lit, str);
4393              if (tail) rb_gc_force_recycle((VALUE)tail);
4394              return head;
4395            default:
4396              if (!last1) {
4397                  last1 = head;
4398                  head = NEW_DSTR(rb_str_new(0, 0));
4399                  head->nd_next = last1 = NEW_LIST(last1);
4400                  head->nd_alen += 1;
4401              }
4402              if (!tail) tail = NEW_STR(str);
4403              list_append(head, tail);
4404              return head;
4405          }
4406      }
4407  }
4408  
4409  static NODE *
4410  literal_concat_dstr(head, tail)
4411      NODE *head, *tail;
4412  {
4413      NODE *last;
4414  
4415      switch (nd_type(head)) {
4416        case NODE_STR:
4417          tail->nd_lit = head->nd_lit;
4418          rb_gc_force_recycle((VALUE)head);
4419          return tail;
4420        case NODE_DSTR:
4421          last = tail->nd_next;
4422          last->nd_alen = tail->nd_alen;
4423          rb_gc_force_recycle((VALUE)tail);
4424          return list_concat(head, last);
4425        default:
4426          head = NEW_LIST(head);
4427        case NODE_ARRAY:
4428        case NODE_ZARRAY:
4429          tail->nd_lit = 0;
4430          tail->nd_alen += head->nd_alen;
4431          tail->nd_next = list_concat(head, tail->nd_next);
4432          return tail;
4433      }
4434  }
4435  
4436  static NODE *
4437  literal_concat_list(head, tail)
4438      NODE *head, *tail;
4439  {
4440      tail = NEW_LIST(tail);
4441      switch (nd_type(head)) {
4442        case NODE_STR:
4443          nd_set_type(head, NODE_DSTR);
4444          head->nd_next = tail;
4445          head->nd_alen = tail->nd_alen;
4446          return head;
4447        case NODE_DSTR:
4448          return list_concat(head, tail);
4449        default:
4450          head = NEW_LIST(head);
4451          return list_concat(NEW_DSTR(rb_str_new(0, 0)), list_concat(head, tail));
4452      }
4453  }
4454  
4455  static NODE *
4456  literal_append(head, tail)
4457      NODE *head, *tail;
4458  {
4459      if (!head) return tail;
4460      if (!tail) return head;
4461  
4462      switch (nd_type(tail)) {
4463        case NODE_STR:
4464          if (nd_type(head) == NODE_STR) {
4465              rb_str_concat(head->nd_lit, tail->nd_lit);
4466              rb_gc_force_recycle((VALUE)tail);
4467              return head;
4468          }
4469  
4470        default:
4471          return literal_concat_list(head, tail);
4472      }
4473  }
4474  
4475  /* concat two string literals */
4476  static NODE *
4477  literal_concat(head, tail)
4478      NODE *head, *tail;
4479  {
4480      if (!head) return tail;
4481      if (!tail) return head;
4482  
4483      switch (nd_type(tail)) {
4484        case NODE_STR:
4485          return literal_concat_string(head, tail, tail->nd_lit);
4486  
4487        case NODE_DSTR:
4488          head = literal_concat_string(head, 0, tail->nd_lit);
4489          return literal_concat_dstr(head, tail);
4490  
4491        default:
4492          return literal_concat_list(head, tail);
4493      }
4494  }
4495  
4496  static NODE *
4497  call_op(recv, id, narg, arg1)
4498      NODE *recv;
4499      ID id;
4500      int narg;
4501      NODE *arg1;
4502  {
4503      value_expr(recv);
4504      if (narg == 1) {
4505          value_expr(arg1);
4506      }
4507  
4508      return NEW_CALL(recv, id, narg==1?NEW_LIST(arg1):0);
4509  }
4510  
4511  static NODE*
4512  match_gen(node1, node2)
4513      NODE *node1;
4514      NODE *node2;
4515  {
4516      local_cnt('~');
4517  
4518      value_expr(node1);
4519      value_expr(node2);
4520      if (node1) {
4521          switch (nd_type(node1)) {
4522            case NODE_DREGX:
4523            case NODE_DREGX_ONCE:
4524              return NEW_MATCH2(node1, node2);
4525  
4526            case NODE_LIT:
4527              if (TYPE(node1->nd_lit) == T_REGEXP) {
4528                  return NEW_MATCH2(node1, node2);
4529              }
4530          }
4531      }
4532  
4533      if (node2) {
4534          switch (nd_type(node2)) {
4535            case NODE_DREGX:
4536            case NODE_DREGX_ONCE:
4537              return NEW_MATCH3(node2, node1);
4538  
4539            case NODE_LIT:
4540              if (TYPE(node2->nd_lit) == T_REGEXP) {
4541                  return NEW_MATCH3(node2, node1);
4542              }
4543          }
4544      }
4545  
4546      return NEW_CALL(node1, tMATCH, NEW_LIST(node2));
4547  }
4548  
4549  static NODE*
4550  gettable(id)
4551      ID id;
4552  {
4553      if (id == kSELF) {
4554          return NEW_SELF();
4555      }
4556      else if (id == kNIL) {
4557          return NEW_NIL();
4558      }
4559      else if (id == kTRUE) {
4560          return NEW_TRUE();
4561      }
4562      else if (id == kFALSE) {
4563          return NEW_FALSE();
4564      }
4565      else if (id == k__FILE__) {
4566          return NEW_STR(rb_str_new2(ruby_sourcefile));
4567      }
4568      else if (id == k__LINE__) {
4569          return NEW_LIT(INT2FIX(ruby_sourceline));
4570      }
4571      else if (is_local_id(id)) {
4572          if (dyna_in_block() && rb_dvar_defined(id)) return NEW_DVAR(id);
4573          if (local_id(id)) return NEW_LVAR(id);
4574          /* method call without arguments */
4575  #if 0
4576          /* Rite will warn this */
4577          rb_warn("ambiguous identifier; %s() or self.%s is better for method call",
4578                  rb_id2name(id), rb_id2name(id));
4579  #endif
4580          return NEW_VCALL(id);
4581      }
4582      else if (is_global_id(id)) {
4583          return NEW_GVAR(id);
4584      }
4585      else if (is_instance_id(id)) {
4586          return NEW_IVAR(id);
4587      }
4588      else if (is_const_id(id)) {
4589          return NEW_CONST(id);
4590      }
4591      else if (is_class_id(id)) {
4592          return NEW_CVAR(id);
4593      }
4594      rb_compile_error("identifier %s is not valid", rb_id2name(id));
4595      return 0;
4596  }
4597  
4598  static NODE*
4599  assignable(id, val)
4600      ID id;
4601      NODE *val;
4602  {
4603      value_expr(val);
4604      if (id == kSELF) {
4605          yyerror("Can't change the value of self");
4606      }
4607      else if (id == kNIL) {
4608          yyerror("Can't assign to nil");
4609      }
4610      else if (id == kTRUE) {
4611          yyerror("Can't assign to true");
4612      }
4613      else if (id == kFALSE) {
4614          yyerror("Can't assign to false");
4615      }
4616      else if (id == k__FILE__) {
4617          yyerror("Can't assign to __FILE__");
4618      }
4619      else if (id == k__LINE__) {
4620          yyerror("Can't assign to __LINE__");
4621      }
4622      else if (is_local_id(id)) {
4623          if (rb_dvar_curr(id)) {
4624              return NEW_DASGN_CURR(id, val);
4625          }
4626          else if (rb_dvar_defined(id)) {
4627              return NEW_DASGN(id, val);
4628          }
4629          else if (local_id(id) || !dyna_in_block()) {
4630              return NEW_LASGN(id, val);
4631          }
4632          else{
4633              rb_dvar_push(id, Qnil);
4634              return NEW_DASGN_CURR(id, val);
4635          }
4636      }
4637      else if (is_global_id(id)) {
4638          return NEW_GASGN(id, val);
4639      }
4640      else if (is_instance_id(id)) {
4641          return NEW_IASGN(id, val);
4642      }
4643      else if (is_const_id(id)) {
4644          if (in_def || in_single)
4645              yyerror("dynamic constant assignment");
4646          return NEW_CDECL(id, val);
4647      }
4648      else if (is_class_id(id)) {
4649          if (in_def || in_single) return NEW_CVASGN(id, val);
4650          return NEW_CVDECL(id, val);
4651      }
4652      else {
4653          rb_bug("bad id for variable");
4654      }
4655      return 0;
4656  }
4657  
4658  static NODE *
4659  aryset(recv, idx)
4660      NODE *recv, *idx;
4661  {
4662      value_expr(recv);
4663      return NEW_CALL(recv, tASET, idx);
4664  }
4665  
4666  ID
4667  rb_id_attrset(id)
4668      ID id;
4669  {
4670      id &= ~ID_SCOPE_MASK;
4671      id |= ID_ATTRSET;
4672      return id;
4673  }
4674  
4675  static NODE *
4676  attrset(recv, id)
4677      NODE *recv;
4678      ID id;
4679  {
4680      value_expr(recv);
4681      return NEW_CALL(recv, rb_id_attrset(id), 0);
4682  }
4683  
4684  static void
4685  rb_backref_error(node)
4686      NODE *node;
4687  {
4688      switch (nd_type(node)) {
4689        case NODE_NTH_REF:
4690          rb_compile_error("Can't set variable $%d", node->nd_nth);
4691          break;
4692        case NODE_BACK_REF:
4693          rb_compile_error("Can't set variable $%c", node->nd_nth);
4694          break;
4695      }
4696  }
4697  
4698  static NODE *
4699  arg_concat(node1, node2)
4700      NODE *node1;
4701      NODE *node2;
4702  {
4703      if (!node2) return node1;
4704      return NEW_ARGSCAT(node1, node2);
4705  }
4706  
4707  static NODE *
4708  arg_add(node1, node2)
4709      NODE *node1;
4710      NODE *node2;
4711  {
4712      if (!node1) return NEW_LIST(node2);
4713      if (nd_type(node1) == NODE_ARRAY) {
4714          return list_append(node1, node2);
4715      }
4716      else {
4717          return NEW_ARGSPUSH(node1, node2);
4718      }
4719  }
4720  
4721  static NODE*
4722  node_assign(lhs, rhs)
4723      NODE *lhs, *rhs;
4724  {
4725      if (!lhs) return 0;
4726  
4727      value_expr(rhs);
4728      switch (nd_type(lhs)) {
4729        case NODE_GASGN:
4730        case NODE_IASGN:
4731        case NODE_LASGN:
4732        case NODE_DASGN:
4733        case NODE_DASGN_CURR:
4734        case NODE_MASGN:
4735        case NODE_CDECL:
4736        case NODE_CVDECL:
4737        case NODE_CVASGN:
4738          lhs->nd_value = rhs;
4739          break;
4740  
4741        case NODE_CALL:
4742          lhs->nd_args = arg_add(lhs->nd_args, rhs);
4743          break;
4744  
4745        default:
4746          /* should not happen */
4747          break;
4748      }
4749  
4750      return lhs;
4751  }
4752  
4753  static int
4754  value_expr(node)
4755      NODE *node;
4756  {
4757      while (node) {
4758          switch (nd_type(node)) {
4759            case NODE_CLASS:
4760            case NODE_MODULE:
4761            case NODE_DEFN:
4762            case NODE_DEFS:
4763              rb_warning("void value expression");
4764              return Qfalse;
4765  
4766            case NODE_RETURN:
4767            case NODE_BREAK:
4768            case NODE_NEXT:
4769            case NODE_REDO:
4770            case NODE_RETRY:
4771              yyerror("void value expression");
4772              /* or "control never reach"? */
4773              return Qfalse;
4774  
4775            case NODE_BLOCK:
4776              while (node->nd_next) {
4777                  node = node->nd_next;
4778              }
4779              node = node->nd_head;
4780              break;
4781  
4782            case NODE_BEGIN:
4783              node = node->nd_body;
4784              break;
4785  
4786            case NODE_IF:
4787              if (!value_expr(node->nd_body)) return Qfalse;
4788              node = node->nd_else;
4789              break;
4790  
4791            case NODE_AND:
4792            case NODE_OR:
4793              node = node->nd_2nd;
4794              break;
4795  
4796            case NODE_NEWLINE:
4797              node = node->nd_next;
4798              break;
4799  
4800            default:
4801              return Qtrue;
4802          }
4803      }
4804  
4805      return Qtrue;
4806  }
4807  
4808  static void
4809  void_expr(node)
4810      NODE *node;
4811  {
4812      char *useless = 0;
4813  
4814      if (!RTEST(ruby_verbose)) return;
4815      if (!node) return;
4816  
4817    again:
4818      switch (nd_type(node)) {
4819        case NODE_NEWLINE:
4820          node = node->nd_next;
4821          goto again;
4822  
4823        case NODE_CALL:
4824          switch (node->nd_mid) {
4825            case '+':
4826            case '-':
4827            case '*':
4828            case '/':
4829            case '%':
4830            case tPOW:
4831            case tUPLUS:
4832            case tUMINUS:
4833            case '|':
4834            case '^':
4835            case '&':
4836            case tCMP:
4837            case '>':
4838            case tGEQ:
4839            case '<':
4840            case tLEQ:
4841            case tEQ:
4842            case tNEQ:
4843              useless = rb_id2name(node->nd_mid);
4844              break;
4845          }
4846          break;
4847  
4848        case NODE_LVAR:
4849        case NODE_DVAR:
4850        case NODE_GVAR:
4851        case NODE_IVAR:
4852        case NODE_CVAR:
4853        case NODE_NTH_REF:
4854        case NODE_BACK_REF:
4855          useless = "a variable";
4856          break;
4857        case NODE_CONST:
4858        case NODE_CREF:
4859          useless = "a constant";
4860          break;
4861        case NODE_LIT:
4862        case NODE_STR:
4863        case NODE_DSTR:
4864        case NODE_DREGX:
4865        case NODE_DREGX_ONCE:
4866          useless = "a literal";
4867          break;
4868        case NODE_COLON2:
4869        case NODE_COLON3:
4870          useless = "::";
4871          break;
4872        case NODE_DOT2:
4873          useless = "..";
4874          break;
4875        case NODE_DOT3:
4876          useless = "...";
4877          break;
4878        case NODE_SELF:
4879          useless = "self";
4880          break;
4881        case NODE_NIL:
4882          useless = "nil";
4883          break;
4884        case NODE_TRUE:
4885          useless = "true";
4886          break;
4887        case NODE_FALSE:
4888          useless = "false";
4889          break;
4890        case NODE_DEFINED:
4891          useless = "defined?";
4892          break;
4893      }
4894  
4895      if (useless) {
4896          int line = ruby_sourceline;
4897  
4898          ruby_sourceline = nd_line(node);
4899          rb_warn("useless use of %s in void context", useless);
4900          ruby_sourceline = line;
4901      }
4902  }
4903  
4904  static void
4905  void_stmts(node)
4906      NODE *node;
4907  {
4908      if (!RTEST(ruby_verbose)) return;
4909      if (!node) return;
4910      if (nd_type(node) != NODE_BLOCK) return;
4911  
4912      for (;;) {
4913          if (!node->nd_next) return;
4914          void_expr(node->nd_head);
4915          node = node->nd_next;
4916      }
4917  }
4918  
4919  static int
4920  assign_in_cond(node)
4921      NODE *node;
4922  {
4923      switch (nd_type(node)) {
4924        case NODE_MASGN:
4925          yyerror("multiple assignment in conditional");
4926          return 1;
4927  
4928        case NODE_LASGN:
4929        case NODE_DASGN:
4930        case NODE_GASGN:
4931        case NODE_IASGN:
4932          break;
4933  
4934        case NODE_NEWLINE:
4935        default:
4936          return 0;
4937      }
4938  
4939      switch (nd_type(node->nd_value)) {
4940        case NODE_LIT:
4941        case NODE_STR:
4942        case NODE_NIL:
4943        case NODE_TRUE:
4944        case NODE_FALSE:
4945          /* reports always */
4946          rb_warn("found = in conditional, should be ==");
4947          return 1;
4948  
4949        case NODE_DSTR:
4950        case NODE_XSTR:
4951        case NODE_DXSTR:
4952        case NODE_EVSTR:
4953        case NODE_DREGX:
4954        default:
4955          break;
4956      }
4957  #if 0
4958      if (assign_in_cond(node->nd_value) == 0) {
4959          rb_warning("assignment in condition");
4960      }
4961  #endif
4962      return 1;
4963  }
4964  
4965  static int
4966  e_option_supplied()
4967  {
4968      if (strcmp(ruby_sourcefile, "-e") == 0)
4969          return Qtrue;
4970      return Qfalse;
4971  }
4972  
4973  static void
4974  warn_unless_e_option(str)
4975      const char *str;
4976  {
4977      if (!e_option_supplied()) rb_warn(str);
4978  }
4979  
4980  static void
4981  warning_unless_e_option(str)
4982      const char *str;
4983  {
4984      if (!e_option_supplied()) rb_warning(str);
4985  }
4986  
4987  static NODE *cond0();
4988  
4989  static NODE*
4990  range_op(node)
4991      NODE *node;
4992  {
4993      enum node_type type;
4994  
4995      if (!e_option_supplied()) return node;
4996      if (node == 0) return 0;
4997  
4998      value_expr(node);
4999      node = cond0(node);
5000      type = nd_type(node);
5001      if (type == NODE_NEWLINE) node = node->nd_next;
5002      if (type == NODE_LIT && FIXNUM_P(node->nd_lit)) {
5003          warn_unless_e_option("integer literal in conditional range");
5004          return call_op(node,tEQ,1,NEW_GVAR(rb_intern("$.")));
5005      }
5006      return node;
5007  }
5008  
5009  static NODE*
5010  cond0(node)
5011      NODE *node;
5012  {
5013      enum node_type type = nd_type(node);
5014  
5015      assign_in_cond(node);
5016  
5017      switch (type) {
5018        case NODE_DSTR:
5019        case NODE_STR:
5020          rb_warn("string literal in condition");
5021          break;
5022  
5023        case NODE_DREGX:
5024        case NODE_DREGX_ONCE:
5025          warning_unless_e_option("regex literal in condition");
5026          local_cnt('_');
5027          local_cnt('~');
5028          return NEW_MATCH2(node, NEW_GVAR(rb_intern("$_")));
5029  
5030        case NODE_AND:
5031        case NODE_OR:
5032          node->nd_1st = cond0(node->nd_1st);
5033          node->nd_2nd = cond0(node->nd_2nd);
5034          break;
5035  
5036        case NODE_DOT2:
5037        case NODE_DOT3:
5038          node->nd_beg = range_op(node->nd_beg);
5039          node->nd_end = range_op(node->nd_end);
5040          if (type == NODE_DOT2) nd_set_type(node,NODE_FLIP2);
5041          else if (type == NODE_DOT3) nd_set_type(node, NODE_FLIP3);
5042          node->nd_cnt = local_append(internal_id());
5043          warning_unless_e_option("range literal in condition");
5044          break;
5045  
5046        case NODE_LIT:
5047          if (TYPE(node->nd_lit) == T_REGEXP) {
5048              warn_unless_e_option("regex literal in condition");
5049              nd_set_type(node, NODE_MATCH);
5050              local_cnt('_');
5051              local_cnt('~');
5052          }
5053          else {
5054              rb_warning("literal in condition");
5055          }
5056        default:
5057          break;
5058      }
5059      return node;
5060  }
5061  
5062  static NODE*
5063  cond(node)
5064      NODE *node;
5065  {
5066      if (node == 0) return 0;
5067      value_expr(node);
5068      if (nd_type(node) == NODE_NEWLINE){
5069          node->nd_next = cond0(node->nd_next);
5070          return node;
5071      }
5072      return cond0(node);
5073  }
5074  
5075  static NODE*
5076  logop(type, left, right)
5077      enum node_type type;
5078      NODE *left, *right;
5079  {
5080      value_expr(left);
5081      if (nd_type(left) == type) {
5082          NODE *node = left, *second;
5083          while ((second = node->nd_2nd) != 0 && nd_type(second) == type) {
5084              node = second;
5085          }
5086          node->nd_2nd = rb_node_newnode(type, second, right, 0);
5087          return left;
5088      }
5089      return rb_node_newnode(type, left, right, 0);
5090  }
5091  
5092  static NODE *
5093  ret_args(node)
5094      NODE *node;
5095  {
5096      if (node) {
5097          if (nd_type(node) == NODE_BLOCK_PASS) {
5098              rb_compile_error("block argument should not be given");
5099          }
5100      }
5101      return node;
5102  }
5103  
5104  static NODE *
5105  arg_blk_pass(node1, node2)
5106      NODE *node1;
5107      NODE *node2;
5108  {
5109      if (node2) {
5110          node2->nd_head = node1;
5111          return node2;
5112      }
5113      return node1;
5114  }
5115  
5116  static NODE*
5117  arg_prepend(node1, node2)
5118      NODE *node1, *node2;
5119  {
5120      switch (nodetype(node2)) {
5121        case NODE_ARRAY:
5122          return list_concat(NEW_LIST(node1), node2);
5123  
5124        case NODE_RESTARGS:
5125          return arg_concat(node1, node2->nd_head);
5126  
5127        case NODE_BLOCK_PASS:
5128          node2->nd_body = arg_prepend(node1, node2->nd_body);
5129          return node2;
5130  
5131        default:
5132          rb_bug("unknown nodetype(%d) for arg_prepend", nodetype(node2));
5133      }
5134      return 0;                   /* not reached */
5135  }
5136  
5137  static NODE*
5138  new_call(r,m,a)
5139      NODE *r;
5140      ID m;
5141      NODE *a;
5142  {
5143      if (a && nd_type(a) == NODE_BLOCK_PASS) {
5144          a->nd_iter = NEW_CALL(r,m,a->nd_head);
5145          return a;
5146      }
5147      return NEW_CALL(r,m,a);
5148  }
5149  
5150  static NODE*
5151  new_fcall(m,a)
5152      ID m;
5153      NODE *a;
5154  {
5155      if (a && nd_type(a) == NODE_BLOCK_PASS) {
5156          a->nd_iter = NEW_FCALL(m,a->nd_head);
5157          return a;
5158      }
5159      return NEW_FCALL(m,a);
5160  }
5161  
5162  static NODE*
5163  new_super(a)
5164      NODE *a;
5165  {
5166      if (a && nd_type(a) == NODE_BLOCK_PASS) {
5167          a->nd_iter = NEW_SUPER(a->nd_head);
5168          return a;
5169      }
5170      return NEW_SUPER(a);
5171  }
5172  
5173  static struct local_vars {
5174      ID *tbl;
5175      int nofree;
5176      int cnt;
5177      int dlev;
5178      struct RVarmap* dyna_vars;
5179      struct local_vars *prev;
5180  } *lvtbl;
5181  
5182  static void
5183  local_push(top)
5184      int top;
5185  {
5186      struct local_vars *local;
5187  
5188      local = ALLOC(struct local_vars);
5189      local->prev = lvtbl;
5190      local->nofree = 0;
5191      local->cnt = 0;
5192      local->tbl = 0;
5193      local->dlev = 0;
5194      local->dyna_vars = ruby_dyna_vars;
5195      lvtbl = local;
5196      if (!top) {
5197          /* preserve reference for GC, but link should be cut. */
5198          rb_dvar_push(0, (VALUE)ruby_dyna_vars);
5199          ruby_dyna_vars->next = 0;
5200      }
5201  }
5202  
5203  static void
5204  local_pop()
5205  {
5206      struct local_vars *local = lvtbl->prev;
5207  
5208      if (lvtbl->tbl) {
5209          if (!lvtbl->nofree) free(lvtbl->tbl);
5210          else lvtbl->tbl[0] = lvtbl->cnt;
5211      }
5212      ruby_dyna_vars = lvtbl->dyna_vars;
5213      free(lvtbl);
5214      lvtbl = local;
5215  }
5216  
5217  static ID*
5218  local_tbl()
5219  {
5220      lvtbl->nofree = 1;
5221      return lvtbl->tbl;
5222  }
5223  
5224  static int
5225  local_append(id)
5226      ID id;
5227  {
5228      if (lvtbl->tbl == 0) {
5229          lvtbl->tbl = ALLOC_N(ID, 4);
5230          lvtbl->tbl[0] = 0;
5231          lvtbl->tbl[1] = '_';
5232          lvtbl->tbl[2] = '~';
5233          lvtbl->cnt = 2;
5234          if (id == '_') return 0;
5235          if (id == '~') return 1;
5236      }
5237      else {
5238          REALLOC_N(lvtbl->tbl, ID, lvtbl->cnt+2);
5239      }
5240  
5241      lvtbl->tbl[lvtbl->cnt+1] = id;
5242      return lvtbl->cnt++;
5243  }
5244  
5245  static int
5246  local_cnt(id)
5247      ID id;
5248  {
5249      int cnt, max;
5250  
5251      if (id == 0) return lvtbl->cnt;
5252  
5253      for (cnt=1, max=lvtbl->cnt+1; cnt<max;cnt++) {
5254          if (lvtbl->tbl[cnt] == id) return cnt-1;
5255      }
5256      return local_append(id);
5257  }
5258  
5259  static int
5260  local_id(id)
5261      ID id;
5262  {
5263      int i, max;
5264  
5265      if (lvtbl == 0) return Qfalse;
5266      for (i=3, max=lvtbl->cnt+1; i<max; i++) {
5267          if (lvtbl->tbl[i] == id) return Qtrue;
5268      }
5269      return Qfalse;
5270  }
5271  
5272  static void
5273  top_local_init()
5274  {
5275      local_push(1);
5276      lvtbl->cnt = ruby_scope->local_tbl?ruby_scope->local_tbl[0]:0;
5277      if (lvtbl->cnt > 0) {
5278          lvtbl->tbl = ALLOC_N(ID, lvtbl->cnt+3);
5279          MEMCPY(lvtbl->tbl, ruby_scope->local_tbl, ID, lvtbl->cnt+1);
5280      }
5281      else {
5282          lvtbl->tbl = 0;
5283      }
5284      if (ruby_dyna_vars)
5285          lvtbl->dlev = 1;
5286      else
5287          lvtbl->dlev = 0;
5288  }
5289  
5290  static void
5291  top_local_setup()
5292  {
5293      int len = lvtbl->cnt;
5294      int i;
5295  
5296      if (len > 0) {
5297          i = ruby_scope->local_tbl?ruby_scope->local_tbl[0]:0;
5298  
5299          if (i < len) {
5300              if (i == 0 || (ruby_scope->flags & SCOPE_MALLOC) == 0) {
5301                  VALUE *vars = ALLOC_N(VALUE, len+1);
5302                  if (ruby_scope->local_vars) {
5303                      *vars++ = ruby_scope->local_vars[-1];
5304                      MEMCPY(vars, ruby_scope->local_vars, VALUE, i);
5305                      rb_mem_clear(vars+i, len-i);
5306                  }
5307                  else {
5308                      *vars++ = 0;
5309                      rb_mem_clear(vars, len);
5310                  }
5311                  ruby_scope->local_vars = vars;
5312                  ruby_scope->flags |= SCOPE_MALLOC;
5313              }
5314              else {
5315                  VALUE *vars = ruby_scope->local_vars-1;
5316                  REALLOC_N(vars, VALUE, len+1);
5317                  ruby_scope->local_vars = vars+1;
5318                  rb_mem_clear(ruby_scope->local_vars+i, len-i);
5319              }
5320              if (ruby_scope->local_tbl && ruby_scope->local_vars[-1] == 0) {
5321                  free(ruby_scope->local_tbl);
5322              }
5323              ruby_scope->local_vars[-1] = 0;
5324              ruby_scope->local_tbl = local_tbl();
5325          }
5326      }
5327      local_pop();
5328  }
5329  
5330  static struct RVarmap*
5331  dyna_push()
5332  {
5333      struct RVarmap* vars = ruby_dyna_vars;
5334  
5335      rb_dvar_push(0, 0);
5336      lvtbl->dlev++;
5337      return vars;
5338  }
5339  
5340  static void
5341  dyna_pop(vars)
5342      struct RVarmap* vars;
5343  {
5344      lvtbl->dlev--;
5345      ruby_dyna_vars = vars;
5346  }
5347  
5348  static int
5349  dyna_in_block()
5350  {
5351      return (lvtbl->dlev > 0);
5352  }
5353  
5354  int
5355  ruby_parser_stack_on_heap()
5356  {
5357  #if defined(YYBISON) && !defined(C_ALLOCA)
5358      return Qfalse;
5359  #else
5360      return Qtrue;
5361  #endif
5362  }
5363  
5364  void
5365  rb_gc_mark_parser()
5366  {
5367      if (!ruby_in_compile) return;
5368  
5369      rb_gc_mark_maybe((VALUE)yylval.node);
5370      rb_gc_mark(ruby_debug_lines);
5371      rb_gc_mark(lex_lastline);
5372      rb_gc_mark(lex_input);
5373      rb_gc_mark((VALUE)lex_strterm);
5374  }
5375  
5376  void
5377  rb_parser_append_print()
5378  {
5379      ruby_eval_tree =
5380          block_append(ruby_eval_tree,
5381                       NEW_FCALL(rb_intern("print"),
5382                                 NEW_ARRAY(NEW_GVAR(rb_intern("$_")))));
5383  }
5384  
5385  void
5386  rb_parser_while_loop(chop, split)
5387      int chop, split;
5388  {
5389      if (split) {
5390          ruby_eval_tree =
5391              block_append(NEW_GASGN(rb_intern("$F"),
5392                                     NEW_CALL(NEW_GVAR(rb_intern("$_")),
5393                                              rb_intern("split"), 0)),
5394                                     ruby_eval_tree);
5395      }
5396      if (chop) {
5397          ruby_eval_tree =
5398              block_append(NEW_CALL(NEW_GVAR(rb_intern("$_")),
5399                                    rb_intern("chop!"), 0), ruby_eval_tree);
5400      }
5401      ruby_eval_tree = NEW_OPT_N(ruby_eval_tree);
5402  }
5403  
5404  static struct {
5405      ID token;
5406      char *name;
5407  } op_tbl[] = {
5408      {tDOT2,     ".."},
5409      {tDOT3,     "..."},
5410      {'+',       "+"},
5411      {'-',       "-"},
5412      {'+',       "+(binary)"},
5413      {'-',       "-(binary)"},
5414      {'*',       "*"},
5415      {'/',       "/"},
5416      {'%',       "%"},
5417      {tPOW,      "**"},
5418      {tUPLUS,    "+@"},
5419      {tUMINUS,   "-@"},
5420      {tUPLUS,    "+(unary)"},
5421      {tUMINUS,   "-(unary)"},
5422      {'|',       "|"},
5423      {'^',       "^"},
5424      {'&',       "&"},
5425      {tCMP,      "<=>"},
5426      {'>',       ">"},
5427      {tGEQ,      ">="},
5428      {'<',       "<"},
5429      {tLEQ,      "<="},
5430      {tEQ,       "=="},
5431      {tEQQ,      "==="},
5432      {tNEQ,      "!="},
5433      {tMATCH,    "=~"},
5434      {tNMATCH,   "!~"},
5435      {'!',       "!"},
5436      {'~',       "~"},
5437      {'!',       "!(unary)"},
5438      {'~',       "~(unary)"},
5439      {'!',       "!@"},
5440      {'~',       "~@"},
5441      {tAREF,     "[]"},
5442      {tASET,     "[]="},
5443      {tLSHFT,    "<<"},
5444      {tRSHFT,    ">>"},
5445      {tCOLON2,   "::"},
5446      {'`',       "`"},
5447      {0, 0}
5448  };
5449  
5450  static st_table *sym_tbl;
5451  static st_table *sym_rev_tbl;
5452  
5453  void
5454  Init_sym()
5455  {
5456      sym_tbl = st_init_strtable_with_size(200);
5457      sym_rev_tbl = st_init_numtable_with_size(200);
5458  }
5459  
5460  static ID last_id = LAST_TOKEN;
5461  
5462  static ID
5463  internal_id()
5464  {
5465      return ID_INTERNAL | (++last_id << ID_SCOPE_SHIFT);
5466  }
5467  
5468  ID
5469  rb_intern(name)
5470      const char *name;
5471  {
5472      const char *m = name;
5473      ID id;
5474      int last;
5475  
5476      if (st_lookup(sym_tbl, name, &id))
5477          return id;
5478  
5479      id = 0;
5480      switch (*name) {
5481        case '$':
5482          id |= ID_GLOBAL;
5483          m++;
5484          if (!is_identchar(*m)) m++;
5485          break;
5486        case '@':
5487          if (name[1] == '@') {
5488              m++;
5489              id |= ID_CLASS;
5490          }
5491          else {
5492              id |= ID_INSTANCE;
5493          }
5494          m++;
5495          break;
5496        default:
5497          if (name[0] != '_' && !ISALPHA(name[0]) && !ismbchar(name[0])) {
5498              /* operators */
5499              int i;
5500  
5501              for (i=0; op_tbl[i].token; i++) {
5502                  if (*op_tbl[i].name == *name &&
5503                      strcmp(op_tbl[i].name, name) == 0) {
5504                      id = op_tbl[i].token;
5505                      goto id_regist;
5506                  }
5507              }
5508          }
5509  
5510          last = strlen(name)-1;
5511          if (name[last] == '=') {
5512              /* attribute assignment */
5513              char *buf = ALLOCA_N(char,last+1);
5514  
5515              strncpy(buf, name, last);
5516              buf[last] = '\0';
5517              id = rb_intern(buf);
5518              if (id > LAST_TOKEN && !is_attrset_id(id)) {
5519                  id = rb_id_attrset(id);
5520                  goto id_regist;
5521              }
5522              id = ID_ATTRSET;
5523          }
5524          else if (ISUPPER(name[0])) {
5525              id = ID_CONST;
5526          }
5527          else {
5528              id = ID_LOCAL;
5529          }
5530          break;
5531      }
5532      while (*m && is_identchar(*m)) {
5533          m++;
5534      }
5535      if (*m) id = ID_JUNK;
5536      id |= ++last_id << ID_SCOPE_SHIFT;
5537    id_regist:
5538      name = strdup(name);
5539      st_add_direct(sym_tbl, name, id);
5540      st_add_direct(sym_rev_tbl, id, name);
5541      return id;
5542  }
5543  
5544  char *
5545  rb_id2name(id)
5546      ID id;
5547  {
5548      char *name;
5549  
5550      if (id < LAST_TOKEN) {
5551          int i = 0;
5552  
5553          for (i=0; op_tbl[i].token; i++) {
5554              if (op_tbl[i].token == id)
5555                  return op_tbl[i].name;
5556          }
5557      }
5558  
5559      if (st_lookup(sym_rev_tbl, id, &name))
5560          return name;
5561  
5562      if (is_attrset_id(id)) {
5563          ID id2 = (id & ~ID_SCOPE_MASK) | ID_LOCAL;
5564  
5565        again:
5566          name = rb_id2name(id2);
5567          if (name) {
5568              char *buf = ALLOCA_N(char, strlen(name)+2);
5569  
5570              strcpy(buf, name);
5571              strcat(buf, "=");
5572              rb_intern(buf);
5573              return rb_id2name(id);
5574          }
5575          if (is_local_id(id2)) {
5576              id2 = (id & ~ID_SCOPE_MASK) | ID_CONST;
5577              goto again;
5578          }
5579      }
5580      return 0;
5581  }
5582  
5583  static int
5584  symbols_i(key, value, ary)
5585      char *key;
5586      ID value;
5587      VALUE ary;
5588  {
5589      rb_ary_push(ary, ID2SYM(value));
5590      return ST_CONTINUE;
5591  }
5592  
5593  VALUE
5594  rb_sym_all_symbols()
5595  {
5596      VALUE ary = rb_ary_new2(sym_tbl->num_entries);
5597  
5598      st_foreach(sym_tbl, symbols_i, ary);
5599      return ary;
5600  }
5601  
5602  int
5603  rb_is_const_id(id)
5604      ID id;
5605  {
5606      if (is_const_id(id)) return Qtrue;
5607      return Qfalse;
5608  }
5609  
5610  int
5611  rb_is_class_id(id)
5612      ID id;
5613  {
5614      if (is_class_id(id)) return Qtrue;
5615      return Qfalse;
5616  }
5617  
5618  int
5619  rb_is_instance_id(id)
5620      ID id;
5621  {
5622      if (is_instance_id(id)) return Qtrue;
5623      return Qfalse;
5624  }
5625  
5626  int
5627  rb_is_local_id(id)
5628      ID id;
5629  {
5630      if (is_local_id(id)) return Qtrue;
5631      return Qfalse;
5632  }
5633  
5634  static void
5635  special_local_set(c, val)
5636      char c;
5637      VALUE val;
5638  {
5639      int cnt;
5640  
5641      top_local_init();
5642      cnt = local_cnt(c);
5643      top_local_setup();
5644      ruby_scope->local_vars[cnt] = val;
5645  }
5646  
5647  VALUE
5648  rb_backref_get()
5649  {
5650      VALUE *var = rb_svar(1);
5651      if (var) {
5652          return *var;
5653      }
5654      return Qnil;
5655  }
5656  
5657  void
5658  rb_backref_set(val)
5659      VALUE val;
5660  {
5661      VALUE *var = rb_svar(1);
5662      if (var) {
5663          *var = val;
5664      }
5665      else {
5666          special_local_set('~', val);
5667      }
5668  }
5669  
5670  VALUE
5671  rb_lastline_get()
5672  {
5673      VALUE *var = rb_svar(0);
5674      if (var) {
5675          return *var;
5676      }
5677      return Qnil;
5678  }
5679  
5680  void
5681  rb_lastline_set(val)
5682      VALUE val;
5683  {
5684      VALUE *var = rb_svar(0);
5685      if (var) {
5686          *var = val;
5687      }
5688      else {
5689          special_local_set('_', val);
5690      }
5691  }