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