00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 %{
00013
00014 #define YYDEBUG 1
00015 #define YYERROR_VERBOSE 1
00016 #define YYSTACK_USE_ALLOCA 0
00017
00018 #include "ruby/ruby.h"
00019 #include "ruby/st.h"
00020 #include "ruby/encoding.h"
00021 #include "node.h"
00022 #include "parse.h"
00023 #include "id.h"
00024 #include "regenc.h"
00025 #include <stdio.h>
00026 #include <errno.h>
00027 #include <ctype.h>
00028
00029 #define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
00030
00031 #define YYMALLOC(size) rb_parser_malloc(parser, size)
00032 #define YYREALLOC(ptr, size) rb_parser_realloc(parser, ptr, size)
00033 #define YYCALLOC(nelem, size) rb_parser_calloc(parser, nelem, size)
00034 #define YYFREE(ptr) rb_parser_free(parser, ptr)
00035 #define malloc YYMALLOC
00036 #define realloc YYREALLOC
00037 #define calloc YYCALLOC
00038 #define free YYFREE
00039
00040 #ifndef RIPPER
00041 static ID register_symid(ID, const char *, long, rb_encoding *);
00042 #define REGISTER_SYMID(id, name) register_symid(id, name, strlen(name), enc)
00043 #include "id.c"
00044 #endif
00045
00046 #define is_notop_id(id) ((id)>tLAST_TOKEN)
00047 #define is_local_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_LOCAL)
00048 #define is_global_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_GLOBAL)
00049 #define is_instance_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_INSTANCE)
00050 #define is_attrset_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_ATTRSET)
00051 #define is_const_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CONST)
00052 #define is_class_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CLASS)
00053 #define is_junk_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_JUNK)
00054
00055 #define is_asgn_or_id(id) ((is_notop_id(id)) && \
00056 (((id)&ID_SCOPE_MASK) == ID_GLOBAL || \
00057 ((id)&ID_SCOPE_MASK) == ID_INSTANCE || \
00058 ((id)&ID_SCOPE_MASK) == ID_CLASS))
00059
00060 enum lex_state_e {
00061 EXPR_BEG,
00062 EXPR_END,
00063 EXPR_ENDARG,
00064 EXPR_ENDFN,
00065 EXPR_ARG,
00066 EXPR_CMDARG,
00067 EXPR_MID,
00068 EXPR_FNAME,
00069 EXPR_DOT,
00070 EXPR_CLASS,
00071 EXPR_VALUE,
00072 EXPR_MAX_STATE
00073 };
00074
00075 typedef VALUE stack_type;
00076
00077 # define BITSTACK_PUSH(stack, n) (stack = (stack<<1)|((n)&1))
00078 # define BITSTACK_POP(stack) (stack = stack >> 1)
00079 # define BITSTACK_LEXPOP(stack) (stack = (stack >> 1) | (stack & 1))
00080 # define BITSTACK_SET_P(stack) (stack&1)
00081
00082 #define COND_PUSH(n) BITSTACK_PUSH(cond_stack, n)
00083 #define COND_POP() BITSTACK_POP(cond_stack)
00084 #define COND_LEXPOP() BITSTACK_LEXPOP(cond_stack)
00085 #define COND_P() BITSTACK_SET_P(cond_stack)
00086
00087 #define CMDARG_PUSH(n) BITSTACK_PUSH(cmdarg_stack, n)
00088 #define CMDARG_POP() BITSTACK_POP(cmdarg_stack)
00089 #define CMDARG_LEXPOP() BITSTACK_LEXPOP(cmdarg_stack)
00090 #define CMDARG_P() BITSTACK_SET_P(cmdarg_stack)
00091
00092 struct vtable {
00093 ID *tbl;
00094 int pos;
00095 int capa;
00096 struct vtable *prev;
00097 };
00098
00099 struct local_vars {
00100 struct vtable *args;
00101 struct vtable *vars;
00102 struct local_vars *prev;
00103 };
00104
00105 #define DVARS_INHERIT ((void*)1)
00106 #define DVARS_TOPSCOPE NULL
00107 #define DVARS_SPECIAL_P(tbl) (!POINTER_P(tbl))
00108 #define POINTER_P(val) ((VALUE)(val) & ~(VALUE)3)
00109
00110 static int
00111 vtable_size(const struct vtable *tbl)
00112 {
00113 if (POINTER_P(tbl)) {
00114 return tbl->pos;
00115 }
00116 else {
00117 return 0;
00118 }
00119 }
00120
00121 #define VTBL_DEBUG 0
00122
00123 static struct vtable *
00124 vtable_alloc(struct vtable *prev)
00125 {
00126 struct vtable *tbl = ALLOC(struct vtable);
00127 tbl->pos = 0;
00128 tbl->capa = 8;
00129 tbl->tbl = ALLOC_N(ID, tbl->capa);
00130 tbl->prev = prev;
00131 if (VTBL_DEBUG) printf("vtable_alloc: %p\n", (void *)tbl);
00132 return tbl;
00133 }
00134
00135 static void
00136 vtable_free(struct vtable *tbl)
00137 {
00138 if (VTBL_DEBUG)printf("vtable_free: %p\n", (void *)tbl);
00139 if (POINTER_P(tbl)) {
00140 if (tbl->tbl) {
00141 xfree(tbl->tbl);
00142 }
00143 xfree(tbl);
00144 }
00145 }
00146
00147 static void
00148 vtable_add(struct vtable *tbl, ID id)
00149 {
00150 if (!POINTER_P(tbl)) {
00151 rb_bug("vtable_add: vtable is not allocated (%p)", (void *)tbl);
00152 }
00153 if (VTBL_DEBUG) printf("vtable_add: %p, %s\n", (void *)tbl, rb_id2name(id));
00154
00155 if (tbl->pos == tbl->capa) {
00156 tbl->capa = tbl->capa * 2;
00157 REALLOC_N(tbl->tbl, ID, tbl->capa);
00158 }
00159 tbl->tbl[tbl->pos++] = id;
00160 }
00161
00162 static int
00163 vtable_included(const struct vtable * tbl, ID id)
00164 {
00165 int i;
00166
00167 if (POINTER_P(tbl)) {
00168 for (i = 0; i < tbl->pos; i++) {
00169 if (tbl->tbl[i] == id) {
00170 return 1;
00171 }
00172 }
00173 }
00174 return 0;
00175 }
00176
00177
00178 #ifndef RIPPER
00179 typedef struct token_info {
00180 const char *token;
00181 int linenum;
00182 int column;
00183 int nonspc;
00184 struct token_info *next;
00185 } token_info;
00186 #endif
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197 struct parser_params {
00198 int is_ripper;
00199 NODE *heap;
00200
00201 YYSTYPE *parser_yylval;
00202 VALUE eofp;
00203
00204 NODE *parser_lex_strterm;
00205 enum lex_state_e parser_lex_state;
00206 stack_type parser_cond_stack;
00207 stack_type parser_cmdarg_stack;
00208 int parser_class_nest;
00209 int parser_paren_nest;
00210 int parser_lpar_beg;
00211 int parser_in_single;
00212 int parser_in_def;
00213 int parser_compile_for_eval;
00214 VALUE parser_cur_mid;
00215 int parser_in_defined;
00216 char *parser_tokenbuf;
00217 int parser_tokidx;
00218 int parser_toksiz;
00219 VALUE parser_lex_input;
00220 VALUE parser_lex_lastline;
00221 VALUE parser_lex_nextline;
00222 const char *parser_lex_pbeg;
00223 const char *parser_lex_p;
00224 const char *parser_lex_pend;
00225 int parser_heredoc_end;
00226 int parser_command_start;
00227 NODE *parser_deferred_nodes;
00228 long parser_lex_gets_ptr;
00229 VALUE (*parser_lex_gets)(struct parser_params*,VALUE);
00230 struct local_vars *parser_lvtbl;
00231 int parser_ruby__end__seen;
00232 int line_count;
00233 int has_shebang;
00234 char *parser_ruby_sourcefile;
00235 int parser_ruby_sourceline;
00236 rb_encoding *enc;
00237 rb_encoding *utf8;
00238
00239 int parser_yydebug;
00240
00241 #ifndef RIPPER
00242
00243 NODE *parser_eval_tree_begin;
00244 NODE *parser_eval_tree;
00245 VALUE debug_lines;
00246 VALUE coverage;
00247 int nerr;
00248
00249 token_info *parser_token_info;
00250 #else
00251
00252 VALUE parser_ruby_sourcefile_string;
00253 const char *tokp;
00254 VALUE delayed;
00255 int delayed_line;
00256 int delayed_col;
00257
00258 VALUE value;
00259 VALUE result;
00260 VALUE parsing_thread;
00261 int toplevel_p;
00262 #endif
00263 };
00264
00265 #define UTF8_ENC() (parser->utf8 ? parser->utf8 : \
00266 (parser->utf8 = rb_utf8_encoding()))
00267 #define STR_NEW(p,n) rb_enc_str_new((p),(n),parser->enc)
00268 #define STR_NEW0() rb_enc_str_new(0,0,parser->enc)
00269 #define STR_NEW2(p) rb_enc_str_new((p),strlen(p),parser->enc)
00270 #define STR_NEW3(p,n,e,func) parser_str_new((p),(n),(e),(func),parser->enc)
00271 #define ENC_SINGLE(cr) ((cr)==ENC_CODERANGE_7BIT)
00272 #define TOK_INTERN(mb) rb_intern3(tok(), toklen(), parser->enc)
00273
00274 #ifdef YYMALLOC
00275 void *rb_parser_malloc(struct parser_params *, size_t);
00276 void *rb_parser_realloc(struct parser_params *, void *, size_t);
00277 void *rb_parser_calloc(struct parser_params *, size_t, size_t);
00278 void rb_parser_free(struct parser_params *, void *);
00279 #endif
00280
00281 static int parser_yyerror(struct parser_params*, const char*);
00282 #define yyerror(msg) parser_yyerror(parser, msg)
00283
00284 #define YYLEX_PARAM parser
00285
00286 #define lex_strterm (parser->parser_lex_strterm)
00287 #define lex_state (parser->parser_lex_state)
00288 #define cond_stack (parser->parser_cond_stack)
00289 #define cmdarg_stack (parser->parser_cmdarg_stack)
00290 #define class_nest (parser->parser_class_nest)
00291 #define paren_nest (parser->parser_paren_nest)
00292 #define lpar_beg (parser->parser_lpar_beg)
00293 #define in_single (parser->parser_in_single)
00294 #define in_def (parser->parser_in_def)
00295 #define compile_for_eval (parser->parser_compile_for_eval)
00296 #define cur_mid (parser->parser_cur_mid)
00297 #define in_defined (parser->parser_in_defined)
00298 #define tokenbuf (parser->parser_tokenbuf)
00299 #define tokidx (parser->parser_tokidx)
00300 #define toksiz (parser->parser_toksiz)
00301 #define lex_input (parser->parser_lex_input)
00302 #define lex_lastline (parser->parser_lex_lastline)
00303 #define lex_nextline (parser->parser_lex_nextline)
00304 #define lex_pbeg (parser->parser_lex_pbeg)
00305 #define lex_p (parser->parser_lex_p)
00306 #define lex_pend (parser->parser_lex_pend)
00307 #define heredoc_end (parser->parser_heredoc_end)
00308 #define command_start (parser->parser_command_start)
00309 #define deferred_nodes (parser->parser_deferred_nodes)
00310 #define lex_gets_ptr (parser->parser_lex_gets_ptr)
00311 #define lex_gets (parser->parser_lex_gets)
00312 #define lvtbl (parser->parser_lvtbl)
00313 #define ruby__end__seen (parser->parser_ruby__end__seen)
00314 #define ruby_sourceline (parser->parser_ruby_sourceline)
00315 #define ruby_sourcefile (parser->parser_ruby_sourcefile)
00316 #define yydebug (parser->parser_yydebug)
00317 #ifdef RIPPER
00318 #else
00319 #define ruby_eval_tree (parser->parser_eval_tree)
00320 #define ruby_eval_tree_begin (parser->parser_eval_tree_begin)
00321 #define ruby_debug_lines (parser->debug_lines)
00322 #define ruby_coverage (parser->coverage)
00323 #endif
00324
00325 static int yylex(void*, void*);
00326
00327 #ifndef RIPPER
00328 #define yyparse ruby_yyparse
00329
00330 static NODE* node_newnode(struct parser_params *, enum node_type, VALUE, VALUE, VALUE);
00331 #define rb_node_newnode(type, a1, a2, a3) node_newnode(parser, type, a1, a2, a3)
00332
00333 static NODE *cond_gen(struct parser_params*,NODE*);
00334 #define cond(node) cond_gen(parser, node)
00335 static NODE *logop_gen(struct parser_params*,enum node_type,NODE*,NODE*);
00336 #define logop(type,node1,node2) logop_gen(parser, type, node1, node2)
00337
00338 static NODE *newline_node(NODE*);
00339 static void fixpos(NODE*,NODE*);
00340
00341 static int value_expr_gen(struct parser_params*,NODE*);
00342 static void void_expr_gen(struct parser_params*,NODE*);
00343 static NODE *remove_begin(NODE*);
00344 #define value_expr(node) value_expr_gen(parser, (node) = remove_begin(node))
00345 #define void_expr0(node) void_expr_gen(parser, (node))
00346 #define void_expr(node) void_expr0((node) = remove_begin(node))
00347 static void void_stmts_gen(struct parser_params*,NODE*);
00348 #define void_stmts(node) void_stmts_gen(parser, node)
00349 static void reduce_nodes_gen(struct parser_params*,NODE**);
00350 #define reduce_nodes(n) reduce_nodes_gen(parser,n)
00351 static void block_dup_check_gen(struct parser_params*,NODE*,NODE*);
00352 #define block_dup_check(n1,n2) block_dup_check_gen(parser,n1,n2)
00353
00354 static NODE *block_append_gen(struct parser_params*,NODE*,NODE*);
00355 #define block_append(h,t) block_append_gen(parser,h,t)
00356 static NODE *list_append_gen(struct parser_params*,NODE*,NODE*);
00357 #define list_append(l,i) list_append_gen(parser,l,i)
00358 static NODE *list_concat_gen(struct parser_params*,NODE*,NODE*);
00359 #define list_concat(h,t) list_concat_gen(parser,h,t)
00360 static NODE *arg_append_gen(struct parser_params*,NODE*,NODE*);
00361 #define arg_append(h,t) arg_append_gen(parser,h,t)
00362 static NODE *arg_concat_gen(struct parser_params*,NODE*,NODE*);
00363 #define arg_concat(h,t) arg_concat_gen(parser,h,t)
00364 static NODE *literal_concat_gen(struct parser_params*,NODE*,NODE*);
00365 #define literal_concat(h,t) literal_concat_gen(parser,h,t)
00366 static int literal_concat0(struct parser_params *, VALUE, VALUE);
00367 static NODE *new_evstr_gen(struct parser_params*,NODE*);
00368 #define new_evstr(n) new_evstr_gen(parser,n)
00369 static NODE *evstr2dstr_gen(struct parser_params*,NODE*);
00370 #define evstr2dstr(n) evstr2dstr_gen(parser,n)
00371 static NODE *splat_array(NODE*);
00372
00373 static NODE *call_bin_op_gen(struct parser_params*,NODE*,ID,NODE*);
00374 #define call_bin_op(recv,id,arg1) call_bin_op_gen(parser, recv,id,arg1)
00375 static NODE *call_uni_op_gen(struct parser_params*,NODE*,ID);
00376 #define call_uni_op(recv,id) call_uni_op_gen(parser, recv,id)
00377
00378 static NODE *new_args_gen(struct parser_params*,NODE*,NODE*,ID,NODE*,ID);
00379 #define new_args(f,o,r,p,b) new_args_gen(parser, f,o,r,p,b)
00380
00381 static NODE *negate_lit(NODE*);
00382 static NODE *ret_args_gen(struct parser_params*,NODE*);
00383 #define ret_args(node) ret_args_gen(parser, node)
00384 static NODE *arg_blk_pass(NODE*,NODE*);
00385 static NODE *new_yield_gen(struct parser_params*,NODE*);
00386 #define new_yield(node) new_yield_gen(parser, node)
00387
00388 static NODE *gettable_gen(struct parser_params*,ID);
00389 #define gettable(id) gettable_gen(parser,id)
00390 static NODE *assignable_gen(struct parser_params*,ID,NODE*);
00391 #define assignable(id,node) assignable_gen(parser, id, node)
00392
00393 static NODE *aryset_gen(struct parser_params*,NODE*,NODE*);
00394 #define aryset(node1,node2) aryset_gen(parser, node1, node2)
00395 static NODE *attrset_gen(struct parser_params*,NODE*,ID);
00396 #define attrset(node,id) attrset_gen(parser, node, id)
00397
00398 static void rb_backref_error_gen(struct parser_params*,NODE*);
00399 #define rb_backref_error(n) rb_backref_error_gen(parser,n)
00400 static NODE *node_assign_gen(struct parser_params*,NODE*,NODE*);
00401 #define node_assign(node1, node2) node_assign_gen(parser, node1, node2)
00402
00403 static NODE *match_op_gen(struct parser_params*,NODE*,NODE*);
00404 #define match_op(node1,node2) match_op_gen(parser, node1, node2)
00405
00406 static ID *local_tbl_gen(struct parser_params*);
00407 #define local_tbl() local_tbl_gen(parser)
00408
00409 static void fixup_nodes(NODE **);
00410
00411 extern int rb_dvar_defined(ID);
00412 extern int rb_local_defined(ID);
00413 extern int rb_parse_in_eval(void);
00414 extern int rb_parse_in_main(void);
00415
00416 static VALUE reg_compile_gen(struct parser_params*, VALUE, int);
00417 #define reg_compile(str,options) reg_compile_gen(parser, str, options)
00418 static void reg_fragment_setenc_gen(struct parser_params*, VALUE, int);
00419 #define reg_fragment_setenc(str,options) reg_fragment_setenc_gen(parser, str, options)
00420 static int reg_fragment_check_gen(struct parser_params*, VALUE, int);
00421 #define reg_fragment_check(str,options) reg_fragment_check_gen(parser, str, options)
00422 static NODE *reg_named_capture_assign_gen(struct parser_params* parser, VALUE regexp, NODE *match);
00423 #define reg_named_capture_assign(regexp,match) reg_named_capture_assign_gen(parser,regexp,match)
00424
00425 #define get_id(id) (id)
00426 #define get_value(val) (val)
00427 #else
00428 #define remove_begin(node) (node)
00429 #define rb_dvar_defined(id) 0
00430 #define rb_local_defined(id) 0
00431 static ID ripper_get_id(VALUE);
00432 #define get_id(id) ripper_get_id(id)
00433 static VALUE ripper_get_value(VALUE);
00434 #define get_value(val) ripper_get_value(val)
00435 static VALUE assignable_gen(struct parser_params*,VALUE);
00436 #define assignable(lhs,node) assignable_gen(parser, lhs)
00437 #endif
00438
00439 static ID formal_argument_gen(struct parser_params*, ID);
00440 #define formal_argument(id) formal_argument_gen(parser, id)
00441 static ID shadowing_lvar_gen(struct parser_params*,ID);
00442 #define shadowing_lvar(name) shadowing_lvar_gen(parser, name)
00443 static void new_bv_gen(struct parser_params*,ID);
00444 #define new_bv(id) new_bv_gen(parser, id)
00445
00446 static void local_push_gen(struct parser_params*,int);
00447 #define local_push(top) local_push_gen(parser,top)
00448 static void local_pop_gen(struct parser_params*);
00449 #define local_pop() local_pop_gen(parser)
00450 static int local_var_gen(struct parser_params*, ID);
00451 #define local_var(id) local_var_gen(parser, id);
00452 static int arg_var_gen(struct parser_params*, ID);
00453 #define arg_var(id) arg_var_gen(parser, id)
00454 static int local_id_gen(struct parser_params*, ID);
00455 #define local_id(id) local_id_gen(parser, id)
00456 static ID internal_id_gen(struct parser_params*);
00457 #define internal_id() internal_id_gen(parser)
00458
00459 static const struct vtable *dyna_push_gen(struct parser_params *);
00460 #define dyna_push() dyna_push_gen(parser)
00461 static void dyna_pop_gen(struct parser_params*, const struct vtable *);
00462 #define dyna_pop(node) dyna_pop_gen(parser, node)
00463 static int dyna_in_block_gen(struct parser_params*);
00464 #define dyna_in_block() dyna_in_block_gen(parser)
00465 #define dyna_var(id) local_var(id)
00466 static int dvar_defined_gen(struct parser_params*,ID);
00467 #define dvar_defined(id) dvar_defined_gen(parser, id)
00468 static int dvar_curr_gen(struct parser_params*,ID);
00469 #define dvar_curr(id) dvar_curr_gen(parser, id)
00470
00471 static int lvar_defined_gen(struct parser_params*, ID);
00472 #define lvar_defined(id) lvar_defined_gen(parser, id)
00473
00474 #define RE_OPTION_ONCE (1<<16)
00475 #define RE_OPTION_ENCODING_SHIFT 8
00476 #define RE_OPTION_ENCODING(e) (((e)&0xff)<<RE_OPTION_ENCODING_SHIFT)
00477 #define RE_OPTION_ENCODING_IDX(o) (((o)>>RE_OPTION_ENCODING_SHIFT)&0xff)
00478 #define RE_OPTION_ENCODING_NONE(o) ((o)&RE_OPTION_ARG_ENCODING_NONE)
00479 #define RE_OPTION_MASK 0xff
00480 #define RE_OPTION_ARG_ENCODING_NONE 32
00481
00482 #define NODE_STRTERM NODE_ZARRAY
00483 #define NODE_HEREDOC NODE_ARRAY
00484 #define SIGN_EXTEND(x,n) (((1<<(n)-1)^((x)&~(~0<<(n))))-(1<<(n)-1))
00485 #define nd_func u1.id
00486 #if SIZEOF_SHORT == 2
00487 #define nd_term(node) ((signed short)(node)->u2.id)
00488 #else
00489 #define nd_term(node) SIGN_EXTEND((node)->u2.id, CHAR_BIT*2)
00490 #endif
00491 #define nd_paren(node) (char)((node)->u2.id >> CHAR_BIT*2)
00492 #define nd_nest u3.cnt
00493
00494
00495
00496 #ifdef RIPPER
00497 #define RIPPER_VERSION "0.1.0"
00498
00499 #include "eventids1.c"
00500 #include "eventids2.c"
00501 static ID ripper_id_gets;
00502
00503 static VALUE ripper_dispatch0(struct parser_params*,ID);
00504 static VALUE ripper_dispatch1(struct parser_params*,ID,VALUE);
00505 static VALUE ripper_dispatch2(struct parser_params*,ID,VALUE,VALUE);
00506 static VALUE ripper_dispatch3(struct parser_params*,ID,VALUE,VALUE,VALUE);
00507 static VALUE ripper_dispatch4(struct parser_params*,ID,VALUE,VALUE,VALUE,VALUE);
00508 static VALUE ripper_dispatch5(struct parser_params*,ID,VALUE,VALUE,VALUE,VALUE,VALUE);
00509
00510 #define dispatch0(n) ripper_dispatch0(parser, TOKEN_PASTE(ripper_id_, n))
00511 #define dispatch1(n,a) ripper_dispatch1(parser, TOKEN_PASTE(ripper_id_, n), a)
00512 #define dispatch2(n,a,b) ripper_dispatch2(parser, TOKEN_PASTE(ripper_id_, n), a, b)
00513 #define dispatch3(n,a,b,c) ripper_dispatch3(parser, TOKEN_PASTE(ripper_id_, n), a, b, c)
00514 #define dispatch4(n,a,b,c,d) ripper_dispatch4(parser, TOKEN_PASTE(ripper_id_, n), a, b, c, d)
00515 #define dispatch5(n,a,b,c,d,e) ripper_dispatch5(parser, TOKEN_PASTE(ripper_id_, n), a, b, c, d, e)
00516
00517 #define yyparse ripper_yyparse
00518
00519 #define ripper_intern(s) ID2SYM(rb_intern(s))
00520 static VALUE ripper_id2sym(ID);
00521 #ifdef __GNUC__
00522 #define ripper_id2sym(id) ((id) < 256 && rb_ispunct(id) ? \
00523 ID2SYM(id) : ripper_id2sym(id))
00524 #endif
00525
00526 #define arg_new() dispatch0(args_new)
00527 #define arg_add(l,a) dispatch2(args_add, l, a)
00528 #define arg_add_star(l,a) dispatch2(args_add_star, l, a)
00529 #define arg_add_block(l,b) dispatch2(args_add_block, l, b)
00530 #define arg_add_optblock(l,b) ((b)==Qundef? l : dispatch2(args_add_block, l, b))
00531 #define bare_assoc(v) dispatch1(bare_assoc_hash, v)
00532 #define arg_add_assocs(l,b) arg_add(l, bare_assoc(b))
00533
00534 #define args2mrhs(a) dispatch1(mrhs_new_from_args, a)
00535 #define mrhs_new() dispatch0(mrhs_new)
00536 #define mrhs_add(l,a) dispatch2(mrhs_add, l, a)
00537 #define mrhs_add_star(l,a) dispatch2(mrhs_add_star, l, a)
00538
00539 #define mlhs_new() dispatch0(mlhs_new)
00540 #define mlhs_add(l,a) dispatch2(mlhs_add, l, a)
00541 #define mlhs_add_star(l,a) dispatch2(mlhs_add_star, l, a)
00542
00543 #define params_new(pars, opts, rest, pars2, blk) \
00544 dispatch5(params, pars, opts, rest, pars2, blk)
00545
00546 #define blockvar_new(p,v) dispatch2(block_var, p, v)
00547 #define blockvar_add_star(l,a) dispatch2(block_var_add_star, l, a)
00548 #define blockvar_add_block(l,a) dispatch2(block_var_add_block, l, a)
00549
00550 #define method_optarg(m,a) ((a)==Qundef ? m : dispatch2(method_add_arg,m,a))
00551 #define method_arg(m,a) dispatch2(method_add_arg,m,a)
00552 #define method_add_block(m,b) dispatch2(method_add_block, m, b)
00553
00554 #define escape_Qundef(x) ((x)==Qundef ? Qnil : (x))
00555
00556 #define FIXME 0
00557
00558 #endif
00559
00560 #ifndef RIPPER
00561 # define ifndef_ripper(x) x
00562 #else
00563 # define ifndef_ripper(x)
00564 #endif
00565
00566 #ifndef RIPPER
00567 # define rb_warn0(fmt) rb_compile_warn(ruby_sourcefile, ruby_sourceline, fmt)
00568 # define rb_warnI(fmt,a) rb_compile_warn(ruby_sourcefile, ruby_sourceline, fmt, a)
00569 # define rb_warnS(fmt,a) rb_compile_warn(ruby_sourcefile, ruby_sourceline, fmt, a)
00570 # define rb_warning0(fmt) rb_compile_warning(ruby_sourcefile, ruby_sourceline, fmt)
00571 # define rb_warningS(fmt,a) rb_compile_warning(ruby_sourcefile, ruby_sourceline, fmt, a)
00572 #else
00573 # define rb_warn0(fmt) ripper_warn0(parser, fmt)
00574 # define rb_warnI(fmt,a) ripper_warnI(parser, fmt, a)
00575 # define rb_warnS(fmt,a) ripper_warnS(parser, fmt, a)
00576 # define rb_warning0(fmt) ripper_warning0(parser, fmt)
00577 # define rb_warningS(fmt,a) ripper_warningS(parser, fmt, a)
00578 static void ripper_warn0(struct parser_params*, const char*);
00579 static void ripper_warnI(struct parser_params*, const char*, int);
00580 #if 0
00581 static void ripper_warnS(struct parser_params*, const char*, const char*);
00582 #endif
00583 static void ripper_warning0(struct parser_params*, const char*);
00584 static void ripper_warningS(struct parser_params*, const char*, const char*);
00585 #endif
00586
00587 #ifdef RIPPER
00588 static void ripper_compile_error(struct parser_params*, const char *fmt, ...);
00589 # define rb_compile_error ripper_compile_error
00590 # define compile_error ripper_compile_error
00591 # define PARSER_ARG parser,
00592 #else
00593 # define compile_error parser->nerr++,rb_compile_error
00594 # define PARSER_ARG ruby_sourcefile, ruby_sourceline,
00595 #endif
00596
00597
00598
00599
00600 #ifdef OLD_YACC
00601 #ifndef YYMAXDEPTH
00602 #define YYMAXDEPTH 10000
00603 #endif
00604 #endif
00605
00606 #ifndef RIPPER
00607 static void token_info_push(struct parser_params*, const char *token);
00608 static void token_info_pop(struct parser_params*, const char *token);
00609 #define token_info_push(token) (RTEST(ruby_verbose) ? token_info_push(parser, token) : (void)0)
00610 #define token_info_pop(token) (RTEST(ruby_verbose) ? token_info_pop(parser, token) : (void)0)
00611 #else
00612 #define token_info_push(token)
00613 #define token_info_pop(token)
00614 #endif
00615 %}
00616
00617 %pure_parser
00618 %parse-param {struct parser_params *parser}
00619
00620 %union {
00621 VALUE val;
00622 NODE *node;
00623 ID id;
00624 int num;
00625 const struct vtable *vars;
00626 }
00627
00628
00629
00630
00631 %token <val>
00632
00633 keyword_class
00634 keyword_module
00635 keyword_def
00636 keyword_undef
00637 keyword_begin
00638 keyword_rescue
00639 keyword_ensure
00640 keyword_end
00641 keyword_if
00642 keyword_unless
00643 keyword_then
00644 keyword_elsif
00645 keyword_else
00646 keyword_case
00647 keyword_when
00648 keyword_while
00649 keyword_until
00650 keyword_for
00651 keyword_break
00652 keyword_next
00653 keyword_redo
00654 keyword_retry
00655 keyword_in
00656 keyword_do
00657 keyword_do_cond
00658 keyword_do_block
00659 keyword_do_LAMBDA
00660 keyword_return
00661 keyword_yield
00662 keyword_super
00663 keyword_self
00664 keyword_nil
00665 keyword_true
00666 keyword_false
00667 keyword_and
00668 keyword_or
00669 keyword_not
00670 modifier_if
00671 modifier_unless
00672 modifier_while
00673 modifier_until
00674 modifier_rescue
00675 keyword_alias
00676 keyword_defined
00677 keyword_BEGIN
00678 keyword_END
00679 keyword__LINE__
00680 keyword__FILE__
00681 keyword__ENCODING__
00682
00683 %token <val> tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tLABEL
00684 %token <val> tINTEGER tFLOAT tSTRING_CONTENT tCHAR
00685 %token <val> tNTH_REF tBACK_REF
00686 %token <val> tREGEXP_END
00687
00688 %type <val> singleton strings string string1 xstring regexp
00689 %type <val> string_contents xstring_contents regexp_contents string_content
00690 %type <val> words qwords word_list qword_list word
00691 %type <val> literal numeric dsym cpath
00692 %type <val> top_compstmt top_stmts top_stmt
00693 %type <val> bodystmt compstmt stmts stmt expr arg primary command command_call method_call
00694 %type <val> expr_value arg_value primary_value
00695 %type <val> if_tail opt_else case_body cases opt_rescue exc_list exc_var opt_ensure
00696 %type <val> args call_args opt_call_args
00697 %type <val> paren_args opt_paren_args
00698 %type <val> command_args aref_args opt_block_arg block_arg var_ref var_lhs
00699 %type <val> mrhs superclass block_call block_command
00700 %type <val> f_block_optarg f_block_opt
00701 %type <val> f_arglist f_args f_arg f_arg_item f_optarg f_marg f_marg_list f_margs
00702 %type <val> assoc_list assocs assoc undef_list backref string_dvar for_var
00703 %type <val> block_param opt_block_param block_param_def f_opt
00704 %type <val> bv_decls opt_bv_decl bvar
00705 %type <val> lambda f_larglist lambda_body
00706 %type <val> brace_block cmd_brace_block do_block lhs none fitem
00707 %type <val> mlhs mlhs_head mlhs_basic mlhs_item mlhs_node mlhs_post mlhs_inner
00708 %type <val> fsym variable sym symbol operation operation2 operation3
00709 %type <val> cname fname op f_rest_arg f_block_arg opt_f_block_arg f_norm_arg f_bad_arg
00710
00711
00712 %type <val> program reswords then do dot_or_colon
00713
00714 %token tUPLUS
00715 %token tUMINUS
00716 %token tPOW
00717 %token tCMP
00718 %token tEQ
00719 %token tEQQ
00720 %token tNEQ
00721 %token tGEQ
00722 %token tLEQ
00723 %token tANDOP tOROP
00724 %token tMATCH tNMATCH
00725 %token tDOT2 tDOT3
00726 %token tAREF tASET
00727 %token tLSHFT tRSHFT
00728 %token tCOLON2
00729 %token tCOLON3
00730 %token <val> tOP_ASGN
00731 %token tASSOC
00732 %token tLPAREN
00733 %token tLPAREN_ARG
00734 %token tRPAREN
00735 %token tLBRACK
00736 %token tLBRACE
00737 %token tLBRACE_ARG
00738 %token tSTAR
00739 %token tAMPER
00740 %token tLAMBDA
00741 %token tSYMBEG tSTRING_BEG tXSTRING_BEG tREGEXP_BEG tWORDS_BEG tQWORDS_BEG
00742 %token tSTRING_DBEG tSTRING_DVAR tSTRING_END tLAMBEG
00743
00744
00745
00746
00747
00748 %nonassoc tLOWEST
00749 %nonassoc tLBRACE_ARG
00750
00751 %nonassoc modifier_if modifier_unless modifier_while modifier_until
00752 %left keyword_or keyword_and
00753 %right keyword_not
00754 %nonassoc keyword_defined
00755 %right '=' tOP_ASGN
00756 %left modifier_rescue
00757 %right '?' ':'
00758 %nonassoc tDOT2 tDOT3
00759 %left tOROP
00760 %left tANDOP
00761 %nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
00762 %left '>' tGEQ '<' tLEQ
00763 %left '|' '^'
00764 %left '&'
00765 %left tLSHFT tRSHFT
00766 %left '+' '-'
00767 %left '*' '/' '%'
00768 %right tUMINUS_NUM tUMINUS
00769 %right tPOW
00770 %right '!' '~' tUPLUS
00771
00772 %nonassoc idNULL
00773 %nonassoc idRespond_to
00774 %nonassoc idIFUNC
00775 %nonassoc idCFUNC
00776 %nonassoc id_core_set_method_alias
00777 %nonassoc id_core_set_variable_alias
00778 %nonassoc id_core_undef_method
00779 %nonassoc id_core_define_method
00780 %nonassoc id_core_define_singleton_method
00781 %nonassoc id_core_set_postexe
00782
00783 %token tLAST_TOKEN
00784
00785 %%
00786 program : {
00787 lex_state = EXPR_BEG;
00788 #if 0
00789 local_push(compile_for_eval || rb_parse_in_main());
00790 #endif
00791 local_push(0);
00792
00793 }
00794 top_compstmt
00795 {
00796 #if 0
00797 if ($2 && !compile_for_eval) {
00798
00799 if (nd_type($2) != NODE_BLOCK) void_expr($2);
00800 else {
00801 NODE *node = $2;
00802 while (node->nd_next) {
00803 node = node->nd_next;
00804 }
00805 void_expr(node->nd_head);
00806 }
00807 }
00808 ruby_eval_tree = NEW_SCOPE(0, block_append(ruby_eval_tree, $2));
00809 #endif
00810 $$ = $2;
00811 parser->result = dispatch1(program, $$);
00812
00813 local_pop();
00814 }
00815 ;
00816
00817 top_compstmt : top_stmts opt_terms
00818 {
00819 #if 0
00820 void_stmts($1);
00821 fixup_nodes(&deferred_nodes);
00822 #endif
00823
00824 $$ = $1;
00825 }
00826 ;
00827
00828 top_stmts : none
00829 {
00830 #if 0
00831 $$ = NEW_BEGIN(0);
00832 #endif
00833 $$ = dispatch2(stmts_add, dispatch0(stmts_new),
00834 dispatch0(void_stmt));
00835
00836 }
00837 | top_stmt
00838 {
00839 #if 0
00840 $$ = newline_node($1);
00841 #endif
00842 $$ = dispatch2(stmts_add, dispatch0(stmts_new), $1);
00843
00844 }
00845 | top_stmts terms top_stmt
00846 {
00847 #if 0
00848 $$ = block_append($1, newline_node($3));
00849 #endif
00850 $$ = dispatch2(stmts_add, $1, $3);
00851
00852 }
00853 | error top_stmt
00854 {
00855 $$ = remove_begin($2);
00856 }
00857 ;
00858
00859 top_stmt : stmt
00860 | keyword_BEGIN
00861 {
00862 if (in_def || in_single) {
00863 yyerror("BEGIN in method");
00864 }
00865 #if 0
00866
00867 #endif
00868
00869 }
00870 '{' top_compstmt '}'
00871 {
00872 #if 0
00873 ruby_eval_tree_begin = block_append(ruby_eval_tree_begin,
00874 $4);
00875
00876
00877 $$ = NEW_BEGIN(0);
00878 #endif
00879 $$ = dispatch1(BEGIN, $4);
00880
00881 }
00882 ;
00883
00884 bodystmt : compstmt
00885 opt_rescue
00886 opt_else
00887 opt_ensure
00888 {
00889 #if 0
00890 $$ = $1;
00891 if ($2) {
00892 $$ = NEW_RESCUE($1, $2, $3);
00893 }
00894 else if ($3) {
00895 rb_warn0("else without rescue is useless");
00896 $$ = block_append($$, $3);
00897 }
00898 if ($4) {
00899 if ($$) {
00900 $$ = NEW_ENSURE($$, $4);
00901 }
00902 else {
00903 $$ = block_append($4, NEW_NIL());
00904 }
00905 }
00906 fixpos($$, $1);
00907 #endif
00908 $$ = dispatch4(bodystmt,
00909 escape_Qundef($1),
00910 escape_Qundef($2),
00911 escape_Qundef($3),
00912 escape_Qundef($4));
00913
00914 }
00915 ;
00916
00917 compstmt : stmts opt_terms
00918 {
00919 #if 0
00920 void_stmts($1);
00921 fixup_nodes(&deferred_nodes);
00922 #endif
00923
00924 $$ = $1;
00925 }
00926 ;
00927
00928 stmts : none
00929 {
00930 #if 0
00931 $$ = NEW_BEGIN(0);
00932 #endif
00933 $$ = dispatch2(stmts_add, dispatch0(stmts_new),
00934 dispatch0(void_stmt));
00935
00936 }
00937 | stmt
00938 {
00939 #if 0
00940 $$ = newline_node($1);
00941 #endif
00942 $$ = dispatch2(stmts_add, dispatch0(stmts_new), $1);
00943
00944 }
00945 | stmts terms stmt
00946 {
00947 #if 0
00948 $$ = block_append($1, newline_node($3));
00949 #endif
00950 $$ = dispatch2(stmts_add, $1, $3);
00951
00952 }
00953 | error stmt
00954 {
00955 $$ = remove_begin($2);
00956 }
00957 ;
00958
00959 stmt : keyword_alias fitem {lex_state = EXPR_FNAME;} fitem
00960 {
00961 #if 0
00962 $$ = NEW_ALIAS($2, $4);
00963 #endif
00964 $$ = dispatch2(alias, $2, $4);
00965
00966 }
00967 | keyword_alias tGVAR tGVAR
00968 {
00969 #if 0
00970 $$ = NEW_VALIAS($2, $3);
00971 #endif
00972 $$ = dispatch2(var_alias, $2, $3);
00973
00974 }
00975 | keyword_alias tGVAR tBACK_REF
00976 {
00977 #if 0
00978 char buf[2];
00979 buf[0] = '$';
00980 buf[1] = (char)$3->nd_nth;
00981 $$ = NEW_VALIAS($2, rb_intern2(buf, 2));
00982 #endif
00983 $$ = dispatch2(var_alias, $2, $3);
00984
00985 }
00986 | keyword_alias tGVAR tNTH_REF
00987 {
00988 #if 0
00989 yyerror("can't make alias for the number variables");
00990 $$ = NEW_BEGIN(0);
00991 #endif
00992 $$ = dispatch2(var_alias, $2, $3);
00993 $$ = dispatch1(alias_error, $$);
00994
00995 }
00996 | keyword_undef undef_list
00997 {
00998 #if 0
00999 $$ = $2;
01000 #endif
01001 $$ = dispatch1(undef, $2);
01002
01003 }
01004 | stmt modifier_if expr_value
01005 {
01006 #if 0
01007 $$ = NEW_IF(cond($3), remove_begin($1), 0);
01008 fixpos($$, $3);
01009 #endif
01010 $$ = dispatch2(if_mod, $3, $1);
01011
01012 }
01013 | stmt modifier_unless expr_value
01014 {
01015 #if 0
01016 $$ = NEW_UNLESS(cond($3), remove_begin($1), 0);
01017 fixpos($$, $3);
01018 #endif
01019 $$ = dispatch2(unless_mod, $3, $1);
01020
01021 }
01022 | stmt modifier_while expr_value
01023 {
01024 #if 0
01025 if ($1 && nd_type($1) == NODE_BEGIN) {
01026 $$ = NEW_WHILE(cond($3), $1->nd_body, 0);
01027 }
01028 else {
01029 $$ = NEW_WHILE(cond($3), $1, 1);
01030 }
01031 #endif
01032 $$ = dispatch2(while_mod, $3, $1);
01033
01034 }
01035 | stmt modifier_until expr_value
01036 {
01037 #if 0
01038 if ($1 && nd_type($1) == NODE_BEGIN) {
01039 $$ = NEW_UNTIL(cond($3), $1->nd_body, 0);
01040 }
01041 else {
01042 $$ = NEW_UNTIL(cond($3), $1, 1);
01043 }
01044 #endif
01045 $$ = dispatch2(until_mod, $3, $1);
01046
01047 }
01048 | stmt modifier_rescue stmt
01049 {
01050 #if 0
01051 NODE *resq = NEW_RESBODY(0, remove_begin($3), 0);
01052 $$ = NEW_RESCUE(remove_begin($1), resq, 0);
01053 #endif
01054 $$ = dispatch2(rescue_mod, $3, $1);
01055
01056 }
01057 | keyword_END '{' compstmt '}'
01058 {
01059 if (in_def || in_single) {
01060 rb_warn0("END in method; use at_exit");
01061 }
01062 #if 0
01063 $$ = NEW_POSTEXE(NEW_NODE(
01064 NODE_SCOPE, 0 , $3 , 0 ));
01065 #endif
01066 $$ = dispatch1(END, $3);
01067
01068 }
01069 | lhs '=' command_call
01070 {
01071 #if 0
01072 value_expr($3);
01073 $$ = node_assign($1, $3);
01074 #endif
01075 $$ = dispatch2(assign, $1, $3);
01076
01077 }
01078 | mlhs '=' command_call
01079 {
01080 #if 0
01081 value_expr($3);
01082 $1->nd_value = $3;
01083 $$ = $1;
01084 #endif
01085 $$ = dispatch2(massign, $1, $3);
01086
01087 }
01088 | var_lhs tOP_ASGN command_call
01089 {
01090 #if 0
01091 value_expr($3);
01092 if ($1) {
01093 ID vid = $1->nd_vid;
01094 if ($2 == tOROP) {
01095 $1->nd_value = $3;
01096 $$ = NEW_OP_ASGN_OR(gettable(vid), $1);
01097 if (is_asgn_or_id(vid)) {
01098 $$->nd_aid = vid;
01099 }
01100 }
01101 else if ($2 == tANDOP) {
01102 $1->nd_value = $3;
01103 $$ = NEW_OP_ASGN_AND(gettable(vid), $1);
01104 }
01105 else {
01106 $$ = $1;
01107 $$->nd_value = NEW_CALL(gettable(vid), $2, NEW_LIST($3));
01108 }
01109 }
01110 else {
01111 $$ = NEW_BEGIN(0);
01112 }
01113 #endif
01114 $$ = dispatch3(opassign, $1, $2, $3);
01115
01116 }
01117 | primary_value '[' opt_call_args rbracket tOP_ASGN command_call
01118 {
01119 #if 0
01120 NODE *args;
01121
01122 value_expr($6);
01123 if (!$3) $3 = NEW_ZARRAY();
01124 args = arg_concat($3, $6);
01125 if ($5 == tOROP) {
01126 $5 = 0;
01127 }
01128 else if ($5 == tANDOP) {
01129 $5 = 1;
01130 }
01131 $$ = NEW_OP_ASGN1($1, $5, args);
01132 fixpos($$, $1);
01133 #endif
01134 $$ = dispatch2(aref_field, $1, escape_Qundef($3));
01135 $$ = dispatch3(opassign, $$, $5, $6);
01136
01137 }
01138 | primary_value '.' tIDENTIFIER tOP_ASGN command_call
01139 {
01140 #if 0
01141 value_expr($5);
01142 if ($4 == tOROP) {
01143 $4 = 0;
01144 }
01145 else if ($4 == tANDOP) {
01146 $4 = 1;
01147 }
01148 $$ = NEW_OP_ASGN2($1, $3, $4, $5);
01149 fixpos($$, $1);
01150 #endif
01151 $$ = dispatch3(field, $1, ripper_id2sym('.'), $3);
01152 $$ = dispatch3(opassign, $$, $4, $5);
01153
01154 }
01155 | primary_value '.' tCONSTANT tOP_ASGN command_call
01156 {
01157 #if 0
01158 value_expr($5);
01159 if ($4 == tOROP) {
01160 $4 = 0;
01161 }
01162 else if ($4 == tANDOP) {
01163 $4 = 1;
01164 }
01165 $$ = NEW_OP_ASGN2($1, $3, $4, $5);
01166 fixpos($$, $1);
01167 #endif
01168 $$ = dispatch3(field, $1, ripper_id2sym('.'), $3);
01169 $$ = dispatch3(opassign, $$, $4, $5);
01170
01171 }
01172 | primary_value tCOLON2 tCONSTANT tOP_ASGN command_call
01173 {
01174 yyerror("constant re-assignment");
01175 $$ = 0;
01176 }
01177 | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call
01178 {
01179 #if 0
01180 value_expr($5);
01181 if ($4 == tOROP) {
01182 $4 = 0;
01183 }
01184 else if ($4 == tANDOP) {
01185 $4 = 1;
01186 }
01187 $$ = NEW_OP_ASGN2($1, $3, $4, $5);
01188 fixpos($$, $1);
01189 #endif
01190 $$ = dispatch3(field, $1, ripper_intern("::"), $3);
01191 $$ = dispatch3(opassign, $$, $4, $5);
01192
01193 }
01194 | backref tOP_ASGN command_call
01195 {
01196 #if 0
01197 rb_backref_error($1);
01198 $$ = NEW_BEGIN(0);
01199 #endif
01200 $$ = dispatch2(assign, dispatch1(var_field, $1), $3);
01201 $$ = dispatch1(assign_error, $$);
01202
01203 }
01204 | lhs '=' mrhs
01205 {
01206 #if 0
01207 value_expr($3);
01208 $$ = node_assign($1, $3);
01209 #endif
01210 $$ = dispatch2(assign, $1, $3);
01211
01212 }
01213 | mlhs '=' arg_value
01214 {
01215 #if 0
01216 $1->nd_value = $3;
01217 $$ = $1;
01218 #endif
01219 $$ = dispatch2(massign, $1, $3);
01220
01221 }
01222 | mlhs '=' mrhs
01223 {
01224 #if 0
01225 $1->nd_value = $3;
01226 $$ = $1;
01227 #endif
01228 $$ = dispatch2(massign, $1, $3);
01229
01230 }
01231 | expr
01232 ;
01233
01234 expr : command_call
01235 | expr keyword_and expr
01236 {
01237 #if 0
01238 $$ = logop(NODE_AND, $1, $3);
01239 #endif
01240 $$ = dispatch3(binary, $1, ripper_intern("and"), $3);
01241
01242 }
01243 | expr keyword_or expr
01244 {
01245 #if 0
01246 $$ = logop(NODE_OR, $1, $3);
01247 #endif
01248 $$ = dispatch3(binary, $1, ripper_intern("or"), $3);
01249
01250 }
01251 | keyword_not opt_nl expr
01252 {
01253 #if 0
01254 $$ = call_uni_op(cond($3), '!');
01255 #endif
01256 $$ = dispatch2(unary, ripper_intern("not"), $3);
01257
01258 }
01259 | '!' command_call
01260 {
01261 #if 0
01262 $$ = call_uni_op(cond($2), '!');
01263 #endif
01264 $$ = dispatch2(unary, ripper_id2sym('!'), $2);
01265
01266 }
01267 | arg
01268 ;
01269
01270 expr_value : expr
01271 {
01272 #if 0
01273 value_expr($1);
01274 $$ = $1;
01275 if (!$$) $$ = NEW_NIL();
01276 #endif
01277 $$ = $1;
01278
01279 }
01280 ;
01281
01282 command_call : command
01283 | block_command
01284 ;
01285
01286 block_command : block_call
01287 | block_call '.' operation2 command_args
01288 {
01289 #if 0
01290 $$ = NEW_CALL($1, $3, $4);
01291 #endif
01292 $$ = dispatch3(call, $1, ripper_id2sym('.'), $3);
01293 $$ = method_arg($$, $4);
01294
01295 }
01296 | block_call tCOLON2 operation2 command_args
01297 {
01298 #if 0
01299 $$ = NEW_CALL($1, $3, $4);
01300 #endif
01301 $$ = dispatch3(call, $1, ripper_intern("::"), $3);
01302 $$ = method_arg($$, $4);
01303
01304 }
01305 ;
01306
01307 cmd_brace_block : tLBRACE_ARG
01308 {
01309 $<vars>1 = dyna_push();
01310 #if 0
01311 $<num>$ = ruby_sourceline;
01312 #endif
01313
01314 }
01315 opt_block_param
01316 compstmt
01317 '}'
01318 {
01319 #if 0
01320 $$ = NEW_ITER($3,$4);
01321 nd_set_line($$, $<num>2);
01322 #endif
01323 $$ = dispatch2(brace_block, escape_Qundef($3), $4);
01324
01325 dyna_pop($<vars>1);
01326 }
01327 ;
01328
01329 command : operation command_args %prec tLOWEST
01330 {
01331 #if 0
01332 $$ = NEW_FCALL($1, $2);
01333 fixpos($$, $2);
01334 #endif
01335 $$ = dispatch2(command, $1, $2);
01336
01337 }
01338 | operation command_args cmd_brace_block
01339 {
01340 #if 0
01341 block_dup_check($2,$3);
01342 $3->nd_iter = NEW_FCALL($1, $2);
01343 $$ = $3;
01344 fixpos($$, $2);
01345 #endif
01346 $$ = dispatch2(command, $1, $2);
01347 $$ = method_add_block($$, $3);
01348
01349 }
01350 | primary_value '.' operation2 command_args %prec tLOWEST
01351 {
01352 #if 0
01353 $$ = NEW_CALL($1, $3, $4);
01354 fixpos($$, $1);
01355 #endif
01356 $$ = dispatch4(command_call, $1, ripper_id2sym('.'), $3, $4);
01357
01358 }
01359 | primary_value '.' operation2 command_args cmd_brace_block
01360 {
01361 #if 0
01362 block_dup_check($4,$5);
01363 $5->nd_iter = NEW_CALL($1, $3, $4);
01364 $$ = $5;
01365 fixpos($$, $1);
01366 #endif
01367 $$ = dispatch4(command_call, $1, ripper_id2sym('.'), $3, $4);
01368 $$ = method_add_block($$, $5);
01369
01370 }
01371 | primary_value tCOLON2 operation2 command_args %prec tLOWEST
01372 {
01373 #if 0
01374 $$ = NEW_CALL($1, $3, $4);
01375 fixpos($$, $1);
01376 #endif
01377 $$ = dispatch4(command_call, $1, ripper_intern("::"), $3, $4);
01378
01379 }
01380 | primary_value tCOLON2 operation2 command_args cmd_brace_block
01381 {
01382 #if 0
01383 block_dup_check($4,$5);
01384 $5->nd_iter = NEW_CALL($1, $3, $4);
01385 $$ = $5;
01386 fixpos($$, $1);
01387 #endif
01388 $$ = dispatch4(command_call, $1, ripper_intern("::"), $3, $4);
01389 $$ = method_add_block($$, $5);
01390
01391 }
01392 | keyword_super command_args
01393 {
01394 #if 0
01395 $$ = NEW_SUPER($2);
01396 fixpos($$, $2);
01397 #endif
01398 $$ = dispatch1(super, $2);
01399
01400 }
01401 | keyword_yield command_args
01402 {
01403 #if 0
01404 $$ = new_yield($2);
01405 fixpos($$, $2);
01406 #endif
01407 $$ = dispatch1(yield, $2);
01408
01409 }
01410 | keyword_return call_args
01411 {
01412 #if 0
01413 $$ = NEW_RETURN(ret_args($2));
01414 #endif
01415 $$ = dispatch1(return, $2);
01416
01417 }
01418 | keyword_break call_args
01419 {
01420 #if 0
01421 $$ = NEW_BREAK(ret_args($2));
01422 #endif
01423 $$ = dispatch1(break, $2);
01424
01425 }
01426 | keyword_next call_args
01427 {
01428 #if 0
01429 $$ = NEW_NEXT(ret_args($2));
01430 #endif
01431 $$ = dispatch1(next, $2);
01432
01433 }
01434 ;
01435
01436 mlhs : mlhs_basic
01437 | tLPAREN mlhs_inner rparen
01438 {
01439 #if 0
01440 $$ = $2;
01441 #endif
01442 $$ = dispatch1(mlhs_paren, $2);
01443
01444 }
01445 ;
01446
01447 mlhs_inner : mlhs_basic
01448 | tLPAREN mlhs_inner rparen
01449 {
01450 #if 0
01451 $$ = NEW_MASGN(NEW_LIST($2), 0);
01452 #endif
01453 $$ = dispatch1(mlhs_paren, $2);
01454
01455 }
01456 ;
01457
01458 mlhs_basic : mlhs_head
01459 {
01460 #if 0
01461 $$ = NEW_MASGN($1, 0);
01462 #endif
01463 $$ = $1;
01464
01465 }
01466 | mlhs_head mlhs_item
01467 {
01468 #if 0
01469 $$ = NEW_MASGN(list_append($1,$2), 0);
01470 #endif
01471 $$ = mlhs_add($1, $2);
01472
01473 }
01474 | mlhs_head tSTAR mlhs_node
01475 {
01476 #if 0
01477 $$ = NEW_MASGN($1, $3);
01478 #endif
01479 $$ = mlhs_add_star($1, $3);
01480
01481 }
01482 | mlhs_head tSTAR mlhs_node ',' mlhs_post
01483 {
01484 #if 0
01485 $$ = NEW_MASGN($1, NEW_POSTARG($3,$5));
01486 #endif
01487 $1 = mlhs_add_star($1, $3);
01488 $$ = mlhs_add($1, $5);
01489
01490 }
01491 | mlhs_head tSTAR
01492 {
01493 #if 0
01494 $$ = NEW_MASGN($1, -1);
01495 #endif
01496 $$ = mlhs_add_star($1, Qnil);
01497
01498 }
01499 | mlhs_head tSTAR ',' mlhs_post
01500 {
01501 #if 0
01502 $$ = NEW_MASGN($1, NEW_POSTARG(-1, $4));
01503 #endif
01504 $$ = mlhs_add_star($1, Qnil);
01505
01506 }
01507 | tSTAR mlhs_node
01508 {
01509 #if 0
01510 $$ = NEW_MASGN(0, $2);
01511 #endif
01512 $$ = mlhs_add_star(mlhs_new(), $2);
01513
01514 }
01515 | tSTAR mlhs_node ',' mlhs_post
01516 {
01517 #if 0
01518 $$ = NEW_MASGN(0, NEW_POSTARG($2,$4));
01519 #endif
01520 $$ = mlhs_add_star(mlhs_new(), $2);
01521
01522 }
01523 | tSTAR
01524 {
01525 #if 0
01526 $$ = NEW_MASGN(0, -1);
01527 #endif
01528 $$ = mlhs_add_star(mlhs_new(), Qnil);
01529
01530 }
01531 | tSTAR ',' mlhs_post
01532 {
01533 #if 0
01534 $$ = NEW_MASGN(0, NEW_POSTARG(-1, $3));
01535 #endif
01536 $$ = mlhs_add_star(mlhs_new(), Qnil);
01537
01538 }
01539 ;
01540
01541 mlhs_item : mlhs_node
01542 | tLPAREN mlhs_inner rparen
01543 {
01544 #if 0
01545 $$ = $2;
01546 #endif
01547 $$ = dispatch1(mlhs_paren, $2);
01548
01549 }
01550 ;
01551
01552 mlhs_head : mlhs_item ','
01553 {
01554 #if 0
01555 $$ = NEW_LIST($1);
01556 #endif
01557 $$ = mlhs_add(mlhs_new(), $1);
01558
01559 }
01560 | mlhs_head mlhs_item ','
01561 {
01562 #if 0
01563 $$ = list_append($1, $2);
01564 #endif
01565 $$ = mlhs_add($1, $2);
01566
01567 }
01568 ;
01569
01570 mlhs_post : mlhs_item
01571 {
01572 #if 0
01573 $$ = NEW_LIST($1);
01574 #endif
01575 $$ = mlhs_add(mlhs_new(), $1);
01576
01577 }
01578 | mlhs_post ',' mlhs_item
01579 {
01580 #if 0
01581 $$ = list_append($1, $3);
01582 #endif
01583 $$ = mlhs_add($1, $3);
01584
01585 }
01586 ;
01587
01588 mlhs_node : variable
01589 {
01590 $$ = assignable($1, 0);
01591 }
01592 | primary_value '[' opt_call_args rbracket
01593 {
01594 #if 0
01595 $$ = aryset($1, $3);
01596 #endif
01597 $$ = dispatch2(aref_field, $1, escape_Qundef($3));
01598
01599 }
01600 | primary_value '.' tIDENTIFIER
01601 {
01602 #if 0
01603 $$ = attrset($1, $3);
01604 #endif
01605 $$ = dispatch3(field, $1, ripper_id2sym('.'), $3);
01606
01607 }
01608 | primary_value tCOLON2 tIDENTIFIER
01609 {
01610 #if 0
01611 $$ = attrset($1, $3);
01612 #endif
01613 $$ = dispatch2(const_path_field, $1, $3);
01614
01615 }
01616 | primary_value '.' tCONSTANT
01617 {
01618 #if 0
01619 $$ = attrset($1, $3);
01620 #endif
01621 $$ = dispatch3(field, $1, ripper_id2sym('.'), $3);
01622
01623 }
01624 | primary_value tCOLON2 tCONSTANT
01625 {
01626 #if 0
01627 if (in_def || in_single)
01628 yyerror("dynamic constant assignment");
01629 $$ = NEW_CDECL(0, 0, NEW_COLON2($1, $3));
01630 #endif
01631 if (in_def || in_single)
01632 yyerror("dynamic constant assignment");
01633 $$ = dispatch2(const_path_field, $1, $3);
01634
01635 }
01636 | tCOLON3 tCONSTANT
01637 {
01638 #if 0
01639 if (in_def || in_single)
01640 yyerror("dynamic constant assignment");
01641 $$ = NEW_CDECL(0, 0, NEW_COLON3($2));
01642 #endif
01643 $$ = dispatch1(top_const_field, $2);
01644
01645 }
01646 | backref
01647 {
01648 #if 0
01649 rb_backref_error($1);
01650 $$ = NEW_BEGIN(0);
01651 #endif
01652 $$ = dispatch1(var_field, $1);
01653 $$ = dispatch1(assign_error, $$);
01654
01655 }
01656 ;
01657
01658 lhs : variable
01659 {
01660 $$ = assignable($1, 0);
01661 #if 0
01662 if (!$$) $$ = NEW_BEGIN(0);
01663 #endif
01664 $$ = dispatch1(var_field, $$);
01665
01666 }
01667 | primary_value '[' opt_call_args rbracket
01668 {
01669 #if 0
01670 $$ = aryset($1, $3);
01671 #endif
01672 $$ = dispatch2(aref_field, $1, escape_Qundef($3));
01673
01674 }
01675 | primary_value '.' tIDENTIFIER
01676 {
01677 #if 0
01678 $$ = attrset($1, $3);
01679 #endif
01680 $$ = dispatch3(field, $1, ripper_id2sym('.'), $3);
01681
01682 }
01683 | primary_value tCOLON2 tIDENTIFIER
01684 {
01685 #if 0
01686 $$ = attrset($1, $3);
01687 #endif
01688 $$ = dispatch3(field, $1, ripper_intern("::"), $3);
01689
01690 }
01691 | primary_value '.' tCONSTANT
01692 {
01693 #if 0
01694 $$ = attrset($1, $3);
01695 #endif
01696 $$ = dispatch3(field, $1, ripper_id2sym('.'), $3);
01697
01698 }
01699 | primary_value tCOLON2 tCONSTANT
01700 {
01701 #if 0
01702 if (in_def || in_single)
01703 yyerror("dynamic constant assignment");
01704 $$ = NEW_CDECL(0, 0, NEW_COLON2($1, $3));
01705 #endif
01706 $$ = dispatch2(const_path_field, $1, $3);
01707 if (in_def || in_single) {
01708 $$ = dispatch1(assign_error, $$);
01709 }
01710
01711 }
01712 | tCOLON3 tCONSTANT
01713 {
01714 #if 0
01715 if (in_def || in_single)
01716 yyerror("dynamic constant assignment");
01717 $$ = NEW_CDECL(0, 0, NEW_COLON3($2));
01718 #endif
01719 $$ = dispatch1(top_const_field, $2);
01720 if (in_def || in_single) {
01721 $$ = dispatch1(assign_error, $$);
01722 }
01723
01724 }
01725 | backref
01726 {
01727 #if 0
01728 rb_backref_error($1);
01729 $$ = NEW_BEGIN(0);
01730 #endif
01731 $$ = dispatch1(assign_error, $1);
01732
01733 }
01734 ;
01735
01736 cname : tIDENTIFIER
01737 {
01738 #if 0
01739 yyerror("class/module name must be CONSTANT");
01740 #endif
01741 $$ = dispatch1(class_name_error, $1);
01742
01743 }
01744 | tCONSTANT
01745 ;
01746
01747 cpath : tCOLON3 cname
01748 {
01749 #if 0
01750 $$ = NEW_COLON3($2);
01751 #endif
01752 $$ = dispatch1(top_const_ref, $2);
01753
01754 }
01755 | cname
01756 {
01757 #if 0
01758 $$ = NEW_COLON2(0, $$);
01759 #endif
01760 $$ = dispatch1(const_ref, $1);
01761
01762 }
01763 | primary_value tCOLON2 cname
01764 {
01765 #if 0
01766 $$ = NEW_COLON2($1, $3);
01767 #endif
01768 $$ = dispatch2(const_path_ref, $1, $3);
01769
01770 }
01771 ;
01772
01773 fname : tIDENTIFIER
01774 | tCONSTANT
01775 | tFID
01776 | op
01777 {
01778 lex_state = EXPR_ENDFN;
01779 $$ = $1;
01780 }
01781 | reswords
01782 {
01783 lex_state = EXPR_ENDFN;
01784 #if 0
01785 $$ = $<id>1;
01786 #endif
01787 $$ = $1;
01788
01789 }
01790 ;
01791
01792 fsym : fname
01793 | symbol
01794 ;
01795
01796 fitem : fsym
01797 {
01798 #if 0
01799 $$ = NEW_LIT(ID2SYM($1));
01800 #endif
01801 $$ = dispatch1(symbol_literal, $1);
01802
01803 }
01804 | dsym
01805 ;
01806
01807 undef_list : fitem
01808 {
01809 #if 0
01810 $$ = NEW_UNDEF($1);
01811 #endif
01812 $$ = rb_ary_new3(1, $1);
01813
01814 }
01815 | undef_list ',' {lex_state = EXPR_FNAME;} fitem
01816 {
01817 #if 0
01818 $$ = block_append($1, NEW_UNDEF($4));
01819 #endif
01820 rb_ary_push($1, $4);
01821
01822 }
01823 ;
01824
01825 op : '|' { ifndef_ripper($$ = '|'); }
01826 | '^' { ifndef_ripper($$ = '^'); }
01827 | '&' { ifndef_ripper($$ = '&'); }
01828 | tCMP { ifndef_ripper($$ = tCMP); }
01829 | tEQ { ifndef_ripper($$ = tEQ); }
01830 | tEQQ { ifndef_ripper($$ = tEQQ); }
01831 | tMATCH { ifndef_ripper($$ = tMATCH); }
01832 | tNMATCH { ifndef_ripper($$ = tNMATCH); }
01833 | '>' { ifndef_ripper($$ = '>'); }
01834 | tGEQ { ifndef_ripper($$ = tGEQ); }
01835 | '<' { ifndef_ripper($$ = '<'); }
01836 | tLEQ { ifndef_ripper($$ = tLEQ); }
01837 | tNEQ { ifndef_ripper($$ = tNEQ); }
01838 | tLSHFT { ifndef_ripper($$ = tLSHFT); }
01839 | tRSHFT { ifndef_ripper($$ = tRSHFT); }
01840 | '+' { ifndef_ripper($$ = '+'); }
01841 | '-' { ifndef_ripper($$ = '-'); }
01842 | '*' { ifndef_ripper($$ = '*'); }
01843 | tSTAR { ifndef_ripper($$ = '*'); }
01844 | '/' { ifndef_ripper($$ = '/'); }
01845 | '%' { ifndef_ripper($$ = '%'); }
01846 | tPOW { ifndef_ripper($$ = tPOW); }
01847 | '!' { ifndef_ripper($$ = '!'); }
01848 | '~' { ifndef_ripper($$ = '~'); }
01849 | tUPLUS { ifndef_ripper($$ = tUPLUS); }
01850 | tUMINUS { ifndef_ripper($$ = tUMINUS); }
01851 | tAREF { ifndef_ripper($$ = tAREF); }
01852 | tASET { ifndef_ripper($$ = tASET); }
01853 | '`' { ifndef_ripper($$ = '`'); }
01854 ;
01855
01856 reswords : keyword__LINE__ | keyword__FILE__ | keyword__ENCODING__
01857 | keyword_BEGIN | keyword_END
01858 | keyword_alias | keyword_and | keyword_begin
01859 | keyword_break | keyword_case | keyword_class | keyword_def
01860 | keyword_defined | keyword_do | keyword_else | keyword_elsif
01861 | keyword_end | keyword_ensure | keyword_false
01862 | keyword_for | keyword_in | keyword_module | keyword_next
01863 | keyword_nil | keyword_not | keyword_or | keyword_redo
01864 | keyword_rescue | keyword_retry | keyword_return | keyword_self
01865 | keyword_super | keyword_then | keyword_true | keyword_undef
01866 | keyword_when | keyword_yield | keyword_if | keyword_unless
01867 | keyword_while | keyword_until
01868 ;
01869
01870 arg : lhs '=' arg
01871 {
01872 #if 0
01873 value_expr($3);
01874 $$ = node_assign($1, $3);
01875 #endif
01876 $$ = dispatch2(assign, $1, $3);
01877
01878 }
01879 | lhs '=' arg modifier_rescue arg
01880 {
01881 #if 0
01882 value_expr($3);
01883 $3 = NEW_RESCUE($3, NEW_RESBODY(0,$5,0), 0);
01884 $$ = node_assign($1, $3);
01885 #endif
01886 $$ = dispatch2(assign, $1, dispatch2(rescue_mod, $3, $5));
01887
01888 }
01889 | var_lhs tOP_ASGN arg
01890 {
01891 #if 0
01892 value_expr($3);
01893 if ($1) {
01894 ID vid = $1->nd_vid;
01895 if ($2 == tOROP) {
01896 $1->nd_value = $3;
01897 $$ = NEW_OP_ASGN_OR(gettable(vid), $1);
01898 if (is_asgn_or_id(vid)) {
01899 $$->nd_aid = vid;
01900 }
01901 }
01902 else if ($2 == tANDOP) {
01903 $1->nd_value = $3;
01904 $$ = NEW_OP_ASGN_AND(gettable(vid), $1);
01905 }
01906 else {
01907 $$ = $1;
01908 $$->nd_value = NEW_CALL(gettable(vid), $2, NEW_LIST($3));
01909 }
01910 }
01911 else {
01912 $$ = NEW_BEGIN(0);
01913 }
01914 #endif
01915 $$ = dispatch3(opassign, $1, $2, $3);
01916
01917 }
01918 | var_lhs tOP_ASGN arg modifier_rescue arg
01919 {
01920 #if 0
01921 value_expr($3);
01922 $3 = NEW_RESCUE($3, NEW_RESBODY(0,$5,0), 0);
01923 if ($1) {
01924 ID vid = $1->nd_vid;
01925 if ($2 == tOROP) {
01926 $1->nd_value = $3;
01927 $$ = NEW_OP_ASGN_OR(gettable(vid), $1);
01928 if (is_asgn_or_id(vid)) {
01929 $$->nd_aid = vid;
01930 }
01931 }
01932 else if ($2 == tANDOP) {
01933 $1->nd_value = $3;
01934 $$ = NEW_OP_ASGN_AND(gettable(vid), $1);
01935 }
01936 else {
01937 $$ = $1;
01938 $$->nd_value = NEW_CALL(gettable(vid), $2, NEW_LIST($3));
01939 }
01940 }
01941 else {
01942 $$ = NEW_BEGIN(0);
01943 }
01944 #endif
01945 $3 = dispatch2(rescue_mod, $3, $5);
01946 $$ = dispatch3(opassign, $1, $2, $3);
01947
01948 }
01949 | primary_value '[' opt_call_args rbracket tOP_ASGN arg
01950 {
01951 #if 0
01952 NODE *args;
01953
01954 value_expr($6);
01955 if (!$3) $3 = NEW_ZARRAY();
01956 if (nd_type($3) == NODE_BLOCK_PASS) {
01957 args = NEW_ARGSCAT($3, $6);
01958 }
01959 else {
01960 args = arg_concat($3, $6);
01961 }
01962 if ($5 == tOROP) {
01963 $5 = 0;
01964 }
01965 else if ($5 == tANDOP) {
01966 $5 = 1;
01967 }
01968 $$ = NEW_OP_ASGN1($1, $5, args);
01969 fixpos($$, $1);
01970 #endif
01971 $1 = dispatch2(aref_field, $1, escape_Qundef($3));
01972 $$ = dispatch3(opassign, $1, $5, $6);
01973
01974 }
01975 | primary_value '.' tIDENTIFIER tOP_ASGN arg
01976 {
01977 #if 0
01978 value_expr($5);
01979 if ($4 == tOROP) {
01980 $4 = 0;
01981 }
01982 else if ($4 == tANDOP) {
01983 $4 = 1;
01984 }
01985 $$ = NEW_OP_ASGN2($1, $3, $4, $5);
01986 fixpos($$, $1);
01987 #endif
01988 $1 = dispatch3(field, $1, ripper_id2sym('.'), $3);
01989 $$ = dispatch3(opassign, $1, $4, $5);
01990
01991 }
01992 | primary_value '.' tCONSTANT tOP_ASGN arg
01993 {
01994 #if 0
01995 value_expr($5);
01996 if ($4 == tOROP) {
01997 $4 = 0;
01998 }
01999 else if ($4 == tANDOP) {
02000 $4 = 1;
02001 }
02002 $$ = NEW_OP_ASGN2($1, $3, $4, $5);
02003 fixpos($$, $1);
02004 #endif
02005 $1 = dispatch3(field, $1, ripper_id2sym('.'), $3);
02006 $$ = dispatch3(opassign, $1, $4, $5);
02007
02008 }
02009 | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg
02010 {
02011 #if 0
02012 value_expr($5);
02013 if ($4 == tOROP) {
02014 $4 = 0;
02015 }
02016 else if ($4 == tANDOP) {
02017 $4 = 1;
02018 }
02019 $$ = NEW_OP_ASGN2($1, $3, $4, $5);
02020 fixpos($$, $1);
02021 #endif
02022 $1 = dispatch3(field, $1, ripper_intern("::"), $3);
02023 $$ = dispatch3(opassign, $1, $4, $5);
02024
02025 }
02026 | primary_value tCOLON2 tCONSTANT tOP_ASGN arg
02027 {
02028 #if 0
02029 yyerror("constant re-assignment");
02030 $$ = NEW_BEGIN(0);
02031 #endif
02032 $$ = dispatch2(const_path_field, $1, $3);
02033 $$ = dispatch3(opassign, $$, $4, $5);
02034 $$ = dispatch1(assign_error, $$);
02035
02036 }
02037 | tCOLON3 tCONSTANT tOP_ASGN arg
02038 {
02039 #if 0
02040 yyerror("constant re-assignment");
02041 $$ = NEW_BEGIN(0);
02042 #endif
02043 $$ = dispatch1(top_const_field, $2);
02044 $$ = dispatch3(opassign, $$, $3, $4);
02045 $$ = dispatch1(assign_error, $$);
02046
02047 }
02048 | backref tOP_ASGN arg
02049 {
02050 #if 0
02051 rb_backref_error($1);
02052 $$ = NEW_BEGIN(0);
02053 #endif
02054 $$ = dispatch1(var_field, $1);
02055 $$ = dispatch3(opassign, $$, $2, $3);
02056 $$ = dispatch1(assign_error, $$);
02057
02058 }
02059 | arg tDOT2 arg
02060 {
02061 #if 0
02062 value_expr($1);
02063 value_expr($3);
02064 $$ = NEW_DOT2($1, $3);
02065 if (nd_type($1) == NODE_LIT && FIXNUM_P($1->nd_lit) &&
02066 nd_type($3) == NODE_LIT && FIXNUM_P($3->nd_lit)) {
02067 deferred_nodes = list_append(deferred_nodes, $$);
02068 }
02069 #endif
02070 $$ = dispatch2(dot2, $1, $3);
02071
02072 }
02073 | arg tDOT3 arg
02074 {
02075 #if 0
02076 value_expr($1);
02077 value_expr($3);
02078 $$ = NEW_DOT3($1, $3);
02079 if (nd_type($1) == NODE_LIT && FIXNUM_P($1->nd_lit) &&
02080 nd_type($3) == NODE_LIT && FIXNUM_P($3->nd_lit)) {
02081 deferred_nodes = list_append(deferred_nodes, $$);
02082 }
02083 #endif
02084 $$ = dispatch2(dot3, $1, $3);
02085
02086 }
02087 | arg '+' arg
02088 {
02089 #if 0
02090 $$ = call_bin_op($1, '+', $3);
02091 #endif
02092 $$ = dispatch3(binary, $1, ID2SYM('+'), $3);
02093
02094 }
02095 | arg '-' arg
02096 {
02097 #if 0
02098 $$ = call_bin_op($1, '-', $3);
02099 #endif
02100 $$ = dispatch3(binary, $1, ID2SYM('-'), $3);
02101
02102 }
02103 | arg '*' arg
02104 {
02105 #if 0
02106 $$ = call_bin_op($1, '*', $3);
02107 #endif
02108 $$ = dispatch3(binary, $1, ID2SYM('*'), $3);
02109
02110 }
02111 | arg '/' arg
02112 {
02113 #if 0
02114 $$ = call_bin_op($1, '/', $3);
02115 #endif
02116 $$ = dispatch3(binary, $1, ID2SYM('/'), $3);
02117
02118 }
02119 | arg '%' arg
02120 {
02121 #if 0
02122 $$ = call_bin_op($1, '%', $3);
02123 #endif
02124 $$ = dispatch3(binary, $1, ID2SYM('%'), $3);
02125
02126 }
02127 | arg tPOW arg
02128 {
02129 #if 0
02130 $$ = call_bin_op($1, tPOW, $3);
02131 #endif
02132 $$ = dispatch3(binary, $1, ripper_intern("**"), $3);
02133
02134 }
02135 | tUMINUS_NUM tINTEGER tPOW arg
02136 {
02137 #if 0
02138 $$ = NEW_CALL(call_bin_op($2, tPOW, $4), tUMINUS, 0);
02139 #endif
02140 $$ = dispatch3(binary, $2, ripper_intern("**"), $4);
02141 $$ = dispatch2(unary, ripper_intern("-@"), $$);
02142
02143 }
02144 | tUMINUS_NUM tFLOAT tPOW arg
02145 {
02146 #if 0
02147 $$ = NEW_CALL(call_bin_op($2, tPOW, $4), tUMINUS, 0);
02148 #endif
02149 $$ = dispatch3(binary, $2, ripper_intern("**"), $4);
02150 $$ = dispatch2(unary, ripper_intern("-@"), $$);
02151
02152 }
02153 | tUPLUS arg
02154 {
02155 #if 0
02156 $$ = call_uni_op($2, tUPLUS);
02157 #endif
02158 $$ = dispatch2(unary, ripper_intern("+@"), $2);
02159
02160 }
02161 | tUMINUS arg
02162 {
02163 #if 0
02164 $$ = call_uni_op($2, tUMINUS);
02165 #endif
02166 $$ = dispatch2(unary, ripper_intern("-@"), $2);
02167
02168 }
02169 | arg '|' arg
02170 {
02171 #if 0
02172 $$ = call_bin_op($1, '|', $3);
02173 #endif
02174 $$ = dispatch3(binary, $1, ID2SYM('|'), $3);
02175
02176 }
02177 | arg '^' arg
02178 {
02179 #if 0
02180 $$ = call_bin_op($1, '^', $3);
02181 #endif
02182 $$ = dispatch3(binary, $1, ID2SYM('^'), $3);
02183
02184 }
02185 | arg '&' arg
02186 {
02187 #if 0
02188 $$ = call_bin_op($1, '&', $3);
02189 #endif
02190 $$ = dispatch3(binary, $1, ID2SYM('&'), $3);
02191
02192 }
02193 | arg tCMP arg
02194 {
02195 #if 0
02196 $$ = call_bin_op($1, tCMP, $3);
02197 #endif
02198 $$ = dispatch3(binary, $1, ripper_intern("<=>"), $3);
02199
02200 }
02201 | arg '>' arg
02202 {
02203 #if 0
02204 $$ = call_bin_op($1, '>', $3);
02205 #endif
02206 $$ = dispatch3(binary, $1, ID2SYM('>'), $3);
02207
02208 }
02209 | arg tGEQ arg
02210 {
02211 #if 0
02212 $$ = call_bin_op($1, tGEQ, $3);
02213 #endif
02214 $$ = dispatch3(binary, $1, ripper_intern(">="), $3);
02215
02216 }
02217 | arg '<' arg
02218 {
02219 #if 0
02220 $$ = call_bin_op($1, '<', $3);
02221 #endif
02222 $$ = dispatch3(binary, $1, ID2SYM('<'), $3);
02223
02224 }
02225 | arg tLEQ arg
02226 {
02227 #if 0
02228 $$ = call_bin_op($1, tLEQ, $3);
02229 #endif
02230 $$ = dispatch3(binary, $1, ripper_intern("<="), $3);
02231
02232 }
02233 | arg tEQ arg
02234 {
02235 #if 0
02236 $$ = call_bin_op($1, tEQ, $3);
02237 #endif
02238 $$ = dispatch3(binary, $1, ripper_intern("=="), $3);
02239
02240 }
02241 | arg tEQQ arg
02242 {
02243 #if 0
02244 $$ = call_bin_op($1, tEQQ, $3);
02245 #endif
02246 $$ = dispatch3(binary, $1, ripper_intern("==="), $3);
02247
02248 }
02249 | arg tNEQ arg
02250 {
02251 #if 0
02252 $$ = call_bin_op($1, tNEQ, $3);
02253 #endif
02254 $$ = dispatch3(binary, $1, ripper_intern("!="), $3);
02255
02256 }
02257 | arg tMATCH arg
02258 {
02259 #if 0
02260 $$ = match_op($1, $3);
02261 if (nd_type($1) == NODE_LIT && TYPE($1->nd_lit) == T_REGEXP) {
02262 $$ = reg_named_capture_assign($1->nd_lit, $$);
02263 }
02264 #endif
02265 $$ = dispatch3(binary, $1, ripper_intern("=~"), $3);
02266
02267 }
02268 | arg tNMATCH arg
02269 {
02270 #if 0
02271 $$ = call_bin_op($1, tNMATCH, $3);
02272 #endif
02273 $$ = dispatch3(binary, $1, ripper_intern("!~"), $3);
02274
02275 }
02276 | '!' arg
02277 {
02278 #if 0
02279 $$ = call_uni_op(cond($2), '!');
02280 #endif
02281 $$ = dispatch2(unary, ID2SYM('!'), $2);
02282
02283 }
02284 | '~' arg
02285 {
02286 #if 0
02287 $$ = call_uni_op($2, '~');
02288 #endif
02289 $$ = dispatch2(unary, ID2SYM('~'), $2);
02290
02291 }
02292 | arg tLSHFT arg
02293 {
02294 #if 0
02295 $$ = call_bin_op($1, tLSHFT, $3);
02296 #endif
02297 $$ = dispatch3(binary, $1, ripper_intern("<<"), $3);
02298
02299 }
02300 | arg tRSHFT arg
02301 {
02302 #if 0
02303 $$ = call_bin_op($1, tRSHFT, $3);
02304 #endif
02305 $$ = dispatch3(binary, $1, ripper_intern(">>"), $3);
02306
02307 }
02308 | arg tANDOP arg
02309 {
02310 #if 0
02311 $$ = logop(NODE_AND, $1, $3);
02312 #endif
02313 $$ = dispatch3(binary, $1, ripper_intern("&&"), $3);
02314
02315 }
02316 | arg tOROP arg
02317 {
02318 #if 0
02319 $$ = logop(NODE_OR, $1, $3);
02320 #endif
02321 $$ = dispatch3(binary, $1, ripper_intern("||"), $3);
02322
02323 }
02324 | keyword_defined opt_nl {in_defined = 1;} arg
02325 {
02326 #if 0
02327 in_defined = 0;
02328 $$ = NEW_DEFINED($4);
02329 #endif
02330 in_defined = 0;
02331 $$ = dispatch1(defined, $4);
02332
02333 }
02334 | arg '?' arg opt_nl ':' arg
02335 {
02336 #if 0
02337 value_expr($1);
02338 $$ = NEW_IF(cond($1), $3, $6);
02339 fixpos($$, $1);
02340 #endif
02341 $$ = dispatch3(ifop, $1, $3, $6);
02342
02343 }
02344 | primary
02345 {
02346 $$ = $1;
02347 }
02348 ;
02349
02350 arg_value : arg
02351 {
02352 #if 0
02353 value_expr($1);
02354 $$ = $1;
02355 if (!$$) $$ = NEW_NIL();
02356 #endif
02357 $$ = $1;
02358
02359 }
02360 ;
02361
02362 aref_args : none
02363 | args trailer
02364 {
02365 $$ = $1;
02366 }
02367 | args ',' assocs trailer
02368 {
02369 #if 0
02370 $$ = arg_append($1, NEW_HASH($3));
02371 #endif
02372 $$ = arg_add_assocs($1, $3);
02373
02374 }
02375 | assocs trailer
02376 {
02377 #if 0
02378 $$ = NEW_LIST(NEW_HASH($1));
02379 #endif
02380 $$ = arg_add_assocs(arg_new(), $1);
02381
02382 }
02383 ;
02384
02385 paren_args : '(' opt_call_args rparen
02386 {
02387 #if 0
02388 $$ = $2;
02389 #endif
02390 $$ = dispatch1(arg_paren, escape_Qundef($2));
02391
02392 }
02393 ;
02394
02395 opt_paren_args : none
02396 | paren_args
02397 ;
02398
02399 opt_call_args : none
02400 | call_args
02401 ;
02402
02403 call_args : command
02404 {
02405 #if 0
02406 value_expr($1);
02407 $$ = NEW_LIST($1);
02408 #endif
02409 $$ = arg_add(arg_new(), $1);
02410
02411 }
02412 | args opt_block_arg
02413 {
02414 #if 0
02415 $$ = arg_blk_pass($1, $2);
02416 #endif
02417 $$ = arg_add_optblock($1, $2);
02418
02419 }
02420 | assocs opt_block_arg
02421 {
02422 #if 0
02423 $$ = NEW_LIST(NEW_HASH($1));
02424 $$ = arg_blk_pass($$, $2);
02425 #endif
02426 $$ = arg_add_assocs(arg_new(), $1);
02427 $$ = arg_add_optblock($$, $2);
02428
02429 }
02430 | args ',' assocs opt_block_arg
02431 {
02432 #if 0
02433 $$ = arg_append($1, NEW_HASH($3));
02434 $$ = arg_blk_pass($$, $4);
02435 #endif
02436 $$ = arg_add_optblock(arg_add_assocs($1, $3), $4);
02437
02438 }
02439 | block_arg
02440
02441
02442 {
02443 $$ = arg_add_block(arg_new(), $1);
02444 }
02445
02446 ;
02447
02448 command_args : {
02449 $<val>$ = cmdarg_stack;
02450 CMDARG_PUSH(1);
02451 }
02452 call_args
02453 {
02454
02455 cmdarg_stack = $<val>1;
02456 $$ = $2;
02457 }
02458 ;
02459
02460 block_arg : tAMPER arg_value
02461 {
02462 #if 0
02463 $$ = NEW_BLOCK_PASS($2);
02464 #endif
02465 $$ = $2;
02466
02467 }
02468 ;
02469
02470 opt_block_arg : ',' block_arg
02471 {
02472 $$ = $2;
02473 }
02474 | ','
02475 {
02476 $$ = 0;
02477 }
02478 | none
02479 {
02480 $$ = 0;
02481 }
02482 ;
02483
02484 args : arg_value
02485 {
02486 #if 0
02487 $$ = NEW_LIST($1);
02488 #endif
02489 $$ = arg_add(arg_new(), $1);
02490
02491 }
02492 | tSTAR arg_value
02493 {
02494 #if 0
02495 $$ = NEW_SPLAT($2);
02496 #endif
02497 $$ = arg_add_star(arg_new(), $2);
02498
02499 }
02500 | args ',' arg_value
02501 {
02502 #if 0
02503 NODE *n1;
02504 if ((n1 = splat_array($1)) != 0) {
02505 $$ = list_append(n1, $3);
02506 }
02507 else {
02508 $$ = arg_append($1, $3);
02509 }
02510 #endif
02511 $$ = arg_add($1, $3);
02512
02513 }
02514 | args ',' tSTAR arg_value
02515 {
02516 #if 0
02517 NODE *n1;
02518 if ((nd_type($4) == NODE_ARRAY) && (n1 = splat_array($1)) != 0) {
02519 $$ = list_concat(n1, $4);
02520 }
02521 else {
02522 $$ = arg_concat($1, $4);
02523 }
02524 #endif
02525 $$ = arg_add_star($1, $4);
02526
02527 }
02528 ;
02529
02530 mrhs : args ',' arg_value
02531 {
02532 #if 0
02533 NODE *n1;
02534 if ((n1 = splat_array($1)) != 0) {
02535 $$ = list_append(n1, $3);
02536 }
02537 else {
02538 $$ = arg_append($1, $3);
02539 }
02540 #endif
02541 $$ = mrhs_add(args2mrhs($1), $3);
02542
02543 }
02544 | args ',' tSTAR arg_value
02545 {
02546 #if 0
02547 NODE *n1;
02548 if (nd_type($4) == NODE_ARRAY &&
02549 (n1 = splat_array($1)) != 0) {
02550 $$ = list_concat(n1, $4);
02551 }
02552 else {
02553 $$ = arg_concat($1, $4);
02554 }
02555 #endif
02556 $$ = mrhs_add_star(args2mrhs($1), $4);
02557
02558 }
02559 | tSTAR arg_value
02560 {
02561 #if 0
02562 $$ = NEW_SPLAT($2);
02563 #endif
02564 $$ = mrhs_add_star(mrhs_new(), $2);
02565
02566 }
02567 ;
02568
02569 primary : literal
02570 | strings
02571 | xstring
02572 | regexp
02573 | words
02574 | qwords
02575 | var_ref
02576 | backref
02577 | tFID
02578 {
02579 #if 0
02580 $$ = NEW_FCALL($1, 0);
02581 #endif
02582 $$ = method_arg(dispatch1(fcall, $1), arg_new());
02583
02584 }
02585 | k_begin
02586 {
02587 #if 0
02588 $<num>$ = ruby_sourceline;
02589 #endif
02590
02591 }
02592 bodystmt
02593 k_end
02594 {
02595 #if 0
02596 if ($3 == NULL) {
02597 $$ = NEW_NIL();
02598 }
02599 else {
02600 if (nd_type($3) == NODE_RESCUE ||
02601 nd_type($3) == NODE_ENSURE)
02602 nd_set_line($3, $<num>2);
02603 $$ = NEW_BEGIN($3);
02604 }
02605 nd_set_line($$, $<num>2);
02606 #endif
02607 $$ = dispatch1(begin, $3);
02608
02609 }
02610 | tLPAREN_ARG expr {lex_state = EXPR_ENDARG;} rparen
02611 {
02612 rb_warning0("(...) interpreted as grouped expression");
02613 #if 0
02614 $$ = $2;
02615 #endif
02616 $$ = dispatch1(paren, $2);
02617
02618 }
02619 | tLPAREN compstmt ')'
02620 {
02621 #if 0
02622 $$ = $2;
02623 #endif
02624 $$ = dispatch1(paren, $2);
02625
02626 }
02627 | primary_value tCOLON2 tCONSTANT
02628 {
02629 #if 0
02630 $$ = NEW_COLON2($1, $3);
02631 #endif
02632 $$ = dispatch2(const_path_ref, $1, $3);
02633
02634 }
02635 | tCOLON3 tCONSTANT
02636 {
02637 #if 0
02638 $$ = NEW_COLON3($2);
02639 #endif
02640 $$ = dispatch1(top_const_ref, $2);
02641
02642 }
02643 | tLBRACK aref_args ']'
02644 {
02645 #if 0
02646 if ($2 == 0) {
02647 $$ = NEW_ZARRAY();
02648 }
02649 else {
02650 $$ = $2;
02651 }
02652 #endif
02653 $$ = dispatch1(array, escape_Qundef($2));
02654
02655 }
02656 | tLBRACE assoc_list '}'
02657 {
02658 #if 0
02659 $$ = NEW_HASH($2);
02660 #endif
02661 $$ = dispatch1(hash, escape_Qundef($2));
02662
02663 }
02664 | keyword_return
02665 {
02666 #if 0
02667 $$ = NEW_RETURN(0);
02668 #endif
02669 $$ = dispatch0(return0);
02670
02671 }
02672 | keyword_yield '(' call_args rparen
02673 {
02674 #if 0
02675 $$ = new_yield($3);
02676 #endif
02677 $$ = dispatch1(yield, dispatch1(paren, $3));
02678
02679 }
02680 | keyword_yield '(' rparen
02681 {
02682 #if 0
02683 $$ = NEW_YIELD(0, Qfalse);
02684 #endif
02685 $$ = dispatch1(yield, dispatch1(paren, arg_new()));
02686
02687 }
02688 | keyword_yield
02689 {
02690 #if 0
02691 $$ = NEW_YIELD(0, Qfalse);
02692 #endif
02693 $$ = dispatch0(yield0);
02694
02695 }
02696 | keyword_defined opt_nl '(' {in_defined = 1;} expr rparen
02697 {
02698 #if 0
02699 in_defined = 0;
02700 $$ = NEW_DEFINED($5);
02701 #endif
02702 in_defined = 0;
02703 $$ = dispatch1(defined, $5);
02704
02705 }
02706 | keyword_not '(' expr rparen
02707 {
02708 #if 0
02709 $$ = call_uni_op(cond($3), '!');
02710 #endif
02711 $$ = dispatch2(unary, ripper_intern("not"), $3);
02712
02713 }
02714 | keyword_not '(' rparen
02715 {
02716 #if 0
02717 $$ = call_uni_op(cond(NEW_NIL()), '!');
02718 #endif
02719 $$ = dispatch2(unary, ripper_intern("not"), Qnil);
02720
02721 }
02722 | operation brace_block
02723 {
02724 #if 0
02725 $2->nd_iter = NEW_FCALL($1, 0);
02726 $$ = $2;
02727 fixpos($2->nd_iter, $2);
02728 #endif
02729 $$ = method_arg(dispatch1(fcall, $1), arg_new());
02730 $$ = method_add_block($$, $2);
02731
02732 }
02733 | method_call
02734 | method_call brace_block
02735 {
02736 #if 0
02737 block_dup_check($1->nd_args, $2);
02738 $2->nd_iter = $1;
02739 $$ = $2;
02740 fixpos($$, $1);
02741 #endif
02742 $$ = method_add_block($1, $2);
02743
02744 }
02745 | tLAMBDA lambda
02746 {
02747 $$ = $2;
02748 }
02749 | k_if expr_value then
02750 compstmt
02751 if_tail
02752 k_end
02753 {
02754 #if 0
02755 $$ = NEW_IF(cond($2), $4, $5);
02756 fixpos($$, $2);
02757 #endif
02758 $$ = dispatch3(if, $2, $4, escape_Qundef($5));
02759
02760 }
02761 | k_unless expr_value then
02762 compstmt
02763 opt_else
02764 k_end
02765 {
02766 #if 0
02767 $$ = NEW_UNLESS(cond($2), $4, $5);
02768 fixpos($$, $2);
02769 #endif
02770 $$ = dispatch3(unless, $2, $4, escape_Qundef($5));
02771
02772 }
02773 | k_while {COND_PUSH(1);} expr_value do {COND_POP();}
02774 compstmt
02775 k_end
02776 {
02777 #if 0
02778 $$ = NEW_WHILE(cond($3), $6, 1);
02779 fixpos($$, $3);
02780 #endif
02781 $$ = dispatch2(while, $3, $6);
02782
02783 }
02784 | k_until {COND_PUSH(1);} expr_value do {COND_POP();}
02785 compstmt
02786 k_end
02787 {
02788 #if 0
02789 $$ = NEW_UNTIL(cond($3), $6, 1);
02790 fixpos($$, $3);
02791 #endif
02792 $$ = dispatch2(until, $3, $6);
02793
02794 }
02795 | k_case expr_value opt_terms
02796 case_body
02797 k_end
02798 {
02799 #if 0
02800 $$ = NEW_CASE($2, $4);
02801 fixpos($$, $2);
02802 #endif
02803 $$ = dispatch2(case, $2, $4);
02804
02805 }
02806 | k_case opt_terms case_body k_end
02807 {
02808 #if 0
02809 $$ = NEW_CASE(0, $3);
02810 #endif
02811 $$ = dispatch2(case, Qnil, $3);
02812
02813 }
02814 | k_for for_var keyword_in
02815 {COND_PUSH(1);}
02816 expr_value do
02817 {COND_POP();}
02818 compstmt
02819 k_end
02820 {
02821 #if 0
02822
02823
02824
02825
02826
02827
02828
02829
02830
02831 ID id = internal_id();
02832 ID *tbl = ALLOC_N(ID, 2);
02833 NODE *m = NEW_ARGS_AUX(0, 0);
02834 NODE *args, *scope;
02835
02836 if (nd_type($2) == NODE_MASGN) {
02837
02838
02839
02840
02841 NODE *one = NEW_LIST(NEW_LIT(INT2FIX(1)));
02842 NODE *zero = NEW_LIST(NEW_LIT(INT2FIX(0)));
02843 m->nd_next = block_append(
02844 NEW_IF(
02845 NEW_NODE(NODE_AND,
02846 NEW_CALL(NEW_CALL(NEW_DVAR(id), rb_intern("length"), 0),
02847 rb_intern("=="), one),
02848 NEW_CALL(NEW_CALL(NEW_DVAR(id), rb_intern("[]"), zero),
02849 rb_intern("kind_of?"), NEW_LIST(NEW_LIT(rb_cArray))),
02850 0),
02851 NEW_DASGN_CURR(id,
02852 NEW_CALL(NEW_DVAR(id), rb_intern("[]"), zero)),
02853 0),
02854 node_assign($2, NEW_DVAR(id)));
02855
02856 args = new_args(m, 0, id, 0, 0);
02857 }
02858 else {
02859 if (nd_type($2) == NODE_LASGN ||
02860 nd_type($2) == NODE_DASGN ||
02861 nd_type($2) == NODE_DASGN_CURR) {
02862 $2->nd_value = NEW_DVAR(id);
02863 m->nd_plen = 1;
02864 m->nd_next = $2;
02865 args = new_args(m, 0, 0, 0, 0);
02866 }
02867 else {
02868 m->nd_next = node_assign(NEW_MASGN(NEW_LIST($2), 0), NEW_DVAR(id));
02869 args = new_args(m, 0, id, 0, 0);
02870 }
02871 }
02872 scope = NEW_NODE(NODE_SCOPE, tbl, $8, args);
02873 tbl[0] = 1; tbl[1] = id;
02874 $$ = NEW_FOR(0, $5, scope);
02875 fixpos($$, $2);
02876 #endif
02877 $$ = dispatch3(for, $2, $5, $8);
02878
02879 }
02880 | k_class cpath superclass
02881 {
02882 if (in_def || in_single)
02883 yyerror("class definition in method body");
02884 local_push(0);
02885 #if 0
02886 $<num>$ = ruby_sourceline;
02887 #endif
02888
02889 }
02890 bodystmt
02891 k_end
02892 {
02893 #if 0
02894 $$ = NEW_CLASS($2, $5, $3);
02895 nd_set_line($$, $<num>4);
02896 #endif
02897 $$ = dispatch3(class, $2, $3, $5);
02898
02899 local_pop();
02900 }
02901 | k_class tLSHFT expr
02902 {
02903 $<num>$ = in_def;
02904 in_def = 0;
02905 }
02906 term
02907 {
02908 $<num>$ = in_single;
02909 in_single = 0;
02910 local_push(0);
02911 }
02912 bodystmt
02913 k_end
02914 {
02915 #if 0
02916 $$ = NEW_SCLASS($3, $7);
02917 fixpos($$, $3);
02918 #endif
02919 $$ = dispatch2(sclass, $3, $7);
02920
02921 local_pop();
02922 in_def = $<num>4;
02923 in_single = $<num>6;
02924 }
02925 | k_module cpath
02926 {
02927 if (in_def || in_single)
02928 yyerror("module definition in method body");
02929 local_push(0);
02930 #if 0
02931 $<num>$ = ruby_sourceline;
02932 #endif
02933
02934 }
02935 bodystmt
02936 k_end
02937 {
02938 #if 0
02939 $$ = NEW_MODULE($2, $4);
02940 nd_set_line($$, $<num>3);
02941 #endif
02942 $$ = dispatch2(module, $2, $4);
02943
02944 local_pop();
02945 }
02946 | k_def fname
02947 {
02948 $<id>$ = cur_mid;
02949 cur_mid = $2;
02950 in_def++;
02951 local_push(0);
02952 }
02953 f_arglist
02954 bodystmt
02955 k_end
02956 {
02957 #if 0
02958 NODE *body = remove_begin($5);
02959 reduce_nodes(&body);
02960 $$ = NEW_DEFN($2, $4, body, NOEX_PRIVATE);
02961 nd_set_line($$, $<num>1);
02962 #endif
02963 $$ = dispatch3(def, $2, $4, $5);
02964
02965 local_pop();
02966 in_def--;
02967 cur_mid = $<id>3;
02968 }
02969 | k_def singleton dot_or_colon {lex_state = EXPR_FNAME;} fname
02970 {
02971 in_single++;
02972 lex_state = EXPR_ENDFN;
02973 local_push(0);
02974 }
02975 f_arglist
02976 bodystmt
02977 k_end
02978 {
02979 #if 0
02980 NODE *body = remove_begin($8);
02981 reduce_nodes(&body);
02982 $$ = NEW_DEFS($2, $5, $7, body);
02983 nd_set_line($$, $<num>1);
02984 #endif
02985 $$ = dispatch5(defs, $2, $3, $5, $7, $8);
02986
02987 local_pop();
02988 in_single--;
02989 }
02990 | keyword_break
02991 {
02992 #if 0
02993 $$ = NEW_BREAK(0);
02994 #endif
02995 $$ = dispatch1(break, arg_new());
02996
02997 }
02998 | keyword_next
02999 {
03000 #if 0
03001 $$ = NEW_NEXT(0);
03002 #endif
03003 $$ = dispatch1(next, arg_new());
03004
03005 }
03006 | keyword_redo
03007 {
03008 #if 0
03009 $$ = NEW_REDO();
03010 #endif
03011 $$ = dispatch0(redo);
03012
03013 }
03014 | keyword_retry
03015 {
03016 #if 0
03017 $$ = NEW_RETRY();
03018 #endif
03019 $$ = dispatch0(retry);
03020
03021 }
03022 ;
03023
03024 primary_value : primary
03025 {
03026 #if 0
03027 value_expr($1);
03028 $$ = $1;
03029 if (!$$) $$ = NEW_NIL();
03030 #endif
03031 $$ = $1;
03032
03033 }
03034 ;
03035
03036 k_begin : keyword_begin
03037 {
03038 token_info_push("begin");
03039 }
03040 ;
03041
03042 k_if : keyword_if
03043 {
03044 token_info_push("if");
03045 }
03046 ;
03047
03048 k_unless : keyword_unless
03049 {
03050 token_info_push("unless");
03051 }
03052 ;
03053
03054 k_while : keyword_while
03055 {
03056 token_info_push("while");
03057 }
03058 ;
03059
03060 k_until : keyword_until
03061 {
03062 token_info_push("until");
03063 }
03064 ;
03065
03066 k_case : keyword_case
03067 {
03068 token_info_push("case");
03069 }
03070 ;
03071
03072 k_for : keyword_for
03073 {
03074 token_info_push("for");
03075 }
03076 ;
03077
03078 k_class : keyword_class
03079 {
03080 token_info_push("class");
03081 }
03082 ;
03083
03084 k_module : keyword_module
03085 {
03086 token_info_push("module");
03087 }
03088 ;
03089
03090 k_def : keyword_def
03091 {
03092 token_info_push("def");
03093 #if 0
03094 $<num>$ = ruby_sourceline;
03095 #endif
03096
03097 }
03098 ;
03099
03100 k_end : keyword_end
03101 {
03102 token_info_pop("end");
03103 }
03104 ;
03105
03106 then : term
03107
03108
03109 { $$ = Qnil; }
03110
03111 | keyword_then
03112 | term keyword_then
03113
03114
03115 { $$ = $2; }
03116
03117 ;
03118
03119 do : term
03120
03121
03122 { $$ = Qnil; }
03123
03124 | keyword_do_cond
03125 ;
03126
03127 if_tail : opt_else
03128 | keyword_elsif expr_value then
03129 compstmt
03130 if_tail
03131 {
03132 #if 0
03133 $$ = NEW_IF(cond($2), $4, $5);
03134 fixpos($$, $2);
03135 #endif
03136 $$ = dispatch3(elsif, $2, $4, escape_Qundef($5));
03137
03138 }
03139 ;
03140
03141 opt_else : none
03142 | keyword_else compstmt
03143 {
03144 #if 0
03145 $$ = $2;
03146 #endif
03147 $$ = dispatch1(else, $2);
03148
03149 }
03150 ;
03151
03152 for_var : lhs
03153 | mlhs
03154 ;
03155
03156 f_marg : f_norm_arg
03157 {
03158 $$ = assignable($1, 0);
03159 #if 0
03160 #endif
03161 $$ = dispatch1(mlhs_paren, $$);
03162
03163 }
03164 | tLPAREN f_margs rparen
03165 {
03166 #if 0
03167 $$ = $2;
03168 #endif
03169 $$ = dispatch1(mlhs_paren, $2);
03170
03171 }
03172 ;
03173
03174 f_marg_list : f_marg
03175 {
03176 #if 0
03177 $$ = NEW_LIST($1);
03178 #endif
03179 $$ = mlhs_add(mlhs_new(), $1);
03180
03181 }
03182 | f_marg_list ',' f_marg
03183 {
03184 #if 0
03185 $$ = list_append($1, $3);
03186 #endif
03187 $$ = mlhs_add($1, $3);
03188
03189 }
03190 ;
03191
03192 f_margs : f_marg_list
03193 {
03194 #if 0
03195 $$ = NEW_MASGN($1, 0);
03196 #endif
03197 $$ = $1;
03198
03199 }
03200 | f_marg_list ',' tSTAR f_norm_arg
03201 {
03202 $$ = assignable($4, 0);
03203 #if 0
03204 $$ = NEW_MASGN($1, $$);
03205 #endif
03206 $$ = mlhs_add_star($1, $$);
03207
03208 }
03209 | f_marg_list ',' tSTAR f_norm_arg ',' f_marg_list
03210 {
03211 $$ = assignable($4, 0);
03212 #if 0
03213 $$ = NEW_MASGN($1, NEW_POSTARG($$, $6));
03214 #endif
03215 $$ = mlhs_add_star($1, $$);
03216
03217 }
03218 | f_marg_list ',' tSTAR
03219 {
03220 #if 0
03221 $$ = NEW_MASGN($1, -1);
03222 #endif
03223 $$ = mlhs_add_star($1, Qnil);
03224
03225 }
03226 | f_marg_list ',' tSTAR ',' f_marg_list
03227 {
03228 #if 0
03229 $$ = NEW_MASGN($1, NEW_POSTARG(-1, $5));
03230 #endif
03231 $$ = mlhs_add_star($1, $5);
03232
03233 }
03234 | tSTAR f_norm_arg
03235 {
03236 $$ = assignable($2, 0);
03237 #if 0
03238 $$ = NEW_MASGN(0, $$);
03239 #endif
03240 $$ = mlhs_add_star(mlhs_new(), $$);
03241
03242 }
03243 | tSTAR f_norm_arg ',' f_marg_list
03244 {
03245 $$ = assignable($2, 0);
03246 #if 0
03247 $$ = NEW_MASGN(0, NEW_POSTARG($$, $4));
03248 #endif
03249 #if 0
03250 TODO: Check me
03251 #endif
03252 $$ = mlhs_add_star($$, $4);
03253
03254 }
03255 | tSTAR
03256 {
03257 #if 0
03258 $$ = NEW_MASGN(0, -1);
03259 #endif
03260 $$ = mlhs_add_star(mlhs_new(), Qnil);
03261
03262 }
03263 | tSTAR ',' f_marg_list
03264 {
03265 #if 0
03266 $$ = NEW_MASGN(0, NEW_POSTARG(-1, $3));
03267 #endif
03268 $$ = mlhs_add_star(mlhs_new(), Qnil);
03269
03270 }
03271 ;
03272
03273 block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_f_block_arg
03274 {
03275 #if 0
03276 $$ = new_args($1, $3, $5, 0, $6);
03277 #endif
03278 $$ = params_new($1, $3, $5, Qnil, escape_Qundef($6));
03279
03280 }
03281 | f_arg ',' f_block_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
03282 {
03283 #if 0
03284 $$ = new_args($1, $3, $5, $7, $8);
03285 #endif
03286 $$ = params_new($1, $3, $5, $7, escape_Qundef($8));
03287
03288 }
03289 | f_arg ',' f_block_optarg opt_f_block_arg
03290 {
03291 #if 0
03292 $$ = new_args($1, $3, 0, 0, $4);
03293 #endif
03294 $$ = params_new($1, $3, Qnil, Qnil, escape_Qundef($4));
03295
03296 }
03297 | f_arg ',' f_block_optarg ',' f_arg opt_f_block_arg
03298 {
03299 #if 0
03300 $$ = new_args($1, $3, 0, $5, $6);
03301 #endif
03302 $$ = params_new($1, $3, Qnil, $5, escape_Qundef($6));
03303
03304 }
03305 | f_arg ',' f_rest_arg opt_f_block_arg
03306 {
03307 #if 0
03308 $$ = new_args($1, 0, $3, 0, $4);
03309 #endif
03310 $$ = params_new($1, Qnil, $3, Qnil, escape_Qundef($4));
03311
03312 }
03313 | f_arg ','
03314 {
03315 #if 0
03316 $$ = new_args($1, 0, 1, 0, 0);
03317 #endif
03318 $$ = params_new($1, Qnil, Qnil, Qnil, Qnil);
03319 dispatch1(excessed_comma, $$);
03320
03321 }
03322 | f_arg ',' f_rest_arg ',' f_arg opt_f_block_arg
03323 {
03324 #if 0
03325 $$ = new_args($1, 0, $3, $5, $6);
03326 #endif
03327 $$ = params_new($1, Qnil, $3, $5, escape_Qundef($6));
03328
03329 }
03330 | f_arg opt_f_block_arg
03331 {
03332 #if 0
03333 $$ = new_args($1, 0, 0, 0, $2);
03334 #endif
03335 $$ = params_new($1, Qnil,Qnil, Qnil, escape_Qundef($2));
03336
03337 }
03338 | f_block_optarg ',' f_rest_arg opt_f_block_arg
03339 {
03340 #if 0
03341 $$ = new_args(0, $1, $3, 0, $4);
03342 #endif
03343 $$ = params_new(Qnil, $1, $3, Qnil, escape_Qundef($4));
03344
03345 }
03346 | f_block_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
03347 {
03348 #if 0
03349 $$ = new_args(0, $1, $3, $5, $6);
03350 #endif
03351 $$ = params_new(Qnil, $1, $3, $5, escape_Qundef($6));
03352
03353 }
03354 | f_block_optarg opt_f_block_arg
03355 {
03356 #if 0
03357 $$ = new_args(0, $1, 0, 0, $2);
03358 #endif
03359 $$ = params_new(Qnil, $1, Qnil, Qnil,escape_Qundef($2));
03360
03361 }
03362 | f_block_optarg ',' f_arg opt_f_block_arg
03363 {
03364 #if 0
03365 $$ = new_args(0, $1, 0, $3, $4);
03366 #endif
03367 $$ = params_new(Qnil, $1, Qnil, $3, escape_Qundef($4));
03368
03369 }
03370 | f_rest_arg opt_f_block_arg
03371 {
03372 #if 0
03373 $$ = new_args(0, 0, $1, 0, $2);
03374 #endif
03375 $$ = params_new(Qnil, Qnil, $1, Qnil, escape_Qundef($2));
03376
03377 }
03378 | f_rest_arg ',' f_arg opt_f_block_arg
03379 {
03380 #if 0
03381 $$ = new_args(0, 0, $1, $3, $4);
03382 #endif
03383 $$ = params_new(Qnil, Qnil, $1, $3, escape_Qundef($4));
03384
03385 }
03386 | f_block_arg
03387 {
03388 #if 0
03389 $$ = new_args(0, 0, 0, 0, $1);
03390 #endif
03391 $$ = params_new(Qnil, Qnil, Qnil, Qnil, $1);
03392
03393 }
03394 ;
03395
03396 opt_block_param : none
03397 | block_param_def
03398 {
03399 command_start = TRUE;
03400 }
03401 ;
03402
03403 block_param_def : '|' opt_bv_decl '|'
03404 {
03405 #if 0
03406 $$ = 0;
03407 #endif
03408 $$ = blockvar_new(params_new(Qnil,Qnil,Qnil,Qnil,Qnil),
03409 escape_Qundef($2));
03410
03411 }
03412 | tOROP
03413 {
03414 #if 0
03415 $$ = 0;
03416 #endif
03417 $$ = blockvar_new(params_new(Qnil,Qnil,Qnil,Qnil,Qnil),
03418 Qnil);
03419
03420 }
03421 | '|' block_param opt_bv_decl '|'
03422 {
03423 #if 0
03424 $$ = $2;
03425 #endif
03426 $$ = blockvar_new(escape_Qundef($2), escape_Qundef($3));
03427
03428 }
03429 ;
03430
03431
03432 opt_bv_decl : none
03433 | ';' bv_decls
03434 {
03435 #if 0
03436 $$ = 0;
03437 #endif
03438 $$ = $2;
03439
03440 }
03441 ;
03442
03443 bv_decls : bvar
03444
03445
03446 {
03447 $$ = rb_ary_new3(1, $1);
03448 }
03449
03450 | bv_decls ',' bvar
03451
03452
03453 {
03454 rb_ary_push($$, $3);
03455 }
03456
03457 ;
03458
03459 bvar : tIDENTIFIER
03460 {
03461 new_bv(get_id($1));
03462 #if 0
03463 #endif
03464 $$ = get_value($1);
03465
03466 }
03467 | f_bad_arg
03468 {
03469 $$ = 0;
03470 }
03471 ;
03472
03473 lambda : {
03474 $<vars>$ = dyna_push();
03475 }
03476 {
03477 $<num>$ = lpar_beg;
03478 lpar_beg = ++paren_nest;
03479 }
03480 f_larglist
03481 lambda_body
03482 {
03483 lpar_beg = $<num>2;
03484 #if 0
03485 $$ = $3;
03486 $$->nd_body = NEW_SCOPE($3->nd_head, $4);
03487 #endif
03488 $$ = dispatch2(lambda, $3, $4);
03489
03490 dyna_pop($<vars>1);
03491 }
03492 ;
03493
03494 f_larglist : '(' f_args opt_bv_decl rparen
03495 {
03496 #if 0
03497 $$ = NEW_LAMBDA($2);
03498 #endif
03499 $$ = dispatch1(paren, $2);
03500
03501 }
03502 | f_args
03503 {
03504 #if 0
03505 $$ = NEW_LAMBDA($1);
03506 #endif
03507 $$ = $1;
03508
03509 }
03510 ;
03511
03512 lambda_body : tLAMBEG compstmt '}'
03513 {
03514 $$ = $2;
03515 }
03516 | keyword_do_LAMBDA compstmt keyword_end
03517 {
03518 $$ = $2;
03519 }
03520 ;
03521
03522 do_block : keyword_do_block
03523 {
03524 $<vars>1 = dyna_push();
03525 #if 0
03526 $<num>$ = ruby_sourceline;
03527 #endif
03528 }
03529 opt_block_param
03530 compstmt
03531 keyword_end
03532 {
03533 #if 0
03534 $$ = NEW_ITER($3,$4);
03535 nd_set_line($$, $<num>2);
03536 #endif
03537 $$ = dispatch2(do_block, escape_Qundef($3), $4);
03538
03539 dyna_pop($<vars>1);
03540 }
03541 ;
03542
03543 block_call : command do_block
03544 {
03545 #if 0
03546 if (nd_type($1) == NODE_YIELD) {
03547 compile_error(PARSER_ARG "block given to yield");
03548 }
03549 else {
03550 block_dup_check($1->nd_args, $2);
03551 }
03552 $2->nd_iter = $1;
03553 $$ = $2;
03554 fixpos($$, $1);
03555 #endif
03556 $$ = method_add_block($1, $2);
03557
03558 }
03559 | block_call '.' operation2 opt_paren_args
03560 {
03561 #if 0
03562 $$ = NEW_CALL($1, $3, $4);
03563 #endif
03564 $$ = dispatch3(call, $1, ripper_id2sym('.'), $3);
03565 $$ = method_optarg($$, $4);
03566
03567 }
03568 | block_call tCOLON2 operation2 opt_paren_args
03569 {
03570 #if 0
03571 $$ = NEW_CALL($1, $3, $4);
03572 #endif
03573 $$ = dispatch3(call, $1, ripper_intern("::"), $3);
03574 $$ = method_optarg($$, $4);
03575
03576 }
03577 ;
03578
03579 method_call : operation paren_args
03580 {
03581 #if 0
03582 $$ = NEW_FCALL($1, $2);
03583 fixpos($$, $2);
03584 #endif
03585 $$ = method_arg(dispatch1(fcall, $1), $2);
03586
03587 }
03588 | primary_value '.' operation2 opt_paren_args
03589 {
03590 #if 0
03591 $$ = NEW_CALL($1, $3, $4);
03592 fixpos($$, $1);
03593 #endif
03594 $$ = dispatch3(call, $1, ripper_id2sym('.'), $3);
03595 $$ = method_optarg($$, $4);
03596
03597 }
03598 | primary_value tCOLON2 operation2 paren_args
03599 {
03600 #if 0
03601 $$ = NEW_CALL($1, $3, $4);
03602 fixpos($$, $1);
03603 #endif
03604 $$ = dispatch3(call, $1, ripper_id2sym('.'), $3);
03605 $$ = method_optarg($$, $4);
03606
03607 }
03608 | primary_value tCOLON2 operation3
03609 {
03610 #if 0
03611 $$ = NEW_CALL($1, $3, 0);
03612 #endif
03613 $$ = dispatch3(call, $1, ripper_intern("::"), $3);
03614
03615 }
03616 | primary_value '.' paren_args
03617 {
03618 #if 0
03619 $$ = NEW_CALL($1, rb_intern("call"), $3);
03620 fixpos($$, $1);
03621 #endif
03622 $$ = dispatch3(call, $1, ripper_id2sym('.'),
03623 ripper_intern("call"));
03624 $$ = method_optarg($$, $3);
03625
03626 }
03627 | primary_value tCOLON2 paren_args
03628 {
03629 #if 0
03630 $$ = NEW_CALL($1, rb_intern("call"), $3);
03631 fixpos($$, $1);
03632 #endif
03633 $$ = dispatch3(call, $1, ripper_intern("::"),
03634 ripper_intern("call"));
03635 $$ = method_optarg($$, $3);
03636
03637 }
03638 | keyword_super paren_args
03639 {
03640 #if 0
03641 $$ = NEW_SUPER($2);
03642 #endif
03643 $$ = dispatch1(super, $2);
03644
03645 }
03646 | keyword_super
03647 {
03648 #if 0
03649 $$ = NEW_ZSUPER();
03650 #endif
03651 $$ = dispatch0(zsuper);
03652
03653 }
03654 | primary_value '[' opt_call_args rbracket
03655 {
03656 #if 0
03657 if ($1 && nd_type($1) == NODE_SELF)
03658 $$ = NEW_FCALL(tAREF, $3);
03659 else
03660 $$ = NEW_CALL($1, tAREF, $3);
03661 fixpos($$, $1);
03662 #endif
03663 $$ = dispatch2(aref, $1, escape_Qundef($3));
03664
03665 }
03666 ;
03667
03668 brace_block : '{'
03669 {
03670 $<vars>1 = dyna_push();
03671 #if 0
03672 $<num>$ = ruby_sourceline;
03673 #endif
03674
03675 }
03676 opt_block_param
03677 compstmt '}'
03678 {
03679 #if 0
03680 $$ = NEW_ITER($3,$4);
03681 nd_set_line($$, $<num>2);
03682 #endif
03683 $$ = dispatch2(brace_block, escape_Qundef($3), $4);
03684
03685 dyna_pop($<vars>1);
03686 }
03687 | keyword_do
03688 {
03689 $<vars>1 = dyna_push();
03690 #if 0
03691 $<num>$ = ruby_sourceline;
03692 #endif
03693
03694 }
03695 opt_block_param
03696 compstmt keyword_end
03697 {
03698 #if 0
03699 $$ = NEW_ITER($3,$4);
03700 nd_set_line($$, $<num>2);
03701 #endif
03702 $$ = dispatch2(do_block, escape_Qundef($3), $4);
03703
03704 dyna_pop($<vars>1);
03705 }
03706 ;
03707
03708 case_body : keyword_when args then
03709 compstmt
03710 cases
03711 {
03712 #if 0
03713 $$ = NEW_WHEN($2, $4, $5);
03714 #endif
03715 $$ = dispatch3(when, $2, $4, escape_Qundef($5));
03716
03717 }
03718 ;
03719
03720 cases : opt_else
03721 | case_body
03722 ;
03723
03724 opt_rescue : keyword_rescue exc_list exc_var then
03725 compstmt
03726 opt_rescue
03727 {
03728 #if 0
03729 if ($3) {
03730 $3 = node_assign($3, NEW_ERRINFO());
03731 $5 = block_append($3, $5);
03732 }
03733 $$ = NEW_RESBODY($2, $5, $6);
03734 fixpos($$, $2?$2:$5);
03735 #endif
03736 $$ = dispatch4(rescue,
03737 escape_Qundef($2),
03738 escape_Qundef($3),
03739 escape_Qundef($5),
03740 escape_Qundef($6));
03741
03742 }
03743 | none
03744 ;
03745
03746 exc_list : arg_value
03747 {
03748 #if 0
03749 $$ = NEW_LIST($1);
03750 #endif
03751 $$ = rb_ary_new3(1, $1);
03752
03753 }
03754 | mrhs
03755 {
03756 #if 0
03757 if (!($$ = splat_array($1))) $$ = $1;
03758 #endif
03759 $$ = $1;
03760
03761 }
03762 | none
03763 ;
03764
03765 exc_var : tASSOC lhs
03766 {
03767 $$ = $2;
03768 }
03769 | none
03770 ;
03771
03772 opt_ensure : keyword_ensure compstmt
03773 {
03774 #if 0
03775 $$ = $2;
03776 #endif
03777 $$ = dispatch1(ensure, $2);
03778
03779 }
03780 | none
03781 ;
03782
03783 literal : numeric
03784 | symbol
03785 {
03786 #if 0
03787 $$ = NEW_LIT(ID2SYM($1));
03788 #endif
03789 $$ = dispatch1(symbol_literal, $1);
03790
03791 }
03792 | dsym
03793 ;
03794
03795 strings : string
03796 {
03797 #if 0
03798 NODE *node = $1;
03799 if (!node) {
03800 node = NEW_STR(STR_NEW0());
03801 }
03802 else {
03803 node = evstr2dstr(node);
03804 }
03805 $$ = node;
03806 #endif
03807 $$ = $1;
03808
03809 }
03810 ;
03811
03812 string : tCHAR
03813 | string1
03814 | string string1
03815 {
03816 #if 0
03817 $$ = literal_concat($1, $2);
03818 #endif
03819 $$ = dispatch2(string_concat, $1, $2);
03820
03821 }
03822 ;
03823
03824 string1 : tSTRING_BEG string_contents tSTRING_END
03825 {
03826 #if 0
03827 $$ = $2;
03828 #endif
03829 $$ = dispatch1(string_literal, $2);
03830
03831 }
03832 ;
03833
03834 xstring : tXSTRING_BEG xstring_contents tSTRING_END
03835 {
03836 #if 0
03837 NODE *node = $2;
03838 if (!node) {
03839 node = NEW_XSTR(STR_NEW0());
03840 }
03841 else {
03842 switch (nd_type(node)) {
03843 case NODE_STR:
03844 nd_set_type(node, NODE_XSTR);
03845 break;
03846 case NODE_DSTR:
03847 nd_set_type(node, NODE_DXSTR);
03848 break;
03849 default:
03850 node = NEW_NODE(NODE_DXSTR, Qnil, 1, NEW_LIST(node));
03851 break;
03852 }
03853 }
03854 $$ = node;
03855 #endif
03856 $$ = dispatch1(xstring_literal, $2);
03857
03858 }
03859 ;
03860
03861 regexp : tREGEXP_BEG regexp_contents tREGEXP_END
03862 {
03863 #if 0
03864 int options = $3;
03865 NODE *node = $2;
03866 NODE *list, *prev;
03867 if (!node) {
03868 node = NEW_LIT(reg_compile(STR_NEW0(), options));
03869 }
03870 else switch (nd_type(node)) {
03871 case NODE_STR:
03872 {
03873 VALUE src = node->nd_lit;
03874 nd_set_type(node, NODE_LIT);
03875 node->nd_lit = reg_compile(src, options);
03876 }
03877 break;
03878 default:
03879 node = NEW_NODE(NODE_DSTR, STR_NEW0(), 1, NEW_LIST(node));
03880 case NODE_DSTR:
03881 if (options & RE_OPTION_ONCE) {
03882 nd_set_type(node, NODE_DREGX_ONCE);
03883 }
03884 else {
03885 nd_set_type(node, NODE_DREGX);
03886 }
03887 node->nd_cflag = options & RE_OPTION_MASK;
03888 if (!NIL_P(node->nd_lit)) reg_fragment_check(node->nd_lit, options);
03889 for (list = (prev = node)->nd_next; list; list = list->nd_next) {
03890 if (nd_type(list->nd_head) == NODE_STR) {
03891 VALUE tail = list->nd_head->nd_lit;
03892 if (reg_fragment_check(tail, options) && prev && !NIL_P(prev->nd_lit)) {
03893 VALUE lit = prev == node ? prev->nd_lit : prev->nd_head->nd_lit;
03894 if (!literal_concat0(parser, lit, tail)) {
03895 node = 0;
03896 break;
03897 }
03898 rb_str_resize(tail, 0);
03899 prev->nd_next = list->nd_next;
03900 rb_gc_force_recycle((VALUE)list->nd_head);
03901 rb_gc_force_recycle((VALUE)list);
03902 list = prev;
03903 }
03904 else {
03905 prev = list;
03906 }
03907 }
03908 else {
03909 prev = 0;
03910 }
03911 }
03912 if (!node->nd_next) {
03913 VALUE src = node->nd_lit;
03914 nd_set_type(node, NODE_LIT);
03915 node->nd_lit = reg_compile(src, options);
03916 }
03917 break;
03918 }
03919 $$ = node;
03920 #endif
03921 $$ = dispatch2(regexp_literal, $2, $3);
03922
03923 }
03924 ;
03925
03926 words : tWORDS_BEG ' ' tSTRING_END
03927 {
03928 #if 0
03929 $$ = NEW_ZARRAY();
03930 #endif
03931 $$ = dispatch0(words_new);
03932
03933 }
03934 | tWORDS_BEG word_list tSTRING_END
03935 {
03936 $$ = $2;
03937 }
03938 ;
03939
03940 word_list :
03941 {
03942 #if 0
03943 $$ = 0;
03944 #endif
03945 $$ = dispatch0(words_new);
03946
03947 }
03948 | word_list word ' '
03949 {
03950 #if 0
03951 $$ = list_append($1, evstr2dstr($2));
03952 #endif
03953 $$ = dispatch2(words_add, $1, $2);
03954
03955 }
03956 ;
03957
03958 word : string_content
03959
03960
03961 {
03962 $$ = dispatch0(word_new);
03963 $$ = dispatch2(word_add, $$, $1);
03964 }
03965
03966 | word string_content
03967 {
03968 #if 0
03969 $$ = literal_concat($1, $2);
03970 #endif
03971 $$ = dispatch2(word_add, $1, $2);
03972
03973 }
03974 ;
03975
03976 qwords : tQWORDS_BEG ' ' tSTRING_END
03977 {
03978 #if 0
03979 $$ = NEW_ZARRAY();
03980 #endif
03981 $$ = dispatch0(qwords_new);
03982
03983 }
03984 | tQWORDS_BEG qword_list tSTRING_END
03985 {
03986 $$ = $2;
03987 }
03988 ;
03989
03990 qword_list :
03991 {
03992 #if 0
03993 $$ = 0;
03994 #endif
03995 $$ = dispatch0(qwords_new);
03996
03997 }
03998 | qword_list tSTRING_CONTENT ' '
03999 {
04000 #if 0
04001 $$ = list_append($1, $2);
04002 #endif
04003 $$ = dispatch2(qwords_add, $1, $2);
04004
04005 }
04006 ;
04007
04008 string_contents :
04009 {
04010 #if 0
04011 $$ = 0;
04012 #endif
04013 $$ = dispatch0(string_content);
04014
04015 }
04016 | string_contents string_content
04017 {
04018 #if 0
04019 $$ = literal_concat($1, $2);
04020 #endif
04021 $$ = dispatch2(string_add, $1, $2);
04022
04023 }
04024 ;
04025
04026 xstring_contents:
04027 {
04028 #if 0
04029 $$ = 0;
04030 #endif
04031 $$ = dispatch0(xstring_new);
04032
04033 }
04034 | xstring_contents string_content
04035 {
04036 #if 0
04037 $$ = literal_concat($1, $2);
04038 #endif
04039 $$ = dispatch2(xstring_add, $1, $2);
04040
04041 }
04042 ;
04043
04044 regexp_contents:
04045 {
04046 #if 0
04047 $$ = 0;
04048 #endif
04049 $$ = dispatch0(regexp_new);
04050
04051 }
04052 | regexp_contents string_content
04053 {
04054 #if 0
04055 NODE *head = $1, *tail = $2;
04056 if (!head) {
04057 $$ = tail;
04058 }
04059 else if (!tail) {
04060 $$ = head;
04061 }
04062 else {
04063 switch (nd_type(head)) {
04064 case NODE_STR:
04065 nd_set_type(head, NODE_DSTR);
04066 break;
04067 case NODE_DSTR:
04068 break;
04069 default:
04070 head = list_append(NEW_DSTR(Qnil), head);
04071 break;
04072 }
04073 $$ = list_append(head, tail);
04074 }
04075 #endif
04076 $$ = dispatch2(regexp_add, $1, $2);
04077
04078 }
04079 ;
04080
04081 string_content : tSTRING_CONTENT
04082 | tSTRING_DVAR
04083 {
04084 $<node>$ = lex_strterm;
04085 lex_strterm = 0;
04086 lex_state = EXPR_BEG;
04087 }
04088 string_dvar
04089 {
04090 #if 0
04091 lex_strterm = $<node>2;
04092 $$ = NEW_EVSTR($3);
04093 #endif
04094 lex_strterm = $<node>2;
04095 $$ = dispatch1(string_dvar, $3);
04096
04097 }
04098 | tSTRING_DBEG
04099 {
04100 $<val>1 = cond_stack;
04101 $<val>$ = cmdarg_stack;
04102 cond_stack = 0;
04103 cmdarg_stack = 0;
04104 }
04105 {
04106 $<node>$ = lex_strterm;
04107 lex_strterm = 0;
04108 lex_state = EXPR_BEG;
04109 }
04110 compstmt '}'
04111 {
04112 cond_stack = $<val>1;
04113 cmdarg_stack = $<val>2;
04114 lex_strterm = $<node>3;
04115 #if 0
04116 if ($4) $4->flags &= ~NODE_FL_NEWLINE;
04117 $$ = new_evstr($4);
04118 #endif
04119 $$ = dispatch1(string_embexpr, $4);
04120
04121 }
04122 ;
04123
04124 string_dvar : tGVAR
04125 {
04126 #if 0
04127 $$ = NEW_GVAR($1);
04128 #endif
04129 $$ = dispatch1(var_ref, $1);
04130
04131 }
04132 | tIVAR
04133 {
04134 #if 0
04135 $$ = NEW_IVAR($1);
04136 #endif
04137 $$ = dispatch1(var_ref, $1);
04138
04139 }
04140 | tCVAR
04141 {
04142 #if 0
04143 $$ = NEW_CVAR($1);
04144 #endif
04145 $$ = dispatch1(var_ref, $1);
04146
04147 }
04148 | backref
04149 ;
04150
04151 symbol : tSYMBEG sym
04152 {
04153 lex_state = EXPR_END;
04154 #if 0
04155 $$ = $2;
04156 #endif
04157 $$ = dispatch1(symbol, $2);
04158
04159 }
04160 ;
04161
04162 sym : fname
04163 | tIVAR
04164 | tGVAR
04165 | tCVAR
04166 ;
04167
04168 dsym : tSYMBEG xstring_contents tSTRING_END
04169 {
04170 lex_state = EXPR_END;
04171 #if 0
04172 if (!($$ = $2)) {
04173 $$ = NEW_LIT(ID2SYM(rb_intern("")));
04174 }
04175 else {
04176 VALUE lit;
04177
04178 switch (nd_type($$)) {
04179 case NODE_DSTR:
04180 nd_set_type($$, NODE_DSYM);
04181 break;
04182 case NODE_STR:
04183 lit = $$->nd_lit;
04184 $$->nd_lit = ID2SYM(rb_intern_str(lit));
04185 nd_set_type($$, NODE_LIT);
04186 break;
04187 default:
04188 $$ = NEW_NODE(NODE_DSYM, Qnil, 1, NEW_LIST($$));
04189 break;
04190 }
04191 }
04192 #endif
04193 $$ = dispatch1(dyna_symbol, $2);
04194
04195 }
04196 ;
04197
04198 numeric : tINTEGER
04199 | tFLOAT
04200 | tUMINUS_NUM tINTEGER %prec tLOWEST
04201 {
04202 #if 0
04203 $$ = negate_lit($2);
04204 #endif
04205 $$ = dispatch2(unary, ripper_intern("-@"), $2);
04206
04207 }
04208 | tUMINUS_NUM tFLOAT %prec tLOWEST
04209 {
04210 #if 0
04211 $$ = negate_lit($2);
04212 #endif
04213 $$ = dispatch2(unary, ripper_intern("-@"), $2);
04214
04215 }
04216 ;
04217
04218 variable : tIDENTIFIER
04219 | tIVAR
04220 | tGVAR
04221 | tCONSTANT
04222 | tCVAR
04223 | keyword_nil {ifndef_ripper($$ = keyword_nil);}
04224 | keyword_self {ifndef_ripper($$ = keyword_self);}
04225 | keyword_true {ifndef_ripper($$ = keyword_true);}
04226 | keyword_false {ifndef_ripper($$ = keyword_false);}
04227 | keyword__FILE__ {ifndef_ripper($$ = keyword__FILE__);}
04228 | keyword__LINE__ {ifndef_ripper($$ = keyword__LINE__);}
04229 | keyword__ENCODING__ {ifndef_ripper($$ = keyword__ENCODING__);}
04230 ;
04231
04232 var_ref : variable
04233 {
04234 #if 0
04235 if (!($$ = gettable($1))) $$ = NEW_BEGIN(0);
04236 #endif
04237 $$ = dispatch1(var_ref, $1);
04238
04239 }
04240 ;
04241
04242 var_lhs : variable
04243 {
04244 $$ = assignable($1, 0);
04245 #if 0
04246 #endif
04247 $$ = dispatch1(var_field, $$);
04248
04249 }
04250 ;
04251
04252 backref : tNTH_REF
04253 | tBACK_REF
04254 ;
04255
04256 superclass : term
04257 {
04258 #if 0
04259 $$ = 0;
04260 #endif
04261 $$ = Qnil;
04262
04263 }
04264 | '<'
04265 {
04266 lex_state = EXPR_BEG;
04267 }
04268 expr_value term
04269 {
04270 $$ = $3;
04271 }
04272 | error term
04273 {
04274 #if 0
04275 yyerrok;
04276 $$ = 0;
04277 #endif
04278 yyerrok;
04279 $$ = Qnil;
04280
04281 }
04282 ;
04283
04284 f_arglist : '(' f_args rparen
04285 {
04286 #if 0
04287 $$ = $2;
04288 #endif
04289 $$ = dispatch1(paren, $2);
04290
04291 lex_state = EXPR_BEG;
04292 command_start = TRUE;
04293 }
04294 | f_args term
04295 {
04296 $$ = $1;
04297 }
04298 ;
04299
04300 f_args : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg
04301 {
04302 #if 0
04303 $$ = new_args($1, $3, $5, 0, $6);
04304 #endif
04305 $$ = params_new($1, $3, $5, Qnil, escape_Qundef($6));
04306
04307 }
04308 | f_arg ',' f_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
04309 {
04310 #if 0
04311 $$ = new_args($1, $3, $5, $7, $8);
04312 #endif
04313 $$ = params_new($1, $3, $5, $7, escape_Qundef($8));
04314
04315 }
04316 | f_arg ',' f_optarg opt_f_block_arg
04317 {
04318 #if 0
04319 $$ = new_args($1, $3, 0, 0, $4);
04320 #endif
04321 $$ = params_new($1, $3, Qnil, Qnil, escape_Qundef($4));
04322
04323 }
04324 | f_arg ',' f_optarg ',' f_arg opt_f_block_arg
04325 {
04326 #if 0
04327 $$ = new_args($1, $3, 0, $5, $6);
04328 #endif
04329 $$ = params_new($1, $3, Qnil, $5, escape_Qundef($6));
04330
04331 }
04332 | f_arg ',' f_rest_arg opt_f_block_arg
04333 {
04334 #if 0
04335 $$ = new_args($1, 0, $3, 0, $4);
04336 #endif
04337 $$ = params_new($1, Qnil, $3, Qnil, escape_Qundef($4));
04338
04339 }
04340 | f_arg ',' f_rest_arg ',' f_arg opt_f_block_arg
04341 {
04342 #if 0
04343 $$ = new_args($1, 0, $3, $5, $6);
04344 #endif
04345 $$ = params_new($1, Qnil, $3, $5, escape_Qundef($6));
04346
04347 }
04348 | f_arg opt_f_block_arg
04349 {
04350 #if 0
04351 $$ = new_args($1, 0, 0, 0, $2);
04352 #endif
04353 $$ = params_new($1, Qnil, Qnil, Qnil,escape_Qundef($2));
04354
04355 }
04356 | f_optarg ',' f_rest_arg opt_f_block_arg
04357 {
04358 #if 0
04359 $$ = new_args(0, $1, $3, 0, $4);
04360 #endif
04361 $$ = params_new(Qnil, $1, $3, Qnil, escape_Qundef($4));
04362
04363 }
04364 | f_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
04365 {
04366 #if 0
04367 $$ = new_args(0, $1, $3, $5, $6);
04368 #endif
04369 $$ = params_new(Qnil, $1, $3, $5, escape_Qundef($6));
04370
04371 }
04372 | f_optarg opt_f_block_arg
04373 {
04374 #if 0
04375 $$ = new_args(0, $1, 0, 0, $2);
04376 #endif
04377 $$ = params_new(Qnil, $1, Qnil, Qnil,escape_Qundef($2));
04378
04379 }
04380 | f_optarg ',' f_arg opt_f_block_arg
04381 {
04382 #if 0
04383 $$ = new_args(0, $1, 0, $3, $4);
04384 #endif
04385 $$ = params_new(Qnil, $1, Qnil, $3, escape_Qundef($4));
04386
04387 }
04388 | f_rest_arg opt_f_block_arg
04389 {
04390 #if 0
04391 $$ = new_args(0, 0, $1, 0, $2);
04392 #endif
04393 $$ = params_new(Qnil, Qnil, $1, Qnil,escape_Qundef($2));
04394
04395 }
04396 | f_rest_arg ',' f_arg opt_f_block_arg
04397 {
04398 #if 0
04399 $$ = new_args(0, 0, $1, $3, $4);
04400 #endif
04401 $$ = params_new(Qnil, Qnil, $1, $3, escape_Qundef($4));
04402
04403 }
04404 | f_block_arg
04405 {
04406 #if 0
04407 $$ = new_args(0, 0, 0, 0, $1);
04408 #endif
04409 $$ = params_new(Qnil, Qnil, Qnil, Qnil, $1);
04410
04411 }
04412 |
04413 {
04414 #if 0
04415 $$ = new_args(0, 0, 0, 0, 0);
04416 #endif
04417 $$ = params_new(Qnil, Qnil, Qnil, Qnil, Qnil);
04418
04419 }
04420 ;
04421
04422 f_bad_arg : tCONSTANT
04423 {
04424 #if 0
04425 yyerror("formal argument cannot be a constant");
04426 $$ = 0;
04427 #endif
04428 $$ = dispatch1(param_error, $1);
04429
04430 }
04431 | tIVAR
04432 {
04433 #if 0
04434 yyerror("formal argument cannot be an instance variable");
04435 $$ = 0;
04436 #endif
04437 $$ = dispatch1(param_error, $1);
04438
04439 }
04440 | tGVAR
04441 {
04442 #if 0
04443 yyerror("formal argument cannot be a global variable");
04444 $$ = 0;
04445 #endif
04446 $$ = dispatch1(param_error, $1);
04447
04448 }
04449 | tCVAR
04450 {
04451 #if 0
04452 yyerror("formal argument cannot be a class variable");
04453 $$ = 0;
04454 #endif
04455 $$ = dispatch1(param_error, $1);
04456
04457 }
04458 ;
04459
04460 f_norm_arg : f_bad_arg
04461 | tIDENTIFIER
04462 {
04463 formal_argument(get_id($1));
04464 $$ = $1;
04465 }
04466 ;
04467
04468 f_arg_item : f_norm_arg
04469 {
04470 arg_var(get_id($1));
04471 #if 0
04472 $$ = NEW_ARGS_AUX($1, 1);
04473 #endif
04474 $$ = get_value($1);
04475
04476 }
04477 | tLPAREN f_margs rparen
04478 {
04479 ID tid = internal_id();
04480 arg_var(tid);
04481 #if 0
04482 if (dyna_in_block()) {
04483 $2->nd_value = NEW_DVAR(tid);
04484 }
04485 else {
04486 $2->nd_value = NEW_LVAR(tid);
04487 }
04488 $$ = NEW_ARGS_AUX(tid, 1);
04489 $$->nd_next = $2;
04490 #endif
04491 $$ = dispatch1(mlhs_paren, $2);
04492
04493 }
04494 ;
04495
04496 f_arg : f_arg_item
04497
04498
04499 {
04500 $$ = rb_ary_new3(1, $1);
04501 }
04502
04503 | f_arg ',' f_arg_item
04504 {
04505 #if 0
04506 $$ = $1;
04507 $$->nd_plen++;
04508 $$->nd_next = block_append($$->nd_next, $3->nd_next);
04509 rb_gc_force_recycle((VALUE)$3);
04510 #endif
04511 $$ = rb_ary_push($1, $3);
04512
04513 }
04514 ;
04515
04516 f_opt : tIDENTIFIER '=' arg_value
04517 {
04518 arg_var(formal_argument(get_id($1)));
04519 $$ = assignable($1, $3);
04520 #if 0
04521 $$ = NEW_OPT_ARG(0, $$);
04522 #endif
04523 $$ = rb_assoc_new($$, $3);
04524
04525 }
04526 ;
04527
04528 f_block_opt : tIDENTIFIER '=' primary_value
04529 {
04530 arg_var(formal_argument(get_id($1)));
04531 $$ = assignable($1, $3);
04532 #if 0
04533 $$ = NEW_OPT_ARG(0, $$);
04534 #endif
04535 $$ = rb_assoc_new($$, $3);
04536
04537 }
04538 ;
04539
04540 f_block_optarg : f_block_opt
04541 {
04542 #if 0
04543 $$ = $1;
04544 #endif
04545 $$ = rb_ary_new3(1, $1);
04546
04547 }
04548 | f_block_optarg ',' f_block_opt
04549 {
04550 #if 0
04551 NODE *opts = $1;
04552
04553 while (opts->nd_next) {
04554 opts = opts->nd_next;
04555 }
04556 opts->nd_next = $3;
04557 $$ = $1;
04558 #endif
04559 $$ = rb_ary_push($1, $3);
04560
04561 }
04562 ;
04563
04564 f_optarg : f_opt
04565 {
04566 #if 0
04567 $$ = $1;
04568 #endif
04569 $$ = rb_ary_new3(1, $1);
04570
04571 }
04572 | f_optarg ',' f_opt
04573 {
04574 #if 0
04575 NODE *opts = $1;
04576
04577 while (opts->nd_next) {
04578 opts = opts->nd_next;
04579 }
04580 opts->nd_next = $3;
04581 $$ = $1;
04582 #endif
04583 $$ = rb_ary_push($1, $3);
04584
04585 }
04586 ;
04587
04588 restarg_mark : '*'
04589 | tSTAR
04590 ;
04591
04592 f_rest_arg : restarg_mark tIDENTIFIER
04593 {
04594 #if 0
04595 if (!is_local_id($2))
04596 yyerror("rest argument must be local variable");
04597 #endif
04598 arg_var(shadowing_lvar(get_id($2)));
04599 #if 0
04600 $$ = $2;
04601 #endif
04602 $$ = dispatch1(rest_param, $2);
04603
04604 }
04605 | restarg_mark
04606 {
04607 #if 0
04608 $$ = internal_id();
04609 arg_var($$);
04610 #endif
04611 $$ = dispatch1(rest_param, Qnil);
04612
04613 }
04614 ;
04615
04616 blkarg_mark : '&'
04617 | tAMPER
04618 ;
04619
04620 f_block_arg : blkarg_mark tIDENTIFIER
04621 {
04622 #if 0
04623 if (!is_local_id($2))
04624 yyerror("block argument must be local variable");
04625 else if (!dyna_in_block() && local_id($2))
04626 yyerror("duplicated block argument name");
04627 #endif
04628 arg_var(shadowing_lvar(get_id($2)));
04629 #if 0
04630 $$ = $2;
04631 #endif
04632 $$ = dispatch1(blockarg, $2);
04633
04634 }
04635 ;
04636
04637 opt_f_block_arg : ',' f_block_arg
04638 {
04639 $$ = $2;
04640 }
04641 | none
04642 {
04643 #if 0
04644 $$ = 0;
04645 #endif
04646 $$ = Qundef;
04647
04648 }
04649 ;
04650
04651 singleton : var_ref
04652 {
04653 #if 0
04654 value_expr($1);
04655 $$ = $1;
04656 if (!$$) $$ = NEW_NIL();
04657 #endif
04658 $$ = $1;
04659
04660 }
04661 | '(' {lex_state = EXPR_BEG;} expr rparen
04662 {
04663 #if 0
04664 if ($3 == 0) {
04665 yyerror("can't define singleton method for ().");
04666 }
04667 else {
04668 switch (nd_type($3)) {
04669 case NODE_STR:
04670 case NODE_DSTR:
04671 case NODE_XSTR:
04672 case NODE_DXSTR:
04673 case NODE_DREGX:
04674 case NODE_LIT:
04675 case NODE_ARRAY:
04676 case NODE_ZARRAY:
04677 yyerror("can't define singleton method for literals");
04678 default:
04679 value_expr($3);
04680 break;
04681 }
04682 }
04683 $$ = $3;
04684 #endif
04685 $$ = dispatch1(paren, $3);
04686
04687 }
04688 ;
04689
04690 assoc_list : none
04691 | assocs trailer
04692 {
04693 #if 0
04694 $$ = $1;
04695 #endif
04696 $$ = dispatch1(assoclist_from_args, $1);
04697
04698 }
04699 ;
04700
04701 assocs : assoc
04702
04703
04704 {
04705 $$ = rb_ary_new3(1, $1);
04706 }
04707
04708 | assocs ',' assoc
04709 {
04710 #if 0
04711 $$ = list_concat($1, $3);
04712 #endif
04713 $$ = rb_ary_push($1, $3);
04714
04715 }
04716 ;
04717
04718 assoc : arg_value tASSOC arg_value
04719 {
04720 #if 0
04721 $$ = list_append(NEW_LIST($1), $3);
04722 #endif
04723 $$ = dispatch2(assoc_new, $1, $3);
04724
04725 }
04726 | tLABEL arg_value
04727 {
04728 #if 0
04729 $$ = list_append(NEW_LIST(NEW_LIT(ID2SYM($1))), $2);
04730 #endif
04731 $$ = dispatch2(assoc_new, $1, $2);
04732
04733 }
04734 ;
04735
04736 operation : tIDENTIFIER
04737 | tCONSTANT
04738 | tFID
04739 ;
04740
04741 operation2 : tIDENTIFIER
04742 | tCONSTANT
04743 | tFID
04744 | op
04745 ;
04746
04747 operation3 : tIDENTIFIER
04748 | tFID
04749 | op
04750 ;
04751
04752 dot_or_colon : '.'
04753
04754
04755 { $$ = $<val>1; }
04756
04757 | tCOLON2
04758
04759
04760 { $$ = $<val>1; }
04761
04762 ;
04763
04764 opt_terms :
04765 | terms
04766 ;
04767
04768 opt_nl :
04769 | '\n'
04770 ;
04771
04772 rparen : opt_nl ')'
04773 ;
04774
04775 rbracket : opt_nl ']'
04776 ;
04777
04778 trailer :
04779 | '\n'
04780 | ','
04781 ;
04782
04783 term : ';' {yyerrok;}
04784 | '\n'
04785 ;
04786
04787 terms : term
04788 | terms ';' {yyerrok;}
04789 ;
04790
04791 none :
04792 {
04793 #if 0
04794 $$ = 0;
04795 #endif
04796 $$ = Qundef;
04797
04798 }
04799 ;
04800 %%
04801 # undef parser
04802 # undef yylex
04803 # undef yylval
04804 # define yylval (*((YYSTYPE*)(parser->parser_yylval)))
04805
04806 static int parser_regx_options(struct parser_params*);
04807 static int parser_tokadd_string(struct parser_params*,int,int,int,long*,rb_encoding**);
04808 static void parser_tokaddmbc(struct parser_params *parser, int c, rb_encoding *enc);
04809 static int parser_parse_string(struct parser_params*,NODE*);
04810 static int parser_here_document(struct parser_params*,NODE*);
04811
04812
04813 # define nextc() parser_nextc(parser)
04814 # define pushback(c) parser_pushback(parser, c)
04815 # define newtok() parser_newtok(parser)
04816 # define tokspace(n) parser_tokspace(parser, n)
04817 # define tokadd(c) parser_tokadd(parser, c)
04818 # define tok_hex(numlen) parser_tok_hex(parser, numlen)
04819 # define read_escape(flags,e) parser_read_escape(parser, flags, e)
04820 # define tokadd_escape(e) parser_tokadd_escape(parser, e)
04821 # define regx_options() parser_regx_options(parser)
04822 # define tokadd_string(f,t,p,n,e) parser_tokadd_string(parser,f,t,p,n,e)
04823 # define parse_string(n) parser_parse_string(parser,n)
04824 # define tokaddmbc(c, enc) parser_tokaddmbc(parser, c, enc)
04825 # define here_document(n) parser_here_document(parser,n)
04826 # define heredoc_identifier() parser_heredoc_identifier(parser)
04827 # define heredoc_restore(n) parser_heredoc_restore(parser,n)
04828 # define whole_match_p(e,l,i) parser_whole_match_p(parser,e,l,i)
04829
04830 #ifndef RIPPER
04831 # define set_yylval_str(x) yylval.node = NEW_STR(x)
04832 # define set_yylval_num(x) yylval.num = x
04833 # define set_yylval_id(x) yylval.id = x
04834 # define set_yylval_name(x) yylval.id = x
04835 # define set_yylval_literal(x) yylval.node = NEW_LIT(x)
04836 # define set_yylval_node(x) yylval.node = x
04837 # define yylval_id() yylval.id
04838 #else
04839 static inline VALUE
04840 ripper_yylval_id(ID x)
04841 {
04842 return (VALUE)NEW_LASGN(x, ID2SYM(x));
04843 }
04844 # define set_yylval_str(x) (void)(x)
04845 # define set_yylval_num(x) (void)(x)
04846 # define set_yylval_id(x) (void)(x)
04847 # define set_yylval_name(x) (void)(yylval.val = ripper_yylval_id(x))
04848 # define set_yylval_literal(x) (void)(x)
04849 # define set_yylval_node(x) (void)(x)
04850 # define yylval_id() yylval.id
04851 #endif
04852
04853 #ifndef RIPPER
04854 #define ripper_flush(p) (void)(p)
04855 #else
04856 #define ripper_flush(p) (p->tokp = p->parser_lex_p)
04857
04858 #define yylval_rval *(RB_TYPE_P(yylval.val, T_NODE) ? &yylval.node->nd_rval : &yylval.val)
04859
04860 static int
04861 ripper_has_scan_event(struct parser_params *parser)
04862 {
04863
04864 if (lex_p < parser->tokp) rb_raise(rb_eRuntimeError, "lex_p < tokp");
04865 return lex_p > parser->tokp;
04866 }
04867
04868 static VALUE
04869 ripper_scan_event_val(struct parser_params *parser, int t)
04870 {
04871 VALUE str = STR_NEW(parser->tokp, lex_p - parser->tokp);
04872 VALUE rval = ripper_dispatch1(parser, ripper_token2eventid(t), str);
04873 ripper_flush(parser);
04874 return rval;
04875 }
04876
04877 static void
04878 ripper_dispatch_scan_event(struct parser_params *parser, int t)
04879 {
04880 if (!ripper_has_scan_event(parser)) return;
04881 yylval_rval = ripper_scan_event_val(parser, t);
04882 }
04883
04884 static void
04885 ripper_dispatch_ignored_scan_event(struct parser_params *parser, int t)
04886 {
04887 if (!ripper_has_scan_event(parser)) return;
04888 (void)ripper_scan_event_val(parser, t);
04889 }
04890
04891 static void
04892 ripper_dispatch_delayed_token(struct parser_params *parser, int t)
04893 {
04894 int saved_line = ruby_sourceline;
04895 const char *saved_tokp = parser->tokp;
04896
04897 ruby_sourceline = parser->delayed_line;
04898 parser->tokp = lex_pbeg + parser->delayed_col;
04899 yylval_rval = ripper_dispatch1(parser, ripper_token2eventid(t), parser->delayed);
04900 parser->delayed = Qnil;
04901 ruby_sourceline = saved_line;
04902 parser->tokp = saved_tokp;
04903 }
04904 #endif
04905
04906 #include "ruby/regex.h"
04907 #include "ruby/util.h"
04908
04909
04910
04911
04912
04913 #undef SIGN_EXTEND_CHAR
04914 #if __STDC__
04915 # define SIGN_EXTEND_CHAR(c) ((signed char)(c))
04916 #else
04917
04918 # define SIGN_EXTEND_CHAR(c) ((((unsigned char)(c)) ^ 128) - 128)
04919 #endif
04920
04921 #define parser_encoding_name() (parser->enc->name)
04922 #define parser_mbclen() mbclen((lex_p-1),lex_pend,parser->enc)
04923 #define parser_precise_mbclen() rb_enc_precise_mbclen((lex_p-1),lex_pend,parser->enc)
04924 #define is_identchar(p,e,enc) (rb_enc_isalnum(*p,enc) || (*p) == '_' || !ISASCII(*p))
04925 #define parser_is_identchar() (!parser->eofp && is_identchar((lex_p-1),lex_pend,parser->enc))
04926
04927 #define parser_isascii() ISASCII(*(lex_p-1))
04928
04929 #ifndef RIPPER
04930 static int
04931 token_info_get_column(struct parser_params *parser, const char *token)
04932 {
04933 int column = 1;
04934 const char *p, *pend = lex_p - strlen(token);
04935 for (p = lex_pbeg; p < pend; p++) {
04936 if (*p == '\t') {
04937 column = (((column - 1) / 8) + 1) * 8;
04938 }
04939 column++;
04940 }
04941 return column;
04942 }
04943
04944 static int
04945 token_info_has_nonspaces(struct parser_params *parser, const char *token)
04946 {
04947 const char *p, *pend = lex_p - strlen(token);
04948 for (p = lex_pbeg; p < pend; p++) {
04949 if (*p != ' ' && *p != '\t') {
04950 return 1;
04951 }
04952 }
04953 return 0;
04954 }
04955
04956 #undef token_info_push
04957 static void
04958 token_info_push(struct parser_params *parser, const char *token)
04959 {
04960 token_info *ptinfo;
04961
04962 if (compile_for_eval) return;
04963 ptinfo = ALLOC(token_info);
04964 ptinfo->token = token;
04965 ptinfo->linenum = ruby_sourceline;
04966 ptinfo->column = token_info_get_column(parser, token);
04967 ptinfo->nonspc = token_info_has_nonspaces(parser, token);
04968 ptinfo->next = parser->parser_token_info;
04969
04970 parser->parser_token_info = ptinfo;
04971 }
04972
04973 #undef token_info_pop
04974 static void
04975 token_info_pop(struct parser_params *parser, const char *token)
04976 {
04977 int linenum;
04978 token_info *ptinfo = parser->parser_token_info;
04979
04980 if (!ptinfo) return;
04981 parser->parser_token_info = ptinfo->next;
04982 if (token_info_get_column(parser, token) == ptinfo->column) {
04983 goto finish;
04984 }
04985 linenum = ruby_sourceline;
04986 if (linenum == ptinfo->linenum) {
04987 goto finish;
04988 }
04989 if (token_info_has_nonspaces(parser, token) || ptinfo->nonspc) {
04990 goto finish;
04991 }
04992 rb_compile_warning(ruby_sourcefile, linenum,
04993 "mismatched indentations at '%s' with '%s' at %d",
04994 token, ptinfo->token, ptinfo->linenum);
04995
04996 finish:
04997 xfree(ptinfo);
04998 }
04999 #endif
05000
05001 static int
05002 parser_yyerror(struct parser_params *parser, const char *msg)
05003 {
05004 #ifndef RIPPER
05005 const int max_line_margin = 30;
05006 const char *p, *pe;
05007 char *buf;
05008 long len;
05009 int i;
05010
05011 compile_error(PARSER_ARG "%s", msg);
05012 p = lex_p;
05013 while (lex_pbeg <= p) {
05014 if (*p == '\n') break;
05015 p--;
05016 }
05017 p++;
05018
05019 pe = lex_p;
05020 while (pe < lex_pend) {
05021 if (*pe == '\n') break;
05022 pe++;
05023 }
05024
05025 len = pe - p;
05026 if (len > 4) {
05027 char *p2;
05028 const char *pre = "", *post = "";
05029
05030 if (len > max_line_margin * 2 + 10) {
05031 if (lex_p - p > max_line_margin) {
05032 p = rb_enc_prev_char(p, lex_p - max_line_margin, pe, rb_enc_get(lex_lastline));
05033 pre = "...";
05034 }
05035 if (pe - lex_p > max_line_margin) {
05036 pe = rb_enc_prev_char(lex_p, lex_p + max_line_margin, pe, rb_enc_get(lex_lastline));
05037 post = "...";
05038 }
05039 len = pe - p;
05040 }
05041 buf = ALLOCA_N(char, len+2);
05042 MEMCPY(buf, p, char, len);
05043 buf[len] = '\0';
05044 rb_compile_error_append("%s%s%s", pre, buf, post);
05045
05046 i = (int)(lex_p - p);
05047 p2 = buf; pe = buf + len;
05048
05049 while (p2 < pe) {
05050 if (*p2 != '\t') *p2 = ' ';
05051 p2++;
05052 }
05053 buf[i] = '^';
05054 buf[i+1] = '\0';
05055 rb_compile_error_append("%s%s", pre, buf);
05056 }
05057 #else
05058 dispatch1(parse_error, STR_NEW2(msg));
05059 #endif
05060 return 0;
05061 }
05062
05063 static void parser_prepare(struct parser_params *parser);
05064
05065 #ifndef RIPPER
05066 VALUE ruby_suppress_tracing(VALUE (*func)(VALUE, int), VALUE arg, int always);
05067
05068 static VALUE
05069 debug_lines(const char *f)
05070 {
05071 ID script_lines;
05072 CONST_ID(script_lines, "SCRIPT_LINES__");
05073 if (rb_const_defined_at(rb_cObject, script_lines)) {
05074 VALUE hash = rb_const_get_at(rb_cObject, script_lines);
05075 if (TYPE(hash) == T_HASH) {
05076 VALUE fname = rb_str_new2(f);
05077 VALUE lines = rb_ary_new();
05078 rb_hash_aset(hash, fname, lines);
05079 return lines;
05080 }
05081 }
05082 return 0;
05083 }
05084
05085 static VALUE
05086 coverage(const char *f, int n)
05087 {
05088 extern VALUE rb_get_coverages(void);
05089 VALUE coverages = rb_get_coverages();
05090 if (RTEST(coverages) && RBASIC(coverages)->klass == 0) {
05091 VALUE fname = rb_str_new2(f);
05092 VALUE lines = rb_ary_new2(n);
05093 int i;
05094 RBASIC(lines)->klass = 0;
05095 for (i = 0; i < n; i++) RARRAY_PTR(lines)[i] = Qnil;
05096 RARRAY(lines)->as.heap.len = n;
05097 rb_hash_aset(coverages, fname, lines);
05098 return lines;
05099 }
05100 return 0;
05101 }
05102
05103 static int
05104 e_option_supplied(struct parser_params *parser)
05105 {
05106 return strcmp(ruby_sourcefile, "-e") == 0;
05107 }
05108
05109 static VALUE
05110 yycompile0(VALUE arg, int tracing)
05111 {
05112 int n;
05113 NODE *tree;
05114 struct parser_params *parser = (struct parser_params *)arg;
05115
05116 if (!compile_for_eval && rb_safe_level() == 0) {
05117 ruby_debug_lines = debug_lines(ruby_sourcefile);
05118 if (ruby_debug_lines && ruby_sourceline > 0) {
05119 VALUE str = STR_NEW0();
05120 n = ruby_sourceline;
05121 do {
05122 rb_ary_push(ruby_debug_lines, str);
05123 } while (--n);
05124 }
05125
05126 if (!e_option_supplied(parser)) {
05127 ruby_coverage = coverage(ruby_sourcefile, ruby_sourceline);
05128 }
05129 }
05130
05131 parser_prepare(parser);
05132 deferred_nodes = 0;
05133 n = yyparse((void*)parser);
05134 ruby_debug_lines = 0;
05135 ruby_coverage = 0;
05136 compile_for_eval = 0;
05137
05138 lex_strterm = 0;
05139 lex_p = lex_pbeg = lex_pend = 0;
05140 lex_lastline = lex_nextline = 0;
05141 if (parser->nerr) {
05142 return 0;
05143 }
05144 tree = ruby_eval_tree;
05145 if (!tree) {
05146 tree = NEW_NIL();
05147 }
05148 else if (ruby_eval_tree_begin) {
05149 tree->nd_body = NEW_PRELUDE(ruby_eval_tree_begin, tree->nd_body);
05150 }
05151 return (VALUE)tree;
05152 }
05153
05154 static NODE*
05155 yycompile(struct parser_params *parser, const char *f, int line)
05156 {
05157 ruby_sourcefile = ruby_strdup(f);
05158 ruby_sourceline = line - 1;
05159 return (NODE *)ruby_suppress_tracing(yycompile0, (VALUE)parser, TRUE);
05160 }
05161 #endif
05162
05163 static rb_encoding *
05164 must_be_ascii_compatible(VALUE s)
05165 {
05166 rb_encoding *enc = rb_enc_get(s);
05167 if (!rb_enc_asciicompat(enc)) {
05168 rb_raise(rb_eArgError, "invalid source encoding");
05169 }
05170 return enc;
05171 }
05172
05173 static VALUE
05174 lex_get_str(struct parser_params *parser, VALUE s)
05175 {
05176 char *beg, *end, *pend;
05177 rb_encoding *enc = must_be_ascii_compatible(s);
05178
05179 beg = RSTRING_PTR(s);
05180 if (lex_gets_ptr) {
05181 if (RSTRING_LEN(s) == lex_gets_ptr) return Qnil;
05182 beg += lex_gets_ptr;
05183 }
05184 pend = RSTRING_PTR(s) + RSTRING_LEN(s);
05185 end = beg;
05186 while (end < pend) {
05187 if (*end++ == '\n') break;
05188 }
05189 lex_gets_ptr = end - RSTRING_PTR(s);
05190 return rb_enc_str_new(beg, end - beg, enc);
05191 }
05192
05193 static VALUE
05194 lex_getline(struct parser_params *parser)
05195 {
05196 VALUE line = (*parser->parser_lex_gets)(parser, parser->parser_lex_input);
05197 if (NIL_P(line)) return line;
05198 must_be_ascii_compatible(line);
05199 #ifndef RIPPER
05200 if (ruby_debug_lines) {
05201 rb_ary_push(ruby_debug_lines, line);
05202 }
05203 if (ruby_coverage) {
05204 rb_ary_push(ruby_coverage, Qnil);
05205 }
05206 #endif
05207 return line;
05208 }
05209
05210 static const rb_data_type_t parser_data_type;
05211
05212 #ifndef RIPPER
05213 static NODE*
05214 parser_compile_string(volatile VALUE vparser, const char *f, VALUE s, int line)
05215 {
05216 struct parser_params *parser;
05217 NODE *node;
05218 volatile VALUE tmp;
05219
05220 TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, parser);
05221 lex_gets = lex_get_str;
05222 lex_gets_ptr = 0;
05223 lex_input = s;
05224 lex_pbeg = lex_p = lex_pend = 0;
05225 compile_for_eval = rb_parse_in_eval();
05226
05227 node = yycompile(parser, f, line);
05228 tmp = vparser;
05229
05230 return node;
05231 }
05232
05233 NODE*
05234 rb_compile_string(const char *f, VALUE s, int line)
05235 {
05236 must_be_ascii_compatible(s);
05237 return parser_compile_string(rb_parser_new(), f, s, line);
05238 }
05239
05240 NODE*
05241 rb_parser_compile_string(volatile VALUE vparser, const char *f, VALUE s, int line)
05242 {
05243 must_be_ascii_compatible(s);
05244 return parser_compile_string(vparser, f, s, line);
05245 }
05246
05247 NODE*
05248 rb_compile_cstr(const char *f, const char *s, int len, int line)
05249 {
05250 VALUE str = rb_str_new(s, len);
05251 return parser_compile_string(rb_parser_new(), f, str, line);
05252 }
05253
05254 NODE*
05255 rb_parser_compile_cstr(volatile VALUE vparser, const char *f, const char *s, int len, int line)
05256 {
05257 VALUE str = rb_str_new(s, len);
05258 return parser_compile_string(vparser, f, str, line);
05259 }
05260
05261 static VALUE
05262 lex_io_gets(struct parser_params *parser, VALUE io)
05263 {
05264 return rb_io_gets(io);
05265 }
05266
05267 NODE*
05268 rb_compile_file(const char *f, VALUE file, int start)
05269 {
05270 VALUE volatile vparser = rb_parser_new();
05271
05272 return rb_parser_compile_file(vparser, f, file, start);
05273 }
05274
05275 NODE*
05276 rb_parser_compile_file(volatile VALUE vparser, const char *f, VALUE file, int start)
05277 {
05278 struct parser_params *parser;
05279 volatile VALUE tmp;
05280 NODE *node;
05281
05282 TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, parser);
05283 lex_gets = lex_io_gets;
05284 lex_input = file;
05285 lex_pbeg = lex_p = lex_pend = 0;
05286 compile_for_eval = rb_parse_in_eval();
05287
05288 node = yycompile(parser, f, start);
05289 tmp = vparser;
05290
05291 return node;
05292 }
05293 #endif
05294
05295 #define STR_FUNC_ESCAPE 0x01
05296 #define STR_FUNC_EXPAND 0x02
05297 #define STR_FUNC_REGEXP 0x04
05298 #define STR_FUNC_QWORDS 0x08
05299 #define STR_FUNC_SYMBOL 0x10
05300 #define STR_FUNC_INDENT 0x20
05301
05302 enum string_type {
05303 str_squote = (0),
05304 str_dquote = (STR_FUNC_EXPAND),
05305 str_xquote = (STR_FUNC_EXPAND),
05306 str_regexp = (STR_FUNC_REGEXP|STR_FUNC_ESCAPE|STR_FUNC_EXPAND),
05307 str_sword = (STR_FUNC_QWORDS),
05308 str_dword = (STR_FUNC_QWORDS|STR_FUNC_EXPAND),
05309 str_ssym = (STR_FUNC_SYMBOL),
05310 str_dsym = (STR_FUNC_SYMBOL|STR_FUNC_EXPAND)
05311 };
05312
05313 static VALUE
05314 parser_str_new(const char *p, long n, rb_encoding *enc, int func, rb_encoding *enc0)
05315 {
05316 VALUE str;
05317
05318 str = rb_enc_str_new(p, n, enc);
05319 if (!(func & STR_FUNC_REGEXP) && rb_enc_asciicompat(enc)) {
05320 if (rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT) {
05321 }
05322 else if (enc0 == rb_usascii_encoding() && enc != rb_utf8_encoding()) {
05323 rb_enc_associate(str, rb_ascii8bit_encoding());
05324 }
05325 }
05326
05327 return str;
05328 }
05329
05330 #define lex_goto_eol(parser) (parser->parser_lex_p = parser->parser_lex_pend)
05331 #define peek(c) (lex_p < lex_pend && (c) == *lex_p)
05332
05333 static inline int
05334 parser_nextc(struct parser_params *parser)
05335 {
05336 int c;
05337
05338 if (lex_p == lex_pend) {
05339 VALUE v = lex_nextline;
05340 lex_nextline = 0;
05341 if (!v) {
05342 if (parser->eofp)
05343 return -1;
05344
05345 if (!lex_input || NIL_P(v = lex_getline(parser))) {
05346 parser->eofp = Qtrue;
05347 lex_goto_eol(parser);
05348 return -1;
05349 }
05350 }
05351 {
05352 #ifdef RIPPER
05353 if (parser->tokp < lex_pend) {
05354 if (NIL_P(parser->delayed)) {
05355 parser->delayed = rb_str_buf_new(1024);
05356 rb_str_buf_cat(parser->delayed,
05357 parser->tokp, lex_pend - parser->tokp);
05358 parser->delayed_line = ruby_sourceline;
05359 parser->delayed_col = (int)(parser->tokp - lex_pbeg);
05360 }
05361 else {
05362 rb_str_buf_cat(parser->delayed,
05363 parser->tokp, lex_pend - parser->tokp);
05364 }
05365 }
05366 #endif
05367 if (heredoc_end > 0) {
05368 ruby_sourceline = heredoc_end;
05369 heredoc_end = 0;
05370 }
05371 ruby_sourceline++;
05372 parser->line_count++;
05373 lex_pbeg = lex_p = RSTRING_PTR(v);
05374 lex_pend = lex_p + RSTRING_LEN(v);
05375 ripper_flush(parser);
05376 lex_lastline = v;
05377 }
05378 }
05379 c = (unsigned char)*lex_p++;
05380 if (c == '\r' && peek('\n')) {
05381 lex_p++;
05382 c = '\n';
05383 }
05384
05385 return c;
05386 }
05387
05388 static void
05389 parser_pushback(struct parser_params *parser, int c)
05390 {
05391 if (c == -1) return;
05392 lex_p--;
05393 if (lex_p > lex_pbeg && lex_p[0] == '\n' && lex_p[-1] == '\r') {
05394 lex_p--;
05395 }
05396 }
05397
05398 #define was_bol() (lex_p == lex_pbeg + 1)
05399
05400 #define tokfix() (tokenbuf[tokidx]='\0')
05401 #define tok() tokenbuf
05402 #define toklen() tokidx
05403 #define toklast() (tokidx>0?tokenbuf[tokidx-1]:0)
05404
05405 static char*
05406 parser_newtok(struct parser_params *parser)
05407 {
05408 tokidx = 0;
05409 if (!tokenbuf) {
05410 toksiz = 60;
05411 tokenbuf = ALLOC_N(char, 60);
05412 }
05413 if (toksiz > 4096) {
05414 toksiz = 60;
05415 REALLOC_N(tokenbuf, char, 60);
05416 }
05417 return tokenbuf;
05418 }
05419
05420 static char *
05421 parser_tokspace(struct parser_params *parser, int n)
05422 {
05423 tokidx += n;
05424
05425 if (tokidx >= toksiz) {
05426 do {toksiz *= 2;} while (toksiz < tokidx);
05427 REALLOC_N(tokenbuf, char, toksiz);
05428 }
05429 return &tokenbuf[tokidx-n];
05430 }
05431
05432 static void
05433 parser_tokadd(struct parser_params *parser, int c)
05434 {
05435 tokenbuf[tokidx++] = (char)c;
05436 if (tokidx >= toksiz) {
05437 toksiz *= 2;
05438 REALLOC_N(tokenbuf, char, toksiz);
05439 }
05440 }
05441
05442 static int
05443 parser_tok_hex(struct parser_params *parser, size_t *numlen)
05444 {
05445 int c;
05446
05447 c = scan_hex(lex_p, 2, numlen);
05448 if (!*numlen) {
05449 yyerror("invalid hex escape");
05450 return 0;
05451 }
05452 lex_p += *numlen;
05453 return c;
05454 }
05455
05456 #define tokcopy(n) memcpy(tokspace(n), lex_p - (n), (n))
05457
05458 static int
05459 parser_tokadd_utf8(struct parser_params *parser, rb_encoding **encp,
05460 int string_literal, int symbol_literal, int regexp_literal)
05461 {
05462
05463
05464
05465
05466
05467
05468
05469 int codepoint;
05470 size_t numlen;
05471
05472 if (regexp_literal) { tokadd('\\'); tokadd('u'); }
05473
05474 if (peek('{')) {
05475 do {
05476 if (regexp_literal) { tokadd(*lex_p); }
05477 nextc();
05478 codepoint = scan_hex(lex_p, 6, &numlen);
05479 if (numlen == 0) {
05480 yyerror("invalid Unicode escape");
05481 return 0;
05482 }
05483 if (codepoint > 0x10ffff) {
05484 yyerror("invalid Unicode codepoint (too large)");
05485 return 0;
05486 }
05487 lex_p += numlen;
05488 if (regexp_literal) {
05489 tokcopy((int)numlen);
05490 }
05491 else if (codepoint >= 0x80) {
05492 *encp = UTF8_ENC();
05493 if (string_literal) tokaddmbc(codepoint, *encp);
05494 }
05495 else if (string_literal) {
05496 tokadd(codepoint);
05497 }
05498 } while (string_literal && (peek(' ') || peek('\t')));
05499
05500 if (!peek('}')) {
05501 yyerror("unterminated Unicode escape");
05502 return 0;
05503 }
05504
05505 if (regexp_literal) { tokadd('}'); }
05506 nextc();
05507 }
05508 else {
05509 codepoint = scan_hex(lex_p, 4, &numlen);
05510 if (numlen < 4) {
05511 yyerror("invalid Unicode escape");
05512 return 0;
05513 }
05514 lex_p += 4;
05515 if (regexp_literal) {
05516 tokcopy(4);
05517 }
05518 else if (codepoint >= 0x80) {
05519 *encp = UTF8_ENC();
05520 if (string_literal) tokaddmbc(codepoint, *encp);
05521 }
05522 else if (string_literal) {
05523 tokadd(codepoint);
05524 }
05525 }
05526
05527 return codepoint;
05528 }
05529
05530 #define ESCAPE_CONTROL 1
05531 #define ESCAPE_META 2
05532
05533 static int
05534 parser_read_escape(struct parser_params *parser, int flags,
05535 rb_encoding **encp)
05536 {
05537 int c;
05538 size_t numlen;
05539
05540 switch (c = nextc()) {
05541 case '\\':
05542 return c;
05543
05544 case 'n':
05545 return '\n';
05546
05547 case 't':
05548 return '\t';
05549
05550 case 'r':
05551 return '\r';
05552
05553 case 'f':
05554 return '\f';
05555
05556 case 'v':
05557 return '\13';
05558
05559 case 'a':
05560 return '\007';
05561
05562 case 'e':
05563 return 033;
05564
05565 case '0': case '1': case '2': case '3':
05566 case '4': case '5': case '6': case '7':
05567 if (flags & (ESCAPE_CONTROL|ESCAPE_META)) goto eof;
05568 pushback(c);
05569 c = scan_oct(lex_p, 3, &numlen);
05570 lex_p += numlen;
05571 return c;
05572
05573 case 'x':
05574 if (flags & (ESCAPE_CONTROL|ESCAPE_META)) goto eof;
05575 c = tok_hex(&numlen);
05576 if (numlen == 0) return 0;
05577 return c;
05578
05579 case 'b':
05580 return '\010';
05581
05582 case 's':
05583 return ' ';
05584
05585 case 'M':
05586 if (flags & ESCAPE_META) goto eof;
05587 if ((c = nextc()) != '-') {
05588 pushback(c);
05589 goto eof;
05590 }
05591 if ((c = nextc()) == '\\') {
05592 if (peek('u')) goto eof;
05593 return read_escape(flags|ESCAPE_META, encp) | 0x80;
05594 }
05595 else if (c == -1 || !ISASCII(c)) goto eof;
05596 else {
05597 return ((c & 0xff) | 0x80);
05598 }
05599
05600 case 'C':
05601 if ((c = nextc()) != '-') {
05602 pushback(c);
05603 goto eof;
05604 }
05605 case 'c':
05606 if (flags & ESCAPE_CONTROL) goto eof;
05607 if ((c = nextc())== '\\') {
05608 if (peek('u')) goto eof;
05609 c = read_escape(flags|ESCAPE_CONTROL, encp);
05610 }
05611 else if (c == '?')
05612 return 0177;
05613 else if (c == -1 || !ISASCII(c)) goto eof;
05614 return c & 0x9f;
05615
05616 eof:
05617 case -1:
05618 yyerror("Invalid escape character syntax");
05619 return '\0';
05620
05621 default:
05622 return c;
05623 }
05624 }
05625
05626 static void
05627 parser_tokaddmbc(struct parser_params *parser, int c, rb_encoding *enc)
05628 {
05629 int len = rb_enc_codelen(c, enc);
05630 rb_enc_mbcput(c, tokspace(len), enc);
05631 }
05632
05633 static int
05634 parser_tokadd_escape(struct parser_params *parser, rb_encoding **encp)
05635 {
05636 int c;
05637 int flags = 0;
05638 size_t numlen;
05639
05640 first:
05641 switch (c = nextc()) {
05642 case '\n':
05643 return 0;
05644
05645 case '0': case '1': case '2': case '3':
05646 case '4': case '5': case '6': case '7':
05647 if (flags & (ESCAPE_CONTROL|ESCAPE_META)) goto eof;
05648 {
05649 ruby_scan_oct(--lex_p, 3, &numlen);
05650 if (numlen == 0) goto eof;
05651 lex_p += numlen;
05652 tokcopy((int)numlen + 1);
05653 }
05654 return 0;
05655
05656 case 'x':
05657 if (flags & (ESCAPE_CONTROL|ESCAPE_META)) goto eof;
05658 {
05659 tok_hex(&numlen);
05660 if (numlen == 0) goto eof;
05661 tokcopy((int)numlen + 2);
05662 }
05663 return 0;
05664
05665 case 'M':
05666 if (flags & ESCAPE_META) goto eof;
05667 if ((c = nextc()) != '-') {
05668 pushback(c);
05669 goto eof;
05670 }
05671 tokcopy(3);
05672 flags |= ESCAPE_META;
05673 goto escaped;
05674
05675 case 'C':
05676 if (flags & ESCAPE_CONTROL) goto eof;
05677 if ((c = nextc()) != '-') {
05678 pushback(c);
05679 goto eof;
05680 }
05681 tokcopy(3);
05682 goto escaped;
05683
05684 case 'c':
05685 if (flags & ESCAPE_CONTROL) goto eof;
05686 tokcopy(2);
05687 flags |= ESCAPE_CONTROL;
05688 escaped:
05689 if ((c = nextc()) == '\\') {
05690 goto first;
05691 }
05692 else if (c == -1) goto eof;
05693 tokadd(c);
05694 return 0;
05695
05696 eof:
05697 case -1:
05698 yyerror("Invalid escape character syntax");
05699 return -1;
05700
05701 default:
05702 tokadd('\\');
05703 tokadd(c);
05704 }
05705 return 0;
05706 }
05707
05708 extern int rb_char_to_option_kcode(int c, int *option, int *kcode);
05709
05710 static int
05711 parser_regx_options(struct parser_params *parser)
05712 {
05713 int kcode = 0;
05714 int kopt = 0;
05715 int options = 0;
05716 int c, opt, kc;
05717
05718 newtok();
05719 while (c = nextc(), ISALPHA(c)) {
05720 if (c == 'o') {
05721 options |= RE_OPTION_ONCE;
05722 }
05723 else if (rb_char_to_option_kcode(c, &opt, &kc)) {
05724 if (kc >= 0) {
05725 if (kc != rb_ascii8bit_encindex()) kcode = c;
05726 kopt = opt;
05727 }
05728 else {
05729 options |= opt;
05730 }
05731 }
05732 else {
05733 tokadd(c);
05734 }
05735 }
05736 options |= kopt;
05737 pushback(c);
05738 if (toklen()) {
05739 tokfix();
05740 compile_error(PARSER_ARG "unknown regexp option%s - %s",
05741 toklen() > 1 ? "s" : "", tok());
05742 }
05743 return options | RE_OPTION_ENCODING(kcode);
05744 }
05745
05746 static void
05747 dispose_string(VALUE str)
05748 {
05749
05750 if (RBASIC(str)->flags & RSTRING_NOEMBED)
05751 xfree(RSTRING_PTR(str));
05752 rb_gc_force_recycle(str);
05753 }
05754
05755 static int
05756 parser_tokadd_mbchar(struct parser_params *parser, int c)
05757 {
05758 int len = parser_precise_mbclen();
05759 if (!MBCLEN_CHARFOUND_P(len)) {
05760 compile_error(PARSER_ARG "invalid multibyte char (%s)", parser_encoding_name());
05761 return -1;
05762 }
05763 tokadd(c);
05764 lex_p += --len;
05765 if (len > 0) tokcopy(len);
05766 return c;
05767 }
05768
05769 #define tokadd_mbchar(c) parser_tokadd_mbchar(parser, c)
05770
05771 static int
05772 parser_tokadd_string(struct parser_params *parser,
05773 int func, int term, int paren, long *nest,
05774 rb_encoding **encp)
05775 {
05776 int c;
05777 int has_nonascii = 0;
05778 rb_encoding *enc = *encp;
05779 char *errbuf = 0;
05780 static const char mixed_msg[] = "%s mixed within %s source";
05781
05782 #define mixed_error(enc1, enc2) if (!errbuf) { \
05783 size_t len = sizeof(mixed_msg) - 4; \
05784 len += strlen(rb_enc_name(enc1)); \
05785 len += strlen(rb_enc_name(enc2)); \
05786 errbuf = ALLOCA_N(char, len); \
05787 snprintf(errbuf, len, mixed_msg, \
05788 rb_enc_name(enc1), \
05789 rb_enc_name(enc2)); \
05790 yyerror(errbuf); \
05791 }
05792 #define mixed_escape(beg, enc1, enc2) do { \
05793 const char *pos = lex_p; \
05794 lex_p = beg; \
05795 mixed_error(enc1, enc2); \
05796 lex_p = pos; \
05797 } while (0)
05798
05799 while ((c = nextc()) != -1) {
05800 if (paren && c == paren) {
05801 ++*nest;
05802 }
05803 else if (c == term) {
05804 if (!nest || !*nest) {
05805 pushback(c);
05806 break;
05807 }
05808 --*nest;
05809 }
05810 else if ((func & STR_FUNC_EXPAND) && c == '#' && lex_p < lex_pend) {
05811 int c2 = *lex_p;
05812 if (c2 == '$' || c2 == '@' || c2 == '{') {
05813 pushback(c);
05814 break;
05815 }
05816 }
05817 else if (c == '\\') {
05818 const char *beg = lex_p - 1;
05819 c = nextc();
05820 switch (c) {
05821 case '\n':
05822 if (func & STR_FUNC_QWORDS) break;
05823 if (func & STR_FUNC_EXPAND) continue;
05824 tokadd('\\');
05825 break;
05826
05827 case '\\':
05828 if (func & STR_FUNC_ESCAPE) tokadd(c);
05829 break;
05830
05831 case 'u':
05832 if ((func & STR_FUNC_EXPAND) == 0) {
05833 tokadd('\\');
05834 break;
05835 }
05836 parser_tokadd_utf8(parser, &enc, 1,
05837 func & STR_FUNC_SYMBOL,
05838 func & STR_FUNC_REGEXP);
05839 if (has_nonascii && enc != *encp) {
05840 mixed_escape(beg, enc, *encp);
05841 }
05842 continue;
05843
05844 default:
05845 if (func & STR_FUNC_REGEXP) {
05846 pushback(c);
05847 if ((c = tokadd_escape(&enc)) < 0)
05848 return -1;
05849 if (has_nonascii && enc != *encp) {
05850 mixed_escape(beg, enc, *encp);
05851 }
05852 continue;
05853 }
05854 else if (func & STR_FUNC_EXPAND) {
05855 pushback(c);
05856 if (func & STR_FUNC_ESCAPE) tokadd('\\');
05857 c = read_escape(0, &enc);
05858 }
05859 else if ((func & STR_FUNC_QWORDS) && ISSPACE(c)) {
05860
05861 }
05862 else if (c != term && !(paren && c == paren)) {
05863 tokadd('\\');
05864 pushback(c);
05865 continue;
05866 }
05867 }
05868 }
05869 else if (!parser_isascii()) {
05870 has_nonascii = 1;
05871 if (enc != *encp) {
05872 mixed_error(enc, *encp);
05873 continue;
05874 }
05875 if (tokadd_mbchar(c) == -1) return -1;
05876 continue;
05877 }
05878 else if ((func & STR_FUNC_QWORDS) && ISSPACE(c)) {
05879 pushback(c);
05880 break;
05881 }
05882 if (c & 0x80) {
05883 has_nonascii = 1;
05884 if (enc != *encp) {
05885 mixed_error(enc, *encp);
05886 continue;
05887 }
05888 }
05889 tokadd(c);
05890 }
05891 *encp = enc;
05892 return c;
05893 }
05894
05895 #define NEW_STRTERM(func, term, paren) \
05896 rb_node_newnode(NODE_STRTERM, (func), (term) | ((paren) << (CHAR_BIT * 2)), 0)
05897
05898 static int
05899 parser_parse_string(struct parser_params *parser, NODE *quote)
05900 {
05901 int func = (int)quote->nd_func;
05902 int term = nd_term(quote);
05903 int paren = nd_paren(quote);
05904 int c, space = 0;
05905 rb_encoding *enc = parser->enc;
05906
05907 if (func == -1) return tSTRING_END;
05908 c = nextc();
05909 if ((func & STR_FUNC_QWORDS) && ISSPACE(c)) {
05910 do {c = nextc();} while (ISSPACE(c));
05911 space = 1;
05912 }
05913 if (c == term && !quote->nd_nest) {
05914 if (func & STR_FUNC_QWORDS) {
05915 quote->nd_func = -1;
05916 return ' ';
05917 }
05918 if (!(func & STR_FUNC_REGEXP)) return tSTRING_END;
05919 set_yylval_num(regx_options());
05920 return tREGEXP_END;
05921 }
05922 if (space) {
05923 pushback(c);
05924 return ' ';
05925 }
05926 newtok();
05927 if ((func & STR_FUNC_EXPAND) && c == '#') {
05928 switch (c = nextc()) {
05929 case '$':
05930 case '@':
05931 pushback(c);
05932 return tSTRING_DVAR;
05933 case '{':
05934 return tSTRING_DBEG;
05935 }
05936 tokadd('#');
05937 }
05938 pushback(c);
05939 if (tokadd_string(func, term, paren, "e->nd_nest,
05940 &enc) == -1) {
05941 ruby_sourceline = nd_line(quote);
05942 if (func & STR_FUNC_REGEXP) {
05943 if (parser->eofp)
05944 compile_error(PARSER_ARG "unterminated regexp meets end of file");
05945 return tREGEXP_END;
05946 }
05947 else {
05948 if (parser->eofp)
05949 compile_error(PARSER_ARG "unterminated string meets end of file");
05950 return tSTRING_END;
05951 }
05952 }
05953
05954 tokfix();
05955 set_yylval_str(STR_NEW3(tok(), toklen(), enc, func));
05956 return tSTRING_CONTENT;
05957 }
05958
05959 static int
05960 parser_heredoc_identifier(struct parser_params *parser)
05961 {
05962 int c = nextc(), term, func = 0;
05963 long len;
05964
05965 if (c == '-') {
05966 c = nextc();
05967 func = STR_FUNC_INDENT;
05968 }
05969 switch (c) {
05970 case '\'':
05971 func |= str_squote; goto quoted;
05972 case '"':
05973 func |= str_dquote; goto quoted;
05974 case '`':
05975 func |= str_xquote;
05976 quoted:
05977 newtok();
05978 tokadd(func);
05979 term = c;
05980 while ((c = nextc()) != -1 && c != term) {
05981 if (tokadd_mbchar(c) == -1) return 0;
05982 }
05983 if (c == -1) {
05984 compile_error(PARSER_ARG "unterminated here document identifier");
05985 return 0;
05986 }
05987 break;
05988
05989 default:
05990 if (!parser_is_identchar()) {
05991 pushback(c);
05992 if (func & STR_FUNC_INDENT) {
05993 pushback('-');
05994 }
05995 return 0;
05996 }
05997 newtok();
05998 term = '"';
05999 tokadd(func |= str_dquote);
06000 do {
06001 if (tokadd_mbchar(c) == -1) return 0;
06002 } while ((c = nextc()) != -1 && parser_is_identchar());
06003 pushback(c);
06004 break;
06005 }
06006
06007 tokfix();
06008 #ifdef RIPPER
06009 ripper_dispatch_scan_event(parser, tHEREDOC_BEG);
06010 #endif
06011 len = lex_p - lex_pbeg;
06012 lex_goto_eol(parser);
06013 lex_strterm = rb_node_newnode(NODE_HEREDOC,
06014 STR_NEW(tok(), toklen()),
06015 len,
06016 lex_lastline);
06017 nd_set_line(lex_strterm, ruby_sourceline);
06018 ripper_flush(parser);
06019 return term == '`' ? tXSTRING_BEG : tSTRING_BEG;
06020 }
06021
06022 static void
06023 parser_heredoc_restore(struct parser_params *parser, NODE *here)
06024 {
06025 VALUE line;
06026
06027 line = here->nd_orig;
06028 lex_lastline = line;
06029 lex_pbeg = RSTRING_PTR(line);
06030 lex_pend = lex_pbeg + RSTRING_LEN(line);
06031 lex_p = lex_pbeg + here->nd_nth;
06032 heredoc_end = ruby_sourceline;
06033 ruby_sourceline = nd_line(here);
06034 dispose_string(here->nd_lit);
06035 rb_gc_force_recycle((VALUE)here);
06036 ripper_flush(parser);
06037 }
06038
06039 static int
06040 parser_whole_match_p(struct parser_params *parser,
06041 const char *eos, long len, int indent)
06042 {
06043 const char *p = lex_pbeg;
06044 long n;
06045
06046 if (indent) {
06047 while (*p && ISSPACE(*p)) p++;
06048 }
06049 n = lex_pend - (p + len);
06050 if (n < 0 || (n > 0 && p[len] != '\n' && p[len] != '\r')) return FALSE;
06051 return strncmp(eos, p, len) == 0;
06052 }
06053
06054 static int
06055 parser_here_document(struct parser_params *parser, NODE *here)
06056 {
06057 int c, func, indent = 0;
06058 const char *eos, *p, *pend;
06059 long len;
06060 VALUE str = 0;
06061 rb_encoding *enc = parser->enc;
06062
06063 eos = RSTRING_PTR(here->nd_lit);
06064 len = RSTRING_LEN(here->nd_lit) - 1;
06065 indent = (func = *eos++) & STR_FUNC_INDENT;
06066
06067 if ((c = nextc()) == -1) {
06068 error:
06069 compile_error(PARSER_ARG "can't find string \"%s\" anywhere before EOF", eos);
06070 #ifdef RIPPER
06071 if (NIL_P(parser->delayed)) {
06072 ripper_dispatch_scan_event(parser, tSTRING_CONTENT);
06073 }
06074 else {
06075 if (str ||
06076 ((len = lex_p - parser->tokp) > 0 &&
06077 (str = STR_NEW3(parser->tokp, len, enc, func), 1))) {
06078 rb_str_append(parser->delayed, str);
06079 }
06080 ripper_dispatch_delayed_token(parser, tSTRING_CONTENT);
06081 }
06082 lex_goto_eol(parser);
06083 #endif
06084 restore:
06085 heredoc_restore(lex_strterm);
06086 lex_strterm = 0;
06087 return 0;
06088 }
06089 if (was_bol() && whole_match_p(eos, len, indent)) {
06090 heredoc_restore(lex_strterm);
06091 return tSTRING_END;
06092 }
06093
06094 if (!(func & STR_FUNC_EXPAND)) {
06095 do {
06096 p = RSTRING_PTR(lex_lastline);
06097 pend = lex_pend;
06098 if (pend > p) {
06099 switch (pend[-1]) {
06100 case '\n':
06101 if (--pend == p || pend[-1] != '\r') {
06102 pend++;
06103 break;
06104 }
06105 case '\r':
06106 --pend;
06107 }
06108 }
06109 if (str)
06110 rb_str_cat(str, p, pend - p);
06111 else
06112 str = STR_NEW(p, pend - p);
06113 if (pend < lex_pend) rb_str_cat(str, "\n", 1);
06114 lex_goto_eol(parser);
06115 if (nextc() == -1) {
06116 if (str) dispose_string(str);
06117 goto error;
06118 }
06119 } while (!whole_match_p(eos, len, indent));
06120 }
06121 else {
06122
06123 newtok();
06124 if (c == '#') {
06125 switch (c = nextc()) {
06126 case '$':
06127 case '@':
06128 pushback(c);
06129 return tSTRING_DVAR;
06130 case '{':
06131 return tSTRING_DBEG;
06132 }
06133 tokadd('#');
06134 }
06135 do {
06136 pushback(c);
06137 if ((c = tokadd_string(func, '\n', 0, NULL, &enc)) == -1) {
06138 if (parser->eofp) goto error;
06139 goto restore;
06140 }
06141 if (c != '\n') {
06142 set_yylval_str(STR_NEW3(tok(), toklen(), enc, func));
06143 return tSTRING_CONTENT;
06144 }
06145 tokadd(nextc());
06146
06147 if ((c = nextc()) == -1) goto error;
06148 } while (!whole_match_p(eos, len, indent));
06149 str = STR_NEW3(tok(), toklen(), enc, func);
06150 }
06151 #ifdef RIPPER
06152 if (!NIL_P(parser->delayed))
06153 ripper_dispatch_delayed_token(parser, tSTRING_CONTENT);
06154 lex_goto_eol(parser);
06155 ripper_dispatch_ignored_scan_event(parser, tHEREDOC_END);
06156 #endif
06157 heredoc_restore(lex_strterm);
06158 lex_strterm = NEW_STRTERM(-1, 0, 0);
06159 set_yylval_str(str);
06160 return tSTRING_CONTENT;
06161 }
06162
06163 #include "lex.c"
06164
06165 static void
06166 arg_ambiguous_gen(struct parser_params *parser)
06167 {
06168 #ifndef RIPPER
06169 rb_warning0("ambiguous first argument; put parentheses or even spaces");
06170 #else
06171 dispatch0(arg_ambiguous);
06172 #endif
06173 }
06174 #define arg_ambiguous() (arg_ambiguous_gen(parser), 1)
06175
06176 static ID
06177 formal_argument_gen(struct parser_params *parser, ID lhs)
06178 {
06179 #ifndef RIPPER
06180 if (!is_local_id(lhs))
06181 yyerror("formal argument must be local variable");
06182 #endif
06183 shadowing_lvar(lhs);
06184 return lhs;
06185 }
06186
06187 static int
06188 lvar_defined_gen(struct parser_params *parser, ID id)
06189 {
06190 return (dyna_in_block() && dvar_defined(id)) || local_id(id);
06191 }
06192
06193
06194 static long
06195 parser_encode_length(struct parser_params *parser, const char *name, long len)
06196 {
06197 long nlen;
06198
06199 if (len > 5 && name[nlen = len - 5] == '-') {
06200 if (rb_memcicmp(name + nlen + 1, "unix", 4) == 0)
06201 return nlen;
06202 }
06203 if (len > 4 && name[nlen = len - 5] == '-') {
06204 if (rb_memcicmp(name + nlen + 1, "dos", 3) == 0)
06205 return nlen;
06206 if (rb_memcicmp(name + nlen + 1, "mac", 3) == 0)
06207 return nlen;
06208 }
06209 return len;
06210 }
06211
06212 static void
06213 parser_set_encode(struct parser_params *parser, const char *name)
06214 {
06215 int idx = rb_enc_find_index(name);
06216 rb_encoding *enc;
06217 VALUE excargs[3];
06218
06219 if (idx < 0) {
06220 VALUE rb_make_backtrace(void);
06221 VALUE rb_make_exception(int, VALUE*);
06222
06223 excargs[1] = rb_sprintf("unknown encoding name: %s", name);
06224 error:
06225 excargs[0] = rb_eArgError;
06226 excargs[2] = rb_make_backtrace();
06227 rb_ary_unshift(excargs[2], rb_sprintf("%s:%d", ruby_sourcefile, ruby_sourceline));
06228 rb_exc_raise(rb_make_exception(3, excargs));
06229 }
06230 enc = rb_enc_from_index(idx);
06231 if (!rb_enc_asciicompat(enc)) {
06232 excargs[1] = rb_sprintf("%s is not ASCII compatible", rb_enc_name(enc));
06233 goto error;
06234 }
06235 parser->enc = enc;
06236 }
06237
06238 static int
06239 comment_at_top(struct parser_params *parser)
06240 {
06241 const char *p = lex_pbeg, *pend = lex_p - 1;
06242 if (parser->line_count != (parser->has_shebang ? 2 : 1)) return 0;
06243 while (p < pend) {
06244 if (!ISSPACE(*p)) return 0;
06245 p++;
06246 }
06247 return 1;
06248 }
06249
06250 #ifndef RIPPER
06251 typedef long (*rb_magic_comment_length_t)(struct parser_params *parser, const char *name, long len);
06252 typedef void (*rb_magic_comment_setter_t)(struct parser_params *parser, const char *name, const char *val);
06253
06254 static void
06255 magic_comment_encoding(struct parser_params *parser, const char *name, const char *val)
06256 {
06257 if (!comment_at_top(parser)) {
06258 return;
06259 }
06260 parser_set_encode(parser, val);
06261 }
06262
06263 struct magic_comment {
06264 const char *name;
06265 rb_magic_comment_setter_t func;
06266 rb_magic_comment_length_t length;
06267 };
06268
06269 static const struct magic_comment magic_comments[] = {
06270 {"coding", magic_comment_encoding, parser_encode_length},
06271 {"encoding", magic_comment_encoding, parser_encode_length},
06272 };
06273 #endif
06274
06275 static const char *
06276 magic_comment_marker(const char *str, long len)
06277 {
06278 long i = 2;
06279
06280 while (i < len) {
06281 switch (str[i]) {
06282 case '-':
06283 if (str[i-1] == '*' && str[i-2] == '-') {
06284 return str + i + 1;
06285 }
06286 i += 2;
06287 break;
06288 case '*':
06289 if (i + 1 >= len) return 0;
06290 if (str[i+1] != '-') {
06291 i += 4;
06292 }
06293 else if (str[i-1] != '-') {
06294 i += 2;
06295 }
06296 else {
06297 return str + i + 2;
06298 }
06299 break;
06300 default:
06301 i += 3;
06302 break;
06303 }
06304 }
06305 return 0;
06306 }
06307
06308 static int
06309 parser_magic_comment(struct parser_params *parser, const char *str, long len)
06310 {
06311 VALUE name = 0, val = 0;
06312 const char *beg, *end, *vbeg, *vend;
06313 #define str_copy(_s, _p, _n) ((_s) \
06314 ? (rb_str_resize((_s), (_n)), \
06315 MEMCPY(RSTRING_PTR(_s), (_p), char, (_n)), (_s)) \
06316 : ((_s) = STR_NEW((_p), (_n))))
06317
06318 if (len <= 7) return FALSE;
06319 if (!(beg = magic_comment_marker(str, len))) return FALSE;
06320 if (!(end = magic_comment_marker(beg, str + len - beg))) return FALSE;
06321 str = beg;
06322 len = end - beg - 3;
06323
06324
06325 while (len > 0) {
06326 #ifndef RIPPER
06327 const struct magic_comment *p = magic_comments;
06328 #endif
06329 char *s;
06330 int i;
06331 long n = 0;
06332
06333 for (; len > 0 && *str; str++, --len) {
06334 switch (*str) {
06335 case '\'': case '"': case ':': case ';':
06336 continue;
06337 }
06338 if (!ISSPACE(*str)) break;
06339 }
06340 for (beg = str; len > 0; str++, --len) {
06341 switch (*str) {
06342 case '\'': case '"': case ':': case ';':
06343 break;
06344 default:
06345 if (ISSPACE(*str)) break;
06346 continue;
06347 }
06348 break;
06349 }
06350 for (end = str; len > 0 && ISSPACE(*str); str++, --len);
06351 if (!len) break;
06352 if (*str != ':') continue;
06353
06354 do str++; while (--len > 0 && ISSPACE(*str));
06355 if (!len) break;
06356 if (*str == '"') {
06357 for (vbeg = ++str; --len > 0 && *str != '"'; str++) {
06358 if (*str == '\\') {
06359 --len;
06360 ++str;
06361 }
06362 }
06363 vend = str;
06364 if (len) {
06365 --len;
06366 ++str;
06367 }
06368 }
06369 else {
06370 for (vbeg = str; len > 0 && *str != '"' && *str != ';' && !ISSPACE(*str); --len, str++);
06371 vend = str;
06372 }
06373 while (len > 0 && (*str == ';' || ISSPACE(*str))) --len, str++;
06374
06375 n = end - beg;
06376 str_copy(name, beg, n);
06377 s = RSTRING_PTR(name);
06378 for (i = 0; i < n; ++i) {
06379 if (s[i] == '-') s[i] = '_';
06380 }
06381 #ifndef RIPPER
06382 do {
06383 if (STRNCASECMP(p->name, s, n) == 0) {
06384 n = vend - vbeg;
06385 if (p->length) {
06386 n = (*p->length)(parser, vbeg, n);
06387 }
06388 str_copy(val, vbeg, n);
06389 (*p->func)(parser, s, RSTRING_PTR(val));
06390 break;
06391 }
06392 } while (++p < magic_comments + numberof(magic_comments));
06393 #else
06394 dispatch2(magic_comment, name, val);
06395 #endif
06396 }
06397
06398 return TRUE;
06399 }
06400
06401 static void
06402 set_file_encoding(struct parser_params *parser, const char *str, const char *send)
06403 {
06404 int sep = 0;
06405 const char *beg = str;
06406 VALUE s;
06407
06408 for (;;) {
06409 if (send - str <= 6) return;
06410 switch (str[6]) {
06411 case 'C': case 'c': str += 6; continue;
06412 case 'O': case 'o': str += 5; continue;
06413 case 'D': case 'd': str += 4; continue;
06414 case 'I': case 'i': str += 3; continue;
06415 case 'N': case 'n': str += 2; continue;
06416 case 'G': case 'g': str += 1; continue;
06417 case '=': case ':':
06418 sep = 1;
06419 str += 6;
06420 break;
06421 default:
06422 str += 6;
06423 if (ISSPACE(*str)) break;
06424 continue;
06425 }
06426 if (STRNCASECMP(str-6, "coding", 6) == 0) break;
06427 }
06428 for (;;) {
06429 do {
06430 if (++str >= send) return;
06431 } while (ISSPACE(*str));
06432 if (sep) break;
06433 if (*str != '=' && *str != ':') return;
06434 sep = 1;
06435 str++;
06436 }
06437 beg = str;
06438 while ((*str == '-' || *str == '_' || ISALNUM(*str)) && ++str < send);
06439 s = rb_str_new(beg, parser_encode_length(parser, beg, str - beg));
06440 parser_set_encode(parser, RSTRING_PTR(s));
06441 rb_str_resize(s, 0);
06442 }
06443
06444 static void
06445 parser_prepare(struct parser_params *parser)
06446 {
06447 int c = nextc();
06448 switch (c) {
06449 case '#':
06450 if (peek('!')) parser->has_shebang = 1;
06451 break;
06452 case 0xef:
06453 if (lex_pend - lex_p >= 2 &&
06454 (unsigned char)lex_p[0] == 0xbb &&
06455 (unsigned char)lex_p[1] == 0xbf) {
06456 parser->enc = rb_utf8_encoding();
06457 lex_p += 2;
06458 lex_pbeg = lex_p;
06459 return;
06460 }
06461 break;
06462 case EOF:
06463 return;
06464 }
06465 pushback(c);
06466 parser->enc = rb_enc_get(lex_lastline);
06467 }
06468
06469 #define IS_ARG() (lex_state == EXPR_ARG || lex_state == EXPR_CMDARG)
06470 #define IS_END() (lex_state == EXPR_END || lex_state == EXPR_ENDARG || lex_state == EXPR_ENDFN)
06471 #define IS_BEG() (lex_state == EXPR_BEG || lex_state == EXPR_MID || lex_state == EXPR_VALUE || lex_state == EXPR_CLASS)
06472 #define IS_SPCARG(c) (IS_ARG() && space_seen && !ISSPACE(c))
06473
06474 #ifndef RIPPER
06475 #define ambiguous_operator(op, syn) ( \
06476 rb_warning0("`"op"' after local variable is interpreted as binary operator"), \
06477 rb_warning0("even though it seems like "syn""))
06478 #else
06479 #define ambiguous_operator(op, syn) dispatch2(operator_ambiguous, ripper_intern(op), rb_str_new_cstr(syn))
06480 #endif
06481 #define warn_balanced(op, syn) \
06482 (last_state != EXPR_CLASS && last_state != EXPR_DOT && \
06483 last_state != EXPR_FNAME && last_state != EXPR_ENDFN && \
06484 last_state != EXPR_ENDARG && \
06485 space_seen && !ISSPACE(c) && \
06486 (ambiguous_operator(op, syn), 0))
06487
06488 static int
06489 parser_yylex(struct parser_params *parser)
06490 {
06491 register int c;
06492 int space_seen = 0;
06493 int cmd_state;
06494 enum lex_state_e last_state;
06495 rb_encoding *enc;
06496 int mb;
06497 #ifdef RIPPER
06498 int fallthru = FALSE;
06499 #endif
06500
06501 if (lex_strterm) {
06502 int token;
06503 if (nd_type(lex_strterm) == NODE_HEREDOC) {
06504 token = here_document(lex_strterm);
06505 if (token == tSTRING_END) {
06506 lex_strterm = 0;
06507 lex_state = EXPR_END;
06508 }
06509 }
06510 else {
06511 token = parse_string(lex_strterm);
06512 if (token == tSTRING_END || token == tREGEXP_END) {
06513 rb_gc_force_recycle((VALUE)lex_strterm);
06514 lex_strterm = 0;
06515 lex_state = EXPR_END;
06516 }
06517 }
06518 return token;
06519 }
06520 cmd_state = command_start;
06521 command_start = FALSE;
06522 retry:
06523 last_state = lex_state;
06524 switch (c = nextc()) {
06525 case '\0':
06526 case '\004':
06527 case '\032':
06528 case -1:
06529 return 0;
06530
06531
06532 case ' ': case '\t': case '\f': case '\r':
06533 case '\13':
06534 space_seen = 1;
06535 #ifdef RIPPER
06536 while ((c = nextc())) {
06537 switch (c) {
06538 case ' ': case '\t': case '\f': case '\r':
06539 case '\13':
06540 break;
06541 default:
06542 goto outofloop;
06543 }
06544 }
06545 outofloop:
06546 pushback(c);
06547 ripper_dispatch_scan_event(parser, tSP);
06548 #endif
06549 goto retry;
06550
06551 case '#':
06552
06553 if (!parser_magic_comment(parser, lex_p, lex_pend - lex_p)) {
06554 if (comment_at_top(parser)) {
06555 set_file_encoding(parser, lex_p, lex_pend);
06556 }
06557 }
06558 lex_p = lex_pend;
06559 #ifdef RIPPER
06560 ripper_dispatch_scan_event(parser, tCOMMENT);
06561 fallthru = TRUE;
06562 #endif
06563
06564 case '\n':
06565 switch (lex_state) {
06566 case EXPR_BEG:
06567 case EXPR_FNAME:
06568 case EXPR_DOT:
06569 case EXPR_CLASS:
06570 case EXPR_VALUE:
06571 #ifdef RIPPER
06572 if (!fallthru) {
06573 ripper_dispatch_scan_event(parser, tIGNORED_NL);
06574 }
06575 fallthru = FALSE;
06576 #endif
06577 goto retry;
06578 default:
06579 break;
06580 }
06581 while ((c = nextc())) {
06582 switch (c) {
06583 case ' ': case '\t': case '\f': case '\r':
06584 case '\13':
06585 space_seen = 1;
06586 break;
06587 case '.': {
06588 if ((c = nextc()) != '.') {
06589 pushback(c);
06590 pushback('.');
06591 goto retry;
06592 }
06593 }
06594 default:
06595 --ruby_sourceline;
06596 lex_nextline = lex_lastline;
06597 case -1:
06598 lex_goto_eol(parser);
06599 #ifdef RIPPER
06600 if (c != -1) {
06601 parser->tokp = lex_p;
06602 }
06603 #endif
06604 goto normal_newline;
06605 }
06606 }
06607 normal_newline:
06608 command_start = TRUE;
06609 lex_state = EXPR_BEG;
06610 return '\n';
06611
06612 case '*':
06613 if ((c = nextc()) == '*') {
06614 if ((c = nextc()) == '=') {
06615 set_yylval_id(tPOW);
06616 lex_state = EXPR_BEG;
06617 return tOP_ASGN;
06618 }
06619 pushback(c);
06620 c = tPOW;
06621 }
06622 else {
06623 if (c == '=') {
06624 set_yylval_id('*');
06625 lex_state = EXPR_BEG;
06626 return tOP_ASGN;
06627 }
06628 pushback(c);
06629 if (IS_SPCARG(c)) {
06630 rb_warning0("`*' interpreted as argument prefix");
06631 c = tSTAR;
06632 }
06633 else if (IS_BEG()) {
06634 c = tSTAR;
06635 }
06636 else {
06637 warn_balanced("*", "argument prefix");
06638 c = '*';
06639 }
06640 }
06641 switch (lex_state) {
06642 case EXPR_FNAME: case EXPR_DOT:
06643 lex_state = EXPR_ARG; break;
06644 default:
06645 lex_state = EXPR_BEG; break;
06646 }
06647 return c;
06648
06649 case '!':
06650 c = nextc();
06651 if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
06652 lex_state = EXPR_ARG;
06653 if (c == '@') {
06654 return '!';
06655 }
06656 }
06657 else {
06658 lex_state = EXPR_BEG;
06659 }
06660 if (c == '=') {
06661 return tNEQ;
06662 }
06663 if (c == '~') {
06664 return tNMATCH;
06665 }
06666 pushback(c);
06667 return '!';
06668
06669 case '=':
06670 if (was_bol()) {
06671
06672 if (strncmp(lex_p, "begin", 5) == 0 && ISSPACE(lex_p[5])) {
06673 #ifdef RIPPER
06674 int first_p = TRUE;
06675
06676 lex_goto_eol(parser);
06677 ripper_dispatch_scan_event(parser, tEMBDOC_BEG);
06678 #endif
06679 for (;;) {
06680 lex_goto_eol(parser);
06681 #ifdef RIPPER
06682 if (!first_p) {
06683 ripper_dispatch_scan_event(parser, tEMBDOC);
06684 }
06685 first_p = FALSE;
06686 #endif
06687 c = nextc();
06688 if (c == -1) {
06689 compile_error(PARSER_ARG "embedded document meets end of file");
06690 return 0;
06691 }
06692 if (c != '=') continue;
06693 if (strncmp(lex_p, "end", 3) == 0 &&
06694 (lex_p + 3 == lex_pend || ISSPACE(lex_p[3]))) {
06695 break;
06696 }
06697 }
06698 lex_goto_eol(parser);
06699 #ifdef RIPPER
06700 ripper_dispatch_scan_event(parser, tEMBDOC_END);
06701 #endif
06702 goto retry;
06703 }
06704 }
06705
06706 switch (lex_state) {
06707 case EXPR_FNAME: case EXPR_DOT:
06708 lex_state = EXPR_ARG; break;
06709 default:
06710 lex_state = EXPR_BEG; break;
06711 }
06712 if ((c = nextc()) == '=') {
06713 if ((c = nextc()) == '=') {
06714 return tEQQ;
06715 }
06716 pushback(c);
06717 return tEQ;
06718 }
06719 if (c == '~') {
06720 return tMATCH;
06721 }
06722 else if (c == '>') {
06723 return tASSOC;
06724 }
06725 pushback(c);
06726 return '=';
06727
06728 case '<':
06729 last_state = lex_state;
06730 c = nextc();
06731 if (c == '<' &&
06732 lex_state != EXPR_DOT &&
06733 lex_state != EXPR_CLASS &&
06734 !IS_END() &&
06735 (!IS_ARG() || space_seen)) {
06736 int token = heredoc_identifier();
06737 if (token) return token;
06738 }
06739 switch (lex_state) {
06740 case EXPR_FNAME: case EXPR_DOT:
06741 lex_state = EXPR_ARG; break;
06742 default:
06743 lex_state = EXPR_BEG; break;
06744 }
06745 if (c == '=') {
06746 if ((c = nextc()) == '>') {
06747 return tCMP;
06748 }
06749 pushback(c);
06750 return tLEQ;
06751 }
06752 if (c == '<') {
06753 if ((c = nextc()) == '=') {
06754 set_yylval_id(tLSHFT);
06755 lex_state = EXPR_BEG;
06756 return tOP_ASGN;
06757 }
06758 pushback(c);
06759 warn_balanced("<<", "here document");
06760 return tLSHFT;
06761 }
06762 pushback(c);
06763 return '<';
06764
06765 case '>':
06766 switch (lex_state) {
06767 case EXPR_FNAME: case EXPR_DOT:
06768 lex_state = EXPR_ARG; break;
06769 default:
06770 lex_state = EXPR_BEG; break;
06771 }
06772 if ((c = nextc()) == '=') {
06773 return tGEQ;
06774 }
06775 if (c == '>') {
06776 if ((c = nextc()) == '=') {
06777 set_yylval_id(tRSHFT);
06778 lex_state = EXPR_BEG;
06779 return tOP_ASGN;
06780 }
06781 pushback(c);
06782 return tRSHFT;
06783 }
06784 pushback(c);
06785 return '>';
06786
06787 case '"':
06788 lex_strterm = NEW_STRTERM(str_dquote, '"', 0);
06789 return tSTRING_BEG;
06790
06791 case '`':
06792 if (lex_state == EXPR_FNAME) {
06793 lex_state = EXPR_ENDFN;
06794 return c;
06795 }
06796 if (lex_state == EXPR_DOT) {
06797 if (cmd_state)
06798 lex_state = EXPR_CMDARG;
06799 else
06800 lex_state = EXPR_ARG;
06801 return c;
06802 }
06803 lex_strterm = NEW_STRTERM(str_xquote, '`', 0);
06804 return tXSTRING_BEG;
06805
06806 case '\'':
06807 lex_strterm = NEW_STRTERM(str_squote, '\'', 0);
06808 return tSTRING_BEG;
06809
06810 case '?':
06811 if (IS_END()) {
06812 lex_state = EXPR_VALUE;
06813 return '?';
06814 }
06815 c = nextc();
06816 if (c == -1) {
06817 compile_error(PARSER_ARG "incomplete character syntax");
06818 return 0;
06819 }
06820 if (rb_enc_isspace(c, parser->enc)) {
06821 if (!IS_ARG()) {
06822 int c2 = 0;
06823 switch (c) {
06824 case ' ':
06825 c2 = 's';
06826 break;
06827 case '\n':
06828 c2 = 'n';
06829 break;
06830 case '\t':
06831 c2 = 't';
06832 break;
06833 case '\v':
06834 c2 = 'v';
06835 break;
06836 case '\r':
06837 c2 = 'r';
06838 break;
06839 case '\f':
06840 c2 = 'f';
06841 break;
06842 }
06843 if (c2) {
06844 rb_warnI("invalid character syntax; use ?\\%c", c2);
06845 }
06846 }
06847 ternary:
06848 pushback(c);
06849 lex_state = EXPR_VALUE;
06850 return '?';
06851 }
06852 newtok();
06853 enc = parser->enc;
06854 if (!parser_isascii()) {
06855 if (tokadd_mbchar(c) == -1) return 0;
06856 }
06857 else if ((rb_enc_isalnum(c, parser->enc) || c == '_') &&
06858 lex_p < lex_pend && is_identchar(lex_p, lex_pend, parser->enc)) {
06859 goto ternary;
06860 }
06861 else if (c == '\\') {
06862 if (peek('u')) {
06863 nextc();
06864 c = parser_tokadd_utf8(parser, &enc, 0, 0, 0);
06865 if (0x80 <= c) {
06866 tokaddmbc(c, enc);
06867 }
06868 else {
06869 tokadd(c);
06870 }
06871 }
06872 else {
06873 c = read_escape(0, &enc);
06874 tokadd(c);
06875 }
06876 }
06877 else {
06878 tokadd(c);
06879 }
06880 tokfix();
06881 set_yylval_str(STR_NEW3(tok(), toklen(), enc, 0));
06882 lex_state = EXPR_END;
06883 return tCHAR;
06884
06885 case '&':
06886 if ((c = nextc()) == '&') {
06887 lex_state = EXPR_BEG;
06888 if ((c = nextc()) == '=') {
06889 set_yylval_id(tANDOP);
06890 lex_state = EXPR_BEG;
06891 return tOP_ASGN;
06892 }
06893 pushback(c);
06894 return tANDOP;
06895 }
06896 else if (c == '=') {
06897 set_yylval_id('&');
06898 lex_state = EXPR_BEG;
06899 return tOP_ASGN;
06900 }
06901 pushback(c);
06902 if (IS_SPCARG(c)) {
06903 rb_warning0("`&' interpreted as argument prefix");
06904 c = tAMPER;
06905 }
06906 else if (IS_BEG()) {
06907 c = tAMPER;
06908 }
06909 else {
06910 warn_balanced("&", "argument prefix");
06911 c = '&';
06912 }
06913 switch (lex_state) {
06914 case EXPR_FNAME: case EXPR_DOT:
06915 lex_state = EXPR_ARG; break;
06916 default:
06917 lex_state = EXPR_BEG;
06918 }
06919 return c;
06920
06921 case '|':
06922 if ((c = nextc()) == '|') {
06923 lex_state = EXPR_BEG;
06924 if ((c = nextc()) == '=') {
06925 set_yylval_id(tOROP);
06926 lex_state = EXPR_BEG;
06927 return tOP_ASGN;
06928 }
06929 pushback(c);
06930 return tOROP;
06931 }
06932 if (c == '=') {
06933 set_yylval_id('|');
06934 lex_state = EXPR_BEG;
06935 return tOP_ASGN;
06936 }
06937 if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
06938 lex_state = EXPR_ARG;
06939 }
06940 else {
06941 lex_state = EXPR_BEG;
06942 }
06943 pushback(c);
06944 return '|';
06945
06946 case '+':
06947 c = nextc();
06948 if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
06949 lex_state = EXPR_ARG;
06950 if (c == '@') {
06951 return tUPLUS;
06952 }
06953 pushback(c);
06954 return '+';
06955 }
06956 if (c == '=') {
06957 set_yylval_id('+');
06958 lex_state = EXPR_BEG;
06959 return tOP_ASGN;
06960 }
06961 if (IS_BEG() || (IS_SPCARG(c) && arg_ambiguous())) {
06962 lex_state = EXPR_BEG;
06963 pushback(c);
06964 if (c != -1 && ISDIGIT(c)) {
06965 c = '+';
06966 goto start_num;
06967 }
06968 return tUPLUS;
06969 }
06970 lex_state = EXPR_BEG;
06971 pushback(c);
06972 warn_balanced("+", "unary operator");
06973 return '+';
06974
06975 case '-':
06976 c = nextc();
06977 if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
06978 lex_state = EXPR_ARG;
06979 if (c == '@') {
06980 return tUMINUS;
06981 }
06982 pushback(c);
06983 return '-';
06984 }
06985 if (c == '=') {
06986 set_yylval_id('-');
06987 lex_state = EXPR_BEG;
06988 return tOP_ASGN;
06989 }
06990 if (c == '>') {
06991 lex_state = EXPR_ARG;
06992 return tLAMBDA;
06993 }
06994 if (IS_BEG() || (IS_SPCARG(c) && arg_ambiguous())) {
06995 lex_state = EXPR_BEG;
06996 pushback(c);
06997 if (c != -1 && ISDIGIT(c)) {
06998 return tUMINUS_NUM;
06999 }
07000 return tUMINUS;
07001 }
07002 lex_state = EXPR_BEG;
07003 pushback(c);
07004 warn_balanced("-", "unary operator");
07005 return '-';
07006
07007 case '.':
07008 lex_state = EXPR_BEG;
07009 if ((c = nextc()) == '.') {
07010 if ((c = nextc()) == '.') {
07011 return tDOT3;
07012 }
07013 pushback(c);
07014 return tDOT2;
07015 }
07016 pushback(c);
07017 if (c != -1 && ISDIGIT(c)) {
07018 yyerror("no .<digit> floating literal anymore; put 0 before dot");
07019 }
07020 lex_state = EXPR_DOT;
07021 return '.';
07022
07023 start_num:
07024 case '0': case '1': case '2': case '3': case '4':
07025 case '5': case '6': case '7': case '8': case '9':
07026 {
07027 int is_float, seen_point, seen_e, nondigit;
07028
07029 is_float = seen_point = seen_e = nondigit = 0;
07030 lex_state = EXPR_END;
07031 newtok();
07032 if (c == '-' || c == '+') {
07033 tokadd(c);
07034 c = nextc();
07035 }
07036 if (c == '0') {
07037 #define no_digits() do {yyerror("numeric literal without digits"); return 0;} while (0)
07038 int start = toklen();
07039 c = nextc();
07040 if (c == 'x' || c == 'X') {
07041
07042 c = nextc();
07043 if (c != -1 && ISXDIGIT(c)) {
07044 do {
07045 if (c == '_') {
07046 if (nondigit) break;
07047 nondigit = c;
07048 continue;
07049 }
07050 if (!ISXDIGIT(c)) break;
07051 nondigit = 0;
07052 tokadd(c);
07053 } while ((c = nextc()) != -1);
07054 }
07055 pushback(c);
07056 tokfix();
07057 if (toklen() == start) {
07058 no_digits();
07059 }
07060 else if (nondigit) goto trailing_uc;
07061 set_yylval_literal(rb_cstr_to_inum(tok(), 16, FALSE));
07062 return tINTEGER;
07063 }
07064 if (c == 'b' || c == 'B') {
07065
07066 c = nextc();
07067 if (c == '0' || c == '1') {
07068 do {
07069 if (c == '_') {
07070 if (nondigit) break;
07071 nondigit = c;
07072 continue;
07073 }
07074 if (c != '0' && c != '1') break;
07075 nondigit = 0;
07076 tokadd(c);
07077 } while ((c = nextc()) != -1);
07078 }
07079 pushback(c);
07080 tokfix();
07081 if (toklen() == start) {
07082 no_digits();
07083 }
07084 else if (nondigit) goto trailing_uc;
07085 set_yylval_literal(rb_cstr_to_inum(tok(), 2, FALSE));
07086 return tINTEGER;
07087 }
07088 if (c == 'd' || c == 'D') {
07089
07090 c = nextc();
07091 if (c != -1 && ISDIGIT(c)) {
07092 do {
07093 if (c == '_') {
07094 if (nondigit) break;
07095 nondigit = c;
07096 continue;
07097 }
07098 if (!ISDIGIT(c)) break;
07099 nondigit = 0;
07100 tokadd(c);
07101 } while ((c = nextc()) != -1);
07102 }
07103 pushback(c);
07104 tokfix();
07105 if (toklen() == start) {
07106 no_digits();
07107 }
07108 else if (nondigit) goto trailing_uc;
07109 set_yylval_literal(rb_cstr_to_inum(tok(), 10, FALSE));
07110 return tINTEGER;
07111 }
07112 if (c == '_') {
07113
07114 goto octal_number;
07115 }
07116 if (c == 'o' || c == 'O') {
07117
07118 c = nextc();
07119 if (c == -1 || c == '_' || !ISDIGIT(c)) {
07120 no_digits();
07121 }
07122 }
07123 if (c >= '0' && c <= '7') {
07124
07125 octal_number:
07126 do {
07127 if (c == '_') {
07128 if (nondigit) break;
07129 nondigit = c;
07130 continue;
07131 }
07132 if (c < '0' || c > '9') break;
07133 if (c > '7') goto invalid_octal;
07134 nondigit = 0;
07135 tokadd(c);
07136 } while ((c = nextc()) != -1);
07137 if (toklen() > start) {
07138 pushback(c);
07139 tokfix();
07140 if (nondigit) goto trailing_uc;
07141 set_yylval_literal(rb_cstr_to_inum(tok(), 8, FALSE));
07142 return tINTEGER;
07143 }
07144 if (nondigit) {
07145 pushback(c);
07146 goto trailing_uc;
07147 }
07148 }
07149 if (c > '7' && c <= '9') {
07150 invalid_octal:
07151 yyerror("Invalid octal digit");
07152 }
07153 else if (c == '.' || c == 'e' || c == 'E') {
07154 tokadd('0');
07155 }
07156 else {
07157 pushback(c);
07158 set_yylval_literal(INT2FIX(0));
07159 return tINTEGER;
07160 }
07161 }
07162
07163 for (;;) {
07164 switch (c) {
07165 case '0': case '1': case '2': case '3': case '4':
07166 case '5': case '6': case '7': case '8': case '9':
07167 nondigit = 0;
07168 tokadd(c);
07169 break;
07170
07171 case '.':
07172 if (nondigit) goto trailing_uc;
07173 if (seen_point || seen_e) {
07174 goto decode_num;
07175 }
07176 else {
07177 int c0 = nextc();
07178 if (c0 == -1 || !ISDIGIT(c0)) {
07179 pushback(c0);
07180 goto decode_num;
07181 }
07182 c = c0;
07183 }
07184 tokadd('.');
07185 tokadd(c);
07186 is_float++;
07187 seen_point++;
07188 nondigit = 0;
07189 break;
07190
07191 case 'e':
07192 case 'E':
07193 if (nondigit) {
07194 pushback(c);
07195 c = nondigit;
07196 goto decode_num;
07197 }
07198 if (seen_e) {
07199 goto decode_num;
07200 }
07201 tokadd(c);
07202 seen_e++;
07203 is_float++;
07204 nondigit = c;
07205 c = nextc();
07206 if (c != '-' && c != '+') continue;
07207 tokadd(c);
07208 nondigit = c;
07209 break;
07210
07211 case '_':
07212 if (nondigit) goto decode_num;
07213 nondigit = c;
07214 break;
07215
07216 default:
07217 goto decode_num;
07218 }
07219 c = nextc();
07220 }
07221
07222 decode_num:
07223 pushback(c);
07224 if (nondigit) {
07225 char tmp[30];
07226 trailing_uc:
07227 snprintf(tmp, sizeof(tmp), "trailing `%c' in number", nondigit);
07228 yyerror(tmp);
07229 }
07230 tokfix();
07231 if (is_float) {
07232 double d = strtod(tok(), 0);
07233 if (errno == ERANGE) {
07234 rb_warningS("Float %s out of range", tok());
07235 errno = 0;
07236 }
07237 set_yylval_literal(DBL2NUM(d));
07238 return tFLOAT;
07239 }
07240 set_yylval_literal(rb_cstr_to_inum(tok(), 10, FALSE));
07241 return tINTEGER;
07242 }
07243
07244 case ')':
07245 case ']':
07246 paren_nest--;
07247 case '}':
07248 COND_LEXPOP();
07249 CMDARG_LEXPOP();
07250 if (c == ')')
07251 lex_state = EXPR_ENDFN;
07252 else
07253 lex_state = EXPR_ENDARG;
07254 return c;
07255
07256 case ':':
07257 c = nextc();
07258 if (c == ':') {
07259 if (IS_BEG() || lex_state == EXPR_CLASS || IS_SPCARG(-1)) {
07260 lex_state = EXPR_BEG;
07261 return tCOLON3;
07262 }
07263 lex_state = EXPR_DOT;
07264 return tCOLON2;
07265 }
07266 if (IS_END() || ISSPACE(c)) {
07267 pushback(c);
07268 warn_balanced(":", "symbol literal");
07269 lex_state = EXPR_BEG;
07270 return ':';
07271 }
07272 switch (c) {
07273 case '\'':
07274 lex_strterm = NEW_STRTERM(str_ssym, c, 0);
07275 break;
07276 case '"':
07277 lex_strterm = NEW_STRTERM(str_dsym, c, 0);
07278 break;
07279 default:
07280 pushback(c);
07281 break;
07282 }
07283 lex_state = EXPR_FNAME;
07284 return tSYMBEG;
07285
07286 case '/':
07287 if (IS_BEG()) {
07288 lex_strterm = NEW_STRTERM(str_regexp, '/', 0);
07289 return tREGEXP_BEG;
07290 }
07291 if ((c = nextc()) == '=') {
07292 set_yylval_id('/');
07293 lex_state = EXPR_BEG;
07294 return tOP_ASGN;
07295 }
07296 pushback(c);
07297 if (IS_SPCARG(c)) {
07298 arg_ambiguous();
07299 lex_strterm = NEW_STRTERM(str_regexp, '/', 0);
07300 return tREGEXP_BEG;
07301 }
07302 switch (lex_state) {
07303 case EXPR_FNAME: case EXPR_DOT:
07304 lex_state = EXPR_ARG; break;
07305 default:
07306 lex_state = EXPR_BEG; break;
07307 }
07308 warn_balanced("/", "regexp literal");
07309 return '/';
07310
07311 case '^':
07312 if ((c = nextc()) == '=') {
07313 set_yylval_id('^');
07314 lex_state = EXPR_BEG;
07315 return tOP_ASGN;
07316 }
07317 switch (lex_state) {
07318 case EXPR_FNAME: case EXPR_DOT:
07319 lex_state = EXPR_ARG; break;
07320 default:
07321 lex_state = EXPR_BEG; break;
07322 }
07323 pushback(c);
07324 return '^';
07325
07326 case ';':
07327 lex_state = EXPR_BEG;
07328 command_start = TRUE;
07329 return ';';
07330
07331 case ',':
07332 lex_state = EXPR_BEG;
07333 return ',';
07334
07335 case '~':
07336 if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
07337 if ((c = nextc()) != '@') {
07338 pushback(c);
07339 }
07340 lex_state = EXPR_ARG;
07341 }
07342 else {
07343 lex_state = EXPR_BEG;
07344 }
07345 return '~';
07346
07347 case '(':
07348 if (IS_BEG()) {
07349 c = tLPAREN;
07350 }
07351 else if (IS_SPCARG(-1)) {
07352 c = tLPAREN_ARG;
07353 }
07354 paren_nest++;
07355 COND_PUSH(0);
07356 CMDARG_PUSH(0);
07357 lex_state = EXPR_BEG;
07358 return c;
07359
07360 case '[':
07361 paren_nest++;
07362 if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
07363 lex_state = EXPR_ARG;
07364 if ((c = nextc()) == ']') {
07365 if ((c = nextc()) == '=') {
07366 return tASET;
07367 }
07368 pushback(c);
07369 return tAREF;
07370 }
07371 pushback(c);
07372 return '[';
07373 }
07374 else if (IS_BEG()) {
07375 c = tLBRACK;
07376 }
07377 else if (IS_ARG() && space_seen) {
07378 c = tLBRACK;
07379 }
07380 lex_state = EXPR_BEG;
07381 COND_PUSH(0);
07382 CMDARG_PUSH(0);
07383 return c;
07384
07385 case '{':
07386 if (lpar_beg && lpar_beg == paren_nest) {
07387 lex_state = EXPR_BEG;
07388 lpar_beg = 0;
07389 --paren_nest;
07390 COND_PUSH(0);
07391 CMDARG_PUSH(0);
07392 return tLAMBEG;
07393 }
07394 if (IS_ARG() || lex_state == EXPR_END || lex_state == EXPR_ENDFN)
07395 c = '{';
07396 else if (lex_state == EXPR_ENDARG)
07397 c = tLBRACE_ARG;
07398 else
07399 c = tLBRACE;
07400 COND_PUSH(0);
07401 CMDARG_PUSH(0);
07402 lex_state = EXPR_BEG;
07403 if (c != tLBRACE) command_start = TRUE;
07404 return c;
07405
07406 case '\\':
07407 c = nextc();
07408 if (c == '\n') {
07409 space_seen = 1;
07410 #ifdef RIPPER
07411 ripper_dispatch_scan_event(parser, tSP);
07412 #endif
07413 goto retry;
07414 }
07415 pushback(c);
07416 return '\\';
07417
07418 case '%':
07419 if (IS_BEG()) {
07420 int term;
07421 int paren;
07422
07423 c = nextc();
07424 quotation:
07425 if (c == -1 || !ISALNUM(c)) {
07426 term = c;
07427 c = 'Q';
07428 }
07429 else {
07430 term = nextc();
07431 if (rb_enc_isalnum(term, parser->enc) || !parser_isascii()) {
07432 yyerror("unknown type of %string");
07433 return 0;
07434 }
07435 }
07436 if (c == -1 || term == -1) {
07437 compile_error(PARSER_ARG "unterminated quoted string meets end of file");
07438 return 0;
07439 }
07440 paren = term;
07441 if (term == '(') term = ')';
07442 else if (term == '[') term = ']';
07443 else if (term == '{') term = '}';
07444 else if (term == '<') term = '>';
07445 else paren = 0;
07446
07447 switch (c) {
07448 case 'Q':
07449 lex_strterm = NEW_STRTERM(str_dquote, term, paren);
07450 return tSTRING_BEG;
07451
07452 case 'q':
07453 lex_strterm = NEW_STRTERM(str_squote, term, paren);
07454 return tSTRING_BEG;
07455
07456 case 'W':
07457 lex_strterm = NEW_STRTERM(str_dword, term, paren);
07458 do {c = nextc();} while (ISSPACE(c));
07459 pushback(c);
07460 return tWORDS_BEG;
07461
07462 case 'w':
07463 lex_strterm = NEW_STRTERM(str_sword, term, paren);
07464 do {c = nextc();} while (ISSPACE(c));
07465 pushback(c);
07466 return tQWORDS_BEG;
07467
07468 case 'x':
07469 lex_strterm = NEW_STRTERM(str_xquote, term, paren);
07470 return tXSTRING_BEG;
07471
07472 case 'r':
07473 lex_strterm = NEW_STRTERM(str_regexp, term, paren);
07474 return tREGEXP_BEG;
07475
07476 case 's':
07477 lex_strterm = NEW_STRTERM(str_ssym, term, paren);
07478 lex_state = EXPR_FNAME;
07479 return tSYMBEG;
07480
07481 default:
07482 yyerror("unknown type of %string");
07483 return 0;
07484 }
07485 }
07486 if ((c = nextc()) == '=') {
07487 set_yylval_id('%');
07488 lex_state = EXPR_BEG;
07489 return tOP_ASGN;
07490 }
07491 if (IS_SPCARG(c)) {
07492 goto quotation;
07493 }
07494 switch (lex_state) {
07495 case EXPR_FNAME: case EXPR_DOT:
07496 lex_state = EXPR_ARG; break;
07497 default:
07498 lex_state = EXPR_BEG; break;
07499 }
07500 pushback(c);
07501 warn_balanced("%%", "string literal");
07502 return '%';
07503
07504 case '$':
07505 lex_state = EXPR_END;
07506 newtok();
07507 c = nextc();
07508 switch (c) {
07509 case '_':
07510 c = nextc();
07511 if (parser_is_identchar()) {
07512 tokadd('$');
07513 tokadd('_');
07514 break;
07515 }
07516 pushback(c);
07517 c = '_';
07518
07519 case '~':
07520 case '*':
07521 case '$':
07522 case '?':
07523 case '!':
07524 case '@':
07525 case '/':
07526 case '\\':
07527 case ';':
07528 case ',':
07529 case '.':
07530 case '=':
07531 case ':':
07532 case '<':
07533 case '>':
07534 case '\"':
07535 tokadd('$');
07536 tokadd(c);
07537 tokfix();
07538 set_yylval_name(rb_intern(tok()));
07539 return tGVAR;
07540
07541 case '-':
07542 tokadd('$');
07543 tokadd(c);
07544 c = nextc();
07545 if (parser_is_identchar()) {
07546 if (tokadd_mbchar(c) == -1) return 0;
07547 }
07548 else {
07549 pushback(c);
07550 }
07551 gvar:
07552 tokfix();
07553 set_yylval_name(rb_intern(tok()));
07554 return tGVAR;
07555
07556 case '&':
07557 case '`':
07558 case '\'':
07559 case '+':
07560 if (last_state == EXPR_FNAME) {
07561 tokadd('$');
07562 tokadd(c);
07563 goto gvar;
07564 }
07565 set_yylval_node(NEW_BACK_REF(c));
07566 return tBACK_REF;
07567
07568 case '1': case '2': case '3':
07569 case '4': case '5': case '6':
07570 case '7': case '8': case '9':
07571 tokadd('$');
07572 do {
07573 tokadd(c);
07574 c = nextc();
07575 } while (c != -1 && ISDIGIT(c));
07576 pushback(c);
07577 if (last_state == EXPR_FNAME) goto gvar;
07578 tokfix();
07579 set_yylval_node(NEW_NTH_REF(atoi(tok()+1)));
07580 return tNTH_REF;
07581
07582 default:
07583 if (!parser_is_identchar()) {
07584 pushback(c);
07585 return '$';
07586 }
07587 case '0':
07588 tokadd('$');
07589 }
07590 break;
07591
07592 case '@':
07593 c = nextc();
07594 newtok();
07595 tokadd('@');
07596 if (c == '@') {
07597 tokadd('@');
07598 c = nextc();
07599 }
07600 if (c != -1 && ISDIGIT(c)) {
07601 if (tokidx == 1) {
07602 compile_error(PARSER_ARG "`@%c' is not allowed as an instance variable name", c);
07603 }
07604 else {
07605 compile_error(PARSER_ARG "`@@%c' is not allowed as a class variable name", c);
07606 }
07607 return 0;
07608 }
07609 if (!parser_is_identchar()) {
07610 pushback(c);
07611 return '@';
07612 }
07613 break;
07614
07615 case '_':
07616 if (was_bol() && whole_match_p("__END__", 7, 0)) {
07617 ruby__end__seen = 1;
07618 parser->eofp = Qtrue;
07619 #ifndef RIPPER
07620 return -1;
07621 #else
07622 lex_goto_eol(parser);
07623 ripper_dispatch_scan_event(parser, k__END__);
07624 return 0;
07625 #endif
07626 }
07627 newtok();
07628 break;
07629
07630 default:
07631 if (!parser_is_identchar()) {
07632 rb_compile_error(PARSER_ARG "Invalid char `\\x%02X' in expression", c);
07633 goto retry;
07634 }
07635
07636 newtok();
07637 break;
07638 }
07639
07640 mb = ENC_CODERANGE_7BIT;
07641 do {
07642 if (!ISASCII(c)) mb = ENC_CODERANGE_UNKNOWN;
07643 if (tokadd_mbchar(c) == -1) return 0;
07644 c = nextc();
07645 } while (parser_is_identchar());
07646 switch (tok()[0]) {
07647 case '@': case '$':
07648 pushback(c);
07649 break;
07650 default:
07651 if ((c == '!' || c == '?') && !peek('=')) {
07652 tokadd(c);
07653 }
07654 else {
07655 pushback(c);
07656 }
07657 }
07658 tokfix();
07659
07660 {
07661 int result = 0;
07662
07663 last_state = lex_state;
07664 switch (tok()[0]) {
07665 case '$':
07666 lex_state = EXPR_END;
07667 result = tGVAR;
07668 break;
07669 case '@':
07670 lex_state = EXPR_END;
07671 if (tok()[1] == '@')
07672 result = tCVAR;
07673 else
07674 result = tIVAR;
07675 break;
07676
07677 default:
07678 if (toklast() == '!' || toklast() == '?') {
07679 result = tFID;
07680 }
07681 else {
07682 if (lex_state == EXPR_FNAME) {
07683 if ((c = nextc()) == '=' && !peek('~') && !peek('>') &&
07684 (!peek('=') || (lex_p + 1 < lex_pend && lex_p[1] == '>'))) {
07685 result = tIDENTIFIER;
07686 tokadd(c);
07687 tokfix();
07688 }
07689 else {
07690 pushback(c);
07691 }
07692 }
07693 if (result == 0 && ISUPPER(tok()[0])) {
07694 result = tCONSTANT;
07695 }
07696 else {
07697 result = tIDENTIFIER;
07698 }
07699 }
07700
07701 if ((lex_state == EXPR_BEG && !cmd_state) ||
07702 IS_ARG()) {
07703 if (peek(':') && !(lex_p + 1 < lex_pend && lex_p[1] == ':')) {
07704 lex_state = EXPR_BEG;
07705 nextc();
07706 set_yylval_name(TOK_INTERN(!ENC_SINGLE(mb)));
07707 return tLABEL;
07708 }
07709 }
07710 if (mb == ENC_CODERANGE_7BIT && lex_state != EXPR_DOT) {
07711 const struct kwtable *kw;
07712
07713
07714 kw = rb_reserved_word(tok(), toklen());
07715 if (kw) {
07716 enum lex_state_e state = lex_state;
07717 lex_state = kw->state;
07718 if (state == EXPR_FNAME) {
07719 set_yylval_name(rb_intern(kw->name));
07720 return kw->id[0];
07721 }
07722 if (kw->id[0] == keyword_do) {
07723 command_start = TRUE;
07724 if (lpar_beg && lpar_beg == paren_nest) {
07725 lpar_beg = 0;
07726 --paren_nest;
07727 return keyword_do_LAMBDA;
07728 }
07729 if (COND_P()) return keyword_do_cond;
07730 if (CMDARG_P() && state != EXPR_CMDARG)
07731 return keyword_do_block;
07732 if (state == EXPR_ENDARG || state == EXPR_BEG)
07733 return keyword_do_block;
07734 return keyword_do;
07735 }
07736 if (state == EXPR_BEG || state == EXPR_VALUE)
07737 return kw->id[0];
07738 else {
07739 if (kw->id[0] != kw->id[1])
07740 lex_state = EXPR_BEG;
07741 return kw->id[1];
07742 }
07743 }
07744 }
07745
07746 if (IS_BEG() ||
07747 lex_state == EXPR_DOT ||
07748 IS_ARG()) {
07749 if (cmd_state) {
07750 lex_state = EXPR_CMDARG;
07751 }
07752 else {
07753 lex_state = EXPR_ARG;
07754 }
07755 }
07756 else if (lex_state == EXPR_FNAME) {
07757 lex_state = EXPR_ENDFN;
07758 }
07759 else {
07760 lex_state = EXPR_END;
07761 }
07762 }
07763 {
07764 ID ident = TOK_INTERN(!ENC_SINGLE(mb));
07765
07766 set_yylval_name(ident);
07767 if (last_state != EXPR_DOT && is_local_id(ident) && lvar_defined(ident)) {
07768 lex_state = EXPR_END;
07769 }
07770 }
07771 return result;
07772 }
07773 }
07774
07775 #if YYPURE
07776 static int
07777 yylex(void *lval, void *p)
07778 #else
07779 yylex(void *p)
07780 #endif
07781 {
07782 struct parser_params *parser = (struct parser_params*)p;
07783 int t;
07784
07785 #if YYPURE
07786 parser->parser_yylval = lval;
07787 parser->parser_yylval->val = Qundef;
07788 #endif
07789 t = parser_yylex(parser);
07790 #ifdef RIPPER
07791 if (!NIL_P(parser->delayed)) {
07792 ripper_dispatch_delayed_token(parser, t);
07793 }
07794 if (t != 0)
07795 ripper_dispatch_scan_event(parser, t);
07796 #endif
07797
07798 return t;
07799 }
07800
07801 #ifndef RIPPER
07802 static NODE*
07803 node_newnode(struct parser_params *parser, enum node_type type, VALUE a0, VALUE a1, VALUE a2)
07804 {
07805 NODE *n = (rb_node_newnode)(type, a0, a1, a2);
07806 nd_set_line(n, ruby_sourceline);
07807 return n;
07808 }
07809
07810 enum node_type
07811 nodetype(NODE *node)
07812 {
07813 return (enum node_type)nd_type(node);
07814 }
07815
07816 int
07817 nodeline(NODE *node)
07818 {
07819 return nd_line(node);
07820 }
07821
07822 static NODE*
07823 newline_node(NODE *node)
07824 {
07825 if (node) {
07826 node = remove_begin(node);
07827 node->flags |= NODE_FL_NEWLINE;
07828 }
07829 return node;
07830 }
07831
07832 static void
07833 fixpos(NODE *node, NODE *orig)
07834 {
07835 if (!node) return;
07836 if (!orig) return;
07837 if (orig == (NODE*)1) return;
07838 nd_set_line(node, nd_line(orig));
07839 }
07840
07841 static void
07842 parser_warning(struct parser_params *parser, NODE *node, const char *mesg)
07843 {
07844 rb_compile_warning(ruby_sourcefile, nd_line(node), "%s", mesg);
07845 }
07846 #define parser_warning(node, mesg) parser_warning(parser, node, mesg)
07847
07848 static void
07849 parser_warn(struct parser_params *parser, NODE *node, const char *mesg)
07850 {
07851 rb_compile_warn(ruby_sourcefile, nd_line(node), "%s", mesg);
07852 }
07853 #define parser_warn(node, mesg) parser_warn(parser, node, mesg)
07854
07855 static NODE*
07856 block_append_gen(struct parser_params *parser, NODE *head, NODE *tail)
07857 {
07858 NODE *end, *h = head, *nd;
07859
07860 if (tail == 0) return head;
07861
07862 if (h == 0) return tail;
07863 switch (nd_type(h)) {
07864 case NODE_LIT:
07865 case NODE_STR:
07866 case NODE_SELF:
07867 case NODE_TRUE:
07868 case NODE_FALSE:
07869 case NODE_NIL:
07870 parser_warning(h, "unused literal ignored");
07871 return tail;
07872 default:
07873 h = end = NEW_BLOCK(head);
07874 end->nd_end = end;
07875 fixpos(end, head);
07876 head = end;
07877 break;
07878 case NODE_BLOCK:
07879 end = h->nd_end;
07880 break;
07881 }
07882
07883 nd = end->nd_head;
07884 switch (nd_type(nd)) {
07885 case NODE_RETURN:
07886 case NODE_BREAK:
07887 case NODE_NEXT:
07888 case NODE_REDO:
07889 case NODE_RETRY:
07890 if (RTEST(ruby_verbose)) {
07891 parser_warning(nd, "statement not reached");
07892 }
07893 break;
07894
07895 default:
07896 break;
07897 }
07898
07899 if (nd_type(tail) != NODE_BLOCK) {
07900 tail = NEW_BLOCK(tail);
07901 tail->nd_end = tail;
07902 }
07903 end->nd_next = tail;
07904 h->nd_end = tail->nd_end;
07905 return head;
07906 }
07907
07908
07909 static NODE*
07910 list_append_gen(struct parser_params *parser, NODE *list, NODE *item)
07911 {
07912 NODE *last;
07913
07914 if (list == 0) return NEW_LIST(item);
07915 if (list->nd_next) {
07916 last = list->nd_next->nd_end;
07917 }
07918 else {
07919 last = list;
07920 }
07921
07922 list->nd_alen += 1;
07923 last->nd_next = NEW_LIST(item);
07924 list->nd_next->nd_end = last->nd_next;
07925 return list;
07926 }
07927
07928
07929 static NODE*
07930 list_concat_gen(struct parser_params *parser, NODE *head, NODE *tail)
07931 {
07932 NODE *last;
07933
07934 if (head->nd_next) {
07935 last = head->nd_next->nd_end;
07936 }
07937 else {
07938 last = head;
07939 }
07940
07941 head->nd_alen += tail->nd_alen;
07942 last->nd_next = tail;
07943 if (tail->nd_next) {
07944 head->nd_next->nd_end = tail->nd_next->nd_end;
07945 }
07946 else {
07947 head->nd_next->nd_end = tail;
07948 }
07949
07950 return head;
07951 }
07952
07953 static int
07954 literal_concat0(struct parser_params *parser, VALUE head, VALUE tail)
07955 {
07956 if (NIL_P(tail)) return 1;
07957 if (!rb_enc_compatible(head, tail)) {
07958 compile_error(PARSER_ARG "string literal encodings differ (%s / %s)",
07959 rb_enc_name(rb_enc_get(head)),
07960 rb_enc_name(rb_enc_get(tail)));
07961 rb_str_resize(head, 0);
07962 rb_str_resize(tail, 0);
07963 return 0;
07964 }
07965 rb_str_buf_append(head, tail);
07966 return 1;
07967 }
07968
07969
07970 static NODE *
07971 literal_concat_gen(struct parser_params *parser, NODE *head, NODE *tail)
07972 {
07973 enum node_type htype;
07974
07975 if (!head) return tail;
07976 if (!tail) return head;
07977
07978 htype = nd_type(head);
07979 if (htype == NODE_EVSTR) {
07980 NODE *node = NEW_DSTR(Qnil);
07981 head = list_append(node, head);
07982 }
07983 switch (nd_type(tail)) {
07984 case NODE_STR:
07985 if (htype == NODE_STR) {
07986 if (!literal_concat0(parser, head->nd_lit, tail->nd_lit)) {
07987 error:
07988 rb_gc_force_recycle((VALUE)head);
07989 rb_gc_force_recycle((VALUE)tail);
07990 return 0;
07991 }
07992 rb_gc_force_recycle((VALUE)tail);
07993 }
07994 else {
07995 list_append(head, tail);
07996 }
07997 break;
07998
07999 case NODE_DSTR:
08000 if (htype == NODE_STR) {
08001 if (!literal_concat0(parser, head->nd_lit, tail->nd_lit))
08002 goto error;
08003 tail->nd_lit = head->nd_lit;
08004 rb_gc_force_recycle((VALUE)head);
08005 head = tail;
08006 }
08007 else if (NIL_P(tail->nd_lit)) {
08008 head->nd_alen += tail->nd_alen - 1;
08009 head->nd_next->nd_end->nd_next = tail->nd_next;
08010 head->nd_next->nd_end = tail->nd_next->nd_end;
08011 rb_gc_force_recycle((VALUE)tail);
08012 }
08013 else {
08014 nd_set_type(tail, NODE_ARRAY);
08015 tail->nd_head = NEW_STR(tail->nd_lit);
08016 list_concat(head, tail);
08017 }
08018 break;
08019
08020 case NODE_EVSTR:
08021 if (htype == NODE_STR) {
08022 nd_set_type(head, NODE_DSTR);
08023 head->nd_alen = 1;
08024 }
08025 list_append(head, tail);
08026 break;
08027 }
08028 return head;
08029 }
08030
08031 static NODE *
08032 evstr2dstr_gen(struct parser_params *parser, NODE *node)
08033 {
08034 if (nd_type(node) == NODE_EVSTR) {
08035 node = list_append(NEW_DSTR(Qnil), node);
08036 }
08037 return node;
08038 }
08039
08040 static NODE *
08041 new_evstr_gen(struct parser_params *parser, NODE *node)
08042 {
08043 NODE *head = node;
08044
08045 if (node) {
08046 switch (nd_type(node)) {
08047 case NODE_STR: case NODE_DSTR: case NODE_EVSTR:
08048 return node;
08049 }
08050 }
08051 return NEW_EVSTR(head);
08052 }
08053
08054 static NODE *
08055 call_bin_op_gen(struct parser_params *parser, NODE *recv, ID id, NODE *arg1)
08056 {
08057 value_expr(recv);
08058 value_expr(arg1);
08059 return NEW_CALL(recv, id, NEW_LIST(arg1));
08060 }
08061
08062 static NODE *
08063 call_uni_op_gen(struct parser_params *parser, NODE *recv, ID id)
08064 {
08065 value_expr(recv);
08066 return NEW_CALL(recv, id, 0);
08067 }
08068
08069 static NODE*
08070 match_op_gen(struct parser_params *parser, NODE *node1, NODE *node2)
08071 {
08072 value_expr(node1);
08073 value_expr(node2);
08074 if (node1) {
08075 switch (nd_type(node1)) {
08076 case NODE_DREGX:
08077 case NODE_DREGX_ONCE:
08078 return NEW_MATCH2(node1, node2);
08079
08080 case NODE_LIT:
08081 if (TYPE(node1->nd_lit) == T_REGEXP) {
08082 return NEW_MATCH2(node1, node2);
08083 }
08084 }
08085 }
08086
08087 if (node2) {
08088 switch (nd_type(node2)) {
08089 case NODE_DREGX:
08090 case NODE_DREGX_ONCE:
08091 return NEW_MATCH3(node2, node1);
08092
08093 case NODE_LIT:
08094 if (TYPE(node2->nd_lit) == T_REGEXP) {
08095 return NEW_MATCH3(node2, node1);
08096 }
08097 }
08098 }
08099
08100 return NEW_CALL(node1, tMATCH, NEW_LIST(node2));
08101 }
08102
08103 static NODE*
08104 gettable_gen(struct parser_params *parser, ID id)
08105 {
08106 if (id == keyword_self) {
08107 return NEW_SELF();
08108 }
08109 else if (id == keyword_nil) {
08110 return NEW_NIL();
08111 }
08112 else if (id == keyword_true) {
08113 return NEW_TRUE();
08114 }
08115 else if (id == keyword_false) {
08116 return NEW_FALSE();
08117 }
08118 else if (id == keyword__FILE__) {
08119 return NEW_STR(rb_external_str_new_with_enc(ruby_sourcefile, strlen(ruby_sourcefile),
08120 rb_filesystem_encoding()));
08121 }
08122 else if (id == keyword__LINE__) {
08123 return NEW_LIT(INT2FIX(ruby_sourceline));
08124 }
08125 else if (id == keyword__ENCODING__) {
08126 return NEW_LIT(rb_enc_from_encoding(parser->enc));
08127 }
08128 else if (is_local_id(id)) {
08129 if (dyna_in_block() && dvar_defined(id)) return NEW_DVAR(id);
08130 if (local_id(id)) return NEW_LVAR(id);
08131
08132 return NEW_VCALL(id);
08133 }
08134 else if (is_global_id(id)) {
08135 return NEW_GVAR(id);
08136 }
08137 else if (is_instance_id(id)) {
08138 return NEW_IVAR(id);
08139 }
08140 else if (is_const_id(id)) {
08141 return NEW_CONST(id);
08142 }
08143 else if (is_class_id(id)) {
08144 return NEW_CVAR(id);
08145 }
08146 compile_error(PARSER_ARG "identifier %s is not valid to get", rb_id2name(id));
08147 return 0;
08148 }
08149 #endif
08150
08151 #ifdef RIPPER
08152 static VALUE
08153 assignable_gen(struct parser_params *parser, VALUE lhs)
08154 #else
08155 static NODE*
08156 assignable_gen(struct parser_params *parser, ID id, NODE *val)
08157 #endif
08158 {
08159 #ifdef RIPPER
08160 ID id = get_id(lhs);
08161 # define assignable_result(x) get_value(lhs)
08162 # define parser_yyerror(parser, x) dispatch1(assign_error, lhs)
08163 #else
08164 # define assignable_result(x) x
08165 #endif
08166 if (!id) return assignable_result(0);
08167 if (id == keyword_self) {
08168 yyerror("Can't change the value of self");
08169 }
08170 else if (id == keyword_nil) {
08171 yyerror("Can't assign to nil");
08172 }
08173 else if (id == keyword_true) {
08174 yyerror("Can't assign to true");
08175 }
08176 else if (id == keyword_false) {
08177 yyerror("Can't assign to false");
08178 }
08179 else if (id == keyword__FILE__) {
08180 yyerror("Can't assign to __FILE__");
08181 }
08182 else if (id == keyword__LINE__) {
08183 yyerror("Can't assign to __LINE__");
08184 }
08185 else if (id == keyword__ENCODING__) {
08186 yyerror("Can't assign to __ENCODING__");
08187 }
08188 else if (is_local_id(id)) {
08189 if (dyna_in_block()) {
08190 if (dvar_curr(id)) {
08191 return assignable_result(NEW_DASGN_CURR(id, val));
08192 }
08193 else if (dvar_defined(id)) {
08194 return assignable_result(NEW_DASGN(id, val));
08195 }
08196 else if (local_id(id)) {
08197 return assignable_result(NEW_LASGN(id, val));
08198 }
08199 else {
08200 dyna_var(id);
08201 return assignable_result(NEW_DASGN_CURR(id, val));
08202 }
08203 }
08204 else {
08205 if (!local_id(id)) {
08206 local_var(id);
08207 }
08208 return assignable_result(NEW_LASGN(id, val));
08209 }
08210 }
08211 else if (is_global_id(id)) {
08212 return assignable_result(NEW_GASGN(id, val));
08213 }
08214 else if (is_instance_id(id)) {
08215 return assignable_result(NEW_IASGN(id, val));
08216 }
08217 else if (is_const_id(id)) {
08218 if (!in_def && !in_single)
08219 return assignable_result(NEW_CDECL(id, val, 0));
08220 yyerror("dynamic constant assignment");
08221 }
08222 else if (is_class_id(id)) {
08223 return assignable_result(NEW_CVASGN(id, val));
08224 }
08225 else {
08226 compile_error(PARSER_ARG "identifier %s is not valid to set", rb_id2name(id));
08227 }
08228 return assignable_result(0);
08229 #undef assignable_result
08230 #undef parser_yyerror
08231 }
08232
08233 static ID
08234 shadowing_lvar_gen(struct parser_params *parser, ID name)
08235 {
08236 ID uscore;
08237
08238 CONST_ID(uscore, "_");
08239 if (uscore == name) return name;
08240 if (dyna_in_block()) {
08241 if (dvar_curr(name)) {
08242 yyerror("duplicated argument name");
08243 }
08244 else if (dvar_defined(name) || local_id(name)) {
08245 rb_warningS("shadowing outer local variable - %s", rb_id2name(name));
08246 vtable_add(lvtbl->vars, name);
08247 }
08248 }
08249 else {
08250 if (local_id(name)) {
08251 yyerror("duplicated argument name");
08252 }
08253 }
08254 return name;
08255 }
08256
08257 static void
08258 new_bv_gen(struct parser_params *parser, ID name)
08259 {
08260 if (!name) return;
08261 if (!is_local_id(name)) {
08262 compile_error(PARSER_ARG "invalid local variable - %s",
08263 rb_id2name(name));
08264 return;
08265 }
08266 shadowing_lvar(name);
08267 dyna_var(name);
08268 }
08269
08270 #ifndef RIPPER
08271 static NODE *
08272 aryset_gen(struct parser_params *parser, NODE *recv, NODE *idx)
08273 {
08274 if (recv && nd_type(recv) == NODE_SELF)
08275 recv = (NODE *)1;
08276 return NEW_ATTRASGN(recv, tASET, idx);
08277 }
08278
08279 static void
08280 block_dup_check_gen(struct parser_params *parser, NODE *node1, NODE *node2)
08281 {
08282 if (node2 && node1 && nd_type(node1) == NODE_BLOCK_PASS) {
08283 compile_error(PARSER_ARG "both block arg and actual block given");
08284 }
08285 }
08286
08287 ID
08288 rb_id_attrset(ID id)
08289 {
08290 id &= ~ID_SCOPE_MASK;
08291 id |= ID_ATTRSET;
08292 return id;
08293 }
08294
08295 static NODE *
08296 attrset_gen(struct parser_params *parser, NODE *recv, ID id)
08297 {
08298 if (recv && nd_type(recv) == NODE_SELF)
08299 recv = (NODE *)1;
08300 return NEW_ATTRASGN(recv, rb_id_attrset(id), 0);
08301 }
08302
08303 static void
08304 rb_backref_error_gen(struct parser_params *parser, NODE *node)
08305 {
08306 switch (nd_type(node)) {
08307 case NODE_NTH_REF:
08308 compile_error(PARSER_ARG "Can't set variable $%ld", node->nd_nth);
08309 break;
08310 case NODE_BACK_REF:
08311 compile_error(PARSER_ARG "Can't set variable $%c", (int)node->nd_nth);
08312 break;
08313 }
08314 }
08315
08316 static NODE *
08317 arg_concat_gen(struct parser_params *parser, NODE *node1, NODE *node2)
08318 {
08319 if (!node2) return node1;
08320 switch (nd_type(node1)) {
08321 case NODE_BLOCK_PASS:
08322 if (node1->nd_head)
08323 node1->nd_head = arg_concat(node1->nd_head, node2);
08324 else
08325 node1->nd_head = NEW_LIST(node2);
08326 return node1;
08327 case NODE_ARGSPUSH:
08328 if (nd_type(node2) != NODE_ARRAY) break;
08329 node1->nd_body = list_concat(NEW_LIST(node1->nd_body), node2);
08330 nd_set_type(node1, NODE_ARGSCAT);
08331 return node1;
08332 case NODE_ARGSCAT:
08333 if (nd_type(node2) != NODE_ARRAY ||
08334 nd_type(node1->nd_body) != NODE_ARRAY) break;
08335 node1->nd_body = list_concat(node1->nd_body, node2);
08336 return node1;
08337 }
08338 return NEW_ARGSCAT(node1, node2);
08339 }
08340
08341 static NODE *
08342 arg_append_gen(struct parser_params *parser, NODE *node1, NODE *node2)
08343 {
08344 if (!node1) return NEW_LIST(node2);
08345 switch (nd_type(node1)) {
08346 case NODE_ARRAY:
08347 return list_append(node1, node2);
08348 case NODE_BLOCK_PASS:
08349 node1->nd_head = arg_append(node1->nd_head, node2);
08350 return node1;
08351 case NODE_ARGSPUSH:
08352 node1->nd_body = list_append(NEW_LIST(node1->nd_body), node2);
08353 nd_set_type(node1, NODE_ARGSCAT);
08354 return node1;
08355 }
08356 return NEW_ARGSPUSH(node1, node2);
08357 }
08358
08359 static NODE *
08360 splat_array(NODE* node)
08361 {
08362 if (nd_type(node) == NODE_SPLAT) node = node->nd_head;
08363 if (nd_type(node) == NODE_ARRAY) return node;
08364 return 0;
08365 }
08366
08367 static NODE *
08368 node_assign_gen(struct parser_params *parser, NODE *lhs, NODE *rhs)
08369 {
08370 if (!lhs) return 0;
08371
08372 switch (nd_type(lhs)) {
08373 case NODE_GASGN:
08374 case NODE_IASGN:
08375 case NODE_IASGN2:
08376 case NODE_LASGN:
08377 case NODE_DASGN:
08378 case NODE_DASGN_CURR:
08379 case NODE_MASGN:
08380 case NODE_CDECL:
08381 case NODE_CVASGN:
08382 lhs->nd_value = rhs;
08383 break;
08384
08385 case NODE_ATTRASGN:
08386 case NODE_CALL:
08387 lhs->nd_args = arg_append(lhs->nd_args, rhs);
08388 break;
08389
08390 default:
08391
08392 break;
08393 }
08394
08395 return lhs;
08396 }
08397
08398 static int
08399 value_expr_gen(struct parser_params *parser, NODE *node)
08400 {
08401 int cond = 0;
08402
08403 if (!node) {
08404 rb_warning0("empty expression");
08405 }
08406 while (node) {
08407 switch (nd_type(node)) {
08408 case NODE_DEFN:
08409 case NODE_DEFS:
08410 parser_warning(node, "void value expression");
08411 return FALSE;
08412
08413 case NODE_RETURN:
08414 case NODE_BREAK:
08415 case NODE_NEXT:
08416 case NODE_REDO:
08417 case NODE_RETRY:
08418 if (!cond) yyerror("void value expression");
08419
08420 return FALSE;
08421
08422 case NODE_BLOCK:
08423 while (node->nd_next) {
08424 node = node->nd_next;
08425 }
08426 node = node->nd_head;
08427 break;
08428
08429 case NODE_BEGIN:
08430 node = node->nd_body;
08431 break;
08432
08433 case NODE_IF:
08434 if (!node->nd_body) {
08435 node = node->nd_else;
08436 break;
08437 }
08438 else if (!node->nd_else) {
08439 node = node->nd_body;
08440 break;
08441 }
08442 if (!value_expr(node->nd_body)) return FALSE;
08443 node = node->nd_else;
08444 break;
08445
08446 case NODE_AND:
08447 case NODE_OR:
08448 cond = 1;
08449 node = node->nd_2nd;
08450 break;
08451
08452 default:
08453 return TRUE;
08454 }
08455 }
08456
08457 return TRUE;
08458 }
08459
08460 static void
08461 void_expr_gen(struct parser_params *parser, NODE *node)
08462 {
08463 const char *useless = 0;
08464
08465 if (!RTEST(ruby_verbose)) return;
08466
08467 if (!node) return;
08468 switch (nd_type(node)) {
08469 case NODE_CALL:
08470 switch (node->nd_mid) {
08471 case '+':
08472 case '-':
08473 case '*':
08474 case '/':
08475 case '%':
08476 case tPOW:
08477 case tUPLUS:
08478 case tUMINUS:
08479 case '|':
08480 case '^':
08481 case '&':
08482 case tCMP:
08483 case '>':
08484 case tGEQ:
08485 case '<':
08486 case tLEQ:
08487 case tEQ:
08488 case tNEQ:
08489 useless = rb_id2name(node->nd_mid);
08490 break;
08491 }
08492 break;
08493
08494 case NODE_LVAR:
08495 case NODE_DVAR:
08496 case NODE_GVAR:
08497 case NODE_IVAR:
08498 case NODE_CVAR:
08499 case NODE_NTH_REF:
08500 case NODE_BACK_REF:
08501 useless = "a variable";
08502 break;
08503 case NODE_CONST:
08504 useless = "a constant";
08505 break;
08506 case NODE_LIT:
08507 case NODE_STR:
08508 case NODE_DSTR:
08509 case NODE_DREGX:
08510 case NODE_DREGX_ONCE:
08511 useless = "a literal";
08512 break;
08513 case NODE_COLON2:
08514 case NODE_COLON3:
08515 useless = "::";
08516 break;
08517 case NODE_DOT2:
08518 useless = "..";
08519 break;
08520 case NODE_DOT3:
08521 useless = "...";
08522 break;
08523 case NODE_SELF:
08524 useless = "self";
08525 break;
08526 case NODE_NIL:
08527 useless = "nil";
08528 break;
08529 case NODE_TRUE:
08530 useless = "true";
08531 break;
08532 case NODE_FALSE:
08533 useless = "false";
08534 break;
08535 case NODE_DEFINED:
08536 useless = "defined?";
08537 break;
08538 }
08539
08540 if (useless) {
08541 int line = ruby_sourceline;
08542
08543 ruby_sourceline = nd_line(node);
08544 rb_warnS("useless use of %s in void context", useless);
08545 ruby_sourceline = line;
08546 }
08547 }
08548
08549 static void
08550 void_stmts_gen(struct parser_params *parser, NODE *node)
08551 {
08552 if (!RTEST(ruby_verbose)) return;
08553 if (!node) return;
08554 if (nd_type(node) != NODE_BLOCK) return;
08555
08556 for (;;) {
08557 if (!node->nd_next) return;
08558 void_expr0(node->nd_head);
08559 node = node->nd_next;
08560 }
08561 }
08562
08563 static NODE *
08564 remove_begin(NODE *node)
08565 {
08566 NODE **n = &node, *n1 = node;
08567 while (n1 && nd_type(n1) == NODE_BEGIN && n1->nd_body) {
08568 *n = n1 = n1->nd_body;
08569 }
08570 return node;
08571 }
08572
08573 static void
08574 reduce_nodes_gen(struct parser_params *parser, NODE **body)
08575 {
08576 NODE *node = *body;
08577
08578 if (!node) {
08579 *body = NEW_NIL();
08580 return;
08581 }
08582 #define subnodes(n1, n2) \
08583 ((!node->n1) ? (node->n2 ? (body = &node->n2, 1) : 0) : \
08584 (!node->n2) ? (body = &node->n1, 1) : \
08585 (reduce_nodes(&node->n1), body = &node->n2, 1))
08586
08587 while (node) {
08588 int newline = (int)(node->flags & NODE_FL_NEWLINE);
08589 switch (nd_type(node)) {
08590 end:
08591 case NODE_NIL:
08592 *body = 0;
08593 return;
08594 case NODE_RETURN:
08595 *body = node = node->nd_stts;
08596 if (newline && node) node->flags |= NODE_FL_NEWLINE;
08597 continue;
08598 case NODE_BEGIN:
08599 *body = node = node->nd_body;
08600 if (newline && node) node->flags |= NODE_FL_NEWLINE;
08601 continue;
08602 case NODE_BLOCK:
08603 body = &node->nd_end->nd_head;
08604 break;
08605 case NODE_IF:
08606 if (subnodes(nd_body, nd_else)) break;
08607 return;
08608 case NODE_CASE:
08609 body = &node->nd_body;
08610 break;
08611 case NODE_WHEN:
08612 if (!subnodes(nd_body, nd_next)) goto end;
08613 break;
08614 case NODE_ENSURE:
08615 if (!subnodes(nd_head, nd_resq)) goto end;
08616 break;
08617 case NODE_RESCUE:
08618 if (!subnodes(nd_head, nd_resq)) goto end;
08619 break;
08620 default:
08621 return;
08622 }
08623 node = *body;
08624 if (newline && node) node->flags |= NODE_FL_NEWLINE;
08625 }
08626
08627 #undef subnodes
08628 }
08629
08630 static int
08631 assign_in_cond(struct parser_params *parser, NODE *node)
08632 {
08633 switch (nd_type(node)) {
08634 case NODE_MASGN:
08635 yyerror("multiple assignment in conditional");
08636 return 1;
08637
08638 case NODE_LASGN:
08639 case NODE_DASGN:
08640 case NODE_DASGN_CURR:
08641 case NODE_GASGN:
08642 case NODE_IASGN:
08643 break;
08644
08645 default:
08646 return 0;
08647 }
08648
08649 switch (nd_type(node->nd_value)) {
08650 case NODE_LIT:
08651 case NODE_STR:
08652 case NODE_NIL:
08653 case NODE_TRUE:
08654 case NODE_FALSE:
08655
08656 parser_warn(node->nd_value, "found = in conditional, should be ==");
08657 return 1;
08658
08659 case NODE_DSTR:
08660 case NODE_XSTR:
08661 case NODE_DXSTR:
08662 case NODE_EVSTR:
08663 case NODE_DREGX:
08664 default:
08665 break;
08666 }
08667 return 1;
08668 }
08669
08670 static void
08671 warn_unless_e_option(struct parser_params *parser, NODE *node, const char *str)
08672 {
08673 if (!e_option_supplied(parser)) parser_warn(node, str);
08674 }
08675
08676 static void
08677 warning_unless_e_option(struct parser_params *parser, NODE *node, const char *str)
08678 {
08679 if (!e_option_supplied(parser)) parser_warning(node, str);
08680 }
08681
08682 static void
08683 fixup_nodes(NODE **rootnode)
08684 {
08685 NODE *node, *next, *head;
08686
08687 for (node = *rootnode; node; node = next) {
08688 enum node_type type;
08689 VALUE val;
08690
08691 next = node->nd_next;
08692 head = node->nd_head;
08693 rb_gc_force_recycle((VALUE)node);
08694 *rootnode = next;
08695 switch (type = nd_type(head)) {
08696 case NODE_DOT2:
08697 case NODE_DOT3:
08698 val = rb_range_new(head->nd_beg->nd_lit, head->nd_end->nd_lit,
08699 type == NODE_DOT3);
08700 rb_gc_force_recycle((VALUE)head->nd_beg);
08701 rb_gc_force_recycle((VALUE)head->nd_end);
08702 nd_set_type(head, NODE_LIT);
08703 head->nd_lit = val;
08704 break;
08705 default:
08706 break;
08707 }
08708 }
08709 }
08710
08711 static NODE *cond0(struct parser_params*,NODE*);
08712
08713 static NODE*
08714 range_op(struct parser_params *parser, NODE *node)
08715 {
08716 enum node_type type;
08717
08718 if (node == 0) return 0;
08719
08720 type = nd_type(node);
08721 value_expr(node);
08722 if (type == NODE_LIT && FIXNUM_P(node->nd_lit)) {
08723 warn_unless_e_option(parser, node, "integer literal in conditional range");
08724 return NEW_CALL(node, tEQ, NEW_LIST(NEW_GVAR(rb_intern("$."))));
08725 }
08726 return cond0(parser, node);
08727 }
08728
08729 static int
08730 literal_node(NODE *node)
08731 {
08732 if (!node) return 1;
08733 switch (nd_type(node)) {
08734 case NODE_LIT:
08735 case NODE_STR:
08736 case NODE_DSTR:
08737 case NODE_EVSTR:
08738 case NODE_DREGX:
08739 case NODE_DREGX_ONCE:
08740 case NODE_DSYM:
08741 return 2;
08742 case NODE_TRUE:
08743 case NODE_FALSE:
08744 case NODE_NIL:
08745 return 1;
08746 }
08747 return 0;
08748 }
08749
08750 static NODE*
08751 cond0(struct parser_params *parser, NODE *node)
08752 {
08753 if (node == 0) return 0;
08754 assign_in_cond(parser, node);
08755
08756 switch (nd_type(node)) {
08757 case NODE_DSTR:
08758 case NODE_EVSTR:
08759 case NODE_STR:
08760 rb_warn0("string literal in condition");
08761 break;
08762
08763 case NODE_DREGX:
08764 case NODE_DREGX_ONCE:
08765 warning_unless_e_option(parser, node, "regex literal in condition");
08766 return NEW_MATCH2(node, NEW_GVAR(rb_intern("$_")));
08767
08768 case NODE_AND:
08769 case NODE_OR:
08770 node->nd_1st = cond0(parser, node->nd_1st);
08771 node->nd_2nd = cond0(parser, node->nd_2nd);
08772 break;
08773
08774 case NODE_DOT2:
08775 case NODE_DOT3:
08776 node->nd_beg = range_op(parser, node->nd_beg);
08777 node->nd_end = range_op(parser, node->nd_end);
08778 if (nd_type(node) == NODE_DOT2) nd_set_type(node,NODE_FLIP2);
08779 else if (nd_type(node) == NODE_DOT3) nd_set_type(node, NODE_FLIP3);
08780 if (!e_option_supplied(parser)) {
08781 int b = literal_node(node->nd_beg);
08782 int e = literal_node(node->nd_end);
08783 if ((b == 1 && e == 1) || (b + e >= 2 && RTEST(ruby_verbose))) {
08784 parser_warn(node, "range literal in condition");
08785 }
08786 }
08787 break;
08788
08789 case NODE_DSYM:
08790 parser_warning(node, "literal in condition");
08791 break;
08792
08793 case NODE_LIT:
08794 if (TYPE(node->nd_lit) == T_REGEXP) {
08795 warn_unless_e_option(parser, node, "regex literal in condition");
08796 nd_set_type(node, NODE_MATCH);
08797 }
08798 else {
08799 parser_warning(node, "literal in condition");
08800 }
08801 default:
08802 break;
08803 }
08804 return node;
08805 }
08806
08807 static NODE*
08808 cond_gen(struct parser_params *parser, NODE *node)
08809 {
08810 if (node == 0) return 0;
08811 return cond0(parser, node);
08812 }
08813
08814 static NODE*
08815 logop_gen(struct parser_params *parser, enum node_type type, NODE *left, NODE *right)
08816 {
08817 value_expr(left);
08818 if (left && (enum node_type)nd_type(left) == type) {
08819 NODE *node = left, *second;
08820 while ((second = node->nd_2nd) != 0 && (enum node_type)nd_type(second) == type) {
08821 node = second;
08822 }
08823 node->nd_2nd = NEW_NODE(type, second, right, 0);
08824 return left;
08825 }
08826 return NEW_NODE(type, left, right, 0);
08827 }
08828
08829 static void
08830 no_blockarg(struct parser_params *parser, NODE *node)
08831 {
08832 if (node && nd_type(node) == NODE_BLOCK_PASS) {
08833 compile_error(PARSER_ARG "block argument should not be given");
08834 }
08835 }
08836
08837 static NODE *
08838 ret_args_gen(struct parser_params *parser, NODE *node)
08839 {
08840 if (node) {
08841 no_blockarg(parser, node);
08842 if (nd_type(node) == NODE_ARRAY) {
08843 if (node->nd_next == 0) {
08844 node = node->nd_head;
08845 }
08846 else {
08847 nd_set_type(node, NODE_VALUES);
08848 }
08849 }
08850 }
08851 return node;
08852 }
08853
08854 static NODE *
08855 new_yield_gen(struct parser_params *parser, NODE *node)
08856 {
08857 long state = Qtrue;
08858
08859 if (node) {
08860 no_blockarg(parser, node);
08861 if (node && nd_type(node) == NODE_SPLAT) {
08862 state = Qtrue;
08863 }
08864 }
08865 else {
08866 state = Qfalse;
08867 }
08868 return NEW_YIELD(node, state);
08869 }
08870
08871 static NODE*
08872 negate_lit(NODE *node)
08873 {
08874 switch (TYPE(node->nd_lit)) {
08875 case T_FIXNUM:
08876 node->nd_lit = LONG2FIX(-FIX2LONG(node->nd_lit));
08877 break;
08878 case T_BIGNUM:
08879 node->nd_lit = rb_funcall(node->nd_lit,tUMINUS,0,0);
08880 break;
08881 case T_FLOAT:
08882 RFLOAT(node->nd_lit)->float_value = -RFLOAT_VALUE(node->nd_lit);
08883 break;
08884 default:
08885 break;
08886 }
08887 return node;
08888 }
08889
08890 static NODE *
08891 arg_blk_pass(NODE *node1, NODE *node2)
08892 {
08893 if (node2) {
08894 node2->nd_head = node1;
08895 return node2;
08896 }
08897 return node1;
08898 }
08899
08900 static NODE*
08901 new_args_gen(struct parser_params *parser, NODE *m, NODE *o, ID r, NODE *p, ID b)
08902 {
08903 int saved_line = ruby_sourceline;
08904 NODE *node;
08905 NODE *i1, *i2 = 0;
08906
08907 node = NEW_ARGS(m ? m->nd_plen : 0, o);
08908 i1 = m ? m->nd_next : 0;
08909 node->nd_next = NEW_ARGS_AUX(r, b);
08910
08911 if (p) {
08912 i2 = p->nd_next;
08913 node->nd_next->nd_next = NEW_ARGS_AUX(p->nd_pid, p->nd_plen);
08914 }
08915 else if (i1) {
08916 node->nd_next->nd_next = NEW_ARGS_AUX(0, 0);
08917 }
08918 if (i1 || i2) {
08919 node->nd_next->nd_next->nd_next = NEW_NODE(NODE_AND, i1, i2, 0);
08920 }
08921 ruby_sourceline = saved_line;
08922 return node;
08923 }
08924 #endif
08925
08926 static void
08927 local_push_gen(struct parser_params *parser, int inherit_dvars)
08928 {
08929 struct local_vars *local;
08930
08931 local = ALLOC(struct local_vars);
08932 local->prev = lvtbl;
08933 local->args = vtable_alloc(0);
08934 local->vars = vtable_alloc(inherit_dvars ? DVARS_INHERIT : DVARS_TOPSCOPE);
08935 lvtbl = local;
08936 }
08937
08938 static void
08939 local_pop_gen(struct parser_params *parser)
08940 {
08941 struct local_vars *local = lvtbl->prev;
08942 vtable_free(lvtbl->args);
08943 vtable_free(lvtbl->vars);
08944 xfree(lvtbl);
08945 lvtbl = local;
08946 }
08947
08948 #ifndef RIPPER
08949 static ID*
08950 vtable_tblcpy(ID *buf, const struct vtable *src)
08951 {
08952 int i, cnt = vtable_size(src);
08953
08954 if (cnt > 0) {
08955 buf[0] = cnt;
08956 for (i = 0; i < cnt; i++) {
08957 buf[i] = src->tbl[i];
08958 }
08959 return buf;
08960 }
08961 return 0;
08962 }
08963
08964 static ID*
08965 local_tbl_gen(struct parser_params *parser)
08966 {
08967 int cnt = vtable_size(lvtbl->args) + vtable_size(lvtbl->vars);
08968 ID *buf;
08969
08970 if (cnt <= 0) return 0;
08971 buf = ALLOC_N(ID, cnt + 1);
08972 vtable_tblcpy(buf+1, lvtbl->args);
08973 vtable_tblcpy(buf+vtable_size(lvtbl->args)+1, lvtbl->vars);
08974 buf[0] = cnt;
08975 return buf;
08976 }
08977 #endif
08978
08979 static int
08980 arg_var_gen(struct parser_params *parser, ID id)
08981 {
08982 vtable_add(lvtbl->args, id);
08983 return vtable_size(lvtbl->args) - 1;
08984 }
08985
08986 static int
08987 local_var_gen(struct parser_params *parser, ID id)
08988 {
08989 vtable_add(lvtbl->vars, id);
08990 return vtable_size(lvtbl->vars) - 1;
08991 }
08992
08993 static int
08994 local_id_gen(struct parser_params *parser, ID id)
08995 {
08996 struct vtable *vars, *args;
08997
08998 vars = lvtbl->vars;
08999 args = lvtbl->args;
09000
09001 while (vars && POINTER_P(vars->prev)) {
09002 vars = vars->prev;
09003 args = args->prev;
09004 }
09005
09006 if (vars && vars->prev == DVARS_INHERIT) {
09007 return rb_local_defined(id);
09008 }
09009 else {
09010 return (vtable_included(args, id) ||
09011 vtable_included(vars, id));
09012 }
09013 }
09014
09015 static const struct vtable *
09016 dyna_push_gen(struct parser_params *parser)
09017 {
09018 lvtbl->args = vtable_alloc(lvtbl->args);
09019 lvtbl->vars = vtable_alloc(lvtbl->vars);
09020 return lvtbl->args;
09021 }
09022
09023 static void
09024 dyna_pop_1(struct parser_params *parser)
09025 {
09026 struct vtable *tmp;
09027
09028 tmp = lvtbl->args;
09029 lvtbl->args = lvtbl->args->prev;
09030 vtable_free(tmp);
09031 tmp = lvtbl->vars;
09032 lvtbl->vars = lvtbl->vars->prev;
09033 vtable_free(tmp);
09034 }
09035
09036 static void
09037 dyna_pop_gen(struct parser_params *parser, const struct vtable *lvargs)
09038 {
09039 while (lvtbl->args != lvargs) {
09040 dyna_pop_1(parser);
09041 if (!lvtbl->args) {
09042 struct local_vars *local = lvtbl->prev;
09043 xfree(lvtbl);
09044 lvtbl = local;
09045 }
09046 }
09047 dyna_pop_1(parser);
09048 }
09049
09050 static int
09051 dyna_in_block_gen(struct parser_params *parser)
09052 {
09053 return POINTER_P(lvtbl->vars) && lvtbl->vars->prev != DVARS_TOPSCOPE;
09054 }
09055
09056 static int
09057 dvar_defined_gen(struct parser_params *parser, ID id)
09058 {
09059 struct vtable *vars, *args;
09060
09061 args = lvtbl->args;
09062 vars = lvtbl->vars;
09063
09064 while (POINTER_P(vars)) {
09065 if (vtable_included(args, id)) {
09066 return 1;
09067 }
09068 if (vtable_included(vars, id)) {
09069 return 1;
09070 }
09071 args = args->prev;
09072 vars = vars->prev;
09073 }
09074
09075 if (vars == DVARS_INHERIT) {
09076 return rb_dvar_defined(id);
09077 }
09078
09079 return 0;
09080 }
09081
09082 static int
09083 dvar_curr_gen(struct parser_params *parser, ID id)
09084 {
09085 return (vtable_included(lvtbl->args, id) ||
09086 vtable_included(lvtbl->vars, id));
09087 }
09088
09089 #ifndef RIPPER
09090 VALUE rb_reg_compile(VALUE str, int options, const char *sourcefile, int sourceline);
09091 VALUE rb_reg_check_preprocess(VALUE);
09092
09093 static void
09094 reg_fragment_setenc_gen(struct parser_params* parser, VALUE str, int options)
09095 {
09096 int c = RE_OPTION_ENCODING_IDX(options);
09097
09098 if (c) {
09099 int opt, idx;
09100 rb_char_to_option_kcode(c, &opt, &idx);
09101 if (idx != ENCODING_GET(str) &&
09102 rb_enc_str_coderange(str) != ENC_CODERANGE_7BIT) {
09103 goto error;
09104 }
09105 ENCODING_SET(str, idx);
09106 }
09107 else if (RE_OPTION_ENCODING_NONE(options)) {
09108 if (!ENCODING_IS_ASCII8BIT(str) &&
09109 rb_enc_str_coderange(str) != ENC_CODERANGE_7BIT) {
09110 c = 'n';
09111 goto error;
09112 }
09113 rb_enc_associate(str, rb_ascii8bit_encoding());
09114 }
09115 else if (parser->enc == rb_usascii_encoding()) {
09116 if (rb_enc_str_coderange(str) != ENC_CODERANGE_7BIT) {
09117
09118 rb_enc_associate(str, rb_usascii_encoding());
09119 }
09120 else {
09121 rb_enc_associate(str, rb_ascii8bit_encoding());
09122 }
09123 }
09124 return;
09125
09126 error:
09127 compile_error(PARSER_ARG
09128 "regexp encoding option '%c' differs from source encoding '%s'",
09129 c, rb_enc_name(rb_enc_get(str)));
09130 }
09131
09132 static int
09133 reg_fragment_check_gen(struct parser_params* parser, VALUE str, int options)
09134 {
09135 VALUE err;
09136 reg_fragment_setenc(str, options);
09137 err = rb_reg_check_preprocess(str);
09138 if (err != Qnil) {
09139 err = rb_obj_as_string(err);
09140 compile_error(PARSER_ARG "%s", RSTRING_PTR(err));
09141 RB_GC_GUARD(err);
09142 return 0;
09143 }
09144 return 1;
09145 }
09146
09147 typedef struct {
09148 struct parser_params* parser;
09149 rb_encoding *enc;
09150 NODE *succ_block;
09151 NODE *fail_block;
09152 int num;
09153 } reg_named_capture_assign_t;
09154
09155 static int
09156 reg_named_capture_assign_iter(const OnigUChar *name, const OnigUChar *name_end,
09157 int back_num, int *back_refs, OnigRegex regex, void *arg0)
09158 {
09159 reg_named_capture_assign_t *arg = (reg_named_capture_assign_t*)arg0;
09160 struct parser_params* parser = arg->parser;
09161 rb_encoding *enc = arg->enc;
09162 long len = name_end - name;
09163 const char *s = (const char *)name;
09164 ID var;
09165
09166 arg->num++;
09167
09168 if (arg->succ_block == 0) {
09169 arg->succ_block = NEW_BEGIN(0);
09170 arg->fail_block = NEW_BEGIN(0);
09171 }
09172
09173 if (!len || (*name != '_' && ISASCII(*name) && !rb_enc_islower(*name, enc)) ||
09174 (len < MAX_WORD_LENGTH && rb_reserved_word(s, (int)len)) ||
09175 !rb_enc_symname2_p(s, len, enc)) {
09176 return ST_CONTINUE;
09177 }
09178 var = rb_intern3(s, len, enc);
09179 if (dvar_defined(var) || local_id(var)) {
09180 rb_warningS("named capture conflicts a local variable - %s",
09181 rb_id2name(var));
09182 }
09183 arg->succ_block = block_append(arg->succ_block,
09184 newline_node(node_assign(assignable(var,0),
09185 NEW_CALL(
09186 gettable(rb_intern("$~")),
09187 idAREF,
09188 NEW_LIST(NEW_LIT(ID2SYM(var))))
09189 )));
09190 arg->fail_block = block_append(arg->fail_block,
09191 newline_node(node_assign(assignable(var,0), NEW_LIT(Qnil))));
09192 return ST_CONTINUE;
09193 }
09194
09195 static NODE *
09196 reg_named_capture_assign_gen(struct parser_params* parser, VALUE regexp, NODE *match)
09197 {
09198 reg_named_capture_assign_t arg;
09199
09200 arg.parser = parser;
09201 arg.enc = rb_enc_get(regexp);
09202 arg.succ_block = 0;
09203 arg.fail_block = 0;
09204 arg.num = 0;
09205 onig_foreach_name(RREGEXP(regexp)->ptr, reg_named_capture_assign_iter, (void*)&arg);
09206
09207 if (arg.num == 0)
09208 return match;
09209
09210 return
09211 block_append(
09212 newline_node(match),
09213 NEW_IF(gettable(rb_intern("$~")),
09214 block_append(
09215 newline_node(arg.succ_block),
09216 newline_node(
09217 NEW_CALL(
09218 gettable(rb_intern("$~")),
09219 rb_intern("begin"),
09220 NEW_LIST(NEW_LIT(INT2FIX(0)))))),
09221 block_append(
09222 newline_node(arg.fail_block),
09223 newline_node(
09224 NEW_LIT(Qnil)))));
09225 }
09226
09227 static VALUE
09228 reg_compile_gen(struct parser_params* parser, VALUE str, int options)
09229 {
09230 VALUE re;
09231 VALUE err;
09232
09233 reg_fragment_setenc(str, options);
09234 err = rb_errinfo();
09235 re = rb_reg_compile(str, options & RE_OPTION_MASK, ruby_sourcefile, ruby_sourceline);
09236 if (NIL_P(re)) {
09237 ID mesg = rb_intern("mesg");
09238 VALUE m = rb_attr_get(rb_errinfo(), mesg);
09239 rb_set_errinfo(err);
09240 if (!NIL_P(err)) {
09241 rb_str_append(rb_str_cat(rb_attr_get(err, mesg), "\n", 1), m);
09242 }
09243 else {
09244 compile_error(PARSER_ARG "%s", RSTRING_PTR(m));
09245 }
09246 return Qnil;
09247 }
09248 return re;
09249 }
09250
09251 void
09252 rb_gc_mark_parser(void)
09253 {
09254 }
09255
09256 NODE*
09257 rb_parser_append_print(VALUE vparser, NODE *node)
09258 {
09259 NODE *prelude = 0;
09260 NODE *scope = node;
09261 struct parser_params *parser;
09262
09263 if (!node) return node;
09264
09265 TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, parser);
09266
09267 node = node->nd_body;
09268
09269 if (nd_type(node) == NODE_PRELUDE) {
09270 prelude = node;
09271 node = node->nd_body;
09272 }
09273
09274 node = block_append(node,
09275 NEW_FCALL(rb_intern("print"),
09276 NEW_ARRAY(NEW_GVAR(rb_intern("$_")))));
09277 if (prelude) {
09278 prelude->nd_body = node;
09279 scope->nd_body = prelude;
09280 }
09281 else {
09282 scope->nd_body = node;
09283 }
09284
09285 return scope;
09286 }
09287
09288 NODE *
09289 rb_parser_while_loop(VALUE vparser, NODE *node, int chop, int split)
09290 {
09291 NODE *prelude = 0;
09292 NODE *scope = node;
09293 struct parser_params *parser;
09294
09295 if (!node) return node;
09296
09297 TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, parser);
09298
09299 node = node->nd_body;
09300
09301 if (nd_type(node) == NODE_PRELUDE) {
09302 prelude = node;
09303 node = node->nd_body;
09304 }
09305 if (split) {
09306 node = block_append(NEW_GASGN(rb_intern("$F"),
09307 NEW_CALL(NEW_GVAR(rb_intern("$_")),
09308 rb_intern("split"), 0)),
09309 node);
09310 }
09311 if (chop) {
09312 node = block_append(NEW_CALL(NEW_GVAR(rb_intern("$_")),
09313 rb_intern("chop!"), 0), node);
09314 }
09315
09316 node = NEW_OPT_N(node);
09317
09318 if (prelude) {
09319 prelude->nd_body = node;
09320 scope->nd_body = prelude;
09321 }
09322 else {
09323 scope->nd_body = node;
09324 }
09325
09326 return scope;
09327 }
09328
09329 static const struct {
09330 ID token;
09331 const char *name;
09332 } op_tbl[] = {
09333 {tDOT2, ".."},
09334 {tDOT3, "..."},
09335 {'+', "+(binary)"},
09336 {'-', "-(binary)"},
09337 {tPOW, "**"},
09338 {tUPLUS, "+@"},
09339 {tUMINUS, "-@"},
09340 {tCMP, "<=>"},
09341 {tGEQ, ">="},
09342 {tLEQ, "<="},
09343 {tEQ, "=="},
09344 {tEQQ, "==="},
09345 {tNEQ, "!="},
09346 {tMATCH, "=~"},
09347 {tNMATCH, "!~"},
09348 {tAREF, "[]"},
09349 {tASET, "[]="},
09350 {tLSHFT, "<<"},
09351 {tRSHFT, ">>"},
09352 {tCOLON2, "::"},
09353 };
09354
09355 #define op_tbl_count numberof(op_tbl)
09356
09357 #ifndef ENABLE_SELECTOR_NAMESPACE
09358 #define ENABLE_SELECTOR_NAMESPACE 0
09359 #endif
09360
09361 static struct symbols {
09362 ID last_id;
09363 st_table *sym_id;
09364 st_table *id_str;
09365 #if ENABLE_SELECTOR_NAMESPACE
09366 st_table *ivar2_id;
09367 st_table *id_ivar2;
09368 #endif
09369 VALUE op_sym[tLAST_TOKEN];
09370 } global_symbols = {tLAST_ID};
09371
09372 static const struct st_hash_type symhash = {
09373 rb_str_hash_cmp,
09374 rb_str_hash,
09375 };
09376
09377 #if ENABLE_SELECTOR_NAMESPACE
09378 struct ivar2_key {
09379 ID id;
09380 VALUE klass;
09381 };
09382
09383 static int
09384 ivar2_cmp(struct ivar2_key *key1, struct ivar2_key *key2)
09385 {
09386 if (key1->id == key2->id && key1->klass == key2->klass) {
09387 return 0;
09388 }
09389 return 1;
09390 }
09391
09392 static int
09393 ivar2_hash(struct ivar2_key *key)
09394 {
09395 return (key->id << 8) ^ (key->klass >> 2);
09396 }
09397
09398 static const struct st_hash_type ivar2_hash_type = {
09399 ivar2_cmp,
09400 ivar2_hash,
09401 };
09402 #endif
09403
09404 void
09405 Init_sym(void)
09406 {
09407 global_symbols.sym_id = st_init_table_with_size(&symhash, 1000);
09408 global_symbols.id_str = st_init_numtable_with_size(1000);
09409 #if ENABLE_SELECTOR_NAMESPACE
09410 global_symbols.ivar2_id = st_init_table_with_size(&ivar2_hash_type, 1000);
09411 global_symbols.id_ivar2 = st_init_numtable_with_size(1000);
09412 #endif
09413
09414 Init_id();
09415 }
09416
09417 void
09418 rb_gc_mark_symbols(void)
09419 {
09420 rb_mark_tbl(global_symbols.id_str);
09421 rb_gc_mark_locations(global_symbols.op_sym,
09422 global_symbols.op_sym + tLAST_TOKEN);
09423 }
09424 #endif
09425
09426 static ID
09427 internal_id_gen(struct parser_params *parser)
09428 {
09429 ID id = (ID)vtable_size(lvtbl->args) + (ID)vtable_size(lvtbl->vars);
09430 id += ((tLAST_TOKEN - ID_INTERNAL) >> ID_SCOPE_SHIFT) + 1;
09431 return ID_INTERNAL | (id << ID_SCOPE_SHIFT);
09432 }
09433
09434 #ifndef RIPPER
09435 static int
09436 is_special_global_name(const char *m, const char *e, rb_encoding *enc)
09437 {
09438 int mb = 0;
09439
09440 if (m >= e) return 0;
09441 switch (*m) {
09442 case '~': case '*': case '$': case '?': case '!': case '@':
09443 case '/': case '\\': case ';': case ',': case '.': case '=':
09444 case ':': case '<': case '>': case '\"':
09445 case '&': case '`': case '\'': case '+':
09446 case '0':
09447 ++m;
09448 break;
09449 case '-':
09450 ++m;
09451 if (m < e && is_identchar(m, e, enc)) {
09452 if (!ISASCII(*m)) mb = 1;
09453 m += rb_enc_mbclen(m, e, enc);
09454 }
09455 break;
09456 default:
09457 if (!rb_enc_isdigit(*m, enc)) return 0;
09458 do {
09459 if (!ISASCII(*m)) mb = 1;
09460 ++m;
09461 } while (m < e && rb_enc_isdigit(*m, enc));
09462 }
09463 return m == e ? mb + 1 : 0;
09464 }
09465
09466 int
09467 rb_symname_p(const char *name)
09468 {
09469 return rb_enc_symname_p(name, rb_ascii8bit_encoding());
09470 }
09471
09472 int
09473 rb_enc_symname_p(const char *name, rb_encoding *enc)
09474 {
09475 return rb_enc_symname2_p(name, strlen(name), enc);
09476 }
09477
09478 int
09479 rb_enc_symname2_p(const char *name, long len, rb_encoding *enc)
09480 {
09481 const char *m = name;
09482 const char *e = m + len;
09483 int localid = FALSE;
09484
09485 if (!m) return FALSE;
09486 switch (*m) {
09487 case '\0':
09488 return FALSE;
09489
09490 case '$':
09491 if (is_special_global_name(++m, e, enc)) return TRUE;
09492 goto id;
09493
09494 case '@':
09495 if (*++m == '@') ++m;
09496 goto id;
09497
09498 case '<':
09499 switch (*++m) {
09500 case '<': ++m; break;
09501 case '=': if (*++m == '>') ++m; break;
09502 default: break;
09503 }
09504 break;
09505
09506 case '>':
09507 switch (*++m) {
09508 case '>': case '=': ++m; break;
09509 }
09510 break;
09511
09512 case '=':
09513 switch (*++m) {
09514 case '~': ++m; break;
09515 case '=': if (*++m == '=') ++m; break;
09516 default: return FALSE;
09517 }
09518 break;
09519
09520 case '*':
09521 if (*++m == '*') ++m;
09522 break;
09523
09524 case '+': case '-':
09525 if (*++m == '@') ++m;
09526 break;
09527
09528 case '|': case '^': case '&': case '/': case '%': case '~': case '`':
09529 ++m;
09530 break;
09531
09532 case '[':
09533 if (*++m != ']') return FALSE;
09534 if (*++m == '=') ++m;
09535 break;
09536
09537 case '!':
09538 switch (*++m) {
09539 case '\0': return TRUE;
09540 case '=': case '~': ++m; break;
09541 default: return FALSE;
09542 }
09543 break;
09544
09545 default:
09546 localid = !rb_enc_isupper(*m, enc);
09547 id:
09548 if (m >= e || (*m != '_' && !rb_enc_isalpha(*m, enc) && ISASCII(*m)))
09549 return FALSE;
09550 while (m < e && is_identchar(m, e, enc)) m += rb_enc_mbclen(m, e, enc);
09551 if (localid) {
09552 switch (*m) {
09553 case '!': case '?': case '=': ++m;
09554 }
09555 }
09556 break;
09557 }
09558 return m == e;
09559 }
09560
09561 static ID
09562 register_symid(ID id, const char *name, long len, rb_encoding *enc)
09563 {
09564 VALUE str = rb_enc_str_new(name, len, enc);
09565 OBJ_FREEZE(str);
09566 st_add_direct(global_symbols.sym_id, (st_data_t)str, id);
09567 st_add_direct(global_symbols.id_str, id, (st_data_t)str);
09568 return id;
09569 }
09570
09571 ID
09572 rb_intern3(const char *name, long len, rb_encoding *enc)
09573 {
09574 const char *m = name;
09575 const char *e = m + len;
09576 unsigned char c;
09577 VALUE str;
09578 ID id;
09579 long last;
09580 int mb;
09581 st_data_t data;
09582 struct RString fake_str;
09583 fake_str.basic.flags = T_STRING|RSTRING_NOEMBED|FL_FREEZE;
09584 fake_str.basic.klass = rb_cString;
09585 fake_str.as.heap.len = len;
09586 fake_str.as.heap.ptr = (char *)name;
09587 fake_str.as.heap.aux.capa = len;
09588 str = (VALUE)&fake_str;
09589 rb_enc_associate(str, enc);
09590
09591 if (rb_enc_str_coderange(str) == ENC_CODERANGE_BROKEN) {
09592 rb_raise(rb_eEncodingError, "invalid encoding symbol");
09593 }
09594
09595 if (st_lookup(global_symbols.sym_id, str, &data))
09596 return (ID)data;
09597
09598 if (rb_cString && !rb_enc_asciicompat(enc)) {
09599 id = ID_JUNK;
09600 goto new_id;
09601 }
09602 last = len-1;
09603 id = 0;
09604 switch (*m) {
09605 case '$':
09606 id |= ID_GLOBAL;
09607 if ((mb = is_special_global_name(++m, e, enc)) != 0) {
09608 if (!--mb) enc = rb_ascii8bit_encoding();
09609 goto new_id;
09610 }
09611 break;
09612 case '@':
09613 if (m[1] == '@') {
09614 m++;
09615 id |= ID_CLASS;
09616 }
09617 else {
09618 id |= ID_INSTANCE;
09619 }
09620 m++;
09621 break;
09622 default:
09623 c = m[0];
09624 if (c != '_' && rb_enc_isascii(c, enc) && rb_enc_ispunct(c, enc)) {
09625
09626 int i;
09627
09628 if (len == 1) {
09629 id = c;
09630 goto id_register;
09631 }
09632 for (i = 0; i < op_tbl_count; i++) {
09633 if (*op_tbl[i].name == *m &&
09634 strcmp(op_tbl[i].name, m) == 0) {
09635 id = op_tbl[i].token;
09636 goto id_register;
09637 }
09638 }
09639 }
09640
09641 if (m[last] == '=') {
09642
09643 id = rb_intern3(name, last, enc);
09644 if (id > tLAST_TOKEN && !is_attrset_id(id)) {
09645 enc = rb_enc_get(rb_id2str(id));
09646 id = rb_id_attrset(id);
09647 goto id_register;
09648 }
09649 id = ID_ATTRSET;
09650 }
09651 else if (rb_enc_isupper(m[0], enc)) {
09652 id = ID_CONST;
09653 }
09654 else {
09655 id = ID_LOCAL;
09656 }
09657 break;
09658 }
09659 mb = 0;
09660 if (!rb_enc_isdigit(*m, enc)) {
09661 while (m <= name + last && is_identchar(m, e, enc)) {
09662 if (ISASCII(*m)) {
09663 m++;
09664 }
09665 else {
09666 mb = 1;
09667 m += rb_enc_mbclen(m, e, enc);
09668 }
09669 }
09670 }
09671 if (m - name < len) id = ID_JUNK;
09672 if (enc != rb_usascii_encoding()) {
09673
09674
09675
09676
09677 if (!mb) {
09678 for (; m <= name + len; ++m) {
09679 if (!ISASCII(*m)) goto mbstr;
09680 }
09681 enc = rb_usascii_encoding();
09682 }
09683 mbstr:;
09684 }
09685 new_id:
09686 if (global_symbols.last_id >= ~(ID)0 >> (ID_SCOPE_SHIFT+RUBY_SPECIAL_SHIFT)) {
09687 if (len > 20) {
09688 rb_raise(rb_eRuntimeError, "symbol table overflow (symbol %.20s...)",
09689 name);
09690 }
09691 else {
09692 rb_raise(rb_eRuntimeError, "symbol table overflow (symbol %.*s)",
09693 (int)len, name);
09694 }
09695 }
09696 id |= ++global_symbols.last_id << ID_SCOPE_SHIFT;
09697 id_register:
09698 return register_symid(id, name, len, enc);
09699 }
09700
09701 ID
09702 rb_intern2(const char *name, long len)
09703 {
09704 return rb_intern3(name, len, rb_usascii_encoding());
09705 }
09706
09707 #undef rb_intern
09708 ID
09709 rb_intern(const char *name)
09710 {
09711 return rb_intern2(name, strlen(name));
09712 }
09713
09714 ID
09715 rb_intern_str(VALUE str)
09716 {
09717 rb_encoding *enc;
09718 ID id;
09719
09720 if (rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT) {
09721 enc = rb_usascii_encoding();
09722 }
09723 else {
09724 enc = rb_enc_get(str);
09725 }
09726 id = rb_intern3(RSTRING_PTR(str), RSTRING_LEN(str), enc);
09727 RB_GC_GUARD(str);
09728 return id;
09729 }
09730
09731 VALUE
09732 rb_id2str(ID id)
09733 {
09734 st_data_t data;
09735
09736 if (id < tLAST_TOKEN) {
09737 int i = 0;
09738
09739 if (id < INT_MAX && rb_ispunct((int)id)) {
09740 VALUE str = global_symbols.op_sym[i = (int)id];
09741 if (!str) {
09742 char name[2];
09743 name[0] = (char)id;
09744 name[1] = 0;
09745 str = rb_usascii_str_new(name, 1);
09746 OBJ_FREEZE(str);
09747 global_symbols.op_sym[i] = str;
09748 }
09749 return str;
09750 }
09751 for (i = 0; i < op_tbl_count; i++) {
09752 if (op_tbl[i].token == id) {
09753 VALUE str = global_symbols.op_sym[i];
09754 if (!str) {
09755 str = rb_usascii_str_new2(op_tbl[i].name);
09756 OBJ_FREEZE(str);
09757 global_symbols.op_sym[i] = str;
09758 }
09759 return str;
09760 }
09761 }
09762 }
09763
09764 if (st_lookup(global_symbols.id_str, id, &data)) {
09765 VALUE str = (VALUE)data;
09766 if (RBASIC(str)->klass == 0)
09767 RBASIC(str)->klass = rb_cString;
09768 return str;
09769 }
09770
09771 if (is_attrset_id(id)) {
09772 ID id2 = (id & ~ID_SCOPE_MASK) | ID_LOCAL;
09773 VALUE str;
09774
09775 while (!(str = rb_id2str(id2))) {
09776 if (!is_local_id(id2)) return 0;
09777 id2 = (id & ~ID_SCOPE_MASK) | ID_CONST;
09778 }
09779 str = rb_str_dup(str);
09780 rb_str_cat(str, "=", 1);
09781 rb_intern_str(str);
09782 if (st_lookup(global_symbols.id_str, id, &data)) {
09783 VALUE str = (VALUE)data;
09784 if (RBASIC(str)->klass == 0)
09785 RBASIC(str)->klass = rb_cString;
09786 return str;
09787 }
09788 }
09789 return 0;
09790 }
09791
09792 const char *
09793 rb_id2name(ID id)
09794 {
09795 VALUE str = rb_id2str(id);
09796
09797 if (!str) return 0;
09798 return RSTRING_PTR(str);
09799 }
09800
09801 static int
09802 symbols_i(VALUE sym, ID value, VALUE ary)
09803 {
09804 rb_ary_push(ary, ID2SYM(value));
09805 return ST_CONTINUE;
09806 }
09807
09808
09809
09810
09811
09812
09813
09814
09815
09816
09817
09818
09819
09820
09821
09822
09823
09824 VALUE
09825 rb_sym_all_symbols(void)
09826 {
09827 VALUE ary = rb_ary_new2(global_symbols.sym_id->num_entries);
09828
09829 st_foreach(global_symbols.sym_id, symbols_i, ary);
09830 return ary;
09831 }
09832
09833 int
09834 rb_is_const_id(ID id)
09835 {
09836 return is_const_id(id);
09837 }
09838
09839 int
09840 rb_is_class_id(ID id)
09841 {
09842 return is_class_id(id);
09843 }
09844
09845 int
09846 rb_is_instance_id(ID id)
09847 {
09848 return is_instance_id(id);
09849 }
09850
09851 int
09852 rb_is_local_id(ID id)
09853 {
09854 return is_local_id(id);
09855 }
09856
09857 int
09858 rb_is_junk_id(ID id)
09859 {
09860 return is_junk_id(id);
09861 }
09862
09863 #endif
09864
09865 static void
09866 parser_initialize(struct parser_params *parser)
09867 {
09868 parser->eofp = Qfalse;
09869
09870 parser->parser_lex_strterm = 0;
09871 parser->parser_cond_stack = 0;
09872 parser->parser_cmdarg_stack = 0;
09873 parser->parser_class_nest = 0;
09874 parser->parser_paren_nest = 0;
09875 parser->parser_lpar_beg = 0;
09876 parser->parser_in_single = 0;
09877 parser->parser_in_def = 0;
09878 parser->parser_in_defined = 0;
09879 parser->parser_compile_for_eval = 0;
09880 parser->parser_cur_mid = 0;
09881 parser->parser_tokenbuf = NULL;
09882 parser->parser_tokidx = 0;
09883 parser->parser_toksiz = 0;
09884 parser->parser_heredoc_end = 0;
09885 parser->parser_command_start = TRUE;
09886 parser->parser_deferred_nodes = 0;
09887 parser->parser_lex_pbeg = 0;
09888 parser->parser_lex_p = 0;
09889 parser->parser_lex_pend = 0;
09890 parser->parser_lvtbl = 0;
09891 parser->parser_ruby__end__seen = 0;
09892 parser->parser_ruby_sourcefile = 0;
09893 #ifndef RIPPER
09894 parser->is_ripper = 0;
09895 parser->parser_eval_tree_begin = 0;
09896 parser->parser_eval_tree = 0;
09897 #else
09898 parser->is_ripper = 1;
09899 parser->parser_ruby_sourcefile_string = Qnil;
09900 parser->delayed = Qnil;
09901
09902 parser->result = Qnil;
09903 parser->parsing_thread = Qnil;
09904 parser->toplevel_p = TRUE;
09905 #endif
09906 #ifdef YYMALLOC
09907 parser->heap = NULL;
09908 #endif
09909 parser->enc = rb_usascii_encoding();
09910 }
09911
09912 #ifdef RIPPER
09913 #define parser_mark ripper_parser_mark
09914 #define parser_free ripper_parser_free
09915 #endif
09916
09917 static void
09918 parser_mark(void *ptr)
09919 {
09920 struct parser_params *p = (struct parser_params*)ptr;
09921
09922 rb_gc_mark((VALUE)p->parser_lex_strterm);
09923 rb_gc_mark((VALUE)p->parser_deferred_nodes);
09924 rb_gc_mark(p->parser_lex_input);
09925 rb_gc_mark(p->parser_lex_lastline);
09926 rb_gc_mark(p->parser_lex_nextline);
09927 #ifndef RIPPER
09928 rb_gc_mark((VALUE)p->parser_eval_tree_begin) ;
09929 rb_gc_mark((VALUE)p->parser_eval_tree) ;
09930 rb_gc_mark(p->debug_lines);
09931 #else
09932 rb_gc_mark(p->parser_ruby_sourcefile_string);
09933 rb_gc_mark(p->delayed);
09934 rb_gc_mark(p->value);
09935 rb_gc_mark(p->result);
09936 rb_gc_mark(p->parsing_thread);
09937 #endif
09938 #ifdef YYMALLOC
09939 rb_gc_mark((VALUE)p->heap);
09940 #endif
09941 }
09942
09943 static void
09944 parser_free(void *ptr)
09945 {
09946 struct parser_params *p = (struct parser_params*)ptr;
09947 struct local_vars *local, *prev;
09948
09949 if (p->parser_tokenbuf) {
09950 xfree(p->parser_tokenbuf);
09951 }
09952 for (local = p->parser_lvtbl; local; local = prev) {
09953 if (local->vars) xfree(local->vars);
09954 prev = local->prev;
09955 xfree(local);
09956 }
09957 #ifndef RIPPER
09958 xfree(p->parser_ruby_sourcefile);
09959 #endif
09960 xfree(p);
09961 }
09962
09963 static size_t
09964 parser_memsize(const void *ptr)
09965 {
09966 struct parser_params *p = (struct parser_params*)ptr;
09967 struct local_vars *local;
09968 size_t size = sizeof(*p);
09969
09970 if (!ptr) return 0;
09971 size += p->parser_toksiz;
09972 for (local = p->parser_lvtbl; local; local = local->prev) {
09973 size += sizeof(*local);
09974 if (local->vars) size += local->vars->capa * sizeof(ID);
09975 }
09976 #ifndef RIPPER
09977 if (p->parser_ruby_sourcefile) {
09978 size += strlen(p->parser_ruby_sourcefile) + 1;
09979 }
09980 #endif
09981 return size;
09982 }
09983
09984 static const rb_data_type_t parser_data_type = {
09985 "parser",
09986 parser_mark,
09987 parser_free,
09988 parser_memsize,
09989 };
09990
09991 VALUE rb_parser_get_yydebug(VALUE);
09992 VALUE rb_parser_set_yydebug(VALUE, VALUE);
09993
09994 #ifndef RIPPER
09995 #undef rb_reserved_word
09996
09997 const struct kwtable *
09998 rb_reserved_word(const char *str, unsigned int len)
09999 {
10000 return reserved_word(str, len);
10001 }
10002
10003 static struct parser_params *
10004 parser_new(void)
10005 {
10006 struct parser_params *p;
10007
10008 p = ALLOC_N(struct parser_params, 1);
10009 MEMZERO(p, struct parser_params, 1);
10010 parser_initialize(p);
10011 return p;
10012 }
10013
10014 VALUE
10015 rb_parser_new(void)
10016 {
10017 struct parser_params *p = parser_new();
10018
10019 return TypedData_Wrap_Struct(0, &parser_data_type, p);
10020 }
10021
10022
10023
10024
10025
10026
10027
10028
10029 VALUE
10030 rb_parser_end_seen_p(VALUE vparser)
10031 {
10032 struct parser_params *parser;
10033
10034 TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, parser);
10035 return ruby__end__seen ? Qtrue : Qfalse;
10036 }
10037
10038
10039
10040
10041
10042
10043
10044 VALUE
10045 rb_parser_encoding(VALUE vparser)
10046 {
10047 struct parser_params *parser;
10048
10049 TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, parser);
10050 return rb_enc_from_encoding(parser->enc);
10051 }
10052
10053
10054
10055
10056
10057
10058
10059 VALUE
10060 rb_parser_get_yydebug(VALUE self)
10061 {
10062 struct parser_params *parser;
10063
10064 TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
10065 return yydebug ? Qtrue : Qfalse;
10066 }
10067
10068
10069
10070
10071
10072
10073
10074 VALUE
10075 rb_parser_set_yydebug(VALUE self, VALUE flag)
10076 {
10077 struct parser_params *parser;
10078
10079 TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
10080 yydebug = RTEST(flag);
10081 return flag;
10082 }
10083
10084 #ifdef YYMALLOC
10085 #define HEAPCNT(n, size) ((n) * (size) / sizeof(YYSTYPE))
10086 #define NEWHEAP() rb_node_newnode(NODE_ALLOCA, 0, (VALUE)parser->heap, 0)
10087 #define ADD2HEAP(n, c, p) ((parser->heap = (n))->u1.node = (p), \
10088 (n)->u3.cnt = (c), (p))
10089
10090 void *
10091 rb_parser_malloc(struct parser_params *parser, size_t size)
10092 {
10093 size_t cnt = HEAPCNT(1, size);
10094 NODE *n = NEWHEAP();
10095 void *ptr = xmalloc(size);
10096
10097 return ADD2HEAP(n, cnt, ptr);
10098 }
10099
10100 void *
10101 rb_parser_calloc(struct parser_params *parser, size_t nelem, size_t size)
10102 {
10103 size_t cnt = HEAPCNT(nelem, size);
10104 NODE *n = NEWHEAP();
10105 void *ptr = xcalloc(nelem, size);
10106
10107 return ADD2HEAP(n, cnt, ptr);
10108 }
10109
10110 void *
10111 rb_parser_realloc(struct parser_params *parser, void *ptr, size_t size)
10112 {
10113 NODE *n;
10114 size_t cnt = HEAPCNT(1, size);
10115
10116 if (ptr && (n = parser->heap) != NULL) {
10117 do {
10118 if (n->u1.node == ptr) {
10119 n->u1.node = ptr = xrealloc(ptr, size);
10120 if (n->u3.cnt) n->u3.cnt = cnt;
10121 return ptr;
10122 }
10123 } while ((n = n->u2.node) != NULL);
10124 }
10125 n = NEWHEAP();
10126 ptr = xrealloc(ptr, size);
10127 return ADD2HEAP(n, cnt, ptr);
10128 }
10129
10130 void
10131 rb_parser_free(struct parser_params *parser, void *ptr)
10132 {
10133 NODE **prev = &parser->heap, *n;
10134
10135 while ((n = *prev) != NULL) {
10136 if (n->u1.node == ptr) {
10137 *prev = n->u2.node;
10138 rb_gc_force_recycle((VALUE)n);
10139 break;
10140 }
10141 prev = &n->u2.node;
10142 }
10143 xfree(ptr);
10144 }
10145 #endif
10146 #endif
10147
10148 #ifdef RIPPER
10149 #ifdef RIPPER_DEBUG
10150 extern int rb_is_pointer_to_heap(VALUE);
10151
10152
10153 static VALUE
10154 ripper_validate_object(VALUE self, VALUE x)
10155 {
10156 if (x == Qfalse) return x;
10157 if (x == Qtrue) return x;
10158 if (x == Qnil) return x;
10159 if (x == Qundef)
10160 rb_raise(rb_eArgError, "Qundef given");
10161 if (FIXNUM_P(x)) return x;
10162 if (SYMBOL_P(x)) return x;
10163 if (!rb_is_pointer_to_heap(x))
10164 rb_raise(rb_eArgError, "invalid pointer: %p", x);
10165 switch (TYPE(x)) {
10166 case T_STRING:
10167 case T_OBJECT:
10168 case T_ARRAY:
10169 case T_BIGNUM:
10170 case T_FLOAT:
10171 return x;
10172 case T_NODE:
10173 if (nd_type(x) != NODE_LASGN) {
10174 rb_raise(rb_eArgError, "NODE given: %p", x);
10175 }
10176 return ((NODE *)x)->nd_rval;
10177 default:
10178 rb_raise(rb_eArgError, "wrong type of ruby object: %p (%s)",
10179 x, rb_obj_classname(x));
10180 }
10181 return x;
10182 }
10183 #endif
10184
10185 #define validate(x) (x = get_value(x))
10186
10187 static VALUE
10188 ripper_dispatch0(struct parser_params *parser, ID mid)
10189 {
10190 return rb_funcall(parser->value, mid, 0);
10191 }
10192
10193 static VALUE
10194 ripper_dispatch1(struct parser_params *parser, ID mid, VALUE a)
10195 {
10196 validate(a);
10197 return rb_funcall(parser->value, mid, 1, a);
10198 }
10199
10200 static VALUE
10201 ripper_dispatch2(struct parser_params *parser, ID mid, VALUE a, VALUE b)
10202 {
10203 validate(a);
10204 validate(b);
10205 return rb_funcall(parser->value, mid, 2, a, b);
10206 }
10207
10208 static VALUE
10209 ripper_dispatch3(struct parser_params *parser, ID mid, VALUE a, VALUE b, VALUE c)
10210 {
10211 validate(a);
10212 validate(b);
10213 validate(c);
10214 return rb_funcall(parser->value, mid, 3, a, b, c);
10215 }
10216
10217 static VALUE
10218 ripper_dispatch4(struct parser_params *parser, ID mid, VALUE a, VALUE b, VALUE c, VALUE d)
10219 {
10220 validate(a);
10221 validate(b);
10222 validate(c);
10223 validate(d);
10224 return rb_funcall(parser->value, mid, 4, a, b, c, d);
10225 }
10226
10227 static VALUE
10228 ripper_dispatch5(struct parser_params *parser, ID mid, VALUE a, VALUE b, VALUE c, VALUE d, VALUE e)
10229 {
10230 validate(a);
10231 validate(b);
10232 validate(c);
10233 validate(d);
10234 validate(e);
10235 return rb_funcall(parser->value, mid, 5, a, b, c, d, e);
10236 }
10237
10238 static const struct kw_assoc {
10239 ID id;
10240 const char *name;
10241 } keyword_to_name[] = {
10242 {keyword_class, "class"},
10243 {keyword_module, "module"},
10244 {keyword_def, "def"},
10245 {keyword_undef, "undef"},
10246 {keyword_begin, "begin"},
10247 {keyword_rescue, "rescue"},
10248 {keyword_ensure, "ensure"},
10249 {keyword_end, "end"},
10250 {keyword_if, "if"},
10251 {keyword_unless, "unless"},
10252 {keyword_then, "then"},
10253 {keyword_elsif, "elsif"},
10254 {keyword_else, "else"},
10255 {keyword_case, "case"},
10256 {keyword_when, "when"},
10257 {keyword_while, "while"},
10258 {keyword_until, "until"},
10259 {keyword_for, "for"},
10260 {keyword_break, "break"},
10261 {keyword_next, "next"},
10262 {keyword_redo, "redo"},
10263 {keyword_retry, "retry"},
10264 {keyword_in, "in"},
10265 {keyword_do, "do"},
10266 {keyword_do_cond, "do"},
10267 {keyword_do_block, "do"},
10268 {keyword_return, "return"},
10269 {keyword_yield, "yield"},
10270 {keyword_super, "super"},
10271 {keyword_self, "self"},
10272 {keyword_nil, "nil"},
10273 {keyword_true, "true"},
10274 {keyword_false, "false"},
10275 {keyword_and, "and"},
10276 {keyword_or, "or"},
10277 {keyword_not, "not"},
10278 {modifier_if, "if"},
10279 {modifier_unless, "unless"},
10280 {modifier_while, "while"},
10281 {modifier_until, "until"},
10282 {modifier_rescue, "rescue"},
10283 {keyword_alias, "alias"},
10284 {keyword_defined, "defined?"},
10285 {keyword_BEGIN, "BEGIN"},
10286 {keyword_END, "END"},
10287 {keyword__LINE__, "__LINE__"},
10288 {keyword__FILE__, "__FILE__"},
10289 {keyword__ENCODING__, "__ENCODING__"},
10290 {0, NULL}
10291 };
10292
10293 static const char*
10294 keyword_id_to_str(ID id)
10295 {
10296 const struct kw_assoc *a;
10297
10298 for (a = keyword_to_name; a->id; a++) {
10299 if (a->id == id)
10300 return a->name;
10301 }
10302 return NULL;
10303 }
10304
10305 #undef ripper_id2sym
10306 static VALUE
10307 ripper_id2sym(ID id)
10308 {
10309 const char *name;
10310 char buf[8];
10311
10312 if (id <= 256) {
10313 buf[0] = (char)id;
10314 buf[1] = '\0';
10315 return ID2SYM(rb_intern2(buf, 1));
10316 }
10317 if ((name = keyword_id_to_str(id))) {
10318 return ID2SYM(rb_intern(name));
10319 }
10320 switch (id) {
10321 case tOROP:
10322 name = "||";
10323 break;
10324 case tANDOP:
10325 name = "&&";
10326 break;
10327 default:
10328 name = rb_id2name(id);
10329 if (!name) {
10330 rb_bug("cannot convert ID to string: %ld", (unsigned long)id);
10331 }
10332 return ID2SYM(id);
10333 }
10334 return ID2SYM(rb_intern(name));
10335 }
10336
10337 static ID
10338 ripper_get_id(VALUE v)
10339 {
10340 NODE *nd;
10341 if (!RB_TYPE_P(v, T_NODE)) return 0;
10342 nd = (NODE *)v;
10343 if (nd_type(nd) != NODE_LASGN) return 0;
10344 return nd->nd_vid;
10345 }
10346
10347 static VALUE
10348 ripper_get_value(VALUE v)
10349 {
10350 NODE *nd;
10351 if (v == Qundef) return Qnil;
10352 if (!RB_TYPE_P(v, T_NODE)) return v;
10353 nd = (NODE *)v;
10354 if (nd_type(nd) != NODE_LASGN) return Qnil;
10355 return nd->nd_rval;
10356 }
10357
10358 static void
10359 ripper_compile_error(struct parser_params *parser, const char *fmt, ...)
10360 {
10361 VALUE str;
10362 va_list args;
10363
10364 va_start(args, fmt);
10365 str = rb_vsprintf(fmt, args);
10366 va_end(args);
10367 rb_funcall(parser->value, rb_intern("compile_error"), 1, str);
10368 }
10369
10370 static void
10371 ripper_warn0(struct parser_params *parser, const char *fmt)
10372 {
10373 rb_funcall(parser->value, rb_intern("warn"), 1, STR_NEW2(fmt));
10374 }
10375
10376 static void
10377 ripper_warnI(struct parser_params *parser, const char *fmt, int a)
10378 {
10379 rb_funcall(parser->value, rb_intern("warn"), 2,
10380 STR_NEW2(fmt), INT2NUM(a));
10381 }
10382
10383 #if 0
10384 static void
10385 ripper_warnS(struct parser_params *parser, const char *fmt, const char *str)
10386 {
10387 rb_funcall(parser->value, rb_intern("warn"), 2,
10388 STR_NEW2(fmt), STR_NEW2(str));
10389 }
10390 #endif
10391
10392 static void
10393 ripper_warning0(struct parser_params *parser, const char *fmt)
10394 {
10395 rb_funcall(parser->value, rb_intern("warning"), 1, STR_NEW2(fmt));
10396 }
10397
10398 static void
10399 ripper_warningS(struct parser_params *parser, const char *fmt, const char *str)
10400 {
10401 rb_funcall(parser->value, rb_intern("warning"), 2,
10402 STR_NEW2(fmt), STR_NEW2(str));
10403 }
10404
10405 static VALUE
10406 ripper_lex_get_generic(struct parser_params *parser, VALUE src)
10407 {
10408 return rb_funcall(src, ripper_id_gets, 0);
10409 }
10410
10411 static VALUE
10412 ripper_s_allocate(VALUE klass)
10413 {
10414 struct parser_params *p;
10415 VALUE self;
10416
10417 p = ALLOC_N(struct parser_params, 1);
10418 MEMZERO(p, struct parser_params, 1);
10419 self = TypedData_Wrap_Struct(klass, &parser_data_type, p);
10420 p->value = self;
10421 return self;
10422 }
10423
10424 #define ripper_initialized_p(r) ((r)->parser_lex_input != 0)
10425
10426
10427
10428
10429
10430
10431
10432
10433
10434
10435
10436 static VALUE
10437 ripper_initialize(int argc, VALUE *argv, VALUE self)
10438 {
10439 struct parser_params *parser;
10440 VALUE src, fname, lineno;
10441
10442 TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
10443 rb_scan_args(argc, argv, "12", &src, &fname, &lineno);
10444 if (rb_obj_respond_to(src, ripper_id_gets, 0)) {
10445 parser->parser_lex_gets = ripper_lex_get_generic;
10446 }
10447 else {
10448 StringValue(src);
10449 parser->parser_lex_gets = lex_get_str;
10450 }
10451 parser->parser_lex_input = src;
10452 parser->eofp = Qfalse;
10453 if (NIL_P(fname)) {
10454 fname = STR_NEW2("(ripper)");
10455 }
10456 else {
10457 StringValue(fname);
10458 }
10459 parser_initialize(parser);
10460
10461 parser->parser_ruby_sourcefile_string = fname;
10462 parser->parser_ruby_sourcefile = RSTRING_PTR(fname);
10463 parser->parser_ruby_sourceline = NIL_P(lineno) ? 0 : NUM2INT(lineno) - 1;
10464
10465 return Qnil;
10466 }
10467
10468 extern VALUE rb_thread_pass(void);
10469
10470 struct ripper_args {
10471 struct parser_params *parser;
10472 int argc;
10473 VALUE *argv;
10474 };
10475
10476 static VALUE
10477 ripper_parse0(VALUE parser_v)
10478 {
10479 struct parser_params *parser;
10480
10481 TypedData_Get_Struct(parser_v, struct parser_params, &parser_data_type, parser);
10482 parser_prepare(parser);
10483 ripper_yyparse((void*)parser);
10484 return parser->result;
10485 }
10486
10487 static VALUE
10488 ripper_ensure(VALUE parser_v)
10489 {
10490 struct parser_params *parser;
10491
10492 TypedData_Get_Struct(parser_v, struct parser_params, &parser_data_type, parser);
10493 parser->parsing_thread = Qnil;
10494 return Qnil;
10495 }
10496
10497
10498
10499
10500
10501
10502
10503 static VALUE
10504 ripper_parse(VALUE self)
10505 {
10506 struct parser_params *parser;
10507
10508 TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
10509 if (!ripper_initialized_p(parser)) {
10510 rb_raise(rb_eArgError, "method called for uninitialized object");
10511 }
10512 if (!NIL_P(parser->parsing_thread)) {
10513 if (parser->parsing_thread == rb_thread_current())
10514 rb_raise(rb_eArgError, "Ripper#parse is not reentrant");
10515 else
10516 rb_raise(rb_eArgError, "Ripper#parse is not multithread-safe");
10517 }
10518 parser->parsing_thread = rb_thread_current();
10519 rb_ensure(ripper_parse0, self, ripper_ensure, self);
10520
10521 return parser->result;
10522 }
10523
10524
10525
10526
10527
10528
10529
10530
10531 static VALUE
10532 ripper_column(VALUE self)
10533 {
10534 struct parser_params *parser;
10535 long col;
10536
10537 TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
10538 if (!ripper_initialized_p(parser)) {
10539 rb_raise(rb_eArgError, "method called for uninitialized object");
10540 }
10541 if (NIL_P(parser->parsing_thread)) return Qnil;
10542 col = parser->tokp - parser->parser_lex_pbeg;
10543 return LONG2NUM(col);
10544 }
10545
10546
10547
10548
10549
10550
10551
10552 static VALUE
10553 ripper_filename(VALUE self)
10554 {
10555 struct parser_params *parser;
10556
10557 TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
10558 if (!ripper_initialized_p(parser)) {
10559 rb_raise(rb_eArgError, "method called for uninitialized object");
10560 }
10561 return parser->parser_ruby_sourcefile_string;
10562 }
10563
10564
10565
10566
10567
10568
10569
10570
10571 static VALUE
10572 ripper_lineno(VALUE self)
10573 {
10574 struct parser_params *parser;
10575
10576 TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
10577 if (!ripper_initialized_p(parser)) {
10578 rb_raise(rb_eArgError, "method called for uninitialized object");
10579 }
10580 if (NIL_P(parser->parsing_thread)) return Qnil;
10581 return INT2NUM(parser->parser_ruby_sourceline);
10582 }
10583
10584 #ifdef RIPPER_DEBUG
10585
10586 static VALUE
10587 ripper_assert_Qundef(VALUE self, VALUE obj, VALUE msg)
10588 {
10589 StringValue(msg);
10590 if (obj == Qundef) {
10591 rb_raise(rb_eArgError, "%s", RSTRING_PTR(msg));
10592 }
10593 return Qnil;
10594 }
10595
10596
10597 static VALUE
10598 ripper_value(VALUE self, VALUE obj)
10599 {
10600 return ULONG2NUM(obj);
10601 }
10602 #endif
10603
10604 void
10605 Init_ripper(void)
10606 {
10607 VALUE Ripper;
10608
10609 Ripper = rb_define_class("Ripper", rb_cObject);
10610 rb_define_const(Ripper, "Version", rb_usascii_str_new2(RIPPER_VERSION));
10611 rb_define_alloc_func(Ripper, ripper_s_allocate);
10612 rb_define_method(Ripper, "initialize", ripper_initialize, -1);
10613 rb_define_method(Ripper, "parse", ripper_parse, 0);
10614 rb_define_method(Ripper, "column", ripper_column, 0);
10615 rb_define_method(Ripper, "filename", ripper_filename, 0);
10616 rb_define_method(Ripper, "lineno", ripper_lineno, 0);
10617 rb_define_method(Ripper, "end_seen?", rb_parser_end_seen_p, 0);
10618 rb_define_method(Ripper, "encoding", rb_parser_encoding, 0);
10619 rb_define_method(Ripper, "yydebug", rb_parser_get_yydebug, 0);
10620 rb_define_method(Ripper, "yydebug=", rb_parser_set_yydebug, 1);
10621 #ifdef RIPPER_DEBUG
10622 rb_define_method(rb_mKernel, "assert_Qundef", ripper_assert_Qundef, 2);
10623 rb_define_method(rb_mKernel, "rawVALUE", ripper_value, 1);
10624 rb_define_method(rb_mKernel, "validate_object", ripper_validate_object, 1);
10625 #endif
10626
10627 ripper_id_gets = rb_intern("gets");
10628 ripper_init_eventids1(Ripper);
10629 ripper_init_eventids2(Ripper);
10630
10631 rb_intern("||");
10632 rb_intern("&&");
10633 }
10634 #endif
10635