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