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