Ruby 2.0.0p247(2013-06-27revision41674)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

Data Structures | Macros | Typedefs | Enumerations | Functions | Variables
parse.y File Reference
`#include "ruby/ruby.h"`
`#include "ruby/st.h"`
`#include "ruby/encoding.h"`
`#include "internal.h"`
`#include "node.h"`
`#include "parse.h"`
`#include "id.h"`
`#include "regenc.h"`
`#include <stdio.h>`
`#include <errno.h>`
`#include <ctype.h>`
`#include "probes.h"`
`#include "id.c"`
`#include "ruby/regex.h"`
`#include "ruby/util.h"`
`#include "lex.c"`
Include dependency graph for parse.y:

Go to the source code of this file.

## Data Structures
struct | vtable
struct | local_vars
struct | token_info
struct | parser_params

## Macros
#define | PARSER_DEBUG 0
#define | YYDEBUG 1
#define | YYERROR_VERBOSE 1
#define | YYSTACK_USE_ALLOCA 0
#define | numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
#define | YYMALLOC(size) rb_parser_malloc(parser, (size))
#define | YYREALLOC(ptr, size) rb_parser_realloc(parser, (ptr), (size))
#define | YYCALLOC(nelem, size) rb_parser_calloc(parser, (nelem), (size))
#define | YYFREE(ptr) rb_parser_free(parser, (ptr))
#define | malloc YYMALLOC
#define | realloc YYREALLOC
#define | calloc YYCALLOC
#define | free YYFREE
#define | REGISTER_SYMID(id, name) register_symid((id), (name), strlen(name), enc)
#define | is_notop_id(id) ((id)>tLAST_OP_ID)
#define | is_local_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_LOCAL)
#define | is_global_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_GLOBAL)
#define | is_instance_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_INSTANCE)
#define | is_attrset_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_ATTRSET)
#define | is_const_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CONST)
#define | is_class_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CLASS)
#define | is_junk_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_JUNK)
#define | id_type(id) (is_notop_id(id) ? (int)((id)&ID_SCOPE_MASK) : -1)
#define | is_asgn_or_id(id)
#define | DEF_EXPR(n) EXPR_##n = (1 << EXPR_##n##_bit)
#define | IS_lex_state_for(x, ls) ((x) & (ls))
#define | IS_lex_state(ls) IS_lex_state_for(lex_state, (ls))
#define | BITSTACK_PUSH(stack, n) ((stack) = ((stack)<<1)|((n)&1))
#define | BITSTACK_POP(stack) ((stack) = (stack) >> 1)
#define | BITSTACK_LEXPOP(stack) ((stack) = ((stack) >> 1) | ((stack) & 1))
#define | BITSTACK_SET_P(stack) ((stack)&1)
#define | COND_PUSH(n) BITSTACK_PUSH(cond_stack, (n))
#define | COND_POP() BITSTACK_POP(cond_stack)
#define | COND_LEXPOP() BITSTACK_LEXPOP(cond_stack)
#define | COND_P() BITSTACK_SET_P(cond_stack)
#define | CMDARG_PUSH(n) BITSTACK_PUSH(cmdarg_stack, (n))
#define | CMDARG_POP() BITSTACK_POP(cmdarg_stack)
#define | CMDARG_LEXPOP() BITSTACK_LEXPOP(cmdarg_stack)
#define | CMDARG_P() BITSTACK_SET_P(cmdarg_stack)
#define | DVARS_INHERIT ((void*)1)
#define | DVARS_TOPSCOPE NULL
#define | DVARS_SPECIAL_P(tbl) (!POINTER_P(tbl))
#define | POINTER_P(val) ((VALUE)(val) & ~(VALUE)3)
#define | VTBL_DEBUG 0
#define | STR_NEW(p, n) rb_enc_str_new((p),(n),current_enc)
#define | STR_NEW0() rb_enc_str_new(0,0,current_enc)
#define | STR_NEW2(p) rb_enc_str_new((p),strlen(p),current_enc)
#define | STR_NEW3(p, n, e, func) parser_str_new((p),(n),(e),(func),current_enc)
#define | ENC_SINGLE(cr) ((cr)==ENC_CODERANGE_7BIT)
#define | TOK_INTERN(mb) rb_intern3(tok(), toklen(), current_enc)
#define | yyerror(msg) parser_yyerror(parser, (msg))
#define | YYLEX_PARAM parser
#define | lex_strterm (parser->parser_lex_strterm)
#define | lex_state (parser->parser_lex_state)
#define | cond_stack (parser->parser_cond_stack)
#define | cmdarg_stack (parser->parser_cmdarg_stack)
#define | class_nest (parser->parser_class_nest)
#define | paren_nest (parser->parser_paren_nest)
#define | lpar_beg (parser->parser_lpar_beg)
#define | brace_nest (parser->parser_brace_nest)
#define | in_single (parser->parser_in_single)
#define | in_def (parser->parser_in_def)
#define | compile_for_eval (parser->parser_compile_for_eval)
#define | cur_mid (parser->parser_cur_mid)
#define | in_defined (parser->parser_in_defined)
#define | tokenbuf (parser->parser_tokenbuf)
#define | tokidx (parser->parser_tokidx)
#define | toksiz (parser->parser_toksiz)
#define | tokline (parser->parser_tokline)
#define | lex_input (parser->parser_lex_input)
#define | lex_lastline (parser->parser_lex_lastline)
#define | lex_nextline (parser->parser_lex_nextline)
#define | lex_pbeg (parser->parser_lex_pbeg)
#define | lex_p (parser->parser_lex_p)
#define | lex_pend (parser->parser_lex_pend)
#define | heredoc_end (parser->parser_heredoc_end)
#define | command_start (parser->parser_command_start)
#define | deferred_nodes (parser->parser_deferred_nodes)
#define | lex_gets_ptr (parser->parser_lex_gets_ptr)
#define | lex_gets (parser->parser_lex_gets)
#define | lvtbl (parser->parser_lvtbl)
#define | ruby__end__seen (parser->parser_ruby__end__seen)
#define | ruby_sourceline (parser->parser_ruby_sourceline)
#define | ruby_sourcefile (parser->parser_ruby_sourcefile)
#define | current_enc (parser->enc)
#define | yydebug (parser->parser_yydebug)
#define | ruby_eval_tree (parser->parser_eval_tree)
#define | ruby_eval_tree_begin (parser->parser_eval_tree_begin)
#define | ruby_debug_lines (parser->debug_lines)
#define | ruby_coverage (parser->coverage)
#define | yyparse ruby_yyparse
#define | rb_node_newnode(type, a1, a2, a3) node_newnode(parser, (type), (a1), (a2), (a3))
#define | cond(node) cond_gen(parser, (node))
#define | logop(type, node1, node2) logop_gen(parser, (type), (node1), (node2))
#define | value_expr(node) value_expr_gen(parser, (node) = remove_begin(node))
#define | void_expr0(node) void_expr_gen(parser, (node))
#define | void_expr(node) void_expr0((node) = remove_begin(node))
#define | void_stmts(node) void_stmts_gen(parser, (node))
#define | reduce_nodes(n) reduce_nodes_gen(parser,(n))
#define | block_dup_check(n1, n2) block_dup_check_gen(parser,(n1),(n2))
#define | block_append(h, t) block_append_gen(parser,(h),(t))
#define | list_append(l, i) list_append_gen(parser,(l),(i))
#define | list_concat(h, t) list_concat_gen(parser,(h),(t))
#define | arg_append(h, t) arg_append_gen(parser,(h),(t))
#define | arg_concat(h, t) arg_concat_gen(parser,(h),(t))
#define | literal_concat(h, t) literal_concat_gen(parser,(h),(t))
#define | new_evstr(n) new_evstr_gen(parser,(n))
#define | evstr2dstr(n) evstr2dstr_gen(parser,(n))
#define | call_bin_op(recv, id, arg1) call_bin_op_gen(parser, (recv),(id),(arg1))
#define | call_uni_op(recv, id) call_uni_op_gen(parser, (recv),(id))
#define | new_args(f, o, r, p, t) new_args_gen(parser, (f),(o),(r),(p),(t))
#define | new_args_tail(k, kr, b) new_args_tail_gen(parser, (k),(kr),(b))
#define | ret_args(node) ret_args_gen(parser, (node))
#define | new_yield(node) new_yield_gen(parser, (node))
#define | dsym_node(node) dsym_node_gen(parser, (node))
#define | gettable(id) gettable_gen(parser,(id))
#define | assignable(id, node) assignable_gen(parser, (id), (node))
#define | aryset(node1, node2) aryset_gen(parser, (node1), (node2))
#define | attrset(node, id) attrset_gen(parser, (node), (id))
#define | rb_backref_error(n) rb_backref_error_gen(parser,(n))
#define | node_assign(node1, node2) node_assign_gen(parser, (node1), (node2))
#define | new_attr_op_assign(lhs, type, attr, op, rhs) new_attr_op_assign_gen(parser, (lhs), (attr), (op), (rhs))
#define | new_const_op_assign(lhs, op, rhs) new_const_op_assign_gen(parser, (lhs), (op), (rhs))
#define | match_op(node1, node2) match_op_gen(parser, (node1), (node2))
#define | local_tbl() local_tbl_gen(parser)
#define | reg_compile(str, options) reg_compile_gen(parser, (str), (options))
#define | reg_fragment_setenc(str, options) reg_fragment_setenc_gen(parser, (str), (options))
#define | reg_fragment_check(str, options) reg_fragment_check_gen(parser, (str), (options))
#define | reg_named_capture_assign(regexp, match) reg_named_capture_assign_gen(parser,(regexp),(match))
#define | get_id(id) (id)
#define | get_value(val) (val)
#define | new_op_assign(lhs, op, rhs) new_op_assign_gen(parser, (lhs), (op), (rhs))
#define | formal_argument(id) formal_argument_gen(parser, (id))
#define | shadowing_lvar(name) shadowing_lvar_gen(parser, (name))
#define | new_bv(id) new_bv_gen(parser, (id))
#define | local_push(top) local_push_gen(parser,(top))
#define | local_pop() local_pop_gen(parser)
#define | local_var(id) local_var_gen(parser, (id))
#define | arg_var(id) arg_var_gen(parser, (id))
#define | local_id(id) local_id_gen(parser, (id))
#define | internal_id() internal_id_gen(parser)
#define | dyna_push() dyna_push_gen(parser)
#define | dyna_pop(node) dyna_pop_gen(parser, (node))
#define | dyna_in_block() dyna_in_block_gen(parser)
#define | dyna_var(id) local_var(id)
#define | dvar_defined(id) dvar_defined_gen(parser, (id), 0)
#define | dvar_defined_get(id) dvar_defined_gen(parser, (id), 1)
#define | dvar_curr(id) dvar_curr_gen(parser, (id))
#define | lvar_defined(id) lvar_defined_gen(parser, (id))
#define | RE_OPTION_ONCE (1<<16)
#define | RE_OPTION_ENCODING_SHIFT 8
#define | RE_OPTION_ENCODING(e) (((e)&0xff)<<RE_OPTION_ENCODING_SHIFT)
#define | RE_OPTION_ENCODING_IDX(o) (((o)>>RE_OPTION_ENCODING_SHIFT)&0xff)
#define | RE_OPTION_ENCODING_NONE(o) ((o)&RE_OPTION_ARG_ENCODING_NONE)
#define | RE_OPTION_MASK 0xff
#define | RE_OPTION_ARG_ENCODING_NONE 32
#define | NODE_STRTERM NODE_ZARRAY /* nothing to gc */
#define | NODE_HEREDOC NODE_ARRAY /* 1, 3 to gc */
#define | SIGN_EXTEND(x, n) (((1<<(n)-1)^((x)&~(~0<<(n))))-(1<<(n)-1))
#define | nd_func u1.id
#define | nd_term(node) SIGN_EXTEND((node)->u2.id, CHAR_BIT*2)
#define | nd_paren(node) (char)((node)->u2.id >> CHAR_BIT*2)
#define | nd_nest u3.cnt
#define | Qnone 0
#define | ifndef_ripper(x) (x)
#define | rb_warn0(fmt) rb_compile_warn(ruby_sourcefile, ruby_sourceline, (fmt))
#define | rb_warnI(fmt, a) rb_compile_warn(ruby_sourcefile, ruby_sourceline, (fmt), (a))
#define | rb_warnS(fmt, a) rb_compile_warn(ruby_sourcefile, ruby_sourceline, (fmt), (a))
#define | rb_warn4S(file, line, fmt, a) rb_compile_warn((file), (line), (fmt), (a))
#define | rb_warning0(fmt) rb_compile_warning(ruby_sourcefile, ruby_sourceline, (fmt))
#define | rb_warningS(fmt, a) rb_compile_warning(ruby_sourcefile, ruby_sourceline, (fmt), (a))
#define | rb_compile_error rb_compile_error_with_enc
#define | compile_error parser->nerr++,rb_compile_error_with_enc
#define | PARSER_ARG ruby_sourcefile, ruby_sourceline, current_enc,
#define | token_info_push(token) (RTEST(ruby_verbose) ? token_info_push(parser, (token)) : (void)0)
#define | token_info_pop(token) (RTEST(ruby_verbose) ? token_info_pop(parser, (token)) : (void)0)
#define | yylval (*((YYSTYPE*)(parser->parser_yylval)))
#define | nextc() parser_nextc(parser)
#define | pushback(c) parser_pushback(parser, (c))
#define | newtok() parser_newtok(parser)
#define | tokspace(n) parser_tokspace(parser, (n))
#define | tokadd(c) parser_tokadd(parser, (c))
#define | tok_hex(numlen) parser_tok_hex(parser, (numlen))
#define | read_escape(flags, e) parser_read_escape(parser, (flags), (e))
#define | tokadd_escape(e) parser_tokadd_escape(parser, (e))
#define | regx_options() parser_regx_options(parser)
#define | tokadd_string(f, t, p, n, e) parser_tokadd_string(parser,(f),(t),(p),(n),(e))
#define | parse_string(n) parser_parse_string(parser,(n))
#define | tokaddmbc(c, enc) parser_tokaddmbc(parser, (c), (enc))
#define | here_document(n) parser_here_document(parser,(n))
#define | heredoc_identifier() parser_heredoc_identifier(parser)
#define | heredoc_restore(n) parser_heredoc_restore(parser,(n))
#define | whole_match_p(e, l, i) parser_whole_match_p(parser,(e),(l),(i))
#define | set_yylval_str(x) (yylval.node = NEW_STR(x))
#define | set_yylval_num(x) (yylval.num = (x))
#define | set_yylval_id(x) (yylval.id = (x))
#define | set_yylval_name(x) (yylval.id = (x))
#define | set_yylval_literal(x) (yylval.node = NEW_LIT(x))
#define | set_yylval_node(x) (yylval.node = (x))
#define | yylval_id() (yylval.id)
#define | ripper_flush(p) (void)(p)
#define | SIGN_EXTEND_CHAR(c) ((((unsigned char)(c)) ^ 128) - 128)
#define | parser_encoding_name() (current_enc->name)
#define | parser_mbclen() mbclen((lex_p-1),lex_pend,current_enc)
#define | parser_precise_mbclen() rb_enc_precise_mbclen((lex_p-1),lex_pend,current_enc)
#define | is_identchar(p, e, enc) (rb_enc_isalnum(*(p),(enc)) || (*(p)) == '_' || !ISASCII(*(p)))
#define | parser_is_identchar() (!parser->eofp && is_identchar((lex_p-1),lex_pend,current_enc))
#define | parser_isascii() ISASCII(*(lex_p-1))
#define | STR_FUNC_ESCAPE 0x01
#define | STR_FUNC_EXPAND 0x02
#define | STR_FUNC_REGEXP 0x04
#define | STR_FUNC_QWORDS 0x08
#define | STR_FUNC_SYMBOL 0x10
#define | STR_FUNC_INDENT 0x20
#define | lex_goto_eol(parser) ((parser)->parser_lex_p = (parser)->parser_lex_pend)
#define | lex_eol_p() (lex_p >= lex_pend)
#define | peek(c) peek_n((c), 0)
#define | peek_n(c, n) (lex_p+(n) < lex_pend && (c) == (unsigned char)lex_p[n])
#define | was_bol() (lex_p == lex_pbeg + 1)
#define | tokfix() (tokenbuf[tokidx]='\0')
#define | tok() tokenbuf
#define | toklen() tokidx
#define | toklast() (tokidx>0?tokenbuf[tokidx-1]:0)
#define | tokcopy(n) memcpy(tokspace(n), lex_p - (n), (n))
#define | ESCAPE_CONTROL 1
#define | ESCAPE_META 2
#define | tokadd_mbchar(c) parser_tokadd_mbchar(parser, (c))
#define | mixed_error(enc1, enc2)
#define | mixed_escape(beg, enc1, enc2)
#define | NEW_STRTERM(func, term, paren) rb_node_newnode(NODE_STRTERM, (func), (term) | ((paren) << (CHAR_BIT * 2)), 0)
#define | flush_string_content(enc) ((void)(enc))
#define | BIT(c, idx) (((c) / 32 - 1 == idx) ? (1U << ((c) % 32)) : 0)
#define | SPECIAL_PUNCT(idx)
#define | dispatch_heredoc_end() ((void)0)
#define | arg_ambiguous() (arg_ambiguous_gen(parser), 1)
#define | str_copy(_s, _p, _n)
#define | IS_ARG() IS_lex_state(EXPR_ARG_ANY)
#define | IS_END() IS_lex_state(EXPR_END_ANY)
#define | IS_BEG() IS_lex_state(EXPR_BEG_ANY)
#define | IS_SPCARG(c) (IS_ARG() && space_seen && !ISSPACE(c))
#define | IS_LABEL_POSSIBLE() ((IS_lex_state(EXPR_BEG | EXPR_ENDFN) && !cmd_state) || IS_ARG())
#define | IS_LABEL_SUFFIX(n) (peek_n(':',(n)) && !peek_n(':', (n)+1))
#define | IS_AFTER_OPERATOR() IS_lex_state(EXPR_FNAME | EXPR_DOT)
#define | ambiguous_operator(op, syn)
#define | warn_balanced(op, syn)
#define | no_digits() do {yyerror("numeric literal without digits"); return 0;} while (0)
#define | parser_warning(node, mesg) parser_warning(parser, (node), (mesg))
#define | parser_warn(node, mesg) parser_warn(parser, (node), (mesg))
#define | assignable_result(x) (x)
#define | LVAR_USED ((ID)1 << (sizeof(ID) * CHAR_BIT - 1))
#define | subnodes(n1, n2)
#define | op_tbl_count numberof(op_tbl)
#define | ENABLE_SELECTOR_NAMESPACE 0
#define | HEAPCNT(n, size) ((n) * (size) / sizeof(YYSTYPE))
#define | NEWHEAP() rb_node_newnode(NODE_ALLOCA, 0, (VALUE)parser->heap, 0)
#define | ADD2HEAP(n, c, p)

## Typedefs
typedef VALUE | stack_type
typedef struct token_info | token_info

## Enumerations
enum | lex_state_bits { EXPR_BEG_bit, EXPR_END_bit, EXPR_ENDARG_bit, EXPR_ENDFN_bit, EXPR_ARG_bit, EXPR_CMDARG_bit, EXPR_MID_bit, EXPR_FNAME_bit, EXPR_DOT_bit, EXPR_CLASS_bit, EXPR_VALUE_bit, EXPR_MAX_STATE, EXPR_BEG_bit, EXPR_END_bit, EXPR_ENDARG_bit, EXPR_ENDFN_bit, EXPR_ARG_bit, EXPR_CMDARG_bit, EXPR_MID_bit, EXPR_FNAME_bit, EXPR_DOT_bit, EXPR_CLASS_bit, EXPR_VALUE_bit, EXPR_MAX_STATE, EXPR_BEG_bit, EXPR_END_bit, EXPR_ENDARG_bit, EXPR_ENDFN_bit, EXPR_ARG_bit, EXPR_CMDARG_bit, EXPR_MID_bit, EXPR_FNAME_bit, EXPR_DOT_bit, EXPR_CLASS_bit, EXPR_VALUE_bit, EXPR_MAX_STATE, EXPR_BEG_bit, EXPR_END_bit, EXPR_ENDARG_bit, EXPR_ENDFN_bit, EXPR_ARG_bit, EXPR_CMDARG_bit, EXPR_MID_bit, EXPR_FNAME_bit, EXPR_DOT_bit, EXPR_CLASS_bit, EXPR_VALUE_bit, EXPR_MAX_STATE }
enum | lex_state_e { DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), EXPR_BEG_ANY = (EXPR_BEG | EXPR_VALUE | EXPR_MID | EXPR_CLASS), EXPR_ARG_ANY = (EXPR_ARG | EXPR_CMDARG), EXPR_END_ANY = (EXPR_END | EXPR_ENDARG | EXPR_ENDFN), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), EXPR_BEG_ANY = (EXPR_BEG | EXPR_VALUE | EXPR_MID | EXPR_CLASS), EXPR_ARG_ANY = (EXPR_ARG | EXPR_CMDARG), EXPR_END_ANY = (EXPR_END | EXPR_ENDARG | EXPR_ENDFN), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), EXPR_BEG_ANY = (EXPR_BEG | EXPR_VALUE | EXPR_MID | EXPR_CLASS), EXPR_ARG_ANY = (EXPR_ARG | EXPR_CMDARG), EXPR_END_ANY = (EXPR_END | EXPR_ENDARG | EXPR_ENDFN), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), EXPR_BEG_ANY = (EXPR_BEG | EXPR_VALUE | EXPR_MID | EXPR_CLASS), EXPR_ARG_ANY = (EXPR_ARG | EXPR_CMDARG), EXPR_END_ANY = (EXPR_END | EXPR_ENDARG | EXPR_ENDFN) }

## Functions
static ID | register_symid_str (ID, VALUE)
static void | Init_id (void)
static int | vtable_size (const struct vtable *tbl)
static struct vtable * | vtable_alloc (struct vtable *prev)
static void | vtable_free (struct vtable *tbl)
static void | vtable_add (struct vtable *tbl, ID id)
static int | vtable_included (const struct vtable *tbl, ID id)
static int | parser_yyerror (struct parser_params *, const char *)
static int | yylex (void *, void *)
static NODE * | node_newnode (struct parser_params *, enum node_type, VALUE, VALUE, VALUE)
static NODE * | cond_gen (struct parser_params *, NODE *)
static NODE * | logop_gen (struct parser_params *, enum node_type, NODE *, NODE *)
static NODE * | newline_node (NODE *)
static void | fixpos (NODE *, NODE *)
static int | value_expr_gen (struct parser_params *, NODE *)
static void | void_expr_gen (struct parser_params *, NODE *)
static NODE * | remove_begin (NODE *)
static void | void_stmts_gen (struct parser_params *, NODE *)
static void | reduce_nodes_gen (struct parser_params *, NODE **)
static void | block_dup_check_gen (struct parser_params *, NODE *, NODE *)
static NODE * | block_append_gen (struct parser_params *, NODE *, NODE *)
static NODE * | list_append_gen (struct parser_params *, NODE *, NODE *)
static NODE * | list_concat_gen (struct parser_params *, NODE *, NODE *)
static NODE * | arg_append_gen (struct parser_params *, NODE *, NODE *)
static NODE * | arg_concat_gen (struct parser_params *, NODE *, NODE *)
static NODE * | literal_concat_gen (struct parser_params *, NODE *, NODE *)
static int | literal_concat0 (struct parser_params *, VALUE, VALUE)
static NODE * | new_evstr_gen (struct parser_params *, NODE *)
static NODE * | evstr2dstr_gen (struct parser_params *, NODE *)
static NODE * | splat_array (NODE *)
static NODE * | call_bin_op_gen (struct parser_params *, NODE *, ID, NODE *)
static NODE * | call_uni_op_gen (struct parser_params *, NODE *, ID)
static NODE * | new_args_gen (struct parser_params *, NODE *, NODE *, ID, NODE *, NODE *)
static NODE * | new_args_tail_gen (struct parser_params *, NODE *, ID, ID)
static NODE * | negate_lit (NODE *)
static NODE * | ret_args_gen (struct parser_params *, NODE *)
static NODE * | arg_blk_pass (NODE *, NODE *)
static NODE * | new_yield_gen (struct parser_params *, NODE *)
static NODE * | dsym_node_gen (struct parser_params *, NODE *)
static NODE * | gettable_gen (struct parser_params *, ID)
static NODE * | assignable_gen (struct parser_params *, ID, NODE *)
static NODE * | aryset_gen (struct parser_params *, NODE *, NODE *)
static NODE * | attrset_gen (struct parser_params *, NODE *, ID)
static void | rb_backref_error_gen (struct parser_params *, NODE *)
static NODE * | node_assign_gen (struct parser_params *, NODE *, NODE *)
static NODE * | new_op_assign_gen (struct parser_params *parser, NODE *lhs, ID op, NODE *rhs)
static NODE * | new_attr_op_assign_gen (struct parser_params *parser, NODE *lhs, ID attr, ID op, NODE *rhs)
static NODE * | new_const_op_assign_gen (struct parser_params *parser, NODE *lhs, ID op, NODE *rhs)
static NODE * | match_op_gen (struct parser_params *, NODE *, NODE *)
static ID * | local_tbl_gen (struct parser_params *)
static void | fixup_nodes (NODE **)
static VALUE | reg_compile_gen (struct parser_params *, VALUE, int)
static void | reg_fragment_setenc_gen (struct parser_params *, VALUE, int)
static int | reg_fragment_check_gen (struct parser_params *, VALUE, int)
static NODE * | reg_named_capture_assign_gen (struct parser_params *parser, VALUE regexp, NODE *match)
static ID | formal_argument_gen (struct parser_params *, ID)
static ID | shadowing_lvar_gen (struct parser_params *, ID)
static void | new_bv_gen (struct parser_params *, ID)
static void | local_push_gen (struct parser_params *, int)
static void | local_pop_gen (struct parser_params *)
static int | local_var_gen (struct parser_params *, ID)
static int | arg_var_gen (struct parser_params *, ID)
static int | local_id_gen (struct parser_params *, ID)
static ID | internal_id_gen (struct parser_params *)
static struct vtable * | dyna_push_gen (struct parser_params *)
static void | dyna_pop_gen (struct parser_params *, const struct vtable *)
static int | dyna_in_block_gen (struct parser_params *)
static int | dvar_defined_gen (struct parser_params *, ID, int)
static int | dvar_curr_gen (struct parser_params *, ID)
static int | lvar_defined_gen (struct parser_params *, ID)
static void | token_info_push (struct parser_params *, const char *token)
static void | token_info_pop (struct parser_params *, const char *token)
| if ($2)
| fixpos ($$, $1) = $3
| if (!$$)$$
| nd_set_line ($$,$< num >2)
| dyna_pop ($< vars >1)
fcall | nd_set_line ($$, tokline)
| if (c== ')') lex_state
| if (IS_END()||ISSPACE(c))
| switch (c)
| if ((c=nextc())== '=')
| if (IS_SPCARG(c))
| warn_balanced ("/","regexp literal")

## Variables
primary_value['opt_call_args rbracket{$$=aryset($1, $3);}|primary_value '.'tIDENTIFIER{$$=attrset($1, $3);}|primary_value tCOLON2 tIDENTIFIER{$$=attrset($1, $3);}|primary_value '.'tCONSTANT{$$=attrset($1, $3);}|primary_value tCOLON2 tCONSTANT{if(in_def||in_single) yyerror("dynamic constant assignment");$$=NEW_CDECL(0, 0, NEW_COLON2($1, $3));}|tCOLON3 tCONSTANT{if(in_def||in_single) yyerror("dynamic constant assignment");$$=NEW_CDECL(0, 0, NEW_COLON3($2));}|backref{rb_backref_error($1);$$=NEW_BEGIN(0);};lhs:user_variable{$$=assignable($1, 0);if(!$$)$$=NEW_BEGIN(0);}|keyword_variable{$$=assignable($1, 0);if(!$$)$$=NEW_BEGIN(0);}|primary_value '['opt_call_args rbracket{$$=aryset($1, $3);}|primary_value '.'tIDENTIFIER{$$=attrset($1, $3);}|primary_value tCOLON2 tIDENTIFIER{$$=attrset($1, $3);}|primary_value '.'tCONSTANT{$$=attrset($1, $3);}|primary_value tCOLON2 tCONSTANT{if(in_def||in_single) yyerror("dynamic constant assignment");$$=NEW_CDECL(0, 0, NEW_COLON2($1, $3));}|tCOLON3 tCONSTANT{if(in_def||in_single) yyerror("dynamic constant assignment");$$=NEW_CDECL(0, 0, NEW_COLON3($2));}|backref{rb_backref_error($1);$$=NEW_BEGIN(0);};cname:tIDENTIFIER{yyerror("class/module name must be CONSTANT");}|tCONSTANT;cpath:tCOLON3 cname{$$=NEW_COLON3($2);}|cname{$$=NEW_COLON2(0,$$);}|primary_value tCOLON2 cname{$$=NEW_COLON2($1, $3);};fname:tIDENTIFIER|tCONSTANT|tFID|op{lex_state=EXPR_ENDFN;$$=$1;}|reswords{lex_state=EXPR_ENDFN;$$=$ < id >1;};fsym:fname|symbol;fitem:fsym{$$=NEW_LIT(ID2SYM($1));}|dsym;undef_list:fitem{$$=NEW_UNDEF($1);}|undef_list ','{lex_state=EXPR_FNAME;}fitem{$$=block_append($1, NEW_UNDEF($4));};op: '|'{ifndef_ripper($$= '|');}| '^'{ifndef_ripper($$= '^');}| '&'{ifndef_ripper($$= '&');}|tCMP{ifndef_ripper($$=tCMP);}|tEQ{ifndef_ripper($$=tEQ);}|tEQQ{ifndef_ripper($$=tEQQ);}|tMATCH{ifndef_ripper($$=tMATCH);}|tNMATCH{ifndef_ripper($$=tNMATCH);}| '> '{ifndef_ripper($$= '> ');}|tGEQ{ifndef_ripper($$=tGEQ);}| ' <'{ifndef_ripper($$= ' <');}|tLEQ{ifndef_ripper($$=tLEQ);}|tNEQ{ifndef_ripper($$=tNEQ);}|tLSHFT{ifndef_ripper($$=tLSHFT);}|tRSHFT{ifndef_ripper($$=tRSHFT);}| '+'{ifndef_ripper($$= '+');}| '-'{ifndef_ripper($$= '-');}| '*'{ifndef_ripper($$= '*');}|tSTAR{ifndef_ripper($$= '*');}| '/'{ifndef_ripper($$= '/');}| '%'{ifndef_ripper($$= '%');}|tPOW{ifndef_ripper($$=tPOW);}|tDSTAR{ifndef_ripper($$=tDSTAR);}| '!'{ifndef_ripper($$= '!');}| '~'{ifndef_ripper($$= '~');}|tUPLUS{ifndef_ripper($$=tUPLUS);}|tUMINUS{ifndef_ripper($$=tUMINUS);}|tAREF{ifndef_ripper($$=tAREF);}|tASET{ifndef_ripper($$=tASET);}| '`'{ifndef_ripper($$= '`');};reswords:keyword__LINE__|keyword__FILE__|keyword__ENCODING__|keyword_BEGIN|keyword_END|keyword_alias|keyword_and|keyword_begin|keyword_break|keyword_case|keyword_class|keyword_def|keyword_defined|keyword_do|keyword_else|keyword_elsif|keyword_end|keyword_ensure|keyword_false|keyword_for|keyword_in|keyword_module|keyword_next|keyword_nil|keyword_not|keyword_or|keyword_redo|keyword_rescue|keyword_retry|keyword_return|keyword_self|keyword_super|keyword_then|keyword_true|keyword_undef|keyword_when|keyword_yield|keyword_if|keyword_unless|keyword_while|keyword_until;arg:lhs '='arg{value_expr($3);$$=node_assign($1, $3);}|lhs '='arg modifier_rescue arg{value_expr($3);$3=NEW_RESCUE($3, NEW_RESBODY(0, $5, 0), 0);$$=node_assign($1, $3);}|var_lhs tOP_ASGN arg{value_expr($3);$$=new_op_assign($1, $2, $3);}|var_lhs tOP_ASGN arg modifier_rescue arg{value_expr($3);$3=NEW_RESCUE($3, NEW_RESBODY(0, $5, 0), 0);$$=new_op_assign($1, $2, $3);}|primary_value '['opt_call_args rbracket tOP_ASGN arg{NODE *args;value_expr($6);if(!$3) $3=NEW_ZARRAY();if(nd_type($3)==NODE_BLOCK_PASS){args=NEW_ARGSCAT($3, $6);}else{args=arg_concat($3, $6);}if($5==tOROP){$5=0;}else if($5==tANDOP){$5=1;}$$=NEW_OP_ASGN1($1, $5, args);fixpos($$, $1);}|primary_value '.'tIDENTIFIER tOP_ASGN arg{value_expr($5);$$=new_attr_op_assign($1, ripper_id2sym('.'), $3, $4, $5);}|primary_value '.'tCONSTANT tOP_ASGN arg{value_expr($5);$$=new_attr_op_assign($1, ripper_id2sym('.'), $3, $4, $5);}|primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg{value_expr($5);$$=new_attr_op_assign($1, ripper_intern("::"), $3, $4, $5);}|primary_value tCOLON2 tCONSTANT tOP_ASGN arg{$$=NEW_COLON2($1, $3);$$=new_const_op_assign($$, $4, $5);}|tCOLON3 tCONSTANT tOP_ASGN arg{$$=NEW_COLON3($2);$$=new_const_op_assign($$, $3, $4);}|backref tOP_ASGN arg{rb_backref_error($1);$$=NEW_BEGIN(0);}|arg tDOT2 arg{value_expr($1);value_expr($3);$$=NEW_DOT2($1, $3);if(nd_type($1)==NODE_LIT &&FIXNUM_P($1->nd_lit)&&nd_type($3)==NODE_LIT &&FIXNUM_P($3->nd_lit)){deferred_nodes=list_append(deferred_nodes,$$);}}|arg tDOT3 arg{value_expr($1);value_expr($3);$$=NEW_DOT3($1, $3);if(nd_type($1)==NODE_LIT &&FIXNUM_P($1->nd_lit)&&nd_type($3)==NODE_LIT &&FIXNUM_P($3->nd_lit)){deferred_nodes=list_append(deferred_nodes,$$);}}|arg '+'arg{$$=call_bin_op($1, '+', $3);}|arg '-'arg{$$=call_bin_op($1, '-', $3);}|arg '*'arg{$$=call_bin_op($1, '*', $3);}|arg '/'arg{$$=call_bin_op($1, '/', $3);}|arg '%'arg{$$=call_bin_op($1, '%', $3);}|arg tPOW arg{$$=call_bin_op($1, tPOW, $3);}|tUMINUS_NUM tINTEGER tPOW arg{$$=NEW_CALL(call_bin_op($2, tPOW, $4), tUMINUS, 0);}|tUMINUS_NUM tFLOAT tPOW arg{$$=NEW_CALL(call_bin_op($2, tPOW, $4), tUMINUS, 0);}|tUPLUS arg{$$=call_uni_op($2, tUPLUS);}|tUMINUS arg{$$=call_uni_op($2, tUMINUS);}|arg '|'arg{$$=call_bin_op($1, '|', $3);}|arg '^'arg{$$=call_bin_op($1, '^', $3);}|arg '&'arg{$$=call_bin_op($1, '&', $3);}|arg tCMP arg{$$=call_bin_op($1, tCMP, $3);}|arg '>'arg{$$=call_bin_op($1, '> ', $3);}|arg tGEQ arg{$$=call_bin_op($1, tGEQ, $3);}|arg '<'arg{$$=call_bin_op($1, ' <', $3);}|arg tLEQ arg{$$=call_bin_op($1, tLEQ, $3);}|arg tEQ arg{$$=call_bin_op($1, tEQ, $3);}|arg tEQQ arg{$$=call_bin_op($1, tEQQ, $3);}|arg tNEQ arg{$$=call_bin_op($1, tNEQ, $3);}|arg tMATCH arg{$$=match_op($1, $3);if(nd_type($1)==NODE_LIT &&RB_TYPE_P($1->nd_lit, T_REGEXP)){$$=reg_named_capture_assign($1-> nd_lit,$$);}}|arg tNMATCH arg{$$=call_bin_op($1, tNMATCH, $3);}| '!'arg{$$=call_uni_op(cond($2), '!');}| '~'arg{$$=call_uni_op($2, '~');}|arg tLSHFT arg{$$=call_bin_op($1, tLSHFT, $3);}|arg tRSHFT arg{$$=call_bin_op($1, tRSHFT, $3);}|arg tANDOP arg{$$=logop(NODE_AND, $1, $3);}|arg tOROP arg{$$=logop(NODE_OR, $1, $3);}|keyword_defined opt_nl{in_defined=1;}arg{in_defined=0;$$=NEW_DEFINED($4);}|arg '?'arg opt_nl ':'arg{value_expr($1);$$=NEW_IF(cond($1), $3, $6);fixpos($$, $1);}|primary{$$=$1;};arg_value:arg{value_expr($1);$$=$1;if(!$$)$$=NEW_NIL();};aref_args:none|args trailer{$$=$1;}|args ','assocs trailer{$$=arg_append($1, NEW_HASH($3));}|assocs trailer{$$=NEW_LIST(NEW_HASH($1));};paren_args: '('opt_call_args rparen{$$=$2;};opt_paren_args:none|paren_args;opt_call_args:none|call_args|args ','{$$=$1;}|args ','assocs ','{$$=arg_append($1, NEW_HASH($3));}|assocs ','{$$=NEW_LIST(NEW_HASH($1));};call_args:command{value_expr($1);$$=NEW_LIST($1);}|args opt_block_arg{$$=arg_blk_pass($1, $2);}|assocs opt_block_arg{$$=NEW_LIST(NEW_HASH($1));$$=arg_blk_pass($$, $2);}|args ','assocs opt_block_arg{$$=arg_append($1, NEW_HASH($3));$$=arg_blk_pass($$, $4);}|block_arg;command_args:{$ < val > $=cmdarg_stack;CMDARG_PUSH(1);}call_args{cmdarg_stack=$ < val > 1;$$=$2;};block_arg:tAMPER arg_value{$$=NEW_BLOCK_PASS($2);};opt_block_arg: ','block_arg{$$=$2;}|none{$$=0;};args:arg_value{$$=NEW_LIST($1);}|tSTAR arg_value{$$=NEW_SPLAT($2);}|args ','arg_value{NODE *n1;if((n1=splat_array($1))!=0){$$=list_append(n1, $3);}else{$$=arg_append($1, $3);}}|args ','tSTAR arg_value{NODE *n1;if((nd_type($4)==NODE_ARRAY)&&(n1=splat_array($1))!=0){$$=list_concat(n1, $4);}else{$$=arg_concat($1, $4);}};mrhs:args ','arg_value{NODE *n1;if((n1=splat_array($1))!=0){$$=list_append(n1, $3);}else{$$=arg_append($1, $3);}}|args ','tSTAR arg_value{NODE *n1;if(nd_type($4)==NODE_ARRAY &&(n1=splat_array($1))!=0){$$=list_concat(n1, $4);}else{$$=arg_concat($1, $4);}}|tSTAR arg_value{$$=NEW_SPLAT($2);};primary:literal|strings|xstring|regexp|words|qwords|symbols|qsymbols|var_ref|backref|tFID{$$=NEW_FCALL($1, 0);}|k_begin{$< val > 1=cmdarg_stack;cmdarg_stack=0;$ < num > $=ruby_sourceline;}bodystmt k_end{cmdarg_stack=$< val > 1;if($3==NULL){$$=NEW_NIL();}else{if(nd_type($3)==NODE_RESCUE||nd_type($3)==NODE_ENSURE) nd_set_line($3,$< num > 2);$$=NEW_BEGIN($3);}nd_set_line($$,$ < num >2);}|tLPAREN_ARG{lex_state=EXPR_ENDARG;}rparen{$$=0;}|tLPAREN_ARG expr{lex_state=EXPR_ENDARG;}rparen{$$=$2;}|tLPAREN compstmt ')'{$$=$2;}|primary_value tCOLON2 tCONSTANT{$$=NEW_COLON2($1, $3);}|tCOLON3 tCONSTANT{$$=NEW_COLON3($2);}|tLBRACK aref_args ']'{if($2==0){$$=NEW_ZARRAY();}else{$$=$2;}}|tLBRACE assoc_list '}'{$$=NEW_HASH($2);}|keyword_return{$$=NEW_RETURN(0);}|keyword_yield '('call_args rparen{$$=new_yield($3);}|keyword_yield '('rparen{$$=NEW_YIELD(0);}|keyword_yield{$$=NEW_YIELD(0);}|keyword_defined opt_nl '('{in_defined=1;}expr rparen{in_defined=0;$$=NEW_DEFINED($5);}|keyword_not '('expr rparen{$$=call_uni_op(cond($3), '!');}|keyword_not '('rparen{$$=call_uni_op(cond(NEW_NIL()), '!');}|fcall brace_block{$2-> nd_iter=$1;$$=$2;}|method_call|method_call brace_block{block_dup_check($1-> nd_args, $2);$2->nd_iter=$1;$$=$2;}|tLAMBDA lambda{$$=$2;}|k_if expr_value then compstmt if_tail k_end{$$=NEW_IF(cond($2), $4, $5);fixpos($$, $2);}|k_unless expr_value then compstmt opt_else k_end{$$=NEW_UNLESS(cond($2), $4, $5);fixpos($$, $2);}|k_while{COND_PUSH(1);}expr_value do{COND_POP();}compstmt k_end{$$=NEW_WHILE(cond($3), $6, 1);fixpos($$, $3);}|k_until{COND_PUSH(1);}expr_value do{COND_POP();}compstmt k_end{$$=NEW_UNTIL(cond($3), $6, 1);fixpos($$, $3);}|k_case expr_value opt_terms case_body k_end{$$=NEW_CASE($2, $4);fixpos($$, $2);}|k_case opt_terms case_body k_end{$$=NEW_CASE(0, $3);}|k_for for_var keyword_in{COND_PUSH(1);}expr_value do{COND_POP();}compstmt k_end{ID id=internal_id();ID *tbl=ALLOC_N(ID, 2);NODE *m=NEW_ARGS_AUX(0, 0);NODE *args,*scope;if(nd_type($2)==NODE_MASGN){NODE *one=NEW_LIST(NEW_LIT(INT2FIX(1)));NODE *zero=NEW_LIST(NEW_LIT(INT2FIX(0)));m-> nd_next=block_append(NEW_IF(NEW_NODE(NODE_AND, NEW_CALL(NEW_CALL(NEW_DVAR(id), idLength, 0), idEq, one), NEW_CALL(NEW_CALL(NEW_DVAR(id), idAREF, zero), rb_intern("kind_of?"), NEW_LIST(NEW_LIT(rb_cArray))), 0), NEW_DASGN_CURR(id, NEW_CALL(NEW_DVAR(id), idAREF, zero)), 0), node_assign($2, NEW_DVAR(id)));args=new_args(m, 0, id, 0, new_args_tail(0, 0, 0));}else{if(nd_type($2)==NODE_LASGN||nd_type($2)==NODE_DASGN||nd_type($2)==NODE_DASGN_CURR){$2-> nd_value=NEW_DVAR(id);m-> nd_plen=1;m->nd_next=$2;args=new_args(m, 0, 0, 0, new_args_tail(0, 0, 0));}else{m->nd_next=node_assign(NEW_MASGN(NEW_LIST($2), 0), NEW_DVAR(id));args=new_args(m, 0, id, 0, new_args_tail(0, 0, 0));}}scope=NEW_NODE(NODE_SCOPE, tbl, $8, args);tbl[0]=1;tbl[1]=id;$$=NEW_FOR(0, $5, scope);fixpos($$, $2);}|k_class cpath superclass{if(in_def||in_single) yyerror("class definition in method body");local_push(0);$ < num > $=ruby_sourceline;}bodystmt k_end{$$=NEW_CLASS($2, $5, $3);nd_set_line($$,$< num > 4);local_pop();}|k_class tLSHFT expr{$< num > $=in_def;in_def=0;}term{$ < num > $=in_single;in_single=0;local_push(0);}bodystmt k_end{$$=NEW_SCLASS($3, $7);fixpos($$, $3);local_pop();in_def=$ < num >4;in_single=$< num > 6;}|k_module cpath{if(in_def||in_single) yyerror("module definition in method body");local_push(0);$ < num > $=ruby_sourceline;}bodystmt k_end{$$=NEW_MODULE($2, $4);nd_set_line($$,$< num > 3);local_pop();}|k_def fname{$ < id > $=cur_mid;cur_mid=$2;in_def++;local_push(0);}f_arglist bodystmt k_end{NODE *body=remove_begin($5);reduce_nodes(&body);$$=NEW_DEFN($2, $4, body, NOEX_PRIVATE);nd_set_line($$,$ < num >1);local_pop();in_def--;cur_mid=$ < id >3;}|k_def singleton dot_or_colon{lex_state=EXPR_FNAME;}fname{in_single++;lex_state=EXPR_ENDFN;local_push(0);}f_arglist bodystmt k_end{NODE *body=remove_begin($8);reduce_nodes(&body);$$=NEW_DEFS($2, $5, $7, body);nd_set_line($$,$ < num >1);local_pop();in_single--;}|keyword_break{$$=NEW_BREAK(0);}|keyword_next{$$=NEW_NEXT(0);}|keyword_redo{$$=NEW_REDO();}|keyword_retry{$$=NEW_RETRY();};primary_value:primary{value_expr($1);$$=$1;if(!$$)$$=NEW_NIL();};k_begin:keyword_begin{token_info_push("begin");};k_if:keyword_if{token_info_push("if");};k_unless:keyword_unless{token_info_push("unless");};k_while:keyword_while{token_info_push("while");};k_until:keyword_until{token_info_push("until");};k_case:keyword_case{token_info_push("case");};k_for:keyword_for{token_info_push("for");};k_class:keyword_class{token_info_push("class");};k_module:keyword_module{token_info_push("module");};k_def:keyword_def{token_info_push("def");$ < num > $=ruby_sourceline;};k_end:keyword_end{token_info_pop("end");};then:term|keyword_then|term keyword_then;do:term|keyword_do_cond;if_tail:opt_else|keyword_elsif expr_value then compstmt if_tail{$$=NEW_IF(cond($2), $4, $5);fixpos($$, $2);};opt_else:none|keyword_else compstmt{$$=$2;};for_var:lhs|mlhs;f_marg:f_norm_arg{$$=assignable($1, 0);}|tLPAREN f_margs rparen{$$=$2;};f_marg_list:f_marg{$$=NEW_LIST($1);}|f_marg_list ','f_marg{$$=list_append($1, $3);};f_margs:f_marg_list{$$=NEW_MASGN($1, 0);}|f_marg_list ','tSTAR f_norm_arg{$$=assignable($4, 0);$$=NEW_MASGN($1,$$);}|f_marg_list ','tSTAR f_norm_arg ','f_marg_list{$$=assignable($4, 0);$$=NEW_MASGN($1, NEW_POSTARG($$, $6));}|f_marg_list ','tSTAR{$$=NEW_MASGN($1,-1);}|f_marg_list ','tSTAR ','f_marg_list{$$=NEW_MASGN($1, NEW_POSTARG(-1, $5));}|tSTAR f_norm_arg{$$=assignable($2, 0);$$=NEW_MASGN(0,$$);}|tSTAR f_norm_arg ','f_marg_list{$$=assignable($2, 0);$$=NEW_MASGN(0, NEW_POSTARG($$, $4));}|tSTAR{$$=NEW_MASGN(0,-1);}|tSTAR ','f_marg_list{$$=NEW_MASGN(0, NEW_POSTARG(-1, $3));};block_args_tail:f_block_kwarg ','f_kwrest opt_f_block_arg{$$=new_args_tail($1, $3, $4);}|f_block_kwarg opt_f_block_arg{$$=new_args_tail($1, Qnone, $2);}|f_kwrest opt_f_block_arg{$$=new_args_tail(Qnone, $1, $2);}|f_block_arg{$$=new_args_tail(Qnone, Qnone, $1);};opt_block_args_tail: ','block_args_tail{$$=$2;}|{$$=new_args_tail(Qnone, Qnone, Qnone);};block_param:f_arg ','f_block_optarg ','f_rest_arg opt_block_args_tail{$$=new_args($1, $3, $5, Qnone, $6);}|f_arg ','f_block_optarg ','f_rest_arg ','f_arg opt_block_args_tail{$$=new_args($1, $3, $5, $7, $8);}|f_arg ','f_block_optarg opt_block_args_tail{$$=new_args($1, $3, Qnone, Qnone, $4);}|f_arg ','f_block_optarg ','f_arg opt_block_args_tail{$$=new_args($1, $3, Qnone, $5, $6);}|f_arg ','f_rest_arg opt_block_args_tail{$$=new_args($1, Qnone, $3, Qnone, $4);}|f_arg ','{$$=new_args($1, Qnone, 1, Qnone, new_args_tail(Qnone, Qnone, Qnone));}|f_arg ','f_rest_arg ','f_arg opt_block_args_tail{$$=new_args($1, Qnone, $3, $5, $6);}|f_arg opt_block_args_tail{$$=new_args($1, Qnone, Qnone, Qnone, $2);}|f_block_optarg ','f_rest_arg opt_block_args_tail{$$=new_args(Qnone, $1, $3, Qnone, $4);}|f_block_optarg ','f_rest_arg ','f_arg opt_block_args_tail{$$=new_args(Qnone, $1, $3, $5, $6);}|f_block_optarg opt_block_args_tail{$$=new_args(Qnone, $1, Qnone, Qnone, $2);}|f_block_optarg ','f_arg opt_block_args_tail{$$=new_args(Qnone, $1, Qnone, $3, $4);}|f_rest_arg opt_block_args_tail{$$=new_args(Qnone, Qnone, $1, Qnone, $2);}|f_rest_arg ','f_arg opt_block_args_tail{$$=new_args(Qnone, Qnone, $1, $3, $4);}|block_args_tail{$$=new_args(Qnone, Qnone, Qnone, Qnone, $1);};opt_block_param:none|block_param_def{command_start=TRUE;};block_param_def: '|'opt_bv_decl '|'{$$=0;}|tOROP{$$=0;}| '|'block_param opt_bv_decl '|'{$$=$2;};opt_bv_decl:opt_nl{$$=0;}|opt_nl ';'bv_decls opt_nl{$$=0;};bv_decls:bvar|bv_decls ','bvar;bvar:tIDENTIFIER{new_bv(get_id($1));}|f_bad_arg{$$=0;};lambda:{$ < vars > $=dyna_push();}{$ < num > $=lpar_beg;lpar_beg=++paren_nest;}f_larglist lambda_body{lpar_beg=$< num > 2;$$=NEW_LAMBDA($3, $4);dyna_pop($< vars > 1);};f_larglist: '('f_args opt_bv_decl ')'{$$=$2;}|f_args{$$=$1;};lambda_body:tLAMBEG compstmt '}'{$$=$2;}|keyword_do_LAMBDA compstmt keyword_end{$$=$2;};do_block:keyword_do_block{$ < vars >1=dyna_push();$< num > $=ruby_sourceline;}opt_block_param compstmt keyword_end{$$=NEW_ITER($3, $4);nd_set_line($$,$< num > 2);dyna_pop($< vars > 1);};block_call:command do_block{if(nd_type($1)==NODE_YIELD){compile_error(PARSER_ARG"block given to yield");}else{block_dup_check($1-> nd_args, $2);}$2->nd_iter=$1;$$=$2;fixpos($$, $1);}|block_call dot_or_colon operation2 opt_paren_args{$$=NEW_CALL($1, $3, $4);}|block_call dot_or_colon operation2 opt_paren_args brace_block{block_dup_check($4, $5);$5-> nd_iter=NEW_CALL($1, $3, $4);$$=$5;fixpos($$, $1);}|block_call dot_or_colon operation2 command_args do_block{block_dup_check($4, $5);$5-> nd_iter=NEW_CALL($1, $3, $4);$$=$5;fixpos($$, $1);};method_call:fcall paren_args{$$=$1;$$->nd_args=$2;}|primary_value '.'operation2{$< num > $=ruby_sourceline;}opt_paren_args{$$=NEW_CALL($1, $3, $5);nd_set_line($$,$< num > 4);}|primary_value tCOLON2 operation2{$< num > $=ruby_sourceline;}paren_args{$$=NEW_CALL($1, $3, $5);nd_set_line($$,$< num > 4);}|primary_value tCOLON2 operation3{$$=NEW_CALL($1, $3, 0);}|primary_value '.'{$ < num > $=ruby_sourceline;}paren_args{$$=NEW_CALL($1, rb_intern("call"), $4);nd_set_line($$,$< num > 3);}|primary_value tCOLON2{$ < num > $=ruby_sourceline;}paren_args{$$=NEW_CALL($1, rb_intern("call"), $4);nd_set_line($$,$< num > 3);}|keyword_super paren_args{$$=NEW_SUPER($2);}|keyword_super{$$=NEW_ZSUPER();}|primary_value '['opt_call_args rbracket{if($1 &&nd_type($1)==NODE_SELF)$$=NEW_FCALL(tAREF, $3);else $$=NEW_CALL($1, tAREF, $3);fixpos($$, $1);};brace_block: '{'{$< vars > 1=dyna_push();$< num > $=ruby_sourceline;}opt_block_param compstmt '}'{$$=NEW_ITER($3, $4);nd_set_line($$,$< num > 2);dyna_pop($< vars > 1);}|keyword_do{$< vars > 1=dyna_push();$< num > $=ruby_sourceline;}opt_block_param compstmt keyword_end{$$=NEW_ITER($3, $4);nd_set_line($$,$< num > 2);dyna_pop($< vars > 1);};case_body:keyword_when args then compstmt cases{$$=NEW_WHEN($2, $4, $5);};cases:opt_else|case_body;opt_rescue:keyword_rescue exc_list exc_var then compstmt opt_rescue{if($3){$3=node_assign($3, NEW_ERRINFO());$5=block_append($3, $5);}$$=NEW_RESBODY($2, $5, $6);fixpos($$, $2?$2:$5);}|none;exc_list:arg_value{$$=NEW_LIST($1);}|mrhs{if(!($$=splat_array($1)))$$=$1;}|none;exc_var:tASSOC lhs{$$=$2;}|none;opt_ensure:keyword_ensure compstmt{$$=$2;}|none;literal:numeric|symbol{$$=NEW_LIT(ID2SYM($1));}|dsym;strings:string{NODE *node=$1;if(!node){node=NEW_STR(STR_NEW0());}else{node=evstr2dstr(node);}$$=node;};string:tCHAR|string1|string string1{$$=literal_concat($1, $2);};string1:tSTRING_BEG string_contents tSTRING_END{$$=$2;};xstring:tXSTRING_BEG xstring_contents tSTRING_END{NODE *node=$2;if(!node){node=NEW_XSTR(STR_NEW0());}else{switch(nd_type(node)){case NODE_STR:nd_set_type(node, NODE_XSTR);break;case NODE_DSTR:nd_set_type(node, NODE_DXSTR);break;default:node=NEW_NODE(NODE_DXSTR, Qnil, 1, NEW_LIST(node));break;}}$$=node;};regexp:tREGEXP_BEG regexp_contents tREGEXP_END{int options=$3;NODE *node=$2;NODE *list,*prev;if(!node){node=NEW_LIT(reg_compile(STR_NEW0(), options));}else switch(nd_type(node)){case NODE_STR:{VALUE src=node-> nd_lit;nd_set_type(node, NODE_LIT);node->nd_lit=reg_compile(src, options);}break;default:node=NEW_NODE(NODE_DSTR, STR_NEW0(), 1, NEW_LIST(node));case NODE_DSTR:if(options &RE_OPTION_ONCE){nd_set_type(node, NODE_DREGX_ONCE);}else{nd_set_type(node, NODE_DREGX);}node->nd_cflag=options &RE_OPTION_MASK;if(!NIL_P(node-> nd_lit)) reg_fragment_check(node-> nd_lit, options);for(list=(prev=node) -> nd_next;list;list=list-> nd_next){if(nd_type(list-> nd_head)==NODE_STR){VALUE tail=list-> nd_head->nd_lit;if(reg_fragment_check(tail, options)&&prev &&!NIL_P(prev-> nd_lit)){VALUE lit=prev==node?prev-> nd_lit:prev->nd_head->nd_lit;if(!literal_concat0(parser, lit, tail)){node=0;break;}rb_str_resize(tail, 0);prev->nd_next=list->nd_next;rb_gc_force_recycle((VALUE) list->nd_head);rb_gc_force_recycle((VALUE) list);list=prev;}else{prev=list;}}else{prev=0;}}if(!node-> nd_next){VALUE src=node-> nd_lit;nd_set_type(node, NODE_LIT);node->nd_lit=reg_compile(src, options);}break;}$$=node;};words:tWORDS_BEG ' 'tSTRING_END{$$=NEW_ZARRAY();}|tWORDS_BEG word_list tSTRING_END{$$=$2;};word_list:{$$=0;}|word_list word ' '{$$=list_append($1, evstr2dstr($2));};word:string_content|word string_content{$$=literal_concat($1, $2);};symbols:tSYMBOLS_BEG ' 'tSTRING_END{$$=NEW_ZARRAY();}|tSYMBOLS_BEG symbol_list tSTRING_END{$$=$2;};symbol_list:{$$=0;}|symbol_list word ' '{$2=evstr2dstr($2);nd_set_type($2, NODE_DSYM);$$=list_append($1, $2);};qwords:tQWORDS_BEG ' 'tSTRING_END{$$=NEW_ZARRAY();}|tQWORDS_BEG qword_list tSTRING_END{$$=$2;};qsymbols:tQSYMBOLS_BEG ' 'tSTRING_END{$$=NEW_ZARRAY();}|tQSYMBOLS_BEG qsym_list tSTRING_END{$$=$2;};qword_list:{$$=0;}|qword_list tSTRING_CONTENT ' '{$$=list_append($1, $2);};qsym_list:{$$=0;}|qsym_list tSTRING_CONTENT ' '{VALUE lit;lit=$2-> nd_lit;$2->nd_lit=ID2SYM(rb_intern_str(lit));nd_set_type($2, NODE_LIT);$$=list_append($1, $2);};string_contents:{$$=0;}|string_contents string_content{$$=literal_concat($1, $2);};xstring_contents:{$$=0;}|xstring_contents string_content{$$=literal_concat($1, $2);};regexp_contents:{$$=0;}|regexp_contents string_content{NODE *head=$1,*tail=$2;if(!head){$$=tail;}else if(!tail){$$=head;}else{switch(nd_type(head)){case NODE_STR:nd_set_type(head, NODE_DSTR);break;case NODE_DSTR:break;default:head=list_append(NEW_DSTR(Qnil), head);break;}$$=list_append(head, tail);}};string_content:tSTRING_CONTENT|tSTRING_DVAR{$ < node > $=lex_strterm;lex_strterm=0;lex_state=EXPR_BEG;}string_dvar{lex_strterm=$ < node >2;$$=NEW_EVSTR($3);}|tSTRING_DBEG{$ < val >1=cond_stack;$< val > $=cmdarg_stack;cond_stack=0;cmdarg_stack=0;}{$ < node > $=lex_strterm;lex_strterm=0;lex_state=EXPR_BEG;}{$ < num > $=brace_nest;brace_nest=0;}compstmt tSTRING_DEND{cond_stack=$< val > 1;cmdarg_stack=$< val > 2;lex_strterm=$< node > 3;brace_nest=$< num >4;if($5) $5-> flags &=~NODE_FL_NEWLINE;$$=new_evstr($5);};string_dvar:tGVAR{$$=NEW_GVAR($1);}|tIVAR{$$=NEW_IVAR($1);}|tCVAR{$$=NEW_CVAR($1);}|backref;symbol:tSYMBEG sym{lex_state=EXPR_END;$$=$2;};sym:fname|tIVAR|tGVAR|tCVAR;dsym:tSYMBEG xstring_contents tSTRING_END{lex_state=EXPR_END;$$=dsym_node($2);};numeric:tINTEGER|tFLOAT|tUMINUS_NUM tINTEGER%prec tLOWEST{$$=negate_lit($2);}|tUMINUS_NUM tFLOAT%prec tLOWEST{$$=negate_lit($2);};user_variable:tIDENTIFIER|tIVAR|tGVAR|tCONSTANT|tCVAR;keyword_variable:keyword_nil{ifndef_ripper($$=keyword_nil);}|keyword_self{ifndef_ripper($$=keyword_self);}|keyword_true{ifndef_ripper($$=keyword_true);}|keyword_false{ifndef_ripper($$=keyword_false);}|keyword__FILE__{ifndef_ripper($$=keyword__FILE__);}|keyword__LINE__{ifndef_ripper($$=keyword__LINE__);}|keyword__ENCODING__{ifndef_ripper($$=keyword__ENCODING__);};var_ref:user_variable{if(!($$=gettable($1)))$$=NEW_BEGIN(0);}|keyword_variable{if(!($$=gettable($1)))$$=NEW_BEGIN(0);};var_lhs:user_variable{$$=assignable($1, 0);}|keyword_variable{$$=assignable($1, 0);};backref:tNTH_REF|tBACK_REF;superclass:term{$$=0;}| ' <'{lex_state=EXPR_BEG;command_start=TRUE;}expr_value term{$$=$3;}|error term{yyerrok;$$=0;};f_arglist: '('f_args rparen{$$=$2;lex_state=EXPR_BEG;command_start=TRUE;}|f_args term{$$=$1;lex_state=EXPR_BEG;command_start=TRUE;};args_tail:f_kwarg ','f_kwrest opt_f_block_arg{$$=new_args_tail($1, $3, $4);}|f_kwarg opt_f_block_arg{$$=new_args_tail($1, Qnone, $2);}|f_kwrest opt_f_block_arg{$$=new_args_tail(Qnone, $1, $2);}|f_block_arg{$$=new_args_tail(Qnone, Qnone, $1);};opt_args_tail: ','args_tail{$$=$2;}|{$$=new_args_tail(Qnone, Qnone, Qnone);};f_args:f_arg ','f_optarg ','f_rest_arg opt_args_tail{$$=new_args($1, $3, $5, Qnone, $6);}|f_arg ','f_optarg ','f_rest_arg ','f_arg opt_args_tail{$$=new_args($1, $3, $5, $7, $8);}|f_arg ','f_optarg opt_args_tail{$$=new_args($1, $3, Qnone, Qnone, $4);}|f_arg ','f_optarg ','f_arg opt_args_tail{$$=new_args($1, $3, Qnone, $5, $6);}|f_arg ','f_rest_arg opt_args_tail{$$=new_args($1, Qnone, $3, Qnone, $4);}|f_arg ','f_rest_arg ','f_arg opt_args_tail{$$=new_args($1, Qnone, $3, $5, $6);}|f_arg opt_args_tail{$$=new_args($1, Qnone, Qnone, Qnone, $2);}|f_optarg ','f_rest_arg opt_args_tail{$$=new_args(Qnone, $1, $3, Qnone, $4);}|f_optarg ','f_rest_arg ','f_arg opt_args_tail{$$=new_args(Qnone, $1, $3, $5, $6);}|f_optarg opt_args_tail{$$=new_args(Qnone, $1, Qnone, Qnone, $2);}|f_optarg ','f_arg opt_args_tail{$$=new_args(Qnone, $1, Qnone, $3, $4);}|f_rest_arg opt_args_tail{$$=new_args(Qnone, Qnone, $1, Qnone, $2);}|f_rest_arg ','f_arg opt_args_tail{$$=new_args(Qnone, Qnone, $1, $3, $4);}|args_tail{$$=new_args(Qnone, Qnone, Qnone, Qnone, $1);}|{$$=new_args_tail(Qnone, Qnone, Qnone);$$=new_args(Qnone, Qnone, Qnone, Qnone,$$);};f_bad_arg:tCONSTANT{yyerror("formal argument cannot be a constant");$$=0;}|tIVAR{yyerror("formal argument cannot be an instance variable");$$=0;}|tGVAR{yyerror("formal argument cannot be a global variable");$$=0;}|tCVAR{yyerror("formal argument cannot be a class variable");$$=0;};f_norm_arg:f_bad_arg|tIDENTIFIER{formal_argument(get_id($1));$$=$1;};f_arg_item:f_norm_arg{arg_var(get_id($1));$$=NEW_ARGS_AUX($1, 1);}|tLPAREN f_margs rparen{ID tid=internal_id();arg_var(tid);if(dyna_in_block()){$2-> nd_value=NEW_DVAR(tid);}else{$2-> nd_value=NEW_LVAR(tid);}$$=NEW_ARGS_AUX(tid, 1);$$-> nd_next=$2;};f_arg:f_arg_item|f_arg ','f_arg_item{$$=$1;$$-> nd_plen++;$$->nd_next=block_append($$-> nd_next, $3->nd_next);rb_gc_force_recycle((VALUE)$3);};f_kw:tLABEL arg_value{arg_var(formal_argument(get_id($1)));$$=assignable($1, $2);$$=NEW_KW_ARG(0,$$);};f_block_kw:tLABEL primary_value{arg_var(formal_argument(get_id($1)));$$=assignable($1, $2);$$=NEW_KW_ARG(0,$$);};f_block_kwarg:f_block_kw{$$=$1;}|f_block_kwarg ','f_block_kw{NODE *kws=$1;while(kws-> nd_next){kws=kws->nd_next;}kws-> nd_next=$3;$$=$1;};f_kwarg:f_kw{$$=$1;}|f_kwarg ','f_kw{NODE *kws=$1;while(kws-> nd_next){kws=kws->nd_next;}kws-> nd_next=$3;$$=$1;};kwrest_mark:tPOW|tDSTAR;f_kwrest:kwrest_mark tIDENTIFIER{shadowing_lvar(get_id($2));$$=$2;}|kwrest_mark{$$=internal_id();};f_opt:tIDENTIFIER '='arg_value{arg_var(formal_argument(get_id($1)));$$=assignable($1, $3);$$=NEW_OPT_ARG(0,$$);};f_block_opt:tIDENTIFIER '='primary_value{arg_var(formal_argument(get_id($1)));$$=assignable($1, $3);$$=NEW_OPT_ARG(0,$$);};f_block_optarg:f_block_opt{$$=$1;}|f_block_optarg ','f_block_opt{NODE *opts=$1;while(opts-> nd_next){opts=opts->nd_next;}opts-> nd_next=$3;$$=$1;};f_optarg:f_opt{$$=$1;}|f_optarg ','f_opt{NODE *opts=$1;while(opts-> nd_next){opts=opts->nd_next;}opts-> nd_next=$3;$$=$1;};restarg_mark: '*'|tSTAR;f_rest_arg:restarg_mark tIDENTIFIER{if(!is_local_id($2)) yyerror("rest argument must be local variable");arg_var(shadowing_lvar(get_id($2)));$$=$2;}|restarg_mark{$$=internal_id();arg_var($$);};blkarg_mark: '&'|tAMPER;f_block_arg:blkarg_mark tIDENTIFIER{if(!is_local_id($2)) yyerror("block argument must be local variable");else if(!dyna_in_block()&&local_id($2)) yyerror("duplicated block argument name");arg_var(shadowing_lvar(get_id($2)));$$=$2;};opt_f_block_arg: ','f_block_arg{$$=$2;}|none{$$=0;};singleton:var_ref{value_expr($1);$$=$1;if(!$$)$$=NEW_NIL();}| '('{lex_state=EXPR_BEG;}expr rparen{if($3==0){yyerror("can't define singleton method for ().");}else{switch(nd_type($3)){case NODE_STR:case NODE_DSTR:case NODE_XSTR:case NODE_DXSTR:case NODE_DREGX:case NODE_LIT:case NODE_ARRAY:case NODE_ZARRAY:yyerror("can't define singleton method for literals");default:value_expr($3);break;}}$$=$3;};assoc_list:none|assocs trailer{$$=$1;};assocs:assoc|assocs ','assoc{$$=list_concat($1, $3);};assoc:arg_value tASSOC arg_value{$$=list_append(NEW_LIST($1), $3);}|tLABEL arg_value{$$=list_append(NEW_LIST(NEW_LIT(ID2SYM($1))), $2);}|tDSTAR arg_value{$$=list_append(NEW_LIST(0), $2);};;operation:tIDENTIFIER|tCONSTANT|tFID;operation2:tIDENTIFIER|tCONSTANT|tFID|op;operation3:tIDENTIFIER|tFID|op;dot_or_colon: '.'|tCOLON2;opt_terms:|terms;opt_nl:| '\n';rparen:opt_nl ')';rbracket:opt_nl ']';trailer:| '\n'| ',';term: ';'{yyerrok;}| '\n';terms:term|terms ';'{yyerrok;};none:{$$=0;};%%#define yylvalstatic int parser_regx_options(struct parser_params *);static int parser_tokadd_string(struct parser_params *, int, int, int, long *, rb_encoding **);static void parser_tokaddmbc(struct parser_params *parser, int c, rb_encoding *enc);static int parser_parse_string(struct parser_params *, NODE *);static int parser_here_document(struct parser_params *, NODE *);#define nextc()#define pushback(c)#define newtok()#define tokspace(n)#define tokadd(c)#define tok_hex(numlen)#define read_escape(flags, e)#define tokadd_escape(e)#define regx_options()#define tokadd_string(f, t, p, n, e)#define parse_string(n)#define tokaddmbc(c, enc)#define here_document(n)#define heredoc_identifier()#define heredoc_restore(n)#define whole_match_p(e, l, i)#define set_yylval_str(x)#define set_yylval_num(x)#define set_yylval_id(x)#define set_yylval_name(x)#define set_yylval_literal(x)#define set_yylval_node(x)#define yylval_id()#define ripper_flush(p)#define SIGN_EXTEND_CHAR(c)#define parser_encoding_name()#define parser_mbclen()#define parser_precise_mbclen()#define is_identchar(p, e, enc)#define parser_is_identchar()#define parser_isascii() static inttoken_info_get_column(struct parser_params *parser, const char *token){int column=1;const char *p,*pend=lex_p-strlen(token);for(p=lex_pbeg;p < pend;p++){if(*p== '\t'){column=(((column-1)/8)+1)*8;}column++;}return column;}static inttoken_info_has_nonspaces(struct parser_params *parser, const char *token){const char *p,*pend=lex_p-strlen(token);for(p=lex_pbeg;p < pend;p++){if(*p!= ' '&&*p!= '\t'){return 1;}}return 0;}static voidtoken_info_push(struct parser_params *parser, const char *token){token_info *ptinfo;if(!parser-> parser_token_info_enabled) return;ptinfo=ALLOC(token_info);ptinfo-> token=token;ptinfo->linenum=ruby_sourceline;ptinfo-> column=token_info_get_column(parser, token);ptinfo->nonspc=token_info_has_nonspaces(parser, token);ptinfo->next=parser-> parser_token_info;parser-> parser_token_info=ptinfo;}static voidtoken_info_pop(struct parser_params *parser, const char *token){int linenum;token_info *ptinfo=parser-> parser_token_info;if(!ptinfo) return;parser-> parser_token_info=ptinfo->next;if(token_info_get_column(parser, token)==ptinfo->column){goto finish;}linenum=ruby_sourceline;if(linenum==ptinfo-> linenum){goto finish;}if(token_info_has_nonspaces(parser, token)||ptinfo->nonspc){goto finish;}if(parser-> parser_token_info_enabled){rb_compile_warn(ruby_sourcefile, linenum,"mismatched indentations at '%s' with '%s' at %d", token, ptinfo->token, ptinfo->linenum);}finish:xfree(ptinfo);}static intparser_yyerror(struct parser_params *parser, const char *msg){const int max_line_margin=30;const char *p,*pe;char *buf;long len;int i;compile_error(PARSER_ARG"%s", msg);p=lex_p;while(lex_pbeg<=p){if(*p== '\n') break;p--;}p++;pe=lex_p;while(pe < lex_pend){if(*pe== '\n') break;pe++;}len=pe-p;if(len > 4){char *p2;const char *pre="",*post="";if(len > max_line_margin *2+10){if(lex_p-p > max_line_margin){p=rb_enc_prev_char(p, lex_p-max_line_margin, pe, rb_enc_get(lex_lastline));pre="...";}if(pe-lex_p > max_line_margin){pe=rb_enc_prev_char(lex_p, lex_p+max_line_margin, pe, rb_enc_get(lex_lastline));post="...";}len=pe-p;}buf=ALLOCA_N(char, len+2);MEMCPY(buf, p, char, len);buf[len]= '\0';rb_compile_error_append("%s%s%s", pre, buf, post);i=(int)(lex_p-p);p2=buf;pe=buf+len;while(p2 < pe){if(*p2!= '\t')*p2= ' ';p2++;}buf[i]= '^';buf[i+1]= '\0';rb_compile_error_append("%s%s", pre, buf);}return 0;}static void parser_prepare(struct parser_params *parser);static VALUEdebug_lines(const char *f){ID script_lines;CONST_ID(script_lines,"SCRIPT_LINES__");if(rb_const_defined_at(rb_cObject, script_lines)){VALUE hash=rb_const_get_at(rb_cObject, script_lines);if(RB_TYPE_P(hash, T_HASH)){VALUE fname=rb_external_str_new_with_enc(f, strlen(f), rb_filesystem_encoding());VALUE lines=rb_ary_new();rb_hash_aset(hash, fname, lines);return lines;}}return 0;}static VALUEcoverage(const char *f, int n){VALUE coverages=rb_get_coverages();if(RTEST(coverages)&&RBASIC(coverages) -> klass==0){VALUE fname=rb_external_str_new_with_enc(f, strlen(f), rb_filesystem_encoding());VALUE lines=rb_ary_new2(n);int i;RBASIC(lines) -> klass=0;for(i=0;i< n;i++) RARRAY_PTR(lines)[i]=Qnil;RARRAY(lines) -> as.heap.len=n;rb_hash_aset(coverages, fname, lines);return lines;}return 0;}static inte_option_supplied(struct parser_params *parser){return strcmp(ruby_sourcefile,"-e")==0;}static VALUEyycompile0(VALUE arg){int n;NODE *tree;struct parser_params *parser=(struct parser_params *) arg;if(!compile_for_eval &&rb_safe_level()==0){ruby_debug_lines=debug_lines(ruby_sourcefile);if(ruby_debug_lines &&ruby_sourceline > 0){VALUE str=STR_NEW0();n=ruby_sourceline;do{rb_ary_push(ruby_debug_lines, str);}while(--n);}if(!e_option_supplied(parser)){ruby_coverage=coverage(ruby_sourcefile, ruby_sourceline);}}parser_prepare(parser);deferred_nodes=0;parser-> parser_token_info_enabled=!compile_for_eval &&RTEST(ruby_verbose);if(RUBY_DTRACE_PARSE_BEGIN_ENABLED()){RUBY_DTRACE_PARSE_BEGIN(parser-> parser_ruby_sourcefile, parser-> parser_ruby_sourceline);}n=yyparse((void *) parser);if(RUBY_DTRACE_PARSE_END_ENABLED()){RUBY_DTRACE_PARSE_END(parser-> parser_ruby_sourcefile, parser-> parser_ruby_sourceline);}ruby_debug_lines=0;ruby_coverage=0;compile_for_eval=0;lex_strterm=0;lex_p=lex_pbeg=lex_pend=0;lex_lastline=lex_nextline=0;if(parser-> nerr){return 0;}tree=ruby_eval_tree;if(!tree){tree=NEW_NIL();}else if(ruby_eval_tree_begin){tree-> nd_body=NEW_PRELUDE(ruby_eval_tree_begin, tree->nd_body);}return(VALUE) tree;}static NODE *yycompile(struct parser_params *parser, const char *f, int line){ruby_sourcefile=ruby_strdup(f);ruby_sourceline=line-1;return(NODE *) rb_suppress_tracing(yycompile0,(VALUE) parser);}static rb_encoding *must_be_ascii_compatible(VALUE s){rb_encoding *enc=rb_enc_get(s);if(!rb_enc_asciicompat(enc)){rb_raise(rb_eArgError,"invalid source encoding");}return enc;}static VALUElex_get_str(struct parser_params *parser, VALUE s){char *beg,*end,*pend;rb_encoding *enc=must_be_ascii_compatible(s);beg=RSTRING_PTR(s);if(lex_gets_ptr){if(RSTRING_LEN(s)==lex_gets_ptr) return Qnil;beg+=lex_gets_ptr;}pend=RSTRING_PTR(s)+RSTRING_LEN(s);end=beg;while(end < pend){if(*end++== '\n') break;}lex_gets_ptr=end-RSTRING_PTR(s);return rb_enc_str_new(beg, end-beg, enc);}static VALUElex_getline(struct parser_params *parser){VALUE line=(*parser->parser_lex_gets)(parser, parser->parser_lex_input);if(NIL_P(line)) return line;must_be_ascii_compatible(line);if(ruby_debug_lines){rb_enc_associate(line, current_enc);rb_ary_push(ruby_debug_lines, line);}if(ruby_coverage){rb_ary_push(ruby_coverage, Qnil);}return line;}static const rb_data_type_t parser_data_type;static NODE *parser_compile_string(volatile VALUE vparser, const char *f, VALUE s, int line){struct parser_params *parser;NODE *node;TypedData_Get_Struct(vparser, struct parser_params,&parser_data_type, parser);lex_gets=lex_get_str;lex_gets_ptr=0;lex_input=s;lex_pbeg=lex_p=lex_pend=0;compile_for_eval=rb_parse_in_eval();node=yycompile(parser, f, line);RB_GC_GUARD(vparser);return node;}NODE *rb_compile_string(const char *f, VALUE s, int line){must_be_ascii_compatible(s);return parser_compile_string(rb_parser_new(), f, s, line);}NODE *rb_parser_compile_string(volatile VALUE vparser, const char *f, VALUE s, int line){must_be_ascii_compatible(s);return parser_compile_string(vparser, f, s, line);}NODE *rb_compile_cstr(const char *f, const char *s, int len, int line){VALUE str=rb_str_new(s, len);return parser_compile_string(rb_parser_new(), f, str, line);}NODE *rb_parser_compile_cstr(volatile VALUE vparser, const char *f, const char *s, int len, int line){VALUE str=rb_str_new(s, len);return parser_compile_string(vparser, f, str, line);}static VALUElex_io_gets(struct parser_params *parser, VALUE io){return rb_io_gets(io);}NODE *rb_compile_file(const char *f, VALUE file, int start){VALUE volatile vparser=rb_parser_new();return rb_parser_compile_file(vparser, f, file, start);}NODE *rb_parser_compile_file(volatile VALUE vparser, const char *f, VALUE file, int start){struct parser_params *parser;NODE *node;TypedData_Get_Struct(vparser, struct parser_params,&parser_data_type, parser);lex_gets=lex_io_gets;lex_input=file;lex_pbeg=lex_p=lex_pend=0;compile_for_eval=rb_parse_in_eval();node=yycompile(parser, f, start);RB_GC_GUARD(vparser);return node;}#define STR_FUNC_ESCAPE#define STR_FUNC_EXPAND#define STR_FUNC_REGEXP#define STR_FUNC_QWORDS#define STR_FUNC_SYMBOL#define STR_FUNC_INDENTenum string_type{str_squote=(0), str_dquote=(STR_FUNC_EXPAND), str_xquote=(STR_FUNC_EXPAND), str_regexp=(STR_FUNC_REGEXP|STR_FUNC_ESCAPE|STR_FUNC_EXPAND), str_sword=(STR_FUNC_QWORDS), str_dword=(STR_FUNC_QWORDS|STR_FUNC_EXPAND), str_ssym=(STR_FUNC_SYMBOL), str_dsym=(STR_FUNC_SYMBOL|STR_FUNC_EXPAND)};static VALUEparser_str_new(const char *p, long n, rb_encoding *enc, int func, rb_encoding *enc0){VALUE str;str=rb_enc_str_new(p, n, enc);if(!(func &STR_FUNC_REGEXP)&&rb_enc_asciicompat(enc)){if(rb_enc_str_coderange(str)==ENC_CODERANGE_7BIT){}else if(enc0==rb_usascii_encoding()&&enc!=rb_utf8_encoding()){rb_enc_associate(str, rb_ascii8bit_encoding());}}return str;}#define lex_goto_eol(parser)#define lex_eol_p()#define peek(c)#define peek_n(c, n) static inline intparser_nextc(struct parser_params *parser){int c;if(lex_p==lex_pend){VALUE v=lex_nextline;lex_nextline=0;if(!v){if(parser-> eofp) return-1;if(!lex_input||NIL_P(v=lex_getline(parser))){parser-> eofp=Qtrue;lex_goto_eol(parser);return-1;}}{if(heredoc_end > 0){ruby_sourceline=heredoc_end;heredoc_end=0;}ruby_sourceline++;parser-> line_count++;lex_pbeg=lex_p=RSTRING_PTR(v);lex_pend=lex_p+RSTRING_LEN(v);ripper_flush(parser);lex_lastline=v;}}c=(unsigned char)*lex_p++;if(c== '\r'&&peek('\n')){lex_p++;c= '\n';}return c;}static voidparser_pushback(struct parser_params *parser, int c){if(c==-1) return;lex_p--;if(lex_p > lex_pbeg &&lex_p[0]== '\n'&&lex_p[-1]== '\r'){lex_p--;}}#define was_bol()#define tokfix()#define tok()#define toklen()#define toklast() static char *parser_newtok(struct parser_params *parser){tokidx=0;tokline=ruby_sourceline;if(!tokenbuf){toksiz=60;tokenbuf=ALLOC_N(char, 60);}if(toksiz > 4096){toksiz=60;REALLOC_N(tokenbuf, char, 60);}return tokenbuf;}static char *parser_tokspace(struct parser_params *parser, int n){tokidx+=n;if(tokidx > =toksiz){do{toksiz *=2;}while(toksiz < tokidx);REALLOC_N(tokenbuf, char, toksiz);}return &tokenbuf[tokidx-n];}static voidparser_tokadd(struct parser_params *parser, int c){tokenbuf[tokidx++]=(char) c;if(tokidx >=toksiz){toksiz *=2;REALLOC_N(tokenbuf, char, toksiz);}}static intparser_tok_hex(struct parser_params *parser, size_t *numlen){int c;c=scan_hex(lex_p, 2, numlen);if(!*numlen){yyerror("invalid hex escape");return 0;}lex_p+=*numlen;return c;}#define tokcopy(n) static intparser_tokadd_utf8(struct parser_params *parser, rb_encoding **encp, int string_literal, int symbol_literal, int regexp_literal){int codepoint;size_t numlen;if(regexp_literal){tokadd('\\');tokadd('u');}if(peek('{')){do{if(regexp_literal){tokadd(*lex_p);}nextc();codepoint=scan_hex(lex_p, 6,&numlen);if(numlen==0){yyerror("invalid Unicode escape");return 0;}if(codepoint > 0x10ffff){yyerror("invalid Unicode codepoint (too large)");return 0;}lex_p+=numlen;if(regexp_literal){tokcopy((int) numlen);}else if(codepoint >=0x80){*encp=rb_utf8_encoding();if(string_literal) tokaddmbc(codepoint,*encp);}else if(string_literal){tokadd(codepoint);}}while(string_literal &&(peek(' ')||peek('\t')));if(!peek('}')){yyerror("unterminated Unicode escape");return 0;}if(regexp_literal){tokadd('}');}nextc();}else{codepoint=scan_hex(lex_p, 4,&numlen);if(numlen< 4){yyerror("invalid Unicode escape");return 0;}lex_p+=4;if(regexp_literal){tokcopy(4);}else if(codepoint >=0x80){*encp=rb_utf8_encoding();if(string_literal) tokaddmbc(codepoint,*encp);}else if(string_literal){tokadd(codepoint);}}return codepoint;}#define ESCAPE_CONTROL#define ESCAPE_METAstatic intparser_read_escape(struct parser_params *parser, int flags, rb_encoding **encp){int c;size_t numlen;switch(c=nextc()){case '\\':return c;case 'n':return '\n';case 't':return '\t';case 'r':return '\r';case 'f':return '\f';case 'v':return '\13';case 'a':return '\007';case 'e':return 033;case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':pushback(c);c=scan_oct(lex_p, 3,&numlen);lex_p+=numlen;return c;case 'x':c=tok_hex(&numlen);if(numlen==0) return 0;return c;case 'b':return '\010';case 's':return ' ';case 'M':if(flags &ESCAPE_META) goto eof;if((c=nextc())!= '-'){pushback(c);goto eof;}if((c=nextc())== '\\'){if(peek('u')) goto eof;return read_escape(flags|ESCAPE_META, encp)|0x80;}else if(c==-1||!ISASCII(c)) goto eof;else{return((c &0xff)|0x80);}case 'C':if((c=nextc())!= '-'){pushback(c);goto eof;}case 'c':if(flags &ESCAPE_CONTROL) goto eof;if((c=nextc())== '\\'){if(peek('u')) goto eof;c=read_escape(flags|ESCAPE_CONTROL, encp);}else if(c== '?') return 0177;else if(c==-1||!ISASCII(c)) goto eof;return c &0x9f;eof:case-1:yyerror("Invalid escape character syntax");return '\0';default:return c;}}static voidparser_tokaddmbc(struct parser_params *parser, int c, rb_encoding *enc){int len=rb_enc_codelen(c, enc);rb_enc_mbcput(c, tokspace(len), enc);}static intparser_tokadd_escape(struct parser_params *parser, rb_encoding **encp){int c;int flags=0;size_t numlen;first:switch(c=nextc()){case '\n':return 0;case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':{ruby_scan_oct(--lex_p, 3,&numlen);if(numlen==0) goto eof;lex_p+=numlen;tokcopy((int) numlen+1);}return 0;case 'x':{tok_hex(&numlen);if(numlen==0) return-1;tokcopy((int) numlen+2);}return 0;case 'M':if(flags &ESCAPE_META) goto eof;if((c=nextc())!= '-'){pushback(c);goto eof;}tokcopy(3);flags|=ESCAPE_META;goto escaped;case 'C':if(flags &ESCAPE_CONTROL) goto eof;if((c=nextc())!= '-'){pushback(c);goto eof;}tokcopy(3);goto escaped;case 'c':if(flags &ESCAPE_CONTROL) goto eof;tokcopy(2);flags|=ESCAPE_CONTROL;escaped:if((c=nextc())== '\\'){goto first;}else if(c==-1) goto eof;tokadd(c);return 0;eof:case-1:yyerror("Invalid escape character syntax");return-1;default:tokadd('\\');tokadd(c);}return 0;}static intparser_regx_options(struct parser_params *parser){int kcode=0;int kopt=0;int options=0;int c, opt, kc;newtok();while(c=nextc(), ISALPHA(c)){if(c== 'o'){options|=RE_OPTION_ONCE;}else if(rb_char_to_option_kcode(c,&opt,&kc)){if(kc >=0){if(kc!=rb_ascii8bit_encindex()) kcode=c;kopt=opt;}else{options|=opt;}}else{tokadd(c);}}options|=kopt;pushback(c);if(toklen()){tokfix();compile_error(PARSER_ARG"unknown regexp option%s - %s", toklen() > 1?"s":"", tok());}return options|RE_OPTION_ENCODING(kcode);}static voiddispose_string(VALUE str){rb_str_free(str);rb_gc_force_recycle(str);}static intparser_tokadd_mbchar(struct parser_params *parser, int c){int len=parser_precise_mbclen();if(!MBCLEN_CHARFOUND_P(len)){compile_error(PARSER_ARG"invalid multibyte char (%s)", parser_encoding_name());return-1;}tokadd(c);lex_p+=--len;if(len > 0) tokcopy(len);return c;}#define tokadd_mbchar(c) static inline intsimple_re_meta(int c){switch(c){case '$':case '*':case '+':case '.':case '?':case '^':case '|':case ')':case ']':case '}':case '>':return TRUE;default:return FALSE;}}static intparser_tokadd_string(struct parser_params *parser, int func, int term, int paren, long *nest, rb_encoding **encp){int c;int has_nonascii=0;rb_encoding *enc=*encp;char *errbuf=0;static const char mixed_msg[]="%s mixed within %s source";#define mixed_error(enc1, enc2)#define mixed_escape(beg, enc1, enc2) while((c=nextc())!=-1){if(paren &&c==paren){++*nest;}else if(c==term){if(!nest||!*nest){pushback(c);break;}--*nest;}else if((func &STR_FUNC_EXPAND)&&c== '#'&&lex_p< lex_pend){int c2=*lex_p;if(c2== '$'||c2== '@'||c2== '{'){pushback(c);break;}}else if(c== '\\'){const char *beg=lex_p-1;c=nextc();switch(c){case '\n':if(func &STR_FUNC_QWORDS) break;if(func &STR_FUNC_EXPAND) continue;tokadd('\\');break;case '\\':if(func &STR_FUNC_ESCAPE) tokadd(c);break;case 'u':if((func &STR_FUNC_EXPAND)==0){tokadd('\\');break;}parser_tokadd_utf8(parser,&enc, 1, func &STR_FUNC_SYMBOL, func &STR_FUNC_REGEXP);if(has_nonascii &&enc!=*encp){mixed_escape(beg, enc,*encp);}continue;default:if(c==-1) return-1;if(!ISASCII(c)){if((func &STR_FUNC_EXPAND)==0) tokadd('\\');goto non_ascii;}if(func &STR_FUNC_REGEXP){if(c==term &&!simple_re_meta(c)){tokadd(c);continue;}pushback(c);if((c=tokadd_escape(&enc))< 0) return-1;if(has_nonascii &&enc!=*encp){mixed_escape(beg, enc,*encp);}continue;}else if(func &STR_FUNC_EXPAND){pushback(c);if(func &STR_FUNC_ESCAPE) tokadd('\\');c=read_escape(0,&enc);}else if((func &STR_FUNC_QWORDS)&&ISSPACE(c)){}else if(c!=term &&!(paren &&c==paren)){tokadd('\\');pushback(c);continue;}}}else if(!parser_isascii()){non_ascii:has_nonascii=1;if(enc!=*encp){mixed_error(enc,*encp);continue;}if(tokadd_mbchar(c)==-1) return-1;continue;}else if((func &STR_FUNC_QWORDS)&&ISSPACE(c)){pushback(c);break;}if(c &0x80){has_nonascii=1;if(enc!=*encp){mixed_error(enc,*encp);continue;}}tokadd(c);}*encp=enc;return c;}#define NEW_STRTERM(func, term, paren)#define flush_string_content(enc) RUBY_FUNC_EXPORTED const unsigned int ruby_global_name_punct_bits[(0x7e-0x20+31)/32];#define BIT(c, idx)#define SPECIAL_PUNCT(idx) const unsigned int ruby_global_name_punct_bits[]={SPECIAL_PUNCT(0), SPECIAL_PUNCT(1), SPECIAL_PUNCT(2),};static inline intis_global_name_punct(const char c){if(c<=0x20||0x7e< c) return 0;return(ruby_global_name_punct_bits[(c-0x20)/32] >>(c%32))&1;}static intparser_peek_variable_name(struct parser_params *parser){int c;const char *p=lex_p;if(p+1 >=lex_pend) return 0;c=*p++;switch(c){case '$':if((c=*p)== '-'){if(++p >=lex_pend) return 0;c=*p;}else if(is_global_name_punct(c)||ISDIGIT(c)){return tSTRING_DVAR;}break;case '@':if((c=*p)== '@'){if(++p >=lex_pend) return 0;c=*p;}break;case '{':lex_p=p;command_start=TRUE;return tSTRING_DBEG;default:return 0;}if(!ISASCII(c)||c== '_'||ISALPHA(c)) return tSTRING_DVAR;return 0;}static intparser_parse_string(struct parser_params *parser, NODE *quote){int func=(int) quote->nd_func;int term=nd_term(quote);int paren=nd_paren(quote);int c, space=0;rb_encoding *enc=current_enc;if(func==-1) return tSTRING_END;c=nextc();if((func &STR_FUNC_QWORDS)&&ISSPACE(c)){do{c=nextc();}while(ISSPACE(c));space=1;}if(c==term &&!quote->nd_nest){if(func &STR_FUNC_QWORDS){quote->nd_func=-1;return ' ';}if(!(func &STR_FUNC_REGEXP)) return tSTRING_END;set_yylval_num(regx_options());return tREGEXP_END;}if(space){pushback(c);return ' ';}newtok();if((func &STR_FUNC_EXPAND)&&c== '#'){int t=parser_peek_variable_name(parser);if(t) return t;tokadd('#');c=nextc();}pushback(c);if(tokadd_string(func, term, paren,&quote->nd_nest,&enc)==-1){ruby_sourceline=nd_line(quote);if(func &STR_FUNC_REGEXP){if(parser->eofp) compile_error(PARSER_ARG"unterminated regexp meets end of file");return tREGEXP_END;}else{if(parser->eofp) compile_error(PARSER_ARG"unterminated string meets end of file");return tSTRING_END;}}tokfix();set_yylval_str(STR_NEW3(tok(), toklen(), enc, func));flush_string_content(enc);return tSTRING_CONTENT;}static intparser_heredoc_identifier(struct parser_params *parser){int c=nextc(), term, func=0;long len;if(c== '-'){c=nextc();func=STR_FUNC_INDENT;}switch(c){case '\'':func|=str_squote;goto quoted;case '"': func |= str_dquote; goto quoted; case '`': func |= str_xquote; quoted: newtok(); tokadd(func); term = c; while ((c = nextc()) != -1 && c != term) { if (tokadd_mbchar(c) == -1) return 0; } if (c == -1) { compile_error(PARSER_ARG "unterminated here document identifier"); return 0; } break; default: if (!parser_is_identchar()) { pushback(c); if (func & STR_FUNC_INDENT) { pushback('-'); } return 0; } newtok(); term = '"';tokadd(func|=str_dquote);do{if(tokadd_mbchar(c)==-1) return 0;}while((c=nextc())!=-1 &&parser_is_identchar());pushback(c);break;}tokfix();len=lex_p-lex_pbeg;lex_goto_eol(parser);lex_strterm=rb_node_newnode(NODE_HEREDOC, STR_NEW(tok(), toklen()), len, lex_lastline);nd_set_line(lex_strterm, ruby_sourceline);ripper_flush(parser);return term== '`'?tXSTRING_BEG:tSTRING_BEG;}static voidparser_heredoc_restore(struct parser_params *parser, NODE *here){VALUE line;line=here->nd_orig;lex_lastline=line;lex_pbeg=RSTRING_PTR(line);lex_pend=lex_pbeg+RSTRING_LEN(line);lex_p=lex_pbeg+here->nd_nth;heredoc_end=ruby_sourceline;ruby_sourceline=nd_line(here);dispose_string(here->nd_lit);rb_gc_force_recycle((VALUE) here);ripper_flush(parser);}static intparser_whole_match_p(struct parser_params *parser, const char *eos, long len, int indent){const char *p=lex_pbeg;long n;if(indent){while(*p &&ISSPACE(*p)) p++;}n=lex_pend-(p+len);if(n< 0||(n > 0 &&p[len]!= '\n'&&p[len]!= '\r')) return FALSE;return strncmp(eos, p, len)==0;}#define dispatch_heredoc_end() static intparser_here_document(struct parser_params *parser, NODE *here){int c, func, indent=0;const char *eos,*p,*pend;long len;VALUE str=0;rb_encoding *enc=current_enc;eos=RSTRING_PTR(here->nd_lit);len=RSTRING_LEN(here->nd_lit)-1;indent=(func=*eos++)&STR_FUNC_INDENT;if((c=nextc())==-1){error:compile_error(PARSER_ARG"can't find string \"%s\" anywhere before EOF", eos);restore:heredoc_restore(lex_strterm);lex_strterm=0;return 0;}if(was_bol()&&whole_match_p(eos, len, indent)){dispatch_heredoc_end();heredoc_restore(lex_strterm);return tSTRING_END;}if(!(func &STR_FUNC_EXPAND)){do{p=RSTRING_PTR(lex_lastline);pend=lex_pend;if(pend > p){switch(pend[-1]){case '\n':if(--pend==p||pend[-1]!= '\r'){pend++;break;}case '\r':--pend;}}if(str) rb_str_cat(str, p, pend-p);else str=STR_NEW(p, pend-p);if(pend< lex_pend) rb_str_cat(str,"\n", 1);lex_goto_eol(parser);if(nextc()==-1){if(str) dispose_string(str);goto error;}}while(!whole_match_p(eos, len, indent));}else{newtok();if(c== '#'){int t=parser_peek_variable_name(parser);if(t) return t;tokadd('#');c=nextc();}do{pushback(c);if((c=tokadd_string(func, '\n', 0, NULL,&enc))==-1){if(parser->eofp) goto error;goto restore;}if(c!= '\n'){set_yylval_str(STR_NEW3(tok(), toklen(), enc, func));flush_string_content(enc);return tSTRING_CONTENT;}tokadd(nextc());if((c=nextc())==-1) goto error;}while(!whole_match_p(eos, len, indent));str=STR_NEW3(tok(), toklen(), enc, func);}dispatch_heredoc_end();heredoc_restore(lex_strterm);lex_strterm=NEW_STRTERM(-1, 0, 0);set_yylval_str(str);return tSTRING_CONTENT;}static voidarg_ambiguous_gen(struct parser_params *parser){rb_warning0("ambiguous first argument; put parentheses or even spaces");}#define arg_ambiguous() static IDformal_argument_gen(struct parser_params *parser, ID lhs){if(!is_local_id(lhs)) yyerror("formal argument must be local variable");shadowing_lvar(lhs);return lhs;}static intlvar_defined_gen(struct parser_params *parser, ID id){return(dyna_in_block()&&dvar_defined_get(id))||local_id(id);}static longparser_encode_length(struct parser_params *parser, const char *name, long len){long nlen;if(len > 5 &&name[nlen=len-5]== '-'){if(rb_memcicmp(name+nlen+1,"unix", 4)==0) return nlen;}if(len > 4 &&name[nlen=len-4]== '-'){if(rb_memcicmp(name+nlen+1,"dos", 3)==0) return nlen;if(rb_memcicmp(name+nlen+1,"mac", 3)==0 &&!(len==8 &&rb_memcicmp(name,"utf8-mac", len)==0)) return nlen;}return len;}static voidparser_set_encode(struct parser_params *parser, const char *name){int idx=rb_enc_find_index(name);rb_encoding *enc;VALUE excargs[3];if(idx< 0){excargs[1]=rb_sprintf("unknown encoding name: %s", name);error:excargs[0]=rb_eArgError;excargs[2]=rb_make_backtrace();rb_ary_unshift(excargs[2], rb_sprintf("%s:%d", ruby_sourcefile, ruby_sourceline));rb_exc_raise(rb_make_exception(3, excargs));}enc=rb_enc_from_index(idx);if(!rb_enc_asciicompat(enc)){excargs[1]=rb_sprintf("%s is not ASCII compatible", rb_enc_name(enc));goto error;}parser->enc=enc;if(ruby_debug_lines){long i, n=RARRAY_LEN(ruby_debug_lines);const VALUE *p=RARRAY_PTR(ruby_debug_lines);for(i=0;i< n;++i){rb_enc_associate_index(*p, idx);}}}static intcomment_at_top(struct parser_params *parser){const char *p=lex_pbeg,*pend=lex_p-1;if(parser->line_count!=(parser->has_shebang?2:1)) return 0;while(p< pend){if(!ISSPACE(*p)) return 0;p++;}return 1;}typedef long(*rb_magic_comment_length_t)(struct parser_params *parser, const char *name, long len);typedef void(*rb_magic_comment_setter_t)(struct parser_params *parser, const char *name, const char *val);static voidmagic_comment_encoding(struct parser_params *parser, const char *name, const char *val){if(!comment_at_top(parser)){return;}parser_set_encode(parser, val);}static voidparser_set_token_info(struct parser_params *parser, const char *name, const char *val){int *p=&parser->parser_token_info_enabled;switch(*val){case 't':case 'T':if(strcasecmp(val,"true")==0){*p=TRUE;return;}break;case 'f':case 'F':if(strcasecmp(val,"false")==0){*p=FALSE;return;}break;}rb_compile_warning(ruby_sourcefile, ruby_sourceline,"invalid value for %s: %s", name, val);}struct magic_comment{const char *name;rb_magic_comment_setter_t func;rb_magic_comment_length_t length;};static const struct magic_comment magic_comments[]={{"coding", magic_comment_encoding, parser_encode_length},{"encoding", magic_comment_encoding, parser_encode_length},{"warn_indent", parser_set_token_info},};static const char *magic_comment_marker(const char *str, long len){long i=2;while(i< len){switch(str[i]){case '-':if(str[i-1]== '*'&&str[i-2]== '-'){return str+i+1;}i+=2;break;case '*':if(i+1 >=len) return 0;if(str[i+1]!= '-'){i+=4;}else if(str[i-1]!= '-'){i+=2;}else{return str+i+2;}break;default:i+=3;break;}}return 0;}static intparser_magic_comment(struct parser_params *parser, const char *str, long len){VALUE name=0, val=0;const char *beg,*end,*vbeg,*vend;#define str_copy(_s, _p, _n) if(len<=7) return FALSE;if(!(beg=magic_comment_marker(str, len))) return FALSE;if(!(end=magic_comment_marker(beg, str+len-beg))) return FALSE;str=beg;len=end-beg-3;while(len > 0){const struct magic_comment *p=magic_comments;char *s;int i;long n=0;for(;len > 0 &&*str;str++,--len){switch(*str){case '\'':case '"': case ':': case ';': continue; } if (!ISSPACE(*str)) break; } for (beg = str; len > 0; str++, --len) { switch (*str) { case '\'': case '"':case ':':case ';':break;default:if(ISSPACE(*str)) break;continue;}break;}for(end=str;len > 0 &&ISSPACE(*str);str++,--len);if(!len) break;if(*str!= ':') continue;do str++;while(--len > 0 &&ISSPACE(*str));if(!len) break;if(*str== '"') { for (vbeg = ++str; --len > 0 && *str != '"';str++){if(*str== '\\'){--len;++str;}}vend=str;if(len){--len;++str;}}else{for(vbeg=str;len > 0 &&*str!= '"' && *str != ';' && !ISSPACE(*str); --len, str++); vend = str; } while (len > 0 && (*str == ';' || ISSPACE(*str))) --len, str++; n = end - beg; str_copy(name, beg, n); s = RSTRING_PTR(name); for (i = 0; i < n; ++i) { if (s[i] == '-') s[i] = '_'; } do { if (STRNCASECMP(p->name, s, n) == 0) { n = vend - vbeg; if (p->length) { n = (*p->length)(parser, vbeg, n); } str_copy(val, vbeg, n); (*p->func)(parser, s, RSTRING_PTR(val)); break; } } while (++p < magic_comments + numberof(magic_comments)); } return TRUE;}static voidset_file_encoding(struct parser_params *parser, const char *str, const char *send){ int sep = 0; const char *beg = str; VALUE s; for (;;) { if (send - str <= 6) return; switch (str[6]) { case 'C': case 'c': str += 6; continue; case 'O': case 'o': str += 5; continue; case 'D': case 'd': str += 4; continue; case 'I': case 'i': str += 3; continue; case 'N': case 'n': str += 2; continue; case 'G': case 'g': str += 1; continue; case '=': case ':': sep = 1; str += 6; break; default: str += 6; if (ISSPACE(*str)) break; continue; } if (STRNCASECMP(str-6, "coding", 6) == 0) break; } for (;;) { do { if (++str >= send) return; } while (ISSPACE(*str)); if (sep) break; if (*str != '=' && *str != ':') return; sep = 1; str++; } beg = str; while ((*str == '-' || *str == '_' || ISALNUM(*str)) && ++str < send); s = rb_str_new(beg, parser_encode_length(parser, beg, str - beg)); parser_set_encode(parser, RSTRING_PTR(s)); rb_str_resize(s, 0);}static voidparser_prepare(struct parser_params *parser){ int c = nextc(); switch (c) { case '#': if (peek('!')) parser->has_shebang = 1; break; case 0xef: if (lex_pend - lex_p >= 2 && (unsigned char)lex_p[0] == 0xbb && (unsigned char)lex_p[1] == 0xbf) { parser->enc = rb_utf8_encoding(); lex_p += 2; lex_pbeg = lex_p; return; } break; case EOF: return; } pushback(c); parser->enc = rb_enc_get(lex_lastline);}#define IS_ARG() #define IS_END() #define IS_BEG() #define IS_SPCARG(c) #define IS_LABEL_POSSIBLE() #define IS_LABEL_SUFFIX(n) #define IS_AFTER_OPERATOR() #define ambiguous_operator(op, syn) #define warn_balanced(op, syn) static intparser_yylex(struct parser_params *parser){ register int c; int space_seen = 0; int cmd_state; enum lex_state_e last_state; rb_encoding *enc; int mb; if (lex_strterm) { int token; if (nd_type(lex_strterm) == NODE_HEREDOC) { token = here_document(lex_strterm); if (token == tSTRING_END) { lex_strterm = 0; lex_state = EXPR_END; } } else { token = parse_string(lex_strterm); if (token == tSTRING_END || token == tREGEXP_END) { rb_gc_force_recycle((VALUE)lex_strterm); lex_strterm = 0; lex_state = EXPR_END; } } return token; } cmd_state = command_start; command_start = FALSE; retry: last_state = lex_state; switch (c = nextc()) { case '\0': case '\004': case '\032': case -1: return 0; case ' ': case '\t': case '\f': case '\r': case '\13': space_seen = 1; goto retry; case '#': if (!parser_magic_comment(parser, lex_p, lex_pend - lex_p)) { if (comment_at_top(parser)) { set_file_encoding(parser, lex_p, lex_pend); } } lex_p = lex_pend; case '\n': if (IS_lex_state(EXPR_BEG | EXPR_VALUE | EXPR_CLASS | EXPR_FNAME | EXPR_DOT)) { goto retry; } while ((c = nextc())) { switch (c) { case ' ': case '\t': case '\f': case '\r': case '\13': space_seen = 1; break; case '.': { if ((c = nextc()) != '.') { pushback(c); pushback('.'); goto retry; } } default: --ruby_sourceline; lex_nextline = lex_lastline; case -1: lex_goto_eol(parser); goto normal_newline; } } normal_newline: command_start = TRUE; lex_state = EXPR_BEG; return '\n'; case '*': if ((c = nextc()) == '*') { if ((c = nextc()) == '=') { set_yylval_id(tPOW); lex_state = EXPR_BEG; return tOP_ASGN; } pushback(c); if (IS_SPCARG(c)) { rb_warning0("`**'interpreted as argument prefix"); c = tDSTAR; } else if (IS_BEG()) { c = tDSTAR; } else { warn_balanced("**", "argument prefix"); c = tPOW; } } else { if (c == '=') { set_yylval_id('*'); lex_state = EXPR_BEG; return tOP_ASGN; } pushback(c); if (IS_SPCARG(c)) { rb_warning0("`*'interpreted as argument prefix"); c = tSTAR; } else if (IS_BEG()) { c = tSTAR; } else { warn_balanced("*", "argument prefix"); c = '*'; } } lex_state = IS_AFTER_OPERATOR() ? EXPR_ARG : EXPR_BEG; return c; case '!': c = nextc(); if (IS_AFTER_OPERATOR()) { lex_state = EXPR_ARG; if (c == '@') { return '!'; } } else { lex_state = EXPR_BEG; } if (c == '=') { return tNEQ; } if (c == '~') { return tNMATCH; } pushback(c); return '!'; case '=': if (was_bol()) { if (strncmp(lex_p, "begin", 5) == 0 && ISSPACE(lex_p[5])) { for (;;) { lex_goto_eol(parser); c = nextc(); if (c == -1) { compile_error(PARSER_ARG "embedded document meets end of file"); return 0; } if (c != '=') continue; if (strncmp(lex_p, "end", 3) == 0 && (lex_p + 3 == lex_pend || ISSPACE(lex_p[3]))) { break; } } lex_goto_eol(parser); goto retry; } } lex_state = IS_AFTER_OPERATOR() ? EXPR_ARG : EXPR_BEG; if ((c = nextc()) == '=') { if ((c = nextc()) == '=') { return tEQQ; } pushback(c); return tEQ; } if (c == '~') { return tMATCH; } else if (c == '>') { return tASSOC; } pushback(c); return '='; case '<': last_state = lex_state; c = nextc(); if (c == '<' && !IS_lex_state(EXPR_DOT | EXPR_CLASS) && !IS_END() && (!IS_ARG() || space_seen)) { int token = heredoc_identifier(); if (token) return token; } if (IS_AFTER_OPERATOR()) { lex_state = EXPR_ARG; } else { if (IS_lex_state(EXPR_CLASS)) command_start = TRUE; lex_state = EXPR_BEG; } if (c == '=') { if ((c = nextc()) == '>') { return tCMP; } pushback(c); return tLEQ; } if (c == '<') { if ((c = nextc()) == '=') { set_yylval_id(tLSHFT); lex_state = EXPR_BEG; return tOP_ASGN; } pushback(c); warn_balanced("<<", "here document"); return tLSHFT; } pushback(c); return '<'; case '>': lex_state = IS_AFTER_OPERATOR() ? EXPR_ARG : EXPR_BEG; if ((c = nextc()) == '=') { return tGEQ; } if (c == '>') { if ((c = nextc()) == '=') { set_yylval_id(tRSHFT); lex_state = EXPR_BEG; return tOP_ASGN; } pushback(c); return tRSHFT; } pushback(c); return '>'; case '"':lex_strterm=NEW_STRTERM(str_dquote, '"', 0); return tSTRING_BEG; case '`': if (IS_lex_state(EXPR_FNAME)) { lex_state = EXPR_ENDFN; return c; } if (IS_lex_state(EXPR_DOT)) { if (cmd_state) lex_state = EXPR_CMDARG; else lex_state = EXPR_ARG; return c; } lex_strterm = NEW_STRTERM(str_xquote, '`', 0); return tXSTRING_BEG; case '\'': lex_strterm = NEW_STRTERM(str_squote, '\'', 0); return tSTRING_BEG; case '?': if (IS_END()) { lex_state = EXPR_VALUE; return '?'; } c = nextc(); if (c == -1) { compile_error(PARSER_ARG "incomplete character syntax"); return 0; } if (rb_enc_isspace(c, current_enc)) { if (!IS_ARG()) { int c2 = 0; switch (c) { case ' ': c2 = 's'; break; case '\n': c2 = 'n'; break; case '\t': c2 = 't'; break; case '\v': c2 = 'v'; break; case '\r': c2 = 'r'; break; case '\f': c2 = 'f'; break; } if (c2) { rb_warnI("invalid character syntax;use?\\%c", c2); } } ternary: pushback(c); lex_state = EXPR_VALUE; return '?'; } newtok(); enc = current_enc; if (!parser_isascii()) { if (tokadd_mbchar(c) == -1) return 0; } else if ((rb_enc_isalnum(c, current_enc) || c == '_') && lex_p < lex_pend && is_identchar(lex_p, lex_pend, current_enc)) { goto ternary; } else if (c == '\\') { if (peek('u')) { nextc(); c = parser_tokadd_utf8(parser, &enc, 0, 0, 0); if (0x80 <= c) { tokaddmbc(c, enc); } else { tokadd(c); } } else if (!lex_eol_p() && !(c = *lex_p, ISASCII(c))) { nextc(); if (tokadd_mbchar(c) == -1) return 0; } else { c = read_escape(0, &enc); tokadd(c); } } else { tokadd(c); } tokfix(); set_yylval_str(STR_NEW3(tok(), toklen(), enc, 0)); lex_state = EXPR_END; return tCHAR; case '&': if ((c = nextc()) == '&') { lex_state = EXPR_BEG; if ((c = nextc()) == '=') { set_yylval_id(tANDOP); lex_state = EXPR_BEG; return tOP_ASGN; } pushback(c); return tANDOP; } else if (c == '=') { set_yylval_id('&'); lex_state = EXPR_BEG; return tOP_ASGN; } pushback(c); if (IS_SPCARG(c)) { rb_warning0("`&'interpreted as argument prefix"); c = tAMPER; } else if (IS_BEG()) { c = tAMPER; } else { warn_balanced("&", "argument prefix"); c = '&'; } lex_state = IS_AFTER_OPERATOR() ? EXPR_ARG : EXPR_BEG; return c; case '|': if ((c = nextc()) == '|') { lex_state = EXPR_BEG; if ((c = nextc()) == '=') { set_yylval_id(tOROP); lex_state = EXPR_BEG; return tOP_ASGN; } pushback(c); return tOROP; } if (c == '=') { set_yylval_id('|'); lex_state = EXPR_BEG; return tOP_ASGN; } lex_state = IS_AFTER_OPERATOR() ? EXPR_ARG : EXPR_BEG; pushback(c); return '|'; case '+': c = nextc(); if (IS_AFTER_OPERATOR()) { lex_state = EXPR_ARG; if (c == '@') { return tUPLUS; } pushback(c); return '+'; } if (c == '=') { set_yylval_id('+'); lex_state = EXPR_BEG; return tOP_ASGN; } if (IS_BEG() || (IS_SPCARG(c) && arg_ambiguous())) { lex_state = EXPR_BEG; pushback(c); if (c != -1 && ISDIGIT(c)) { c = '+'; goto start_num; } return tUPLUS; } lex_state = EXPR_BEG; pushback(c); warn_balanced("+", "unary operator"); return '+'; case '-': c = nextc(); if (IS_AFTER_OPERATOR()) { lex_state = EXPR_ARG; if (c == '@') { return tUMINUS; } pushback(c); return '-'; } if (c == '=') { set_yylval_id('-'); lex_state = EXPR_BEG; return tOP_ASGN; } if (c == '>') { lex_state = EXPR_ENDFN; return tLAMBDA; } if (IS_BEG() || (IS_SPCARG(c) && arg_ambiguous())) { lex_state = EXPR_BEG; pushback(c); if (c != -1 && ISDIGIT(c)) { return tUMINUS_NUM; } return tUMINUS; } lex_state = EXPR_BEG; pushback(c); warn_balanced("-", "unary operator"); return '-'; case '.': lex_state = EXPR_BEG; if ((c = nextc()) == '.') { if ((c = nextc()) == '.') { return tDOT3; } pushback(c); return tDOT2; } pushback(c); if (c != -1 && ISDIGIT(c)) { yyerror("no.< digit > floating literal anymore;put 0 before dot"); } lex_state = EXPR_DOT; return '.'; start_num: case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { int is_float, seen_point, seen_e, nondigit; is_float = seen_point = seen_e = nondigit = 0; lex_state = EXPR_END; newtok(); if (c == '-' || c == '+') { tokadd(c); c = nextc(); } if (c == '0') {#define no_digits() int start = toklen(); c = nextc(); if (c == 'x' || c == 'X') { c = nextc(); if (c != -1 && ISXDIGIT(c)) { do { if (c == '_') { if (nondigit) break; nondigit = c; continue; } if (!ISXDIGIT(c)) break; nondigit = 0; tokadd(c); } while ((c = nextc()) != -1); } pushback(c); tokfix(); if (toklen() == start) { no_digits(); } else if (nondigit) goto trailing_uc; set_yylval_literal(rb_cstr_to_inum(tok(), 16, FALSE)); return tINTEGER; } if (c == 'b' || c == 'B') { c = nextc(); if (c == '0' || c == '1') { do { if (c == '_') { if (nondigit) break; nondigit = c; continue; } if (c != '0' && c != '1') break; nondigit = 0; tokadd(c); } while ((c = nextc()) != -1); } pushback(c); tokfix(); if (toklen() == start) { no_digits(); } else if (nondigit) goto trailing_uc; set_yylval_literal(rb_cstr_to_inum(tok(), 2, FALSE)); return tINTEGER; } if (c == 'd' || c == 'D') { c = nextc(); if (c != -1 && ISDIGIT(c)) { do { if (c == '_') { if (nondigit) break; nondigit = c; continue; } if (!ISDIGIT(c)) break; nondigit = 0; tokadd(c); } while ((c = nextc()) != -1); } pushback(c); tokfix(); if (toklen() == start) { no_digits(); } else if (nondigit) goto trailing_uc; set_yylval_literal(rb_cstr_to_inum(tok(), 10, FALSE)); return tINTEGER; } if (c == '_') { goto octal_number; } if (c == 'o' || c == 'O') { c = nextc(); if (c == -1 || c == '_' || !ISDIGIT(c)) { no_digits(); } } if (c >= '0' && c <= '7') { octal_number: do { if (c == '_') { if (nondigit) break; nondigit = c; continue; } if (c < '0' || c > '9') break; if (c > '7') goto invalid_octal; nondigit = 0; tokadd(c); } while ((c = nextc()) != -1); if (toklen() > start) { pushback(c); tokfix(); if (nondigit) goto trailing_uc; set_yylval_literal(rb_cstr_to_inum(tok(), 8, FALSE)); return tINTEGER; } if (nondigit) { pushback(c); goto trailing_uc; } } if (c > '7' && c <= '9') { invalid_octal: yyerror("Invalid octal digit"); } else if (c == '.' || c == 'e' || c == 'E') { tokadd('0'); } else { pushback(c); set_yylval_literal(INT2FIX(0)); return tINTEGER; } } for (;;) { switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': nondigit = 0; tokadd(c); break; case '.': if (nondigit) goto trailing_uc; if (seen_point || seen_e) { goto decode_num; } else { int c0 = nextc(); if (c0 == -1 || !ISDIGIT(c0)) { pushback(c0); goto decode_num; } c = c0; } tokadd('.'); tokadd(c); is_float++; seen_point++; nondigit = 0; break; case 'e': case 'E': if (nondigit) { pushback(c); c = nondigit; goto decode_num; } if (seen_e) { goto decode_num; } tokadd(c); seen_e++; is_float++; nondigit = c; c = nextc(); if (c != '-' && c != '+') continue; tokadd(c); nondigit = c; break; case '_': if (nondigit) goto decode_num; nondigit = c; break; default: goto decode_num; } c = nextc(); } decode_num: pushback(c); if (nondigit) { char tmp[30]; trailing_uc: snprintf(tmp, sizeof(tmp), "trailing`%c'in number", nondigit); yyerror(tmp); } tokfix(); if (is_float) { double d = strtod(tok(), 0); if (errno == ERANGE) { rb_warningS("Float%s out of range", tok()); errno = 0; } set_yylval_literal(DBL2NUM(d)); return tFLOAT; } set_yylval_literal(rb_cstr_to_inum(tok(), 10, FALSE)); return tINTEGER; } case ')': case '] | __pad18__
pure_parser parse | param
top_compstmt | __pad0__
fixup_nodes & | deferred_nodes
top_stmts | __pad1__ = $1
| top_stmt
top_stmt | __pad2__
top_stmt | bodystmt = NEW_BEGIN(0)
compstmt | __pad3__
stmts | __pad4__ = $1
| stmt_or_begin
error | stmt
stmt_or_begin | __pad5__
| keyword_BEGIN
command_asgn | __pad6__
| lhs
expr | __pad7__
expr expr keyword_or | expr
| command_call
| arg
expr_value | __pad8__
command_call | __pad9__
block_command | __pad10__
block_command | cmd_brace_block
< num > opt_block_param | compstmt
fcall | __pad11__
command | __pad12__
| nd_args = $2
| nd_iter = $1
primary_value operation2 command_args prec | tLOWEST
keyword_super | command_args
keyword_return | call_args
mlhs | __pad13__
mlhs_inner | __pad14__
mlhs_inner | mlhs_basic
mlhs_inner mlhs_head | mlhs_item
mlhs_head tSTAR | mlhs_node
mlhs_head tSTAR | mlhs_post
mlhs_head | tSTAR
mlhs_item | __pad15__
mlhs_head | __pad16__
mlhs_node | __pad17__
mlhs_node | keyword_variable
case | __pad19__
else | lex_state = EXPR_ENDARG
return | c
case | __pad20__
return | tSYMBEG
case | __pad21__
case return | tREGEXP_BEG
| return
case | __pad22__
return | tOP_ASGN
| case
| __pad23__
| command_start = TRUE
| __pad24__
case | __pad25__
| else

## Macro Definition Documentation

#define ADD2HEAP | ( |  | n,
|  |  | c,
|  |  | p
| ) |  |

Value:
((parser->heap = (n))->u1.node = (p), \
(n)->u3.cnt = (c), (p))

#define ambiguous_operator | ( |  | op,
|  |  | syn
| ) |  |

Value:
( \
rb_warning0("`"op"' after local variable is interpreted as binary operator"), \
rb_warning0("even though it seems like "syn""))

#define arg_ambiguous | ( | ) |  | (arg_ambiguous_gen(parser), 1)

#define arg_append | ( |  | h,
|  |  | t
| ) |  | arg_append_gen(parser,(h),(t))

Definition at line 389 of file parse.y.

#define arg_concat | ( |  | h,
|  |  | t
| ) |  | arg_concat_gen(parser,(h),(t))

Definition at line 391 of file parse.y.

#define arg_var | ( |  | id) |  | arg_var_gen(parser, (id))

Definition at line 498 of file parse.y.

#define aryset | ( |  | node1,
|  |  | node2
| ) |  | aryset_gen(parser, (node1), (node2))

Definition at line 426 of file parse.y.

#define assignable | ( |  | id,
|  |  | node
| ) |  | assignable_gen(parser, (id), (node))

Definition at line 423 of file parse.y.

#define assignable_result | ( |  | x) |  | (x)

#define attrset | ( |  | node,
|  |  | id
| ) |  | attrset_gen(parser, (node), (id))

Definition at line 428 of file parse.y.

#define BIT | ( |  | c,
|  |  | idx
| ) |  | (((c) / 32 - 1 == idx) ? (1U << ((c) % 32)) : 0)

#define BITSTACK_LEXPOP | ( |  | stack) |  | ((stack) = ((stack) >> 1) | ((stack) & 1))

Definition at line 110 of file parse.y.

#define BITSTACK_POP | ( |  | stack) |  | ((stack) = (stack) >> 1)

Definition at line 109 of file parse.y.

#define BITSTACK_PUSH | ( |  | stack,
|  |  | n
| ) |  | ((stack) = ((stack)<<1)|((n)&1))

Definition at line 108 of file parse.y.

#define BITSTACK_SET_P | ( |  | stack) |  | ((stack)&1)

Definition at line 111 of file parse.y.

#define block_append | ( |  | h,
|  |  | t
| ) |  | block_append_gen(parser,(h),(t))

Definition at line 383 of file parse.y.

#define block_dup_check | ( |  | n1,
|  |  | n2
| ) |  | block_dup_check_gen(parser,(n1),(n2))

Definition at line 380 of file parse.y.

#define brace_nest (parser->parser_brace_nest)

Definition at line 318 of file parse.y.

#define call_bin_op | ( |  | recv,
|  |  | id,
|  |  | arg1
| ) |  | call_bin_op_gen(parser, (recv),(id),(arg1))

Definition at line 402 of file parse.y.

#define call_uni_op | ( |  | recv,
|  |  | id
| ) |  | call_uni_op_gen(parser, (recv),(id))

Definition at line 404 of file parse.y.

#define calloc YYCALLOC

#define class_nest (parser->parser_class_nest)

Definition at line 315 of file parse.y.

#define CMDARG_LEXPOP | ( | ) |  | BITSTACK_LEXPOP(cmdarg_stack)

Definition at line 120 of file parse.y.

#define CMDARG_P | ( | ) |  | BITSTACK_SET_P(cmdarg_stack)

Definition at line 121 of file parse.y.

#define CMDARG_POP | ( | ) |  | BITSTACK_POP(cmdarg_stack)

Definition at line 119 of file parse.y.

#define CMDARG_PUSH | ( |  | n) |  | BITSTACK_PUSH(cmdarg_stack, (n))

Definition at line 118 of file parse.y.

#define cmdarg_stack (parser->parser_cmdarg_stack)

Definition at line 314 of file parse.y.

#define command_start (parser->parser_command_start)

Definition at line 335 of file parse.y.

#define compile_error parser->nerr++,rb_compile_error_with_enc

Definition at line 659 of file parse.y.

#define compile_for_eval (parser->parser_compile_for_eval)

Definition at line 321 of file parse.y.

#define cond | ( |  | node) |  | cond_gen(parser, (node))

Definition at line 362 of file parse.y.

#define COND_LEXPOP | ( | ) |  | BITSTACK_LEXPOP(cond_stack)

Definition at line 115 of file parse.y.

#define COND_P | ( | ) |  | BITSTACK_SET_P(cond_stack)

Definition at line 116 of file parse.y.

#define COND_POP | ( | ) |  | BITSTACK_POP(cond_stack)

Definition at line 114 of file parse.y.

#define COND_PUSH | ( |  | n) |  | BITSTACK_PUSH(cond_stack, (n))

Definition at line 113 of file parse.y.

#define cond_stack (parser->parser_cond_stack)

Definition at line 313 of file parse.y.

#define cur_mid (parser->parser_cur_mid)

Definition at line 322 of file parse.y.

#define current_enc (parser->enc)

Definition at line 343 of file parse.y.

#define DEF_EXPR | ( |  | n) |  | EXPR_##n = (1 << EXPR_##n##_bit)

Definition at line 83 of file parse.y.

#define deferred_nodes (parser->parser_deferred_nodes)

Definition at line 336 of file parse.y.

#define dispatch_heredoc_end | ( | ) |  | ((void)0)

#define dsym_node | ( |  | node) |  | dsym_node_gen(parser, (node))

Definition at line 418 of file parse.y.

#define dvar_curr | ( |  | id) |  | dvar_curr_gen(parser, (id))

Definition at line 515 of file parse.y.

#define dvar_defined | ( |  | id) |  | dvar_defined_gen(parser, (id), 0)

Definition at line 512 of file parse.y.

#define dvar_defined_get | ( |  | id) |  | dvar_defined_gen(parser, (id), 1)

Definition at line 513 of file parse.y.

#define DVARS_INHERIT ((void*)1)

Definition at line 137 of file parse.y.

#define DVARS_SPECIAL_P | ( |  | tbl) |  | (!POINTER_P(tbl))

Definition at line 139 of file parse.y.

#define DVARS_TOPSCOPE NULL

Definition at line 138 of file parse.y.

#define dyna_in_block | ( | ) |  | dyna_in_block_gen(parser)

Definition at line 509 of file parse.y.

#define dyna_pop | ( |  | node) |  | dyna_pop_gen(parser, (node))

Definition at line 507 of file parse.y.

#define dyna_push | ( | ) |  | dyna_push_gen(parser)

Definition at line 505 of file parse.y.

#define dyna_var | ( |  | id) |  | local_var(id)

Definition at line 510 of file parse.y.

#define ENABLE_SELECTOR_NAMESPACE 0

#define ENC_SINGLE | ( |  | cr) |  | ((cr)==ENC_CODERANGE_7BIT)

Definition at line 303 of file parse.y.

#define ESCAPE_CONTROL 1

#define ESCAPE_META 2

#define evstr2dstr | ( |  | n) |  | evstr2dstr_gen(parser,(n))

Definition at line 398 of file parse.y.

#define flush_string_content | ( |  | enc) |  | ((void)(enc))

#define formal_argument | ( |  | id) |  | formal_argument_gen(parser, (id))

Definition at line 485 of file parse.y.

#define free YYFREE

#define get_id | ( |  | id) |  | (id)

Definition at line 458 of file parse.y.

#define get_value | ( |  | val) |  | (val)

Definition at line 459 of file parse.y.

#define gettable | ( |  | id) |  | gettable_gen(parser,(id))

Definition at line 421 of file parse.y.

#define HEAPCNT | ( |  | n,
|  |  | size
| ) |  | ((n) * (size) / sizeof(YYSTYPE))

#define here_document | ( |  | n) |  | parser_here_document(parser,(n))

#define heredoc_end (parser->parser_heredoc_end)

Definition at line 334 of file parse.y.

#define heredoc_identifier | ( | ) |  | parser_heredoc_identifier(parser)

#define heredoc_restore | ( |  | n) |  | parser_heredoc_restore(parser,(n))

#define id_type | ( |  | id) |  | (is_notop_id(id) ? (int)((id)&ID_SCOPE_MASK) : -1)

Definition at line 60 of file parse.y.

#define ifndef_ripper | ( |  | x) |  | (x)

Definition at line 625 of file parse.y.

#define in_def (parser->parser_in_def)

Definition at line 320 of file parse.y.

#define in_defined (parser->parser_in_defined)

Definition at line 323 of file parse.y.

#define in_single (parser->parser_in_single)

Definition at line 319 of file parse.y.

#define internal_id | ( | ) |  | internal_id_gen(parser)

Definition at line 502 of file parse.y.

#define IS_AFTER_OPERATOR | ( | ) |  | IS_lex_state(EXPR_FNAME | EXPR_DOT)

#define IS_ARG | ( | ) |  | IS_lex_state(EXPR_ARG_ANY)

#define is_asgn_or_id | ( |  | id) |  |

Value:
((is_notop_id(id)) && \
(((id)&ID_SCOPE_MASK) == ID_GLOBAL || \
((id)&ID_SCOPE_MASK) == ID_INSTANCE || \
((id)&ID_SCOPE_MASK) == ID_CLASS))

Definition at line 62 of file parse.y.

#define is_attrset_id | ( |  | id) |  | (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_ATTRSET)

Definition at line 56 of file parse.y.

#define IS_BEG | ( | ) |  | IS_lex_state(EXPR_BEG_ANY)

#define is_class_id | ( |  | id) |  | (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CLASS)

Definition at line 58 of file parse.y.

#define is_const_id | ( |  | id) |  | (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CONST)

Definition at line 57 of file parse.y.

#define IS_END | ( | ) |  | IS_lex_state(EXPR_END_ANY)

#define is_global_id | ( |  | id) |  | (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_GLOBAL)

Definition at line 54 of file parse.y.

#define is_identchar | ( |  | p,
|  |  | e,
|  |  | enc
| ) |  | (rb_enc_isalnum(*(p),(enc)) || (*(p)) == '_' || !ISASCII(*(p)))

#define is_instance_id | ( |  | id) |  | (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_INSTANCE)

Definition at line 55 of file parse.y.

#define is_junk_id | ( |  | id) |  | (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_JUNK)

Definition at line 59 of file parse.y.

#define IS_LABEL_POSSIBLE | ( | ) |  | ((IS_lex_state(EXPR_BEG | EXPR_ENDFN) && !cmd_state) || IS_ARG())

#define IS_LABEL_SUFFIX | ( |  | n) |  | (peek_n(':',(n)) && !peek_n(':', (n)+1))

#define IS_lex_state | ( |  | ls) |  | IS_lex_state_for(lex_state, (ls))

Definition at line 100 of file parse.y.

#define IS_lex_state_for | ( |  | x,
|  |  | ls
| ) |  | ((x) & (ls))

Definition at line 99 of file parse.y.

#define is_local_id | ( |  | id) |  | (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_LOCAL)

Definition at line 53 of file parse.y.

#define is_notop_id | ( |  | id) |  | ((id)>tLAST_OP_ID)

Definition at line 52 of file parse.y.

#define IS_SPCARG | ( |  | c) |  | (IS_ARG() && space_seen && !ISSPACE(c))

#define lex_eol_p | ( | ) |  | (lex_p >= lex_pend)

#define lex_gets (parser->parser_lex_gets)

Definition at line 338 of file parse.y.

#define lex_gets_ptr (parser->parser_lex_gets_ptr)

Definition at line 337 of file parse.y.

#define lex_goto_eol | ( |  | parser) |  | ((parser)->parser_lex_p = (parser)->parser_lex_pend)

#define lex_input (parser->parser_lex_input)

Definition at line 328 of file parse.y.

#define lex_lastline (parser->parser_lex_lastline)

Definition at line 329 of file parse.y.

#define lex_nextline (parser->parser_lex_nextline)

Definition at line 330 of file parse.y.

#define lex_p (parser->parser_lex_p)

Definition at line 332 of file parse.y.

#define lex_pbeg (parser->parser_lex_pbeg)

Definition at line 331 of file parse.y.

#define lex_pend (parser->parser_lex_pend)

Definition at line 333 of file parse.y.

#define lex_state (parser->parser_lex_state)

Definition at line 312 of file parse.y.

#define lex_strterm (parser->parser_lex_strterm)

Definition at line 311 of file parse.y.

Referenced by if(), and switch().

#define list_append | ( |  | l,
|  |  | i
| ) |  | list_append_gen(parser,(l),(i))

Definition at line 385 of file parse.y.

#define list_concat | ( |  | h,
|  |  | t
| ) |  | list_concat_gen(parser,(h),(t))

Definition at line 387 of file parse.y.

#define literal_concat | ( |  | h,
|  |  | t
| ) |  | literal_concat_gen(parser,(h),(t))

Definition at line 393 of file parse.y.

#define local_id | ( |  | id) |  | local_id_gen(parser, (id))

Definition at line 500 of file parse.y.

#define local_pop | ( | ) |  | local_pop_gen(parser)

Definition at line 494 of file parse.y.

#define local_push | ( |  | top) |  | local_push_gen(parser,(top))

Definition at line 492 of file parse.y.

#define local_tbl | ( | ) |  | local_tbl_gen(parser)

Definition at line 445 of file parse.y.

#define local_var | ( |  | id) |  | local_var_gen(parser, (id))

Definition at line 496 of file parse.y.

#define logop | ( |  | type,
|  |  | node1,
|  |  | node2
| ) |  | logop_gen(parser, (type), (node1), (node2))

Definition at line 364 of file parse.y.

#define lpar_beg (parser->parser_lpar_beg)

Definition at line 317 of file parse.y.

#define lvar_defined | ( |  | id) |  | lvar_defined_gen(parser, (id))

Definition at line 518 of file parse.y.

#define LVAR_USED ((ID)1 << (sizeof(ID) * CHAR_BIT - 1))

#define lvtbl (parser->parser_lvtbl)

Definition at line 339 of file parse.y.

#define malloc YYMALLOC

#define match_op | ( |  | node1,
|  |  | node2
| ) |  | match_op_gen(parser, (node1), (node2))

Definition at line 442 of file parse.y.

#define mixed_error | ( |  | enc1,
|  |  | enc2
| ) |  |

Value:
if (!errbuf) { \
size_t len = sizeof(mixed_msg) - 4; \
len += strlen(rb_enc_name(enc1)); \
len += strlen(rb_enc_name(enc2)); \
errbuf = ALLOCA_N(char, len); \
snprintf(errbuf, len, mixed_msg, \
rb_enc_name(enc1), \
rb_enc_name(enc2)); \
yyerror(errbuf); \
}

#define mixed_escape | ( |  | beg,
|  |  | enc1,
|  |  | enc2
| ) |  |

Value:
do { \
const char *pos = lex_p; \
lex_p = (beg); \
mixed_error((enc1), (enc2)); \
lex_p = pos; \
} while (0)

#define nd_func u1.id

Definition at line 531 of file parse.y.

#define nd_nest u3.cnt

Definition at line 538 of file parse.y.

#define nd_paren | ( |  | node) |  | (char)((node)->u2.id >> CHAR_BIT*2)

Definition at line 537 of file parse.y.

#define nd_term | ( |  | node) |  | SIGN_EXTEND((node)->u2.id, CHAR_BIT*2)

Definition at line 535 of file parse.y.

#define new_args | ( |  | f,
|  |  | o,
|  |  | r,
|  |  | p,
|  |  | t
| ) |  | new_args_gen(parser, (f),(o),(r),(p),(t))

Definition at line 407 of file parse.y.

#define new_args_tail | ( |  | k,
|  |  | kr,
|  |  | b
| ) |  | new_args_tail_gen(parser, (k),(kr),(b))

Definition at line 409 of file parse.y.

#define new_attr_op_assign | ( |  | lhs,
|  |  | type,
|  |  | attr,
|  |  | op,
|  |  | rhs
| ) |  | new_attr_op_assign_gen(parser, (lhs), (attr), (op), (rhs))

Definition at line 437 of file parse.y.

#define new_bv | ( |  | id) |  | new_bv_gen(parser, (id))

Definition at line 489 of file parse.y.

#define new_const_op_assign | ( |  | lhs,
|  |  | op,
|  |  | rhs
| ) |  | new_const_op_assign_gen(parser, (lhs), (op), (rhs))

Definition at line 439 of file parse.y.

#define new_evstr | ( |  | n) |  | new_evstr_gen(parser,(n))

Definition at line 396 of file parse.y.

#define new_op_assign | ( |  | lhs,
|  |  | op,
|  |  | rhs
| ) |  | new_op_assign_gen(parser, (lhs), (op), (rhs))

Definition at line 482 of file parse.y.

#define NEW_STRTERM | ( |  | func,
|  |  | term,
|  |  | paren
| ) |  | rb_node_newnode(NODE_STRTERM, (func), (term) | ((paren) << (CHAR_BIT * 2)), 0)

#define new_yield | ( |  | node) |  | new_yield_gen(parser, (node))

Definition at line 416 of file parse.y.

#define NEWHEAP | ( | ) |  | rb_node_newnode(NODE_ALLOCA, 0, (VALUE)parser->heap, 0)

#define newtok | ( | ) |  | parser_newtok(parser)

#define nextc | ( | ) |  | parser_nextc(parser)

#define no_digits | ( | ) |  | do {yyerror("numeric literal without digits"); return 0;} while (0)

#define node_assign | ( |  | node1,
|  |  | node2
| ) |  | node_assign_gen(parser, (node1), (node2))

Definition at line 433 of file parse.y.

#define NODE_HEREDOC NODE_ARRAY /* 1, 3 to gc */

Definition at line 529 of file parse.y.

#define NODE_STRTERM NODE_ZARRAY /* nothing to gc */

Definition at line 528 of file parse.y.

#define numberof | ( |  | array) |  | (int)(sizeof(array) / sizeof((array)[0]))

#define op_tbl_count numberof(op_tbl)

#define paren_nest (parser->parser_paren_nest)

Definition at line 316 of file parse.y.

#define parse_string | ( |  | n) |  | parser_parse_string(parser,(n))

#define PARSER_ARG ruby_sourcefile, ruby_sourceline, current_enc,

Definition at line 660 of file parse.y.

#define PARSER_DEBUG 0

#define parser_encoding_name | ( | ) |  | (current_enc->name)

#define parser_is_identchar | ( | ) |  | (!parser->eofp && is_identchar((lex_p-1),lex_pend,current_enc))

#define parser_isascii | ( | ) |  | ISASCII(*(lex_p-1))

#define parser_mbclen | ( | ) |  | mbclen((lex_p-1),lex_pend,current_enc)

#define parser_precise_mbclen | ( | ) |  | rb_enc_precise_mbclen((lex_p-1),lex_pend,current_enc)

#define parser_warn | ( |  | node,
|  |  | mesg
| ) |  | parser_warn(parser, (node), (mesg))

#define parser_warning | ( |  | node,
|  |  | mesg
| ) |  | parser_warning(parser, (node), (mesg))

#define peek | ( |  | c) |  | peek_n((c), 0)

#define peek_n | ( |  | c,
|  |  | n
| ) |  | (lex_p+(n) < lex_pend && (c) == (unsigned char)lex_p[n])

#define POINTER_P | ( |  | val) |  | ((VALUE)(val) & ~(VALUE)3)

Definition at line 140 of file parse.y.

Referenced by vtable_add(), vtable_free(), vtable_included(), and vtable_size().

#define pushback | ( |  | c) |  | parser_pushback(parser, (c))

#define Qnone 0

Definition at line 624 of file parse.y.

#define rb_backref_error | ( |  | n) |  | rb_backref_error_gen(parser,(n))

Definition at line 431 of file parse.y.

#define rb_compile_error rb_compile_error_with_enc

Definition at line 658 of file parse.y.

#define rb_node_newnode | ( |  | type,
|  |  | a1,
|  |  | a2,
|  |  | a3
| ) |  | node_newnode(parser, (type), (a1), (a2), (a3))

Definition at line 359 of file parse.y.

#define rb_warn0 | ( |  | fmt) |  | rb_compile_warn(ruby_sourcefile, ruby_sourceline, (fmt))

Definition at line 632 of file parse.y.

#define rb_warn4S | ( |  | file,
|  |  | line,
|  |  | fmt,
|  |  | a
| ) |  | rb_compile_warn((file), (line), (fmt), (a))

Definition at line 635 of file parse.y.

#define rb_warnI | ( |  | fmt,
|  |  | a
| ) |  | rb_compile_warn(ruby_sourcefile, ruby_sourceline, (fmt), (a))

Definition at line 633 of file parse.y.

#define rb_warning0 | ( |  | fmt) |  | rb_compile_warning(ruby_sourcefile, ruby_sourceline, (fmt))

Definition at line 636 of file parse.y.

#define rb_warningS | ( |  | fmt,
|  |  | a
| ) |  | rb_compile_warning(ruby_sourcefile, ruby_sourceline, (fmt), (a))

Definition at line 637 of file parse.y.

#define rb_warnS | ( |  | fmt,
|  |  | a
| ) |  | rb_compile_warn(ruby_sourcefile, ruby_sourceline, (fmt), (a))

Definition at line 634 of file parse.y.

#define RE_OPTION_ARG_ENCODING_NONE 32

Definition at line 526 of file parse.y.

#define RE_OPTION_ENCODING | ( |  | e) |  | (((e)&0xff)<<RE_OPTION_ENCODING_SHIFT)

Definition at line 522 of file parse.y.

#define RE_OPTION_ENCODING_IDX | ( |  | o) |  | (((o)>>RE_OPTION_ENCODING_SHIFT)&0xff)

Definition at line 523 of file parse.y.

#define RE_OPTION_ENCODING_NONE | ( |  | o) |  | ((o)&RE_OPTION_ARG_ENCODING_NONE)

Definition at line 524 of file parse.y.

#define RE_OPTION_ENCODING_SHIFT 8

Definition at line 521 of file parse.y.

#define RE_OPTION_MASK 0xff

Definition at line 525 of file parse.y.

#define RE_OPTION_ONCE (1<<16)

Definition at line 520 of file parse.y.

#define read_escape | ( |  | flags,
|  |  | e
| ) |  | parser_read_escape(parser, (flags), (e))

#define realloc YYREALLOC

#define reduce_nodes | ( |  | n) |  | reduce_nodes_gen(parser,(n))

Definition at line 378 of file parse.y.

#define reg_compile | ( |  | str,
|  |  | options
| ) |  | reg_compile_gen(parser, (str), (options))

Definition at line 450 of file parse.y.

#define reg_fragment_check | ( |  | str,
|  |  | options
| ) |  | reg_fragment_check_gen(parser, (str), (options))

Definition at line 454 of file parse.y.

#define reg_fragment_setenc | ( |  | str,
|  |  | options
| ) |  | reg_fragment_setenc_gen(parser, (str), (options))

Definition at line 452 of file parse.y.

#define reg_named_capture_assign | ( |  | regexp,
|  |  | match
| ) |  | reg_named_capture_assign_gen(parser,(regexp),(match))

Definition at line 456 of file parse.y.

#define REGISTER_SYMID | ( |  | id,
|  |  | name
| ) |  | register_symid((id), (name), strlen(name), enc)

Definition at line 4055 of file parse.y.

#define regx_options | ( | ) |  | parser_regx_options(parser)

#define ret_args | ( |  | node) |  | ret_args_gen(parser, (node))

Definition at line 413 of file parse.y.

#define ripper_flush | ( |  | p) |  | (void)(p)

#define ruby__end__seen (parser->parser_ruby__end__seen)

Definition at line 340 of file parse.y.

#define ruby_coverage (parser->coverage)

Definition at line 350 of file parse.y.

#define ruby_debug_lines (parser->debug_lines)

Definition at line 349 of file parse.y.

#define ruby_eval_tree (parser->parser_eval_tree)

Definition at line 347 of file parse.y.

#define ruby_eval_tree_begin (parser->parser_eval_tree_begin)

Definition at line 348 of file parse.y.

#define ruby_sourcefile (parser->parser_ruby_sourcefile)

Definition at line 342 of file parse.y.

#define ruby_sourceline (parser->parser_ruby_sourceline)

Definition at line 341 of file parse.y.

#define set_yylval_id | ( |  | x) |  | (yylval.id = (x))

#define set_yylval_literal | ( |  | x) |  | (yylval.node = NEW_LIT(x))

#define set_yylval_name | ( |  | x) |  | (yylval.id = (x))

#define set_yylval_node | ( |  | x) |  | (yylval.node = (x))

#define set_yylval_num | ( |  | x) |  | (yylval.num = (x))

#define set_yylval_str | ( |  | x) |  | (yylval.node = NEW_STR(x))

#define shadowing_lvar | ( |  | name) |  | shadowing_lvar_gen(parser, (name))

Definition at line 487 of file parse.y.

#define SIGN_EXTEND | ( |  | x,
|  |  | n
| ) |  | (((1<<(n)-1)^((x)&~(~0<<(n))))-(1<<(n)-1))

Definition at line 530 of file parse.y.

#define SIGN_EXTEND_CHAR | ( |  | c) |  | ((((unsigned char)(c)) ^ 128) - 128)

#define SPECIAL_PUNCT | ( |  | idx) |  |

Value:
( \
BIT('~', idx) | BIT('*', idx) | BIT('$', idx) | BIT('?', idx) | \
BIT('!', idx) | BIT('@', idx) | BIT('/', idx) | BIT('\\', idx) | \
BIT(';', idx) | BIT(',', idx) | BIT('.', idx) | BIT('=', idx) | \
BIT(':', idx) | BIT('<', idx) | BIT('>', idx) | BIT('\"', idx) | \
BIT('&', idx) | BIT('`', idx) | BIT('\'', idx) | BIT('+', idx) | \
BIT('0', idx))

#define str_copy | ( |  | _s,
|  |  | _p,
|  |  | _n
| ) |  |

Value:
((_s) \
? (void)(rb_str_resize((_s), (_n)), \
MEMCPY(RSTRING_PTR(_s), (_p), char, (_n)), (_s)) \
: (void)((_s) = STR_NEW((_p), (_n))))

#define STR_FUNC_ESCAPE 0x01

#define STR_FUNC_EXPAND 0x02

#define STR_FUNC_INDENT 0x20

#define STR_FUNC_QWORDS 0x08

#define STR_FUNC_REGEXP 0x04

#define STR_FUNC_SYMBOL 0x10

#define STR_NEW | ( |  | p,
|  |  | n
| ) |  | rb_enc_str_new((p),(n),current_enc)

Definition at line 299 of file parse.y.

#define STR_NEW0 | ( | ) |  | rb_enc_str_new(0,0,current_enc)

Definition at line 300 of file parse.y.

#define STR_NEW2 | ( |  | p) |  | rb_enc_str_new((p),strlen(p),current_enc)

Definition at line 301 of file parse.y.

#define STR_NEW3 | ( |  | p,
|  |  | n,
|  |  | e,
|  |  | func
| ) |  | parser_str_new((p),(n),(e),(func),current_enc)

Definition at line 302 of file parse.y.

#define subnodes | ( |  | n1,
|  |  | n2
| ) |  |

Value:
((!node->n1) ? (node->n2 ? (body = &node->n2, 1) : 0) : \
(!node->n2) ? (body = &node->n1, 1) : \
(reduce_nodes(&node->n1), body = &node->n2, 1))

#define tok | ( | ) |  | tokenbuf

#define tok_hex | ( |  | numlen) |  | parser_tok_hex(parser, (numlen))

#define TOK_INTERN | ( |  | mb) |  | rb_intern3(tok(), toklen(), current_enc)

Definition at line 304 of file parse.y.

#define tokadd | ( |  | c) |  | parser_tokadd(parser, (c))

#define tokadd_escape | ( |  | e) |  | parser_tokadd_escape(parser, (e))

#define tokadd_mbchar | ( |  | c) |  | parser_tokadd_mbchar(parser, (c))

#define tokadd_string | ( |  | f,
|  |  | t,
|  |  | p,
|  |  | n,
|  |  | e
| ) |  | parser_tokadd_string(parser,(f),(t),(p),(n),(e))

#define tokaddmbc | ( |  | c,
|  |  | enc
| ) |  | parser_tokaddmbc(parser, (c), (enc))

#define tokcopy | ( |  | n) |  | memcpy(tokspace(n), lex_p - (n), (n))

#define token_info_pop | ( |  | token) |  | (RTEST(ruby_verbose) ? token_info_pop(parser, (token)) : (void)0)

Definition at line 676 of file parse.y.

#define token_info_push | ( |  | token) |  | (RTEST(ruby_verbose) ? token_info_push(parser, (token)) : (void)0)

Definition at line 675 of file parse.y.

#define tokenbuf (parser->parser_tokenbuf)

Definition at line 324 of file parse.y.

#define tokfix | ( | ) |  | (tokenbuf[tokidx]='\0')

#define tokidx (parser->parser_tokidx)

Definition at line 325 of file parse.y.

#define toklast | ( | ) |  | (tokidx>0?tokenbuf[tokidx-1]:0)

#define toklen | ( | ) |  | tokidx

#define tokline (parser->parser_tokline)

Definition at line 327 of file parse.y.

#define toksiz (parser->parser_toksiz)

Definition at line 326 of file parse.y.

#define tokspace | ( |  | n) |  | parser_tokspace(parser, (n))

#define value_expr | ( |  | node) |  | value_expr_gen(parser, (node) = remove_begin(node))

Definition at line 372 of file parse.y.

#define void_expr | ( |  | node) |  | void_expr0((node) = remove_begin(node))

Definition at line 374 of file parse.y.

#define void_expr0 | ( |  | node) |  | void_expr_gen(parser, (node))

Definition at line 373 of file parse.y.

#define void_stmts | ( |  | node) |  | void_stmts_gen(parser, (node))

Definition at line 376 of file parse.y.

#define VTBL_DEBUG 0

Definition at line 153 of file parse.y.

Referenced by vtable_add(), vtable_alloc(), and vtable_free().

#define warn_balanced | ( |  | op,
|  |  | syn
| ) |  |

Value:
((void) \
(!IS_lex_state_for(last_state, EXPR_CLASS|EXPR_DOT|EXPR_FNAME|EXPR_ENDFN|EXPR_ENDARG) && \
space_seen && !ISSPACE(c) && \
(ambiguous_operator(op, syn), 0)))

#define was_bol | ( | ) |  | (lex_p == lex_pbeg + 1)

#define whole_match_p | ( |  | e,
|  |  | l,
|  |  | i
| ) |  | parser_whole_match_p(parser,(e),(l),(i))

#define YYCALLOC | ( |  | nelem,
|  |  | size
| ) |  | rb_parser_calloc(parser, (nelem), (size))

#define YYDEBUG 1

#define yydebug (parser->parser_yydebug)

Definition at line 344 of file parse.y.

#define yyerror | ( |  | msg) |  | parser_yyerror(parser, (msg))

Definition at line 307 of file parse.y.

#define YYERROR_VERBOSE 1

#define YYFREE | ( |  | ptr) |  | rb_parser_free(parser, (ptr))

#define YYLEX_PARAM parser

Definition at line 309 of file parse.y.

#define yylval (*((YYSTYPE*)(parser->parser_yylval)))

#define yylval_id | ( | ) |  | (yylval.id)

#define YYMALLOC | ( |  | size) |  | rb_parser_malloc(parser, (size))

#define yyparse ruby_yyparse

Definition at line 356 of file parse.y.

#define YYREALLOC | ( |  | ptr,
|  |  | size
| ) |  | rb_parser_realloc(parser, (ptr), (size))

#define YYSTACK_USE_ALLOCA 0

## Typedef Documentation

typedef VALUE stack_type

Definition at line 106 of file parse.y.

typedef struct token_info token_info

## Enumeration Type Documentation

enum lex_state_bits

Enumerator
EXPR_BEG_bit |
EXPR_END_bit |
EXPR_ENDARG_bit |
EXPR_ENDFN_bit |
EXPR_ARG_bit |
EXPR_CMDARG_bit |
EXPR_MID_bit |
EXPR_FNAME_bit |
EXPR_DOT_bit |
EXPR_CLASS_bit |
EXPR_VALUE_bit |
EXPR_MAX_STATE |
EXPR_BEG_bit |
EXPR_END_bit |
EXPR_ENDARG_bit |
EXPR_ENDFN_bit |
EXPR_ARG_bit |
EXPR_CMDARG_bit |
EXPR_MID_bit |
EXPR_FNAME_bit |
EXPR_DOT_bit |
EXPR_CLASS_bit |
EXPR_VALUE_bit |
EXPR_MAX_STATE |
EXPR_BEG_bit |
EXPR_END_bit |
EXPR_ENDARG_bit |
EXPR_ENDFN_bit |
EXPR_ARG_bit |
EXPR_CMDARG_bit |
EXPR_MID_bit |
EXPR_FNAME_bit |
EXPR_DOT_bit |
EXPR_CLASS_bit |
EXPR_VALUE_bit |
EXPR_MAX_STATE |
EXPR_BEG_bit |
EXPR_END_bit |
EXPR_ENDARG_bit |
EXPR_ENDFN_bit |
EXPR_ARG_bit |
EXPR_CMDARG_bit |
EXPR_MID_bit |
EXPR_FNAME_bit |
EXPR_DOT_bit |
EXPR_CLASS_bit |
EXPR_VALUE_bit |
EXPR_MAX_STATE |

Definition at line 67 of file parse.y.

enum lex_state_e

Enumerator
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
EXPR_BEG_ANY |
EXPR_ARG_ANY |
EXPR_END_ANY |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
EXPR_BEG_ANY |
EXPR_ARG_ANY |
EXPR_END_ANY |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
EXPR_BEG_ANY |
EXPR_ARG_ANY |
EXPR_END_ANY |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
DEF_EXPR |
EXPR_BEG_ANY |
EXPR_ARG_ANY |
EXPR_END_ANY |

Definition at line 82 of file parse.y.

## Function Documentation

static NODE* arg_append_gen | ( | struct parser_params * | ,
|  | NODE * | ,
|  | NODE * |
| ) |  |
| static

static NODE* arg_blk_pass | ( | NODE * | ,
|  | NODE * |
| ) |  |
| static

static NODE* arg_concat_gen | ( | struct parser_params * | ,
|  | NODE * | ,
|  | NODE * |
| ) |  |
| static

static int arg_var_gen | ( | struct parser_params * | ,
|  | ID |
| ) |  |
| static

static NODE* aryset_gen | ( | struct parser_params * | ,
|  | NODE * | ,
|  | NODE * |
| ) |  |
| static

static NODE* assignable_gen | ( | struct parser_params * | ,
|  | ID | ,
|  | NODE * |
| ) |  |
| static

static NODE* attrset_gen | ( | struct parser_params * | ,
|  | NODE * | ,
|  | ID |
| ) |  |
| static

static NODE* block_append_gen | ( | struct parser_params * | ,
|  | NODE * | ,
|  | NODE * |
| ) |  |
| static

static void block_dup_check_gen | ( | struct parser_params * | ,
|  | NODE * | ,
|  | NODE * |
| ) |  |
| static

static NODE* call_bin_op_gen | ( | struct parser_params * | ,
|  | NODE * | ,
|  | ID | ,
|  | NODE * |
| ) |  |
| static

static NODE* call_uni_op_gen | ( | struct parser_params * | ,
|  | NODE * | ,
|  | ID |
| ) |  |
| static

static NODE* cond_gen | ( | struct parser_params * | ,
|  | NODE * |
| ) |  |
| static

static NODE* dsym_node_gen | ( | struct parser_params * | ,
|  | NODE * |
| ) |  |
| static

static int dvar_curr_gen | ( | struct parser_params * | ,
|  | ID |
| ) |  |
| static

static int dvar_defined_gen | ( | struct parser_params * | ,
|  | ID | ,
|  | int |
| ) |  |
| static

static int dyna_in_block_gen | ( | struct parser_params * | ) |  |
| static

dyna_pop | ( |  | $< vars >) |  |

static void dyna_pop_gen | ( | struct parser_params * | ,
|  | const struct vtable * |
| ) |  |
| static

static struct vtable* dyna_push_gen | ( | struct parser_params * | ) |  |
| static

static NODE* evstr2dstr_gen | ( | struct parser_params * | ,
|  | NODE * |
| ) |  |
| static

static void fixpos | ( | NODE * | ,
|  | NODE * |
| ) |  |
| static

fixpos | ( |  | $$,
|  |  | $1
| ) |  | = $3

static void fixup_nodes | ( | NODE ** | ) |  |
| static

static ID formal_argument_gen | ( | struct parser_params * | ,
|  | ID |
| ) |  |
| static

static NODE* gettable_gen | ( | struct parser_params * | ,
|  | ID |
| ) |  |
| static

if | ( |  | $2) |  |

Definition at line 952 of file parse.y.

References NEW_RESCUE.

if | ( | ! | $$) |  |

if | ( | c | = `= ')'`) |  |

if | ( | IS_END()||ISSPACE(c) | ) |  |

Definition at line 7595 of file parse.y.

References IS_END, lex_state, pushback, and warn_balanced.

if | ( | (c=nextc()) | = `= '='`) |  |

Definition at line 7620 of file parse.y.

References lex_state, nextc, set_yylval_id, and tOP_ASGN.

if | ( | IS_SPCARG(c) | ) |  |

Definition at line 7626 of file parse.y.

References arg_ambiguous, IS_SPCARG, lex_strterm, NEW_STRTERM, str_regexp, and tREGEXP_BEG.

static void Init_id | ( | void | ) |  |
| static

Definition at line 14 of file id.c.

References id_core_define_method, id_core_define_singleton_method, id_core_hash_from_ary, id_core_hash_merge_ary, id_core_hash_merge_kwd, id_core_hash_merge_ptr, id_core_set_method_alias, id_core_set_postexe, id_core_set_variable_alias, id_core_undef_method, idCFUNC, idEmptyP, idIFUNC, idNULL, idRespond_to, idRespond_to_missing, rb_usascii_encoding(), and REGISTER_SYMID.

static ID internal_id_gen | ( | struct parser_params * | ) |  |
| static

static NODE* list_append_gen | ( | struct parser_params * | ,
|  | NODE * | ,
|  | NODE * |
| ) |  |
| static

static NODE* list_concat_gen | ( | struct parser_params * | ,
|  | NODE * | ,
|  | NODE * |
| ) |  |
| static

static int literal_concat0 | ( | struct parser_params * | ,
|  | VALUE | ,
|  | VALUE |
| ) |  |
| static

static NODE* literal_concat_gen | ( | struct parser_params * | ,
|  | NODE * | ,
|  | NODE * |
| ) |  |
| static

static int local_id_gen | ( | struct parser_params * | ,
|  | ID |
| ) |  |
| static

static void local_pop_gen | ( | struct parser_params * | ) |  |
| static

static void local_push_gen | ( | struct parser_params * | ,
|  | int |
| ) |  |
| static

static ID* local_tbl_gen | ( | struct parser_params * | ) |  |
| static

static int local_var_gen | ( | struct parser_params * | ,
|  | ID |
| ) |  |
| static

static NODE* logop_gen | ( | struct parser_params * | ,
|  | enum | node_type,
|  | NODE * | ,
|  | NODE * |
| ) |  |
| static

static int lvar_defined_gen | ( | struct parser_params * | ,
|  | ID |
| ) |  |
| static

static NODE* match_op_gen | ( | struct parser_params * | ,
|  | NODE * | ,
|  | NODE * |
| ) |  |
| static

nd_set_line | ( |  | $$,
|  |  | $< num >
| ) |  |

fcall nd_set_line | ( |  | $$,
|  | tokline |
| ) |  |

static NODE* negate_lit | ( | NODE * | ) |  |
| static

static NODE* new_args_gen | ( | struct parser_params * | ,
|  | NODE * | ,
|  | NODE * | ,
|  | ID | ,
|  | NODE * | ,
|  | NODE * |
| ) |  |
| static

static NODE* new_args_tail_gen | ( | struct parser_params * | ,
|  | NODE * | ,
|  | ID | ,
|  | ID |
| ) |  |
| static

static NODE* new_attr_op_assign_gen | ( | struct parser_params * | parser,
|  | NODE * | lhs,
|  | ID | attr,
|  | ID | op,
|  | NODE * | rhs
| ) |  |
| static

static void new_bv_gen | ( | struct parser_params * | ,
|  | ID |
| ) |  |
| static

static NODE* new_const_op_assign_gen | ( | struct parser_params * | parser,
|  | NODE * | lhs,
|  | ID | op,
|  | NODE * | rhs
| ) |  |
| static

static NODE* new_evstr_gen | ( | struct parser_params * | ,
|  | NODE * |
| ) |  |
| static

static NODE* new_op_assign_gen | ( | struct parser_params * | parser,
|  | NODE * | lhs,
|  | ID | op,
|  | NODE * | rhs
| ) |  |
| static

static NODE* new_yield_gen | ( | struct parser_params * | ,
|  | NODE * |
| ) |  |
| static

static NODE* newline_node | ( | NODE * | ) |  |
| static

static NODE* node_assign_gen | ( | struct parser_params * | ,
|  | NODE * | ,
|  | NODE * |
| ) |  |
| static

static NODE* node_newnode | ( | struct parser_params * | ,
|  | enum | node_type,
|  | VALUE | ,
|  | VALUE | ,
|  | VALUE |
| ) |  |
| static

static int parser_yyerror | ( | struct parser_params * | ,
|  | const char * |
| ) |  |
| static

static void rb_backref_error_gen | ( | struct parser_params * | ,
|  | NODE * |
| ) |  |
| static

static void reduce_nodes_gen | ( | struct parser_params * | ,
|  | NODE ** |
| ) |  |
| static

static VALUE reg_compile_gen | ( | struct parser_params * | ,
|  | VALUE | ,
|  | int |
| ) |  |
| static

static int reg_fragment_check_gen | ( | struct parser_params * | ,
|  | VALUE | ,
|  | int |
| ) |  |
| static

static void reg_fragment_setenc_gen | ( | struct parser_params * | ,
|  | VALUE | ,
|  | int |
| ) |  |
| static

static NODE* reg_named_capture_assign_gen | ( | struct parser_params * | parser,
|  | VALUE | regexp,
|  | NODE * | match
| ) |  |
| static

static ID register_symid_str | ( | ID | ,
|  | VALUE |
| ) |  |
| static

static NODE* remove_begin | ( | NODE * | ) |  |
| static

static NODE* ret_args_gen | ( | struct parser_params * | ,
|  | NODE * |
| ) |  |
| static

static ID shadowing_lvar_gen | ( | struct parser_params * | ,
|  | ID |
| ) |  |
| static

static NODE* splat_array | ( | NODE * | ) |  |
| static

switch | ( | c | ) |  |

Definition at line 7601 of file parse.y.

References lex_strterm, NEW_STRTERM, pushback, str_dsym, and str_ssym.

static void token_info_pop | ( | struct parser_params * | ,
|  | const char * | token
| ) |  |
| static

static void token_info_push | ( | struct parser_params * | ,
|  | const char * | token
| ) |  |
| static

static int value_expr_gen | ( | struct parser_params * | ,
|  | NODE * |
| ) |  |
| static

static void void_expr_gen | ( | struct parser_params * | ,
|  | NODE * |
| ) |  |
| static

static void void_stmts_gen | ( | struct parser_params * | ,
|  | NODE * |
| ) |  |
| static

static void vtable_add | ( | struct vtable * | tbl,
|  | ID | id
| ) |  |
| static

Definition at line 180 of file parse.y.

References vtable::capa, id, POINTER_P, vtable::pos, rb_bug(), rb_id2name(), REALLOC_N, vtable::tbl, and VTBL_DEBUG.

static struct vtable* vtable_alloc | ( | struct vtable * | prev) |  |
| static

Definition at line 156 of file parse.y.

References ALLOC, ALLOC_N, vtable::capa, vtable::pos, vtable::prev, vtable::tbl, and VTBL_DEBUG.

static void vtable_free | ( | struct vtable * | tbl) |  |
| static

Definition at line 168 of file parse.y.

References POINTER_P, vtable::tbl, VTBL_DEBUG, and xfree.

static int vtable_included | ( | const struct vtable * | tbl,
|  | ID | id
| ) |  |
| static

Definition at line 195 of file parse.y.

References i, POINTER_P, vtable::pos, and vtable::tbl.

static int vtable_size | ( | const struct vtable * | tbl) |  |
| static

Definition at line 143 of file parse.y.

References POINTER_P, and vtable::pos.

warn_balanced | ( | "/" | ,
|  | "regexp literal" |
| ) |  |

static int yylex | ( | void * | ,
|  | void * |
| ) |  |
| static

## Variable Documentation

top_compstmt __pad0__

Definition at line 884 of file parse.y.

block_command __pad10__

Definition at line 1334 of file parse.y.

fcall __pad11__

Definition at line 1362 of file parse.y.

command __pad12__

Definition at line 1372 of file parse.y.

mlhs __pad13__

Definition at line 1480 of file parse.y.

mlhs_inner __pad14__

Definition at line 1491 of file parse.y.

mlhs_item __pad15__

Definition at line 1588 of file parse.y.

mlhs_head __pad16__

Definition at line 1599 of file parse.y.

mlhs_node __pad17__

Definition at line 1635 of file parse.y.

primary_value [' opt_call_args rbracket { $$ = aryset($1, $3); } | primary_value '.' tIDENTIFIER { $$ = attrset($1, $3); } | primary_value tCOLON2 tIDENTIFIER { $$ = attrset($1, $3); } | primary_value '.' tCONSTANT { $$ = attrset($1, $3); } | primary_value tCOLON2 tCONSTANT { if (in_def || in_single) yyerror("dynamic constant assignment"); $$ = NEW_CDECL(0, 0, NEW_COLON2($1, $3)); } | tCOLON3 tCONSTANT { if (in_def || in_single) yyerror("dynamic constant assignment"); $$ = NEW_CDECL(0, 0, NEW_COLON3($2)); } | backref { rb_backref_error($1); $$ = NEW_BEGIN(0); } ;lhs : user_variable { $$ = assignable($1, 0); if (!$$) $$ = NEW_BEGIN(0); } | keyword_variable { $$ = assignable($1, 0); if (!$$) $$ = NEW_BEGIN(0); } | primary_value '[' opt_call_args rbracket { $$ = aryset($1, $3); } | primary_value '.' tIDENTIFIER { $$ = attrset($1, $3); } | primary_value tCOLON2 tIDENTIFIER { $$ = attrset($1, $3); } | primary_value '.' tCONSTANT { $$ = attrset($1, $3); } | primary_value tCOLON2 tCONSTANT { if (in_def || in_single) yyerror("dynamic constant assignment"); $$ = NEW_CDECL(0, 0, NEW_COLON2($1, $3)); } | tCOLON3 tCONSTANT { if (in_def || in_single) yyerror("dynamic constant assignment"); $$ = NEW_CDECL(0, 0, NEW_COLON3($2)); } | backref { rb_backref_error($1); $$ = NEW_BEGIN(0); } ;cname : tIDENTIFIER { yyerror("class/module name must be CONSTANT"); } | tCONSTANT ;cpath : tCOLON3 cname { $$ = NEW_COLON3($2); } | cname { $$ = NEW_COLON2(0, $$); } | primary_value tCOLON2 cname { $$ = NEW_COLON2($1, $3); } ;fname : tIDENTIFIER | tCONSTANT | tFID | op { lex_state = EXPR_ENDFN; $$ = $1; } | reswords { lex_state = EXPR_ENDFN; $$ = $<id>1; } ;fsym : fname | symbol ;fitem : fsym { $$ = NEW_LIT(ID2SYM($1)); } | dsym ;undef_list : fitem { $$ = NEW_UNDEF($1); } | undef_list ',' {lex_state = EXPR_FNAME;} fitem { $$ = block_append($1, NEW_UNDEF($4)); } ;op : '|' { ifndef_ripper($$ = '|'); } | '^' { ifndef_ripper($$ = '^'); } | '&' { ifndef_ripper($$ = '&'); } | tCMP { ifndef_ripper($$ = tCMP); } | tEQ { ifndef_ripper($$ = tEQ); } | tEQQ { ifndef_ripper($$ = tEQQ); } | tMATCH { ifndef_ripper($$ = tMATCH); } | tNMATCH { ifndef_ripper($$ = tNMATCH); } | '>' { ifndef_ripper($$ = '>'); } | tGEQ { ifndef_ripper($$ = tGEQ); } | '<' { ifndef_ripper($$ = '<'); } | tLEQ { ifndef_ripper($$ = tLEQ); } | tNEQ { ifndef_ripper($$ = tNEQ); } | tLSHFT { ifndef_ripper($$ = tLSHFT); } | tRSHFT { ifndef_ripper($$ = tRSHFT); } | '+' { ifndef_ripper($$ = '+'); } | '-' { ifndef_ripper($$ = '-'); } | '*' { ifndef_ripper($$ = '*'); } | tSTAR { ifndef_ripper($$ = '*'); } | '/' { ifndef_ripper($$ = '/'); } | '%' { ifndef_ripper($$ = '%'); } | tPOW { ifndef_ripper($$ = tPOW); } | tDSTAR { ifndef_ripper($$ = tDSTAR); } | '!' { ifndef_ripper($$ = '!'); } | '~' { ifndef_ripper($$ = '~'); } | tUPLUS { ifndef_ripper($$ = tUPLUS); } | tUMINUS { ifndef_ripper($$ = tUMINUS); } | tAREF { ifndef_ripper($$ = tAREF); } | tASET { ifndef_ripper($$ = tASET); } | '`' { ifndef_ripper($$ = '`'); } ;reswords : keyword__LINE__ | keyword__FILE__ | keyword__ENCODING__ | keyword_BEGIN | keyword_END | keyword_alias | keyword_and | keyword_begin | keyword_break | keyword_case | keyword_class | keyword_def | keyword_defined | keyword_do | keyword_else | keyword_elsif | keyword_end | keyword_ensure | keyword_false | keyword_for | keyword_in | keyword_module | keyword_next | keyword_nil | keyword_not | keyword_or | keyword_redo | keyword_rescue | keyword_retry | keyword_return | keyword_self | keyword_super | keyword_then | keyword_true | keyword_undef | keyword_when | keyword_yield | keyword_if | keyword_unless | keyword_while | keyword_until ;arg : lhs '=' arg { value_expr($3); $$ = node_assign($1, $3); } | lhs '=' arg modifier_rescue arg { value_expr($3); $3 = NEW_RESCUE($3, NEW_RESBODY(0,$5,0), 0); $$ = node_assign($1, $3); } | var_lhs tOP_ASGN arg { value_expr($3); $$ = new_op_assign($1, $2, $3); } | var_lhs tOP_ASGN arg modifier_rescue arg { value_expr($3); $3 = NEW_RESCUE($3, NEW_RESBODY(0,$5,0), 0); $$ = new_op_assign($1, $2, $3); } | primary_value '[' opt_call_args rbracket tOP_ASGN arg { NODE *args; value_expr($6); if (!$3) $3 = NEW_ZARRAY(); if (nd_type($3) == NODE_BLOCK_PASS) { args = NEW_ARGSCAT($3, $6); } else { args = arg_concat($3, $6); } if ($5 == tOROP) { $5 = 0; } else if ($5 == tANDOP) { $5 = 1; } $$ = NEW_OP_ASGN1($1, $5, args); fixpos($$, $1); } | primary_value '.' tIDENTIFIER tOP_ASGN arg { value_expr($5); $$ = new_attr_op_assign($1, ripper_id2sym('.'), $3, $4, $5); } | primary_value '.' tCONSTANT tOP_ASGN arg { value_expr($5); $$ = new_attr_op_assign($1, ripper_id2sym('.'), $3, $4, $5); } | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg { value_expr($5); $$ = new_attr_op_assign($1, ripper_intern("::"), $3, $4, $5); } | primary_value tCOLON2 tCONSTANT tOP_ASGN arg { $$ = NEW_COLON2($1, $3); $$ = new_const_op_assign($$, $4, $5); } | tCOLON3 tCONSTANT tOP_ASGN arg { $$ = NEW_COLON3($2); $$ = new_const_op_assign($$, $3, $4); } | backref tOP_ASGN arg { rb_backref_error($1); $$ = NEW_BEGIN(0); } | arg tDOT2 arg { value_expr($1); value_expr($3); $$ = NEW_DOT2($1, $3); if (nd_type($1) == NODE_LIT && FIXNUM_P($1->nd_lit) && nd_type($3) == NODE_LIT && FIXNUM_P($3->nd_lit)) { deferred_nodes = list_append(deferred_nodes, $$); } } | arg tDOT3 arg { value_expr($1); value_expr($3); $$ = NEW_DOT3($1, $3); if (nd_type($1) == NODE_LIT && FIXNUM_P($1->nd_lit) && nd_type($3) == NODE_LIT && FIXNUM_P($3->nd_lit)) { deferred_nodes = list_append(deferred_nodes, $$); } } | arg '+' arg { $$ = call_bin_op($1, '+', $3); } | arg '-' arg { $$ = call_bin_op($1, '-', $3); } | arg '*' arg { $$ = call_bin_op($1, '*', $3); } | arg '/' arg { $$ = call_bin_op($1, '/', $3); } | arg '%' arg { $$ = call_bin_op($1, '%', $3); } | arg tPOW arg { $$ = call_bin_op($1, tPOW, $3); } | tUMINUS_NUM tINTEGER tPOW arg { $$ = NEW_CALL(call_bin_op($2, tPOW, $4), tUMINUS, 0); } | tUMINUS_NUM tFLOAT tPOW arg { $$ = NEW_CALL(call_bin_op($2, tPOW, $4), tUMINUS, 0); } | tUPLUS arg { $$ = call_uni_op($2, tUPLUS); } | tUMINUS arg { $$ = call_uni_op($2, tUMINUS); } | arg '|' arg { $$ = call_bin_op($1, '|', $3); } | arg '^' arg { $$ = call_bin_op($1, '^', $3); } | arg '&' arg { $$ = call_bin_op($1, '&', $3); } | arg tCMP arg { $$ = call_bin_op($1, tCMP, $3); } | arg '>' arg { $$ = call_bin_op($1, '>', $3); } | arg tGEQ arg { $$ = call_bin_op($1, tGEQ, $3); } | arg '<' arg { $$ = call_bin_op($1, '<', $3); } | arg tLEQ arg { $$ = call_bin_op($1, tLEQ, $3); } | arg tEQ arg { $$ = call_bin_op($1, tEQ, $3); } | arg tEQQ arg { $$ = call_bin_op($1, tEQQ, $3); } | arg tNEQ arg { $$ = call_bin_op($1, tNEQ, $3); } | arg tMATCH arg { $$ = match_op($1, $3); if (nd_type($1) == NODE_LIT && RB_TYPE_P($1->nd_lit, T_REGEXP)) { $$ = reg_named_capture_assign($1->nd_lit, $$); } } | arg tNMATCH arg { $$ = call_bin_op($1, tNMATCH, $3); } | '!' arg { $$ = call_uni_op(cond($2), '!'); } | '~' arg { $$ = call_uni_op($2, '~'); } | arg tLSHFT arg { $$ = call_bin_op($1, tLSHFT, $3); } | arg tRSHFT arg { $$ = call_bin_op($1, tRSHFT, $3); } | arg tANDOP arg { $$ = logop(NODE_AND, $1, $3); } | arg tOROP arg { $$ = logop(NODE_OR, $1, $3); } | keyword_defined opt_nl {in_defined = 1;} arg { in_defined = 0; $$ = NEW_DEFINED($4); } | arg '?' arg opt_nl ':' arg { value_expr($1); $$ = NEW_IF(cond($1), $3, $6); fixpos($$, $1); } | primary { $$ = $1; } ;arg_value : arg { value_expr($1); $$ = $1; if (!$$) $$ = NEW_NIL(); } ;aref_args : none | args trailer { $$ = $1; } | args ',' assocs trailer { $$ = arg_append($1, NEW_HASH($3)); } | assocs trailer { $$ = NEW_LIST(NEW_HASH($1)); } ;paren_args : '(' opt_call_args rparen { $$ = $2; } ;opt_paren_args : none | paren_args ;opt_call_args : none | call_args | args ',' { $$ = $1; } | args ',' assocs ',' { $$ = arg_append($1, NEW_HASH($3)); } | assocs ',' { $$ = NEW_LIST(NEW_HASH($1)); } ;call_args : command { value_expr($1); $$ = NEW_LIST($1); } | args opt_block_arg { $$ = arg_blk_pass($1, $2); } | assocs opt_block_arg { $$ = NEW_LIST(NEW_HASH($1)); $$ = arg_blk_pass($$, $2); } | args ',' assocs opt_block_arg { $$ = arg_append($1, NEW_HASH($3)); $$ = arg_blk_pass($$, $4); } | block_arg ;command_args : { $<val>$ = cmdarg_stack; CMDARG_PUSH(1); } call_args { cmdarg_stack = $<val>1; $$ = $2; } ;block_arg : tAMPER arg_value { $$ = NEW_BLOCK_PASS($2); } ;opt_block_arg : ',' block_arg { $$ = $2; } | none { $$ = 0; } ;args : arg_value { $$ = NEW_LIST($1); } | tSTAR arg_value { $$ = NEW_SPLAT($2); } | args ',' arg_value { NODE *n1; if ((n1 = splat_array($1)) != 0) { $$ = list_append(n1, $3); } else { $$ = arg_append($1, $3); } } | args ',' tSTAR arg_value { NODE *n1; if ((nd_type($4) == NODE_ARRAY) && (n1 = splat_array($1)) != 0) { $$ = list_concat(n1, $4); } else { $$ = arg_concat($1, $4); } } ;mrhs : args ',' arg_value { NODE *n1; if ((n1 = splat_array($1)) != 0) { $$ = list_append(n1, $3); } else { $$ = arg_append($1, $3); } } | args ',' tSTAR arg_value { NODE *n1; if (nd_type($4) == NODE_ARRAY && (n1 = splat_array($1)) != 0) { $$ = list_concat(n1, $4); } else { $$ = arg_concat($1, $4); } } | tSTAR arg_value { $$ = NEW_SPLAT($2); } ;primary : literal | strings | xstring | regexp | words | qwords | symbols | qsymbols | var_ref | backref | tFID { $$ = NEW_FCALL($1, 0); } | k_begin { $<val>1 = cmdarg_stack; cmdarg_stack = 0; $<num>$ = ruby_sourceline; } bodystmt k_end { cmdarg_stack = $<val>1; if ($3 == NULL) { $$ = NEW_NIL(); } else { if (nd_type($3) == NODE_RESCUE || nd_type($3) == NODE_ENSURE) nd_set_line($3, $<num>2); $$ = NEW_BEGIN($3); } nd_set_line($$, $<num>2); } | tLPAREN_ARG {lex_state = EXPR_ENDARG;} rparen { $$ = 0; } | tLPAREN_ARG expr {lex_state = EXPR_ENDARG;} rparen { $$ = $2; } | tLPAREN compstmt ')' { $$ = $2; } | primary_value tCOLON2 tCONSTANT { $$ = NEW_COLON2($1, $3); } | tCOLON3 tCONSTANT { $$ = NEW_COLON3($2); } | tLBRACK aref_args ']' { if ($2 == 0) { $$ = NEW_ZARRAY(); } else { $$ = $2; } } | tLBRACE assoc_list '}' { $$ = NEW_HASH($2); } | keyword_return { $$ = NEW_RETURN(0); } | keyword_yield '(' call_args rparen { $$ = new_yield($3); } | keyword_yield '(' rparen { $$ = NEW_YIELD(0); } | keyword_yield { $$ = NEW_YIELD(0); } | keyword_defined opt_nl '(' {in_defined = 1;} expr rparen { in_defined = 0; $$ = NEW_DEFINED($5); } | keyword_not '(' expr rparen { $$ = call_uni_op(cond($3), '!'); } | keyword_not '(' rparen { $$ = call_uni_op(cond(NEW_NIL()), '!'); } | fcall brace_block { $2->nd_iter = $1; $$ = $2; } | method_call | method_call brace_block { block_dup_check($1->nd_args, $2); $2->nd_iter = $1; $$ = $2; } | tLAMBDA lambda { $$ = $2; } | k_if expr_value then compstmt if_tail k_end { $$ = NEW_IF(cond($2), $4, $5); fixpos($$, $2); } | k_unless expr_value then compstmt opt_else k_end { $$ = NEW_UNLESS(cond($2), $4, $5); fixpos($$, $2); } | k_while {COND_PUSH(1);} expr_value do {COND_POP();} compstmt k_end { $$ = NEW_WHILE(cond($3), $6, 1); fixpos($$, $3); } | k_until {COND_PUSH(1);} expr_value do {COND_POP();} compstmt k_end { $$ = NEW_UNTIL(cond($3), $6, 1); fixpos($$, $3); } | k_case expr_value opt_terms case_body k_end { $$ = NEW_CASE($2, $4); fixpos($$, $2); } | k_case opt_terms case_body k_end { $$ = NEW_CASE(0, $3); } | k_for for_var keyword_in {COND_PUSH(1);} expr_value do {COND_POP();} compstmt k_end { ID id = internal_id(); ID *tbl = ALLOC_N(ID, 2); NODE *m = NEW_ARGS_AUX(0, 0); NODE *args, *scope; if (nd_type($2) == NODE_MASGN) { NODE *one = NEW_LIST(NEW_LIT(INT2FIX(1))); NODE *zero = NEW_LIST(NEW_LIT(INT2FIX(0))); m->nd_next = block_append( NEW_IF( NEW_NODE(NODE_AND, NEW_CALL(NEW_CALL(NEW_DVAR(id), idLength, 0), idEq, one), NEW_CALL(NEW_CALL(NEW_DVAR(id), idAREF, zero), rb_intern("kind_of?"), NEW_LIST(NEW_LIT(rb_cArray))), 0), NEW_DASGN_CURR(id, NEW_CALL(NEW_DVAR(id), idAREF, zero)), 0), node_assign($2, NEW_DVAR(id))); args = new_args(m, 0, id, 0, new_args_tail(0, 0, 0)); } else { if (nd_type($2) == NODE_LASGN || nd_type($2) == NODE_DASGN || nd_type($2) == NODE_DASGN_CURR) { $2->nd_value = NEW_DVAR(id); m->nd_plen = 1; m->nd_next = $2; args = new_args(m, 0, 0, 0, new_args_tail(0, 0, 0)); } else { m->nd_next = node_assign(NEW_MASGN(NEW_LIST($2), 0), NEW_DVAR(id)); args = new_args(m, 0, id, 0, new_args_tail(0, 0, 0)); } } scope = NEW_NODE(NODE_SCOPE, tbl, $8, args); tbl[0] = 1; tbl[1] = id; $$ = NEW_FOR(0, $5, scope); fixpos($$, $2); } | k_class cpath superclass { if (in_def || in_single) yyerror("class definition in method body"); local_push(0); $<num>$ = ruby_sourceline; } bodystmt k_end { $$ = NEW_CLASS($2, $5, $3); nd_set_line($$, $<num>4); local_pop(); } | k_class tLSHFT expr { $<num>$ = in_def; in_def = 0; } term { $<num>$ = in_single; in_single = 0; local_push(0); } bodystmt k_end { $$ = NEW_SCLASS($3, $7); fixpos($$, $3); local_pop(); in_def = $<num>4; in_single = $<num>6; } | k_module cpath { if (in_def || in_single) yyerror("module definition in method body"); local_push(0); $<num>$ = ruby_sourceline; } bodystmt k_end { $$ = NEW_MODULE($2, $4); nd_set_line($$, $<num>3); local_pop(); } | k_def fname { $<id>$ = cur_mid; cur_mid = $2; in_def++; local_push(0); } f_arglist bodystmt k_end { NODE *body = remove_begin($5); reduce_nodes(&body); $$ = NEW_DEFN($2, $4, body, NOEX_PRIVATE); nd_set_line($$, $<num>1); local_pop(); in_def--; cur_mid = $<id>3; } | k_def singleton dot_or_colon {lex_state = EXPR_FNAME;} fname { in_single++; lex_state = EXPR_ENDFN; local_push(0); } f_arglist bodystmt k_end { NODE *body = remove_begin($8); reduce_nodes(&body); $$ = NEW_DEFS($2, $5, $7, body); nd_set_line($$, $<num>1); local_pop(); in_single--; } | keyword_break { $$ = NEW_BREAK(0); } | keyword_next { $$ = NEW_NEXT(0); } | keyword_redo { $$ = NEW_REDO(); } | keyword_retry { $$ = NEW_RETRY(); } ;primary_value : primary { value_expr($1); $$ = $1; if (!$$) $$ = NEW_NIL(); } ;k_begin : keyword_begin { token_info_push("begin"); } ;k_if : keyword_if { token_info_push("if"); } ;k_unless : keyword_unless { token_info_push("unless"); } ;k_while : keyword_while { token_info_push("while"); } ;k_until : keyword_until { token_info_push("until"); } ;k_case : keyword_case { token_info_push("case"); } ;k_for : keyword_for { token_info_push("for"); } ;k_class : keyword_class { token_info_push("class"); } ;k_module : keyword_module { token_info_push("module"); } ;k_def : keyword_def { token_info_push("def"); $<num>$ = ruby_sourceline; } ;k_end : keyword_end { token_info_pop("end"); } ;then : term | keyword_then | term keyword_then ;do : term | keyword_do_cond ;if_tail : opt_else | keyword_elsif expr_value then compstmt if_tail { $$ = NEW_IF(cond($2), $4, $5); fixpos($$, $2); } ;opt_else : none | keyword_else compstmt { $$ = $2; } ;for_var : lhs | mlhs ;f_marg : f_norm_arg { $$ = assignable($1, 0); } | tLPAREN f_margs rparen { $$ = $2; } ;f_marg_list : f_marg { $$ = NEW_LIST($1); } | f_marg_list ',' f_marg { $$ = list_append($1, $3); } ;f_margs : f_marg_list { $$ = NEW_MASGN($1, 0); } | f_marg_list ',' tSTAR f_norm_arg { $$ = assignable($4, 0); $$ = NEW_MASGN($1, $$); } | f_marg_list ',' tSTAR f_norm_arg ',' f_marg_list { $$ = assignable($4, 0); $$ = NEW_MASGN($1, NEW_POSTARG($$, $6)); } | f_marg_list ',' tSTAR { $$ = NEW_MASGN($1, -1); } | f_marg_list ',' tSTAR ',' f_marg_list { $$ = NEW_MASGN($1, NEW_POSTARG(-1, $5)); } | tSTAR f_norm_arg { $$ = assignable($2, 0); $$ = NEW_MASGN(0, $$); } | tSTAR f_norm_arg ',' f_marg_list { $$ = assignable($2, 0); $$ = NEW_MASGN(0, NEW_POSTARG($$, $4)); } | tSTAR { $$ = NEW_MASGN(0, -1); } | tSTAR ',' f_marg_list { $$ = NEW_MASGN(0, NEW_POSTARG(-1, $3)); } ;block_args_tail : f_block_kwarg ',' f_kwrest opt_f_block_arg { $$ = new_args_tail($1, $3, $4); } | f_block_kwarg opt_f_block_arg { $$ = new_args_tail($1, Qnone, $2); } | f_kwrest opt_f_block_arg { $$ = new_args_tail(Qnone, $1, $2); } | f_block_arg { $$ = new_args_tail(Qnone, Qnone, $1); } ;opt_block_args_tail : ',' block_args_tail { $$ = $2; } | { $$ = new_args_tail(Qnone, Qnone, Qnone); } ;block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_block_args_tail { $$ = new_args($1, $3, $5, Qnone, $6); } | f_arg ',' f_block_optarg ',' f_rest_arg ',' f_arg opt_block_args_tail { $$ = new_args($1, $3, $5, $7, $8); } | f_arg ',' f_block_optarg opt_block_args_tail { $$ = new_args($1, $3, Qnone, Qnone, $4); } | f_arg ',' f_block_optarg ',' f_arg opt_block_args_tail { $$ = new_args($1, $3, Qnone, $5, $6); } | f_arg ',' f_rest_arg opt_block_args_tail { $$ = new_args($1, Qnone, $3, Qnone, $4); } | f_arg ',' { $$ = new_args($1, Qnone, 1, Qnone, new_args_tail(Qnone, Qnone, Qnone)); } | f_arg ',' f_rest_arg ',' f_arg opt_block_args_tail { $$ = new_args($1, Qnone, $3, $5, $6); } | f_arg opt_block_args_tail { $$ = new_args($1, Qnone, Qnone, Qnone, $2); } | f_block_optarg ',' f_rest_arg opt_block_args_tail { $$ = new_args(Qnone, $1, $3, Qnone, $4); } | f_block_optarg ',' f_rest_arg ',' f_arg opt_block_args_tail { $$ = new_args(Qnone, $1, $3, $5, $6); } | f_block_optarg opt_block_args_tail { $$ = new_args(Qnone, $1, Qnone, Qnone, $2); } | f_block_optarg ',' f_arg opt_block_args_tail { $$ = new_args(Qnone, $1, Qnone, $3, $4); } | f_rest_arg opt_block_args_tail { $$ = new_args(Qnone, Qnone, $1, Qnone, $2); } | f_rest_arg ',' f_arg opt_block_args_tail { $$ = new_args(Qnone, Qnone, $1, $3, $4); } | block_args_tail { $$ = new_args(Qnone, Qnone, Qnone, Qnone, $1); } ;opt_block_param : none | block_param_def { command_start = TRUE; } ;block_param_def : '|' opt_bv_decl '|' { $$ = 0; } | tOROP { $$ = 0; } | '|' block_param opt_bv_decl '|' { $$ = $2; } ;opt_bv_decl : opt_nl { $$ = 0; } | opt_nl ';' bv_decls opt_nl { $$ = 0; } ;bv_decls : bvar | bv_decls ',' bvar ;bvar : tIDENTIFIER { new_bv(get_id($1)); } | f_bad_arg { $$ = 0; } ;lambda : { $<vars>$ = dyna_push(); } { $<num>$ = lpar_beg; lpar_beg = ++paren_nest; } f_larglist lambda_body { lpar_beg = $<num>2; $$ = NEW_LAMBDA($3, $4); dyna_pop($<vars>1); } ;f_larglist : '(' f_args opt_bv_decl ')' { $$ = $2; } | f_args { $$ = $1; } ;lambda_body : tLAMBEG compstmt '}' { $$ = $2; } | keyword_do_LAMBDA compstmt keyword_end { $$ = $2; } ;do_block : keyword_do_block { $<vars>1 = dyna_push(); $<num>$ = ruby_sourceline; } opt_block_param compstmt keyword_end { $$ = NEW_ITER($3,$4); nd_set_line($$, $<num>2); dyna_pop($<vars>1); } ;block_call : command do_block { if (nd_type($1) == NODE_YIELD) { compile_error(PARSER_ARG "block given to yield"); } else { block_dup_check($1->nd_args, $2); } $2->nd_iter = $1; $$ = $2; fixpos($$, $1); } | block_call dot_or_colon operation2 opt_paren_args { $$ = NEW_CALL($1, $3, $4); } | block_call dot_or_colon operation2 opt_paren_args brace_block { block_dup_check($4, $5); $5->nd_iter = NEW_CALL($1, $3, $4); $$ = $5; fixpos($$, $1); } | block_call dot_or_colon operation2 command_args do_block { block_dup_check($4, $5); $5->nd_iter = NEW_CALL($1, $3, $4); $$ = $5; fixpos($$, $1); } ;method_call : fcall paren_args { $$ = $1; $$->nd_args = $2; } | primary_value '.' operation2 { $<num>$ = ruby_sourceline; } opt_paren_args { $$ = NEW_CALL($1, $3, $5); nd_set_line($$, $<num>4); } | primary_value tCOLON2 operation2 { $<num>$ = ruby_sourceline; } paren_args { $$ = NEW_CALL($1, $3, $5); nd_set_line($$, $<num>4); } | primary_value tCOLON2 operation3 { $$ = NEW_CALL($1, $3, 0); } | primary_value '.' { $<num>$ = ruby_sourceline; } paren_args { $$ = NEW_CALL($1, rb_intern("call"), $4); nd_set_line($$, $<num>3); } | primary_value tCOLON2 { $<num>$ = ruby_sourceline; } paren_args { $$ = NEW_CALL($1, rb_intern("call"), $4); nd_set_line($$, $<num>3); } | keyword_super paren_args { $$ = NEW_SUPER($2); } | keyword_super { $$ = NEW_ZSUPER(); } | primary_value '[' opt_call_args rbracket { if ($1 && nd_type($1) == NODE_SELF) $$ = NEW_FCALL(tAREF, $3); else $$ = NEW_CALL($1, tAREF, $3); fixpos($$, $1); } ;brace_block : '{' { $<vars>1 = dyna_push(); $<num>$ = ruby_sourceline; } opt_block_param compstmt '}' { $$ = NEW_ITER($3,$4); nd_set_line($$, $<num>2); dyna_pop($<vars>1); } | keyword_do { $<vars>1 = dyna_push(); $<num>$ = ruby_sourceline; } opt_block_param compstmt keyword_end { $$ = NEW_ITER($3,$4); nd_set_line($$, $<num>2); dyna_pop($<vars>1); } ;case_body : keyword_when args then compstmt cases { $$ = NEW_WHEN($2, $4, $5); } ;cases : opt_else | case_body ;opt_rescue : keyword_rescue exc_list exc_var then compstmt opt_rescue { if ($3) { $3 = node_assign($3, NEW_ERRINFO()); $5 = block_append($3, $5); } $$ = NEW_RESBODY($2, $5, $6); fixpos($$, $2?$2:$5); } | none ;exc_list : arg_value { $$ = NEW_LIST($1); } | mrhs { if (!($$ = splat_array($1))) $$ = $1; } | none ;exc_var : tASSOC lhs { $$ = $2; } | none ;opt_ensure : keyword_ensure compstmt { $$ = $2; } | none ;literal : numeric | symbol { $$ = NEW_LIT(ID2SYM($1)); } | dsym ;strings : string { NODE *node = $1; if (!node) { node = NEW_STR(STR_NEW0()); } else { node = evstr2dstr(node); } $$ = node; } ;string : tCHAR | string1 | string string1 { $$ = literal_concat($1, $2); } ;string1 : tSTRING_BEG string_contents tSTRING_END { $$ = $2; } ;xstring : tXSTRING_BEG xstring_contents tSTRING_END { NODE *node = $2; if (!node) { node = NEW_XSTR(STR_NEW0()); } else { switch (nd_type(node)) { case NODE_STR: nd_set_type(node, NODE_XSTR); break; case NODE_DSTR: nd_set_type(node, NODE_DXSTR); break; default: node = NEW_NODE(NODE_DXSTR, Qnil, 1, NEW_LIST(node)); break; } } $$ = node; } ;regexp : tREGEXP_BEG regexp_contents tREGEXP_END { int options = $3; NODE *node = $2; NODE *list, *prev; if (!node) { node = NEW_LIT(reg_compile(STR_NEW0(), options)); } else switch (nd_type(node)) { case NODE_STR: { VALUE src = node->nd_lit; nd_set_type(node, NODE_LIT); node->nd_lit = reg_compile(src, options); } break; default: node = NEW_NODE(NODE_DSTR, STR_NEW0(), 1, NEW_LIST(node)); case NODE_DSTR: if (options & RE_OPTION_ONCE) { nd_set_type(node, NODE_DREGX_ONCE); } else { nd_set_type(node, NODE_DREGX); } node->nd_cflag = options & RE_OPTION_MASK; if (!NIL_P(node->nd_lit)) reg_fragment_check(node->nd_lit, options); for (list = (prev = node)->nd_next; list; list = list->nd_next) { if (nd_type(list->nd_head) == NODE_STR) { VALUE tail = list->nd_head->nd_lit; if (reg_fragment_check(tail, options) && prev && !NIL_P(prev->nd_lit)) { VALUE lit = prev == node ? prev->nd_lit : prev->nd_head->nd_lit; if (!literal_concat0(parser, lit, tail)) { node = 0; break; } rb_str_resize(tail, 0); prev->nd_next = list->nd_next; rb_gc_force_recycle((VALUE)list->nd_head); rb_gc_force_recycle((VALUE)list); list = prev; } else { prev = list; } } else { prev = 0; } } if (!node->nd_next) { VALUE src = node->nd_lit; nd_set_type(node, NODE_LIT); node->nd_lit = reg_compile(src, options); } break; } $$ = node; } ;words : tWORDS_BEG ' ' tSTRING_END { $$ = NEW_ZARRAY(); } | tWORDS_BEG word_list tSTRING_END { $$ = $2; } ;word_list : { $$ = 0; } | word_list word ' ' { $$ = list_append($1, evstr2dstr($2)); } ;word : string_content | word string_content { $$ = literal_concat($1, $2); } ;symbols : tSYMBOLS_BEG ' ' tSTRING_END { $$ = NEW_ZARRAY(); } | tSYMBOLS_BEG symbol_list tSTRING_END { $$ = $2; } ;symbol_list : { $$ = 0; } | symbol_list word ' ' { $2 = evstr2dstr($2); nd_set_type($2, NODE_DSYM); $$ = list_append($1, $2); } ;qwords : tQWORDS_BEG ' ' tSTRING_END { $$ = NEW_ZARRAY(); } | tQWORDS_BEG qword_list tSTRING_END { $$ = $2; } ;qsymbols : tQSYMBOLS_BEG ' ' tSTRING_END { $$ = NEW_ZARRAY(); } | tQSYMBOLS_BEG qsym_list tSTRING_END { $$ = $2; } ;qword_list : { $$ = 0; } | qword_list tSTRING_CONTENT ' ' { $$ = list_append($1, $2); } ;qsym_list : { $$ = 0; } | qsym_list tSTRING_CONTENT ' ' { VALUE lit; lit = $2->nd_lit; $2->nd_lit = ID2SYM(rb_intern_str(lit)); nd_set_type($2, NODE_LIT); $$ = list_append($1, $2); } ;string_contents : { $$ = 0; } | string_contents string_content { $$ = literal_concat($1, $2); } ;xstring_contents: { $$ = 0; } | xstring_contents string_content { $$ = literal_concat($1, $2); } ;regexp_contents: { $$ = 0; } | regexp_contents string_content { NODE *head = $1, *tail = $2; if (!head) { $$ = tail; } else if (!tail) { $$ = head; } else { switch (nd_type(head)) { case NODE_STR: nd_set_type(head, NODE_DSTR); break; case NODE_DSTR: break; default: head = list_append(NEW_DSTR(Qnil), head); break; } $$ = list_append(head, tail); } } ;string_content : tSTRING_CONTENT | tSTRING_DVAR { $<node>$ = lex_strterm; lex_strterm = 0; lex_state = EXPR_BEG; } string_dvar { lex_strterm = $<node>2; $$ = NEW_EVSTR($3); } | tSTRING_DBEG { $<val>1 = cond_stack; $<val>$ = cmdarg_stack; cond_stack = 0; cmdarg_stack = 0; } { $<node>$ = lex_strterm; lex_strterm = 0; lex_state = EXPR_BEG; } { $<num>$ = brace_nest; brace_nest = 0; } compstmt tSTRING_DEND { cond_stack = $<val>1; cmdarg_stack = $<val>2; lex_strterm = $<node>3; brace_nest = $<num>4; if ($5) $5->flags &= ~NODE_FL_NEWLINE; $$ = new_evstr($5); } ;string_dvar : tGVAR { $$ = NEW_GVAR($1); } | tIVAR { $$ = NEW_IVAR($1); } | tCVAR { $$ = NEW_CVAR($1); } | backref ;symbol : tSYMBEG sym { lex_state = EXPR_END; $$ = $2; } ;sym : fname | tIVAR | tGVAR | tCVAR ;dsym : tSYMBEG xstring_contents tSTRING_END { lex_state = EXPR_END; $$ = dsym_node($2); } ;numeric : tINTEGER | tFLOAT | tUMINUS_NUM tINTEGER %prec tLOWEST { $$ = negate_lit($2); } | tUMINUS_NUM tFLOAT %prec tLOWEST { $$ = negate_lit($2); } ;user_variable : tIDENTIFIER | tIVAR | tGVAR | tCONSTANT | tCVAR ;keyword_variable: keyword_nil {ifndef_ripper($$ = keyword_nil);} | keyword_self {ifndef_ripper($$ = keyword_self);} | keyword_true {ifndef_ripper($$ = keyword_true);} | keyword_false {ifndef_ripper($$ = keyword_false);} | keyword__FILE__ {ifndef_ripper($$ = keyword__FILE__);} | keyword__LINE__ {ifndef_ripper($$ = keyword__LINE__);} | keyword__ENCODING__ {ifndef_ripper($$ = keyword__ENCODING__);} ;var_ref : user_variable { if (!($$ = gettable($1))) $$ = NEW_BEGIN(0); } | keyword_variable { if (!($$ = gettable($1))) $$ = NEW_BEGIN(0); } ;var_lhs : user_variable { $$ = assignable($1, 0); } | keyword_variable { $$ = assignable($1, 0); } ;backref : tNTH_REF | tBACK_REF ;superclass : term { $$ = 0; } | '<' { lex_state = EXPR_BEG; command_start = TRUE; } expr_value term { $$ = $3; } | error term { yyerrok; $$ = 0; } ;f_arglist : '(' f_args rparen { $$ = $2; lex_state = EXPR_BEG; command_start = TRUE; } | f_args term { $$ = $1; lex_state = EXPR_BEG; command_start = TRUE; } ;args_tail : f_kwarg ',' f_kwrest opt_f_block_arg { $$ = new_args_tail($1, $3, $4); } | f_kwarg opt_f_block_arg { $$ = new_args_tail($1, Qnone, $2); } | f_kwrest opt_f_block_arg { $$ = new_args_tail(Qnone, $1, $2); } | f_block_arg { $$ = new_args_tail(Qnone, Qnone, $1); } ;opt_args_tail : ',' args_tail { $$ = $2; } | { $$ = new_args_tail(Qnone, Qnone, Qnone); } ;f_args : f_arg ',' f_optarg ',' f_rest_arg opt_args_tail { $$ = new_args($1, $3, $5, Qnone, $6); } | f_arg ',' f_optarg ',' f_rest_arg ',' f_arg opt_args_tail { $$ = new_args($1, $3, $5, $7, $8); } | f_arg ',' f_optarg opt_args_tail { $$ = new_args($1, $3, Qnone, Qnone, $4); } | f_arg ',' f_optarg ',' f_arg opt_args_tail { $$ = new_args($1, $3, Qnone, $5, $6); } | f_arg ',' f_rest_arg opt_args_tail { $$ = new_args($1, Qnone, $3, Qnone, $4); } | f_arg ',' f_rest_arg ',' f_arg opt_args_tail { $$ = new_args($1, Qnone, $3, $5, $6); } | f_arg opt_args_tail { $$ = new_args($1, Qnone, Qnone, Qnone, $2); } | f_optarg ',' f_rest_arg opt_args_tail { $$ = new_args(Qnone, $1, $3, Qnone, $4); } | f_optarg ',' f_rest_arg ',' f_arg opt_args_tail { $$ = new_args(Qnone, $1, $3, $5, $6); } | f_optarg opt_args_tail { $$ = new_args(Qnone, $1, Qnone, Qnone, $2); } | f_optarg ',' f_arg opt_args_tail { $$ = new_args(Qnone, $1, Qnone, $3, $4); } | f_rest_arg opt_args_tail { $$ = new_args(Qnone, Qnone, $1, Qnone, $2); } | f_rest_arg ',' f_arg opt_args_tail { $$ = new_args(Qnone, Qnone, $1, $3, $4); } | args_tail { $$ = new_args(Qnone, Qnone, Qnone, Qnone, $1); } | { $$ = new_args_tail(Qnone, Qnone, Qnone); $$ = new_args(Qnone, Qnone, Qnone, Qnone, $$); } ;f_bad_arg : tCONSTANT { yyerror("formal argument cannot be a constant"); $$ = 0; } | tIVAR { yyerror("formal argument cannot be an instance variable"); $$ = 0; } | tGVAR { yyerror("formal argument cannot be a global variable"); $$ = 0; } | tCVAR { yyerror("formal argument cannot be a class variable"); $$ = 0; } ;f_norm_arg : f_bad_arg | tIDENTIFIER { formal_argument(get_id($1)); $$ = $1; } ;f_arg_item : f_norm_arg { arg_var(get_id($1)); $$ = NEW_ARGS_AUX($1, 1); } | tLPAREN f_margs rparen { ID tid = internal_id(); arg_var(tid); if (dyna_in_block()) { $2->nd_value = NEW_DVAR(tid); } else { $2->nd_value = NEW_LVAR(tid); } $$ = NEW_ARGS_AUX(tid, 1); $$->nd_next = $2; } ;f_arg : f_arg_item | f_arg ',' f_arg_item { $$ = $1; $$->nd_plen++; $$->nd_next = block_append($$->nd_next, $3->nd_next); rb_gc_force_recycle((VALUE)$3); } ;f_kw : tLABEL arg_value { arg_var(formal_argument(get_id($1))); $$ = assignable($1, $2); $$ = NEW_KW_ARG(0, $$); } ;f_block_kw : tLABEL primary_value { arg_var(formal_argument(get_id($1))); $$ = assignable($1, $2); $$ = NEW_KW_ARG(0, $$); } ;f_block_kwarg : f_block_kw { $$ = $1; } | f_block_kwarg ',' f_block_kw { NODE *kws = $1; while (kws->nd_next) { kws = kws->nd_next; } kws->nd_next = $3; $$ = $1; } ;f_kwarg : f_kw { $$ = $1; } | f_kwarg ',' f_kw { NODE *kws = $1; while (kws->nd_next) { kws = kws->nd_next; } kws->nd_next = $3; $$ = $1; } ;kwrest_mark : tPOW | tDSTAR ;f_kwrest : kwrest_mark tIDENTIFIER { shadowing_lvar(get_id($2)); $$ = $2; } | kwrest_mark { $$ = internal_id(); } ;f_opt : tIDENTIFIER '=' arg_value { arg_var(formal_argument(get_id($1))); $$ = assignable($1, $3); $$ = NEW_OPT_ARG(0, $$); } ;f_block_opt : tIDENTIFIER '=' primary_value { arg_var(formal_argument(get_id($1))); $$ = assignable($1, $3); $$ = NEW_OPT_ARG(0, $$); } ;f_block_optarg : f_block_opt { $$ = $1; } | f_block_optarg ',' f_block_opt { NODE *opts = $1; while (opts->nd_next) { opts = opts->nd_next; } opts->nd_next = $3; $$ = $1; } ;f_optarg : f_opt { $$ = $1; } | f_optarg ',' f_opt { NODE *opts = $1; while (opts->nd_next) { opts = opts->nd_next; } opts->nd_next = $3; $$ = $1; } ;restarg_mark : '*' | tSTAR ;f_rest_arg : restarg_mark tIDENTIFIER { if (!is_local_id($2)) yyerror("rest argument must be local variable"); arg_var(shadowing_lvar(get_id($2))); $$ = $2; } | restarg_mark { $$ = internal_id(); arg_var($$); } ;blkarg_mark : '&' | tAMPER ;f_block_arg : blkarg_mark tIDENTIFIER { if (!is_local_id($2)) yyerror("block argument must be local variable"); else if (!dyna_in_block() && local_id($2)) yyerror("duplicated block argument name"); arg_var(shadowing_lvar(get_id($2))); $$ = $2; } ;opt_f_block_arg : ',' f_block_arg { $$ = $2; } | none { $$ = 0; } ;singleton : var_ref { value_expr($1); $$ = $1; if (!$$) $$ = NEW_NIL(); } | '(' {lex_state = EXPR_BEG;} expr rparen { if ($3 == 0) { yyerror("can't define singleton method for ()."); } else { switch (nd_type($3)) { case NODE_STR: case NODE_DSTR: case NODE_XSTR: case NODE_DXSTR: case NODE_DREGX: case NODE_LIT: case NODE_ARRAY: case NODE_ZARRAY: yyerror("can't define singleton method for literals"); default: value_expr($3); break; } } $$ = $3; } ;assoc_list : none | assocs trailer { $$ = $1; } ;assocs : assoc | assocs ',' assoc { $$ = list_concat($1, $3); } ;assoc : arg_value tASSOC arg_value { $$ = list_append(NEW_LIST($1), $3); } | tLABEL arg_value { $$ = list_append(NEW_LIST(NEW_LIT(ID2SYM($1))), $2); } | tDSTAR arg_value { $$ = list_append(NEW_LIST(0), $2); } ; ;operation : tIDENTIFIER | tCONSTANT | tFID ;operation2 : tIDENTIFIER | tCONSTANT | tFID | op ;operation3 : tIDENTIFIER | tFID | op ;dot_or_colon : '.' | tCOLON2 ;opt_terms : | terms ;opt_nl : | '\n' ;rparen : opt_nl ')' ;rbracket : opt_nl ']' ;trailer : | '\n' | ',' ;term : ';' {yyerrok;} | '\n' ;terms : term | terms ';' {yyerrok;} ;none : { $$ = 0; } ;%%#define yylvalstatic int parser_regx_options(struct parser_params*);static int parser_tokadd_string(struct parser_params*,int,int,int,long*,rb_encoding**);static void parser_tokaddmbc(struct parser_params *parser, int c, rb_encoding *enc);static int parser_parse_string(struct parser_params*,NODE*);static int parser_here_document(struct parser_params*,NODE*);#define nextc() #define pushback(c) #define newtok() #define tokspace(n) #define tokadd(c) #define tok_hex(numlen) #define read_escape(flags,e) #define tokadd_escape(e) #define regx_options() #define tokadd_string(f,t,p,n,e) #define parse_string(n) #define tokaddmbc(c, enc) #define here_document(n) #define heredoc_identifier() #define heredoc_restore(n) #define whole_match_p(e,l,i) #define set_yylval_str(x) #define set_yylval_num(x) #define set_yylval_id(x) #define set_yylval_name(x) #define set_yylval_literal(x) #define set_yylval_node(x) #define yylval_id() #define ripper_flush(p) #define SIGN_EXTEND_CHAR(c) #define parser_encoding_name() #define parser_mbclen() #define parser_precise_mbclen() #define is_identchar(p,e,enc) #define parser_is_identchar() #define parser_isascii() static inttoken_info_get_column(struct parser_params *parser, const char *token){ int column = 1; const char *p, *pend = lex_p - strlen(token); for (p = lex_pbeg; p < pend; p++) { if (*p == '\t') { column = (((column - 1) / 8) + 1) * 8; } column++; } return column;}static inttoken_info_has_nonspaces(struct parser_params *parser, const char *token){ const char *p, *pend = lex_p - strlen(token); for (p = lex_pbeg; p < pend; p++) { if (*p != ' ' && *p != '\t') { return 1; } } return 0;}static voidtoken_info_push(struct parser_params *parser, const char *token){ token_info *ptinfo; if (!parser->parser_token_info_enabled) return; ptinfo = ALLOC(token_info); ptinfo->token = token; ptinfo->linenum = ruby_sourceline; ptinfo->column = token_info_get_column(parser, token); ptinfo->nonspc = token_info_has_nonspaces(parser, token); ptinfo->next = parser->parser_token_info; parser->parser_token_info = ptinfo;}static voidtoken_info_pop(struct parser_params *parser, const char *token){ int linenum; token_info *ptinfo = parser->parser_token_info; if (!ptinfo) return; parser->parser_token_info = ptinfo->next; if (token_info_get_column(parser, token) == ptinfo->column) { goto finish; } linenum = ruby_sourceline; if (linenum == ptinfo->linenum) { goto finish; } if (token_info_has_nonspaces(parser, token) || ptinfo->nonspc) { goto finish; } if (parser->parser_token_info_enabled) { rb_compile_warn(ruby_sourcefile, linenum, "mismatched indentations at '%s' with '%s' at %d", token, ptinfo->token, ptinfo->linenum); } finish: xfree(ptinfo);}static intparser_yyerror(struct parser_params *parser, const char *msg){ const int max_line_margin = 30; const char *p, *pe; char *buf; long len; int i; compile_error(PARSER_ARG "%s", msg); p = lex_p; while (lex_pbeg <= p) { if (*p == '\n') break; p--; } p++; pe = lex_p; while (pe < lex_pend) { if (*pe == '\n') break; pe++; } len = pe - p; if (len > 4) { char *p2; const char *pre = "", *post = ""; if (len > max_line_margin * 2 + 10) { if (lex_p - p > max_line_margin) { p = rb_enc_prev_char(p, lex_p - max_line_margin, pe, rb_enc_get(lex_lastline)); pre = "..."; } if (pe - lex_p > max_line_margin) { pe = rb_enc_prev_char(lex_p, lex_p + max_line_margin, pe, rb_enc_get(lex_lastline)); post = "..."; } len = pe - p; } buf = ALLOCA_N(char, len+2); MEMCPY(buf, p, char, len); buf[len] = '\0'; rb_compile_error_append("%s%s%s", pre, buf, post); i = (int)(lex_p - p); p2 = buf; pe = buf + len; while (p2 < pe) { if (*p2 != '\t') *p2 = ' '; p2++; } buf[i] = '^'; buf[i+1] = '\0'; rb_compile_error_append("%s%s", pre, buf); } return 0;}static void parser_prepare(struct parser_params *parser);static VALUEdebug_lines(const char *f){ ID script_lines; CONST_ID(script_lines, "SCRIPT_LINES__"); if (rb_const_defined_at(rb_cObject, script_lines)) { VALUE hash = rb_const_get_at(rb_cObject, script_lines); if (RB_TYPE_P(hash, T_HASH)) { VALUE fname = rb_external_str_new_with_enc(f, strlen(f), rb_filesystem_encoding()); VALUE lines = rb_ary_new(); rb_hash_aset(hash, fname, lines); return lines; } } return 0;}static VALUEcoverage(const char *f, int n){ VALUE coverages = rb_get_coverages(); if (RTEST(coverages) && RBASIC(coverages)->klass == 0) { VALUE fname = rb_external_str_new_with_enc(f, strlen(f), rb_filesystem_encoding()); VALUE lines = rb_ary_new2(n); int i; RBASIC(lines)->klass = 0; for (i = 0; i < n; i++) RARRAY_PTR(lines)[i] = Qnil; RARRAY(lines)->as.heap.len = n; rb_hash_aset(coverages, fname, lines); return lines; } return 0;}static inte_option_supplied(struct parser_params *parser){ return strcmp(ruby_sourcefile, "-e") == 0;}static VALUEyycompile0(VALUE arg){ int n; NODE *tree; struct parser_params *parser = (struct parser_params *)arg; if (!compile_for_eval && rb_safe_level() == 0) { ruby_debug_lines = debug_lines(ruby_sourcefile); if (ruby_debug_lines && ruby_sourceline > 0) { VALUE str = STR_NEW0(); n = ruby_sourceline; do { rb_ary_push(ruby_debug_lines, str); } while (--n); } if (!e_option_supplied(parser)) { ruby_coverage = coverage(ruby_sourcefile, ruby_sourceline); } } parser_prepare(parser); deferred_nodes = 0; parser->parser_token_info_enabled = !compile_for_eval && RTEST(ruby_verbose); if (RUBY_DTRACE_PARSE_BEGIN_ENABLED()) { RUBY_DTRACE_PARSE_BEGIN(parser->parser_ruby_sourcefile, parser->parser_ruby_sourceline); } n = yyparse((void*)parser); if (RUBY_DTRACE_PARSE_END_ENABLED()) { RUBY_DTRACE_PARSE_END(parser->parser_ruby_sourcefile, parser->parser_ruby_sourceline); } ruby_debug_lines = 0; ruby_coverage = 0; compile_for_eval = 0; lex_strterm = 0; lex_p = lex_pbeg = lex_pend = 0; lex_lastline = lex_nextline = 0; if (parser->nerr) { return 0; } tree = ruby_eval_tree; if (!tree) { tree = NEW_NIL(); } else if (ruby_eval_tree_begin) { tree->nd_body = NEW_PRELUDE(ruby_eval_tree_begin, tree->nd_body); } return (VALUE)tree;}static NODE*yycompile(struct parser_params *parser, const char *f, int line){ ruby_sourcefile = ruby_strdup(f); ruby_sourceline = line - 1; return (NODE *)rb_suppress_tracing(yycompile0, (VALUE)parser);}static rb_encoding *must_be_ascii_compatible(VALUE s){ rb_encoding *enc = rb_enc_get(s); if (!rb_enc_asciicompat(enc)) { rb_raise(rb_eArgError, "invalid source encoding"); } return enc;}static VALUElex_get_str(struct parser_params *parser, VALUE s){ char *beg, *end, *pend; rb_encoding *enc = must_be_ascii_compatible(s); beg = RSTRING_PTR(s); if (lex_gets_ptr) { if (RSTRING_LEN(s) == lex_gets_ptr) return Qnil; beg += lex_gets_ptr; } pend = RSTRING_PTR(s) + RSTRING_LEN(s); end = beg; while (end < pend) { if (*end++ == '\n') break; } lex_gets_ptr = end - RSTRING_PTR(s); return rb_enc_str_new(beg, end - beg, enc);}static VALUElex_getline(struct parser_params *parser){ VALUE line = (*parser->parser_lex_gets)(parser, parser->parser_lex_input); if (NIL_P(line)) return line; must_be_ascii_compatible(line); if (ruby_debug_lines) { rb_enc_associate(line, current_enc); rb_ary_push(ruby_debug_lines, line); } if (ruby_coverage) { rb_ary_push(ruby_coverage, Qnil); } return line;}static const rb_data_type_t parser_data_type;static NODE*parser_compile_string(volatile VALUE vparser, const char *f, VALUE s, int line){ struct parser_params *parser; NODE *node; TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, parser); lex_gets = lex_get_str; lex_gets_ptr = 0; lex_input = s; lex_pbeg = lex_p = lex_pend = 0; compile_for_eval = rb_parse_in_eval(); node = yycompile(parser, f, line); RB_GC_GUARD(vparser); return node;}NODE*rb_compile_string(const char *f, VALUE s, int line){ must_be_ascii_compatible(s); return parser_compile_string(rb_parser_new(), f, s, line);}NODE*rb_parser_compile_string(volatile VALUE vparser, const char *f, VALUE s, int line){ must_be_ascii_compatible(s); return parser_compile_string(vparser, f, s, line);}NODE*rb_compile_cstr(const char *f, const char *s, int len, int line){ VALUE str = rb_str_new(s, len); return parser_compile_string(rb_parser_new(), f, str, line);}NODE*rb_parser_compile_cstr(volatile VALUE vparser, const char *f, const char *s, int len, int line){ VALUE str = rb_str_new(s, len); return parser_compile_string(vparser, f, str, line);}static VALUElex_io_gets(struct parser_params *parser, VALUE io){ return rb_io_gets(io);}NODE*rb_compile_file(const char *f, VALUE file, int start){ VALUE volatile vparser = rb_parser_new(); return rb_parser_compile_file(vparser, f, file, start);}NODE*rb_parser_compile_file(volatile VALUE vparser, const char *f, VALUE file, int start){ struct parser_params *parser; NODE *node; TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, parser); lex_gets = lex_io_gets; lex_input = file; lex_pbeg = lex_p = lex_pend = 0; compile_for_eval = rb_parse_in_eval(); node = yycompile(parser, f, start); RB_GC_GUARD(vparser); return node;}#define STR_FUNC_ESCAPE#define STR_FUNC_EXPAND#define STR_FUNC_REGEXP#define STR_FUNC_QWORDS#define STR_FUNC_SYMBOL#define STR_FUNC_INDENTenum string_type { str_squote = (0), str_dquote = (STR_FUNC_EXPAND), str_xquote = (STR_FUNC_EXPAND), str_regexp = (STR_FUNC_REGEXP|STR_FUNC_ESCAPE|STR_FUNC_EXPAND), str_sword = (STR_FUNC_QWORDS), str_dword = (STR_FUNC_QWORDS|STR_FUNC_EXPAND), str_ssym = (STR_FUNC_SYMBOL), str_dsym = (STR_FUNC_SYMBOL|STR_FUNC_EXPAND)};static VALUEparser_str_new(const char *p, long n, rb_encoding *enc, int func, rb_encoding *enc0){ VALUE str; str = rb_enc_str_new(p, n, enc); if (!(func & STR_FUNC_REGEXP) && rb_enc_asciicompat(enc)) { if (rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT) { } else if (enc0 == rb_usascii_encoding() && enc != rb_utf8_encoding()) { rb_enc_associate(str, rb_ascii8bit_encoding()); } } return str;}#define lex_goto_eol(parser) #define lex_eol_p() #define peek(c) #define peek_n(c,n) static inline intparser_nextc(struct parser_params *parser){ int c; if (lex_p == lex_pend) { VALUE v = lex_nextline; lex_nextline = 0; if (!v) { if (parser->eofp) return -1; if (!lex_input || NIL_P(v = lex_getline(parser))) { parser->eofp = Qtrue; lex_goto_eol(parser); return -1; } } { if (heredoc_end > 0) { ruby_sourceline = heredoc_end; heredoc_end = 0; } ruby_sourceline++; parser->line_count++; lex_pbeg = lex_p = RSTRING_PTR(v); lex_pend = lex_p + RSTRING_LEN(v); ripper_flush(parser); lex_lastline = v; } } c = (unsigned char)*lex_p++; if (c == '\r' && peek('\n')) { lex_p++; c = '\n'; } return c;}static voidparser_pushback(struct parser_params *parser, int c){ if (c == -1) return; lex_p--; if (lex_p > lex_pbeg && lex_p[0] == '\n' && lex_p[-1] == '\r') { lex_p--; }}#define was_bol() #define tokfix() #define tok() #define toklen() #define toklast() static char*parser_newtok(struct parser_params *parser){ tokidx = 0; tokline = ruby_sourceline; if (!tokenbuf) { toksiz = 60; tokenbuf = ALLOC_N(char, 60); } if (toksiz > 4096) { toksiz = 60; REALLOC_N(tokenbuf, char, 60); } return tokenbuf;}static char *parser_tokspace(struct parser_params *parser, int n){ tokidx += n; if (tokidx >= toksiz) { do {toksiz *= 2;} while (toksiz < tokidx); REALLOC_N(tokenbuf, char, toksiz); } return &tokenbuf[tokidx-n];}static voidparser_tokadd(struct parser_params *parser, int c){ tokenbuf[tokidx++] = (char)c; if (tokidx >= toksiz) { toksiz *= 2; REALLOC_N(tokenbuf, char, toksiz); }}static intparser_tok_hex(struct parser_params *parser, size_t *numlen){ int c; c = scan_hex(lex_p, 2, numlen); if (!*numlen) { yyerror("invalid hex escape"); return 0; } lex_p += *numlen; return c;}#define tokcopy(n) static intparser_tokadd_utf8(struct parser_params *parser, rb_encoding **encp, int string_literal, int symbol_literal, int regexp_literal){ int codepoint; size_t numlen; if (regexp_literal) { tokadd('\\'); tokadd('u'); } if (peek('{')) { do { if (regexp_literal) { tokadd(*lex_p); } nextc(); codepoint = scan_hex(lex_p, 6, &numlen); if (numlen == 0) { yyerror("invalid Unicode escape"); return 0; } if (codepoint > 0x10ffff) { yyerror("invalid Unicode codepoint (too large)"); return 0; } lex_p += numlen; if (regexp_literal) { tokcopy((int)numlen); } else if (codepoint >= 0x80) { *encp = rb_utf8_encoding(); if (string_literal) tokaddmbc(codepoint, *encp); } else if (string_literal) { tokadd(codepoint); } } while (string_literal && (peek(' ') || peek('\t'))); if (!peek('}')) { yyerror("unterminated Unicode escape"); return 0; } if (regexp_literal) { tokadd('}'); } nextc(); } else { codepoint = scan_hex(lex_p, 4, &numlen); if (numlen < 4) { yyerror("invalid Unicode escape"); return 0; } lex_p += 4; if (regexp_literal) { tokcopy(4); } else if (codepoint >= 0x80) { *encp = rb_utf8_encoding(); if (string_literal) tokaddmbc(codepoint, *encp); } else if (string_literal) { tokadd(codepoint); } } return codepoint;}#define ESCAPE_CONTROL#define ESCAPE_METAstatic intparser_read_escape(struct parser_params *parser, int flags, rb_encoding **encp){ int c; size_t numlen; switch (c = nextc()) { case '\\': return c; case 'n': return '\n'; case 't': return '\t'; case 'r': return '\r'; case 'f': return '\f'; case 'v': return '\13'; case 'a': return '\007'; case 'e': return 033; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': pushback(c); c = scan_oct(lex_p, 3, &numlen); lex_p += numlen; return c; case 'x': c = tok_hex(&numlen); if (numlen == 0) return 0; return c; case 'b': return '\010'; case 's': return ' '; case 'M': if (flags & ESCAPE_META) goto eof; if ((c = nextc()) != '-') { pushback(c); goto eof; } if ((c = nextc()) == '\\') { if (peek('u')) goto eof; return read_escape(flags|ESCAPE_META, encp) | 0x80; } else if (c == -1 || !ISASCII(c)) goto eof; else { return ((c & 0xff) | 0x80); } case 'C': if ((c = nextc()) != '-') { pushback(c); goto eof; } case 'c': if (flags & ESCAPE_CONTROL) goto eof; if ((c = nextc())== '\\') { if (peek('u')) goto eof; c = read_escape(flags|ESCAPE_CONTROL, encp); } else if (c == '?') return 0177; else if (c == -1 || !ISASCII(c)) goto eof; return c & 0x9f; eof: case -1: yyerror("Invalid escape character syntax"); return '\0'; default: return c; }}static voidparser_tokaddmbc(struct parser_params *parser, int c, rb_encoding *enc){ int len = rb_enc_codelen(c, enc); rb_enc_mbcput(c, tokspace(len), enc);}static intparser_tokadd_escape(struct parser_params *parser, rb_encoding **encp){ int c; int flags = 0; size_t numlen; first: switch (c = nextc()) { case '\n': return 0; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': { ruby_scan_oct(--lex_p, 3, &numlen); if (numlen == 0) goto eof; lex_p += numlen; tokcopy((int)numlen + 1); } return 0; case 'x': { tok_hex(&numlen); if (numlen == 0) return -1; tokcopy((int)numlen + 2); } return 0; case 'M': if (flags & ESCAPE_META) goto eof; if ((c = nextc()) != '-') { pushback(c); goto eof; } tokcopy(3); flags |= ESCAPE_META; goto escaped; case 'C': if (flags & ESCAPE_CONTROL) goto eof; if ((c = nextc()) != '-') { pushback(c); goto eof; } tokcopy(3); goto escaped; case 'c': if (flags & ESCAPE_CONTROL) goto eof; tokcopy(2); flags |= ESCAPE_CONTROL; escaped: if ((c = nextc()) == '\\') { goto first; } else if (c == -1) goto eof; tokadd(c); return 0; eof: case -1: yyerror("Invalid escape character syntax"); return -1; default: tokadd('\\'); tokadd(c); } return 0;}static intparser_regx_options(struct parser_params *parser){ int kcode = 0; int kopt = 0; int options = 0; int c, opt, kc; newtok(); while (c = nextc(), ISALPHA(c)) { if (c == 'o') { options |= RE_OPTION_ONCE; } else if (rb_char_to_option_kcode(c, &opt, &kc)) { if (kc >= 0) { if (kc != rb_ascii8bit_encindex()) kcode = c; kopt = opt; } else { options |= opt; } } else { tokadd(c); } } options |= kopt; pushback(c); if (toklen()) { tokfix(); compile_error(PARSER_ARG "unknown regexp option%s - %s", toklen() > 1 ? "s" : "", tok()); } return options | RE_OPTION_ENCODING(kcode);}static voiddispose_string(VALUE str){ rb_str_free(str); rb_gc_force_recycle(str);}static intparser_tokadd_mbchar(struct parser_params *parser, int c){ int len = parser_precise_mbclen(); if (!MBCLEN_CHARFOUND_P(len)) { compile_error(PARSER_ARG "invalid multibyte char (%s)", parser_encoding_name()); return -1; } tokadd(c); lex_p += --len; if (len > 0) tokcopy(len); return c;}#define tokadd_mbchar(c) static inline intsimple_re_meta(int c){ switch (c) { case '$': case '*': case '+': case '.': case '?': case '^': case '|': case ')': case ']': case '}': case '>': return TRUE; default: return FALSE; }}static intparser_tokadd_string(struct parser_params *parser, int func, int term, int paren, long *nest, rb_encoding **encp){ int c; int has_nonascii = 0; rb_encoding *enc = *encp; char *errbuf = 0; static const char mixed_msg[] = "%s mixed within %s source";#define mixed_error(enc1, enc2) #define mixed_escape(beg, enc1, enc2) while ((c = nextc()) != -1) { if (paren && c == paren) { ++*nest; } else if (c == term) { if (!nest || !*nest) { pushback(c); break; } --*nest; } else if ((func & STR_FUNC_EXPAND) && c == '#' && lex_p < lex_pend) { int c2 = *lex_p; if (c2 == '$' || c2 == '@' || c2 == '{') { pushback(c); break; } } else if (c == '\\') { const char *beg = lex_p - 1; c = nextc(); switch (c) { case '\n': if (func & STR_FUNC_QWORDS) break; if (func & STR_FUNC_EXPAND) continue; tokadd('\\'); break; case '\\': if (func & STR_FUNC_ESCAPE) tokadd(c); break; case 'u': if ((func & STR_FUNC_EXPAND) == 0) { tokadd('\\'); break; } parser_tokadd_utf8(parser, &enc, 1, func & STR_FUNC_SYMBOL, func & STR_FUNC_REGEXP); if (has_nonascii && enc != *encp) { mixed_escape(beg, enc, *encp); } continue; default: if (c == -1) return -1; if (!ISASCII(c)) { if ((func & STR_FUNC_EXPAND) == 0) tokadd('\\'); goto non_ascii; } if (func & STR_FUNC_REGEXP) { if (c == term && !simple_re_meta(c)) { tokadd(c); continue; } pushback(c); if ((c = tokadd_escape(&enc)) < 0) return -1; if (has_nonascii && enc != *encp) { mixed_escape(beg, enc, *encp); } continue; } else if (func & STR_FUNC_EXPAND) { pushback(c); if (func & STR_FUNC_ESCAPE) tokadd('\\'); c = read_escape(0, &enc); } else if ((func & STR_FUNC_QWORDS) && ISSPACE(c)) { } else if (c != term && !(paren && c == paren)) { tokadd('\\'); pushback(c); continue; } } } else if (!parser_isascii()) { non_ascii: has_nonascii = 1; if (enc != *encp) { mixed_error(enc, *encp); continue; } if (tokadd_mbchar(c) == -1) return -1; continue; } else if ((func & STR_FUNC_QWORDS) && ISSPACE(c)) { pushback(c); break; } if (c & 0x80) { has_nonascii = 1; if (enc != *encp) { mixed_error(enc, *encp); continue; } } tokadd(c); } *encp = enc; return c;}#define NEW_STRTERM(func, term, paren) #define flush_string_content(enc) RUBY_FUNC_EXPORTED const unsigned int ruby_global_name_punct_bits[(0x7e - 0x20 + 31) / 32];#define BIT(c, idx) #define SPECIAL_PUNCT(idx) const unsigned int ruby_global_name_punct_bits[] = { SPECIAL_PUNCT(0), SPECIAL_PUNCT(1), SPECIAL_PUNCT(2),};static inline intis_global_name_punct(const char c){ if (c <= 0x20 || 0x7e < c) return 0; return (ruby_global_name_punct_bits[(c - 0x20) / 32] >> (c % 32)) & 1;}static intparser_peek_variable_name(struct parser_params *parser){ int c; const char *p = lex_p; if (p + 1 >= lex_pend) return 0; c = *p++; switch (c) { case '$': if ((c = *p) == '-') { if (++p >= lex_pend) return 0; c = *p; } else if (is_global_name_punct(c) || ISDIGIT(c)) { return tSTRING_DVAR; } break; case '@': if ((c = *p) == '@') { if (++p >= lex_pend) return 0; c = *p; } break; case '{': lex_p = p; command_start = TRUE; return tSTRING_DBEG; default: return 0; } if (!ISASCII(c) || c == '_' || ISALPHA(c)) return tSTRING_DVAR; return 0;}static intparser_parse_string(struct parser_params *parser, NODE *quote){ int func = (int)quote->nd_func; int term = nd_term(quote); int paren = nd_paren(quote); int c, space = 0; rb_encoding *enc = current_enc; if (func == -1) return tSTRING_END; c = nextc(); if ((func & STR_FUNC_QWORDS) && ISSPACE(c)) { do {c = nextc();} while (ISSPACE(c)); space = 1; } if (c == term && !quote->nd_nest) { if (func & STR_FUNC_QWORDS) { quote->nd_func = -1; return ' '; } if (!(func & STR_FUNC_REGEXP)) return tSTRING_END; set_yylval_num(regx_options()); return tREGEXP_END; } if (space) { pushback(c); return ' '; } newtok(); if ((func & STR_FUNC_EXPAND) && c == '#') { int t = parser_peek_variable_name(parser); if (t) return t; tokadd('#'); c = nextc(); } pushback(c); if (tokadd_string(func, term, paren, &quote->nd_nest, &enc) == -1) { ruby_sourceline = nd_line(quote); if (func & STR_FUNC_REGEXP) { if (parser->eofp) compile_error(PARSER_ARG "unterminated regexp meets end of file"); return tREGEXP_END; } else { if (parser->eofp) compile_error(PARSER_ARG "unterminated string meets end of file"); return tSTRING_END; } } tokfix(); set_yylval_str(STR_NEW3(tok(), toklen(), enc, func)); flush_string_content(enc); return tSTRING_CONTENT;}static intparser_heredoc_identifier(struct parser_params *parser){ int c = nextc(), term, func = 0; long len; if (c == '-') { c = nextc(); func = STR_FUNC_INDENT; } switch (c) { case '\'': func |= str_squote; goto quoted; case '"': func |= str_dquote; goto quoted; case '`': func |= str_xquote; quoted: newtok(); tokadd(func); term = c; while ((c = nextc()) != -1 && c != term) { if (tokadd_mbchar(c) == -1) return 0; } if (c == -1) { compile_error(PARSER_ARG "unterminated here document identifier"); return 0; } break; default: if (!parser_is_identchar()) { pushback(c); if (func & STR_FUNC_INDENT) { pushback('-'); } return 0; } newtok(); term = '"'; tokadd(func |= str_dquote); do { if (tokadd_mbchar(c) == -1) return 0; } while ((c = nextc()) != -1 && parser_is_identchar()); pushback(c); break; } tokfix(); len = lex_p - lex_pbeg; lex_goto_eol(parser); lex_strterm = rb_node_newnode(NODE_HEREDOC, STR_NEW(tok(), toklen()), len, lex_lastline); nd_set_line(lex_strterm, ruby_sourceline); ripper_flush(parser); return term == '`' ? tXSTRING_BEG : tSTRING_BEG;}static voidparser_heredoc_restore(struct parser_params *parser, NODE *here){ VALUE line; line = here->nd_orig; lex_lastline = line; lex_pbeg = RSTRING_PTR(line); lex_pend = lex_pbeg + RSTRING_LEN(line); lex_p = lex_pbeg + here->nd_nth; heredoc_end = ruby_sourceline; ruby_sourceline = nd_line(here); dispose_string(here->nd_lit); rb_gc_force_recycle((VALUE)here); ripper_flush(parser);}static intparser_whole_match_p(struct parser_params *parser, const char *eos, long len, int indent){ const char *p = lex_pbeg; long n; if (indent) { while (*p && ISSPACE(*p)) p++; } n = lex_pend - (p + len); if (n < 0 || (n > 0 && p[len] != '\n' && p[len] != '\r')) return FALSE; return strncmp(eos, p, len) == 0;}#define dispatch_heredoc_end() static intparser_here_document(struct parser_params *parser, NODE *here){ int c, func, indent = 0; const char *eos, *p, *pend; long len; VALUE str = 0; rb_encoding *enc = current_enc; eos = RSTRING_PTR(here->nd_lit); len = RSTRING_LEN(here->nd_lit) - 1; indent = (func = *eos++) & STR_FUNC_INDENT; if ((c = nextc()) == -1) { error: compile_error(PARSER_ARG "can't find string \"%s\" anywhere before EOF", eos); restore: heredoc_restore(lex_strterm); lex_strterm = 0; return 0; } if (was_bol() && whole_match_p(eos, len, indent)) { dispatch_heredoc_end(); heredoc_restore(lex_strterm); return tSTRING_END; } if (!(func & STR_FUNC_EXPAND)) { do { p = RSTRING_PTR(lex_lastline); pend = lex_pend; if (pend > p) { switch (pend[-1]) { case '\n': if (--pend == p || pend[-1] != '\r') { pend++; break; } case '\r': --pend; } } if (str) rb_str_cat(str, p, pend - p); else str = STR_NEW(p, pend - p); if (pend < lex_pend) rb_str_cat(str, "\n", 1); lex_goto_eol(parser); if (nextc() == -1) { if (str) dispose_string(str); goto error; } } while (!whole_match_p(eos, len, indent)); } else { newtok(); if (c == '#') { int t = parser_peek_variable_name(parser); if (t) return t; tokadd('#'); c = nextc(); } do { pushback(c); if ((c = tokadd_string(func, '\n', 0, NULL, &enc)) == -1) { if (parser->eofp) goto error; goto restore; } if (c != '\n') { set_yylval_str(STR_NEW3(tok(), toklen(), enc, func)); flush_string_content(enc); return tSTRING_CONTENT; } tokadd(nextc()); if ((c = nextc()) == -1) goto error; } while (!whole_match_p(eos, len, indent)); str = STR_NEW3(tok(), toklen(), enc, func); } dispatch_heredoc_end(); heredoc_restore(lex_strterm); lex_strterm = NEW_STRTERM(-1, 0, 0); set_yylval_str(str); return tSTRING_CONTENT;}static voidarg_ambiguous_gen(struct parser_params *parser){ rb_warning0("ambiguous first argument; put parentheses or even spaces");}#define arg_ambiguous() static IDformal_argument_gen(struct parser_params *parser, ID lhs){ if (!is_local_id(lhs)) yyerror("formal argument must be local variable"); shadowing_lvar(lhs); return lhs;}static intlvar_defined_gen(struct parser_params *parser, ID id){ return (dyna_in_block() && dvar_defined_get(id)) || local_id(id);}static longparser_encode_length(struct parser_params *parser, const char *name, long len){ long nlen; if (len > 5 && name[nlen = len - 5] == '-') { if (rb_memcicmp(name + nlen + 1, "unix", 4) == 0) return nlen; } if (len > 4 && name[nlen = len - 4] == '-') { if (rb_memcicmp(name + nlen + 1, "dos", 3) == 0) return nlen; if (rb_memcicmp(name + nlen + 1, "mac", 3) == 0 && !(len == 8 && rb_memcicmp(name, "utf8-mac", len) == 0)) return nlen; } return len;}static voidparser_set_encode(struct parser_params *parser, const char *name){ int idx = rb_enc_find_index(name); rb_encoding *enc; VALUE excargs[3]; if (idx < 0) { excargs[1] = rb_sprintf("unknown encoding name: %s", name); error: excargs[0] = rb_eArgError; excargs[2] = rb_make_backtrace(); rb_ary_unshift(excargs[2], rb_sprintf("%s:%d", ruby_sourcefile, ruby_sourceline)); rb_exc_raise(rb_make_exception(3, excargs)); } enc = rb_enc_from_index(idx); if (!rb_enc_asciicompat(enc)) { excargs[1] = rb_sprintf("%s is not ASCII compatible", rb_enc_name(enc)); goto error; } parser->enc = enc; if (ruby_debug_lines) { long i, n = RARRAY_LEN(ruby_debug_lines); const VALUE *p = RARRAY_PTR(ruby_debug_lines); for (i = 0; i < n; ++i) { rb_enc_associate_index(*p, idx); } }}static intcomment_at_top(struct parser_params *parser){ const char *p = lex_pbeg, *pend = lex_p - 1; if (parser->line_count != (parser->has_shebang ? 2 : 1)) return 0; while (p < pend) { if (!ISSPACE(*p)) return 0; p++; } return 1;}typedef long (*rb_magic_comment_length_t)(struct parser_params *parser, const char *name, long len);typedef void (*rb_magic_comment_setter_t)(struct parser_params *parser, const char *name, const char *val);static voidmagic_comment_encoding(struct parser_params *parser, const char *name, const char *val){ if (!comment_at_top(parser)) { return; } parser_set_encode(parser, val);}static voidparser_set_token_info(struct parser_params *parser, const char *name, const char *val){ int *p = &parser->parser_token_info_enabled; switch (*val) { case 't': case 'T': if (strcasecmp(val, "true") == 0) { *p = TRUE; return; } break; case 'f': case 'F': if (strcasecmp(val, "false") == 0) { *p = FALSE; return; } break; } rb_compile_warning(ruby_sourcefile, ruby_sourceline, "invalid value for %s: %s", name, val);}struct magic_comment { const char *name; rb_magic_comment_setter_t func; rb_magic_comment_length_t length;};static const struct magic_comment magic_comments[] = { {"coding", magic_comment_encoding, parser_encode_length}, {"encoding", magic_comment_encoding, parser_encode_length}, {"warn_indent", parser_set_token_info},};static const char *magic_comment_marker(const char *str, long len){ long i = 2; while (i < len) { switch (str[i]) { case '-': if (str[i-1] == '*' && str[i-2] == '-') { return str + i + 1; } i += 2; break; case '*': if (i + 1 >= len) return 0; if (str[i+1] != '-') { i += 4; } else if (str[i-1] != '-') { i += 2; } else { return str + i + 2; } break; default: i += 3; break; } } return 0;}static intparser_magic_comment(struct parser_params *parser, const char *str, long len){ VALUE name = 0, val = 0; const char *beg, *end, *vbeg, *vend;#define str_copy(_s, _p, _n) if (len <= 7) return FALSE; if (!(beg = magic_comment_marker(str, len))) return FALSE; if (!(end = magic_comment_marker(beg, str + len - beg))) return FALSE; str = beg; len = end - beg - 3; while (len > 0) { const struct magic_comment *p = magic_comments; char *s; int i; long n = 0; for (; len > 0 && *str; str++, --len) { switch (*str) { case '\'': case '"': case ':': case ';': continue; } if (!ISSPACE(*str)) break; } for (beg = str; len > 0; str++, --len) { switch (*str) { case '\'': case '"': case ':': case ';': break; default: if (ISSPACE(*str)) break; continue; } break; } for (end = str; len > 0 && ISSPACE(*str); str++, --len); if (!len) break; if (*str != ':') continue; do str++; while (--len > 0 && ISSPACE(*str)); if (!len) break; if (*str == '"') { for (vbeg = ++str; --len > 0 && *str != '"'; str++) { if (*str == '\\') { --len; ++str; } } vend = str; if (len) { --len; ++str; } } else { for (vbeg = str; len > 0 && *str != '"' && *str != ';' && !ISSPACE(*str); --len, str++); vend = str; } while (len > 0 && (*str == ';' || ISSPACE(*str))) --len, str++; n = end - beg; str_copy(name, beg, n); s = RSTRING_PTR(name); for (i = 0; i < n; ++i) { if (s[i] == '-') s[i] = '_'; } do { if (STRNCASECMP(p->name, s, n) == 0) { n = vend - vbeg; if (p->length) { n = (*p->length)(parser, vbeg, n); } str_copy(val, vbeg, n); (*p->func)(parser, s, RSTRING_PTR(val)); break; } } while (++p < magic_comments + numberof(magic_comments)); } return TRUE;}static voidset_file_encoding(struct parser_params *parser, const char *str, const char *send){ int sep = 0; const char *beg = str; VALUE s; for (;;) { if (send - str <= 6) return; switch (str[6]) { case 'C': case 'c': str += 6; continue; case 'O': case 'o': str += 5; continue; case 'D': case 'd': str += 4; continue; case 'I': case 'i': str += 3; continue; case 'N': case 'n': str += 2; continue; case 'G': case 'g': str += 1; continue; case '=': case ':': sep = 1; str += 6; break; default: str += 6; if (ISSPACE(*str)) break; continue; } if (STRNCASECMP(str-6, "coding", 6) == 0) break; } for (;;) { do { if (++str >= send) return; } while (ISSPACE(*str)); if (sep) break; if (*str != '=' && *str != ':') return; sep = 1; str++; } beg = str; while ((*str == '-' || *str == '_' || ISALNUM(*str)) && ++str < send); s = rb_str_new(beg, parser_encode_length(parser, beg, str - beg)); parser_set_encode(parser, RSTRING_PTR(s)); rb_str_resize(s, 0);}static voidparser_prepare(struct parser_params *parser){ int c = nextc(); switch (c) { case '#': if (peek('!')) parser->has_shebang = 1; break; case 0xef: if (lex_pend - lex_p >= 2 && (unsigned char)lex_p[0] == 0xbb && (unsigned char)lex_p[1] == 0xbf) { parser->enc = rb_utf8_encoding(); lex_p += 2; lex_pbeg = lex_p; return; } break; case EOF: return; } pushback(c); parser->enc = rb_enc_get(lex_lastline);}#define IS_ARG() #define IS_END() #define IS_BEG() #define IS_SPCARG(c) #define IS_LABEL_POSSIBLE() #define IS_LABEL_SUFFIX(n) #define IS_AFTER_OPERATOR() #define ambiguous_operator(op, syn) #define warn_balanced(op, syn) static intparser_yylex(struct parser_params *parser){ register int c; int space_seen = 0; int cmd_state; enum lex_state_e last_state; rb_encoding *enc; int mb; if (lex_strterm) { int token; if (nd_type(lex_strterm) == NODE_HEREDOC) { token = here_document(lex_strterm); if (token == tSTRING_END) { lex_strterm = 0; lex_state = EXPR_END; } } else { token = parse_string(lex_strterm); if (token == tSTRING_END || token == tREGEXP_END) { rb_gc_force_recycle((VALUE)lex_strterm); lex_strterm = 0; lex_state = EXPR_END; } } return token; } cmd_state = command_start; command_start = FALSE; retry: last_state = lex_state; switch (c = nextc()) { case '\0': case '\004': case '\032': case -1: return 0; case ' ': case '\t': case '\f': case '\r': case '\13': space_seen = 1; goto retry; case '#': if (!parser_magic_comment(parser, lex_p, lex_pend - lex_p)) { if (comment_at_top(parser)) { set_file_encoding(parser, lex_p, lex_pend); } } lex_p = lex_pend; case '\n': if (IS_lex_state(EXPR_BEG | EXPR_VALUE | EXPR_CLASS | EXPR_FNAME | EXPR_DOT)) { goto retry; } while ((c = nextc())) { switch (c) { case ' ': case '\t': case '\f': case '\r': case '\13': space_seen = 1; break; case '.': { if ((c = nextc()) != '.') { pushback(c); pushback('.'); goto retry; } } default: --ruby_sourceline; lex_nextline = lex_lastline; case -1: lex_goto_eol(parser); goto normal_newline; } } normal_newline: command_start = TRUE; lex_state = EXPR_BEG; return '\n'; case '*': if ((c = nextc()) == '*') { if ((c = nextc()) == '=') { set_yylval_id(tPOW); lex_state = EXPR_BEG; return tOP_ASGN; } pushback(c); if (IS_SPCARG(c)) { rb_warning0("`**' interpreted as argument prefix"); c = tDSTAR; } else if (IS_BEG()) { c = tDSTAR; } else { warn_balanced("**", "argument prefix"); c = tPOW; } } else { if (c == '=') { set_yylval_id('*'); lex_state = EXPR_BEG; return tOP_ASGN; } pushback(c); if (IS_SPCARG(c)) { rb_warning0("`*' interpreted as argument prefix"); c = tSTAR; } else if (IS_BEG()) { c = tSTAR; } else { warn_balanced("*", "argument prefix"); c = '*'; } } lex_state = IS_AFTER_OPERATOR() ? EXPR_ARG : EXPR_BEG; return c; case '!': c = nextc(); if (IS_AFTER_OPERATOR()) { lex_state = EXPR_ARG; if (c == '@') { return '!'; } } else { lex_state = EXPR_BEG; } if (c == '=') { return tNEQ; } if (c == '~') { return tNMATCH; } pushback(c); return '!'; case '=': if (was_bol()) { if (strncmp(lex_p, "begin", 5) == 0 && ISSPACE(lex_p[5])) { for (;;) { lex_goto_eol(parser); c = nextc(); if (c == -1) { compile_error(PARSER_ARG "embedded document meets end of file"); return 0; } if (c != '=') continue; if (strncmp(lex_p, "end", 3) == 0 && (lex_p + 3 == lex_pend || ISSPACE(lex_p[3]))) { break; } } lex_goto_eol(parser); goto retry; } } lex_state = IS_AFTER_OPERATOR() ? EXPR_ARG : EXPR_BEG; if ((c = nextc()) == '=') { if ((c = nextc()) == '=') { return tEQQ; } pushback(c); return tEQ; } if (c == '~') { return tMATCH; } else if (c == '>') { return tASSOC; } pushback(c); return '='; case '<': last_state = lex_state; c = nextc(); if (c == '<' && !IS_lex_state(EXPR_DOT | EXPR_CLASS) && !IS_END() && (!IS_ARG() || space_seen)) { int token = heredoc_identifier(); if (token) return token; } if (IS_AFTER_OPERATOR()) { lex_state = EXPR_ARG; } else { if (IS_lex_state(EXPR_CLASS)) command_start = TRUE; lex_state = EXPR_BEG; } if (c == '=') { if ((c = nextc()) == '>') { return tCMP; } pushback(c); return tLEQ; } if (c == '<') { if ((c = nextc()) == '=') { set_yylval_id(tLSHFT); lex_state = EXPR_BEG; return tOP_ASGN; } pushback(c); warn_balanced("<<", "here document"); return tLSHFT; } pushback(c); return '<'; case '>': lex_state = IS_AFTER_OPERATOR() ? EXPR_ARG : EXPR_BEG; if ((c = nextc()) == '=') { return tGEQ; } if (c == '>') { if ((c = nextc()) == '=') { set_yylval_id(tRSHFT); lex_state = EXPR_BEG; return tOP_ASGN; } pushback(c); return tRSHFT; } pushback(c); return '>'; case '"': lex_strterm = NEW_STRTERM(str_dquote, '"', 0); return tSTRING_BEG; case '`': if (IS_lex_state(EXPR_FNAME)) { lex_state = EXPR_ENDFN; return c; } if (IS_lex_state(EXPR_DOT)) { if (cmd_state) lex_state = EXPR_CMDARG; else lex_state = EXPR_ARG; return c; } lex_strterm = NEW_STRTERM(str_xquote, '`', 0); return tXSTRING_BEG; case '\'': lex_strterm = NEW_STRTERM(str_squote, '\'', 0); return tSTRING_BEG; case '?': if (IS_END()) { lex_state = EXPR_VALUE; return '?'; } c = nextc(); if (c == -1) { compile_error(PARSER_ARG "incomplete character syntax"); return 0; } if (rb_enc_isspace(c, current_enc)) { if (!IS_ARG()) { int c2 = 0; switch (c) { case ' ': c2 = 's'; break; case '\n': c2 = 'n'; break; case '\t': c2 = 't'; break; case '\v': c2 = 'v'; break; case '\r': c2 = 'r'; break; case '\f': c2 = 'f'; break; } if (c2) { rb_warnI("invalid character syntax; use ?\\%c", c2); } } ternary: pushback(c); lex_state = EXPR_VALUE; return '?'; } newtok(); enc = current_enc; if (!parser_isascii()) { if (tokadd_mbchar(c) == -1) return 0; } else if ((rb_enc_isalnum(c, current_enc) || c == '_') && lex_p < lex_pend && is_identchar(lex_p, lex_pend, current_enc)) { goto ternary; } else if (c == '\\') { if (peek('u')) { nextc(); c = parser_tokadd_utf8(parser, &enc, 0, 0, 0); if (0x80 <= c) { tokaddmbc(c, enc); } else { tokadd(c); } } else if (!lex_eol_p() && !(c = *lex_p, ISASCII(c))) { nextc(); if (tokadd_mbchar(c) == -1) return 0; } else { c = read_escape(0, &enc); tokadd(c); } } else { tokadd(c); } tokfix(); set_yylval_str(STR_NEW3(tok(), toklen(), enc, 0)); lex_state = EXPR_END; return tCHAR; case '&': if ((c = nextc()) == '&') { lex_state = EXPR_BEG; if ((c = nextc()) == '=') { set_yylval_id(tANDOP); lex_state = EXPR_BEG; return tOP_ASGN; } pushback(c); return tANDOP; } else if (c == '=') { set_yylval_id('&'); lex_state = EXPR_BEG; return tOP_ASGN; } pushback(c); if (IS_SPCARG(c)) { rb_warning0("`&' interpreted as argument prefix"); c = tAMPER; } else if (IS_BEG()) { c = tAMPER; } else { warn_balanced("&", "argument prefix"); c = '&'; } lex_state = IS_AFTER_OPERATOR() ? EXPR_ARG : EXPR_BEG; return c; case '|': if ((c = nextc()) == '|') { lex_state = EXPR_BEG; if ((c = nextc()) == '=') { set_yylval_id(tOROP); lex_state = EXPR_BEG; return tOP_ASGN; } pushback(c); return tOROP; } if (c == '=') { set_yylval_id('|'); lex_state = EXPR_BEG; return tOP_ASGN; } lex_state = IS_AFTER_OPERATOR() ? EXPR_ARG : EXPR_BEG; pushback(c); return '|'; case '+': c = nextc(); if (IS_AFTER_OPERATOR()) { lex_state = EXPR_ARG; if (c == '@') { return tUPLUS; } pushback(c); return '+'; } if (c == '=') { set_yylval_id('+'); lex_state = EXPR_BEG; return tOP_ASGN; } if (IS_BEG() || (IS_SPCARG(c) && arg_ambiguous())) { lex_state = EXPR_BEG; pushback(c); if (c != -1 && ISDIGIT(c)) { c = '+'; goto start_num; } return tUPLUS; } lex_state = EXPR_BEG; pushback(c); warn_balanced("+", "unary operator"); return '+'; case '-': c = nextc(); if (IS_AFTER_OPERATOR()) { lex_state = EXPR_ARG; if (c == '@') { return tUMINUS; } pushback(c); return '-'; } if (c == '=') { set_yylval_id('-'); lex_state = EXPR_BEG; return tOP_ASGN; } if (c == '>') { lex_state = EXPR_ENDFN; return tLAMBDA; } if (IS_BEG() || (IS_SPCARG(c) && arg_ambiguous())) { lex_state = EXPR_BEG; pushback(c); if (c != -1 && ISDIGIT(c)) { return tUMINUS_NUM; } return tUMINUS; } lex_state = EXPR_BEG; pushback(c); warn_balanced("-", "unary operator"); return '-'; case '.': lex_state = EXPR_BEG; if ((c = nextc()) == '.') { if ((c = nextc()) == '.') { return tDOT3; } pushback(c); return tDOT2; } pushback(c); if (c != -1 && ISDIGIT(c)) { yyerror("no .<digit> floating literal anymore; put 0 before dot"); } lex_state = EXPR_DOT; return '.'; start_num: case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { int is_float, seen_point, seen_e, nondigit; is_float = seen_point = seen_e = nondigit = 0; lex_state = EXPR_END; newtok(); if (c == '-' || c == '+') { tokadd(c); c = nextc(); } if (c == '0') {#define no_digits() int start = toklen(); c = nextc(); if (c == 'x' || c == 'X') { c = nextc(); if (c != -1 && ISXDIGIT(c)) { do { if (c == '_') { if (nondigit) break; nondigit = c; continue; } if (!ISXDIGIT(c)) break; nondigit = 0; tokadd(c); } while ((c = nextc()) != -1); } pushback(c); tokfix(); if (toklen() == start) { no_digits(); } else if (nondigit) goto trailing_uc; set_yylval_literal(rb_cstr_to_inum(tok(), 16, FALSE)); return tINTEGER; } if (c == 'b' || c == 'B') { c = nextc(); if (c == '0' || c == '1') { do { if (c == '_') { if (nondigit) break; nondigit = c; continue; } if (c != '0' && c != '1') break; nondigit = 0; tokadd(c); } while ((c = nextc()) != -1); } pushback(c); tokfix(); if (toklen() == start) { no_digits(); } else if (nondigit) goto trailing_uc; set_yylval_literal(rb_cstr_to_inum(tok(), 2, FALSE)); return tINTEGER; } if (c == 'd' || c == 'D') { c = nextc(); if (c != -1 && ISDIGIT(c)) { do { if (c == '_') { if (nondigit) break; nondigit = c; continue; } if (!ISDIGIT(c)) break; nondigit = 0; tokadd(c); } while ((c = nextc()) != -1); } pushback(c); tokfix(); if (toklen() == start) { no_digits(); } else if (nondigit) goto trailing_uc; set_yylval_literal(rb_cstr_to_inum(tok(), 10, FALSE)); return tINTEGER; } if (c == '_') { goto octal_number; } if (c == 'o' || c == 'O') { c = nextc(); if (c == -1 || c == '_' || !ISDIGIT(c)) { no_digits(); } } if (c >= '0' && c <= '7') { octal_number: do { if (c == '_') { if (nondigit) break; nondigit = c; continue; } if (c < '0' || c > '9') break; if (c > '7') goto invalid_octal; nondigit = 0; tokadd(c); } while ((c = nextc()) != -1); if (toklen() > start) { pushback(c); tokfix(); if (nondigit) goto trailing_uc; set_yylval_literal(rb_cstr_to_inum(tok(), 8, FALSE)); return tINTEGER; } if (nondigit) { pushback(c); goto trailing_uc; } } if (c > '7' && c <= '9') { invalid_octal: yyerror("Invalid octal digit"); } else if (c == '.' || c == 'e' || c == 'E') { tokadd('0'); } else { pushback(c); set_yylval_literal(INT2FIX(0)); return tINTEGER; } } for (;;) { switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': nondigit = 0; tokadd(c); break; case '.': if (nondigit) goto trailing_uc; if (seen_point || seen_e) { goto decode_num; } else { int c0 = nextc(); if (c0 == -1 || !ISDIGIT(c0)) { pushback(c0); goto decode_num; } c = c0; } tokadd('.'); tokadd(c); is_float++; seen_point++; nondigit = 0; break; case 'e': case 'E': if (nondigit) { pushback(c); c = nondigit; goto decode_num; } if (seen_e) { goto decode_num; } tokadd(c); seen_e++; is_float++; nondigit = c; c = nextc(); if (c != '-' && c != '+') continue; tokadd(c); nondigit = c; break; case '_': if (nondigit) goto decode_num; nondigit = c; break; default: goto decode_num; } c = nextc(); } decode_num: pushback(c); if (nondigit) { char tmp[30]; trailing_uc: snprintf(tmp, sizeof(tmp), "trailing `%c' in number", nondigit); yyerror(tmp); } tokfix(); if (is_float) { double d = strtod(tok(), 0); if (errno == ERANGE) { rb_warningS("Float %s out of range", tok()); errno = 0; } set_yylval_literal(DBL2NUM(d)); return tFLOAT; } set_yylval_literal(rb_cstr_to_inum(tok(), 10, FALSE)); return tINTEGER; } case ')': case '] __pad18__

Definition at line 7572 of file parse.y.

case __pad19__

Definition at line 7574 of file parse.y.

top_stmts __pad1__ = $1

Definition at line 888 of file parse.y.

case __pad20__

Definition at line 7586 of file parse.y.

case __pad21__

Definition at line 7617 of file parse.y.

case __pad22__

Definition at line 7637 of file parse.y.

__pad23__

Definition at line 7646 of file parse.y.

__pad24__

Definition at line 7648 of file parse.y.

case __pad25__

Definition at line 7652 of file parse.y.

top_stmt __pad2__

Definition at line 921 of file parse.y.

compstmt __pad3__

Definition at line 976 of file parse.y.

stmts __pad4__ = $1

Definition at line 985 of file parse.y.

stmt_or_begin __pad5__

Definition at line 1018 of file parse.y.

command_asgn __pad6__

Definition at line 1032 of file parse.y.

expr __pad7__

Definition at line 1282 of file parse.y.

expr_value __pad8__

Definition at line 1317 of file parse.y.

command_call __pad9__

Definition at line 1324 of file parse.y.

arg

Definition at line 1312 of file parse.y.

top_stmt bodystmt = NEW_BEGIN(0)

Definition at line 938 of file parse.y.

return c

Definition at line 7583 of file parse.y.

keyword_next call_args

Initial value:
{
$$ = NEW_RETURN(ret_args($2))

Definition at line 1457 of file parse.y.

case

Definition at line 7645 of file parse.y.

primary_value tCOLON2 operation2 command_args cmd_brace_block

Initial value:
{
block_dup_check($2,$3)

Definition at line 1334 of file parse.y.

keyword_yield command_args

Initial value:
{
$$ = NEW_SUPER($2)

Definition at line 1439 of file parse.y.

command_call

Initial value:
{
$$ = call_uni_op(cond($2), '!')

Definition at line 1304 of file parse.y.

command_start = TRUE

Definition at line 7647 of file parse.y.

<num> opt_block_param compstmt

Initial value:
{
$$ = NEW_ITER($3,$4)

Definition at line 1353 of file parse.y.

fixup_nodes& deferred_nodes

Definition at line 885 of file parse.y.

else

Initial value:
{
lex_state = EXPR_BEG

Definition at line 7661 of file parse.y.

keyword_not opt_nl expr

Initial value:
{
$$ = logop(NODE_OR, $1, $3)

Definition at line 1288 of file parse.y.

keyword_BEGIN

Initial value:
{
yyerror("BEGIN is permitted only at toplevel")

Definition at line 1025 of file parse.y.

mlhs_node keyword_variable

Initial value:
{
$$ = assignable($1, 0)

Definition at line 1642 of file parse.y.

lex_state = EXPR_ENDARG

Definition at line 7579 of file parse.y.

lhs

Initial value:
=' command_asgn
{
value_expr($3);
$$ = node_assign($1, $3);
}

Definition at line 1266 of file parse.y.

mlhs_inner mlhs_basic

Definition at line 1491 of file parse.y.

mlhs_item

Initial value:
{
$$ = NEW_MASGN(list_append($1,$2), 0)

Definition at line 1513 of file parse.y.

tSTAR mlhs_node

Initial value:
{
$$ = NEW_MASGN($1, $3)

Definition at line 1521 of file parse.y.

mlhs_post

Initial value:
{
$$ = NEW_MASGN($1, NEW_POSTARG($3,$5))

Definition at line 1529 of file parse.y.

nd_args = $2

Definition at line 1378 of file parse.y.

Referenced by dump_node(), and yyparse().

nd_iter = $1

Definition at line 1388 of file parse.y.

Referenced by dump_node(), and yyparse().

pure_parser parse param

Definition at line 684 of file parse.y.

return

Definition at line 7633 of file parse.y.

error stmt

Initial value:
{
$$ = remove_begin($2)

Definition at line 1015 of file parse.y.

stmts terms stmt_or_begin

Initial value:
{
$$ = newline_node($1)

Definition at line 999 of file parse.y.

primary_value tCOLON2 operation2 command_args prec tLOWEST

Initial value:
{
$$ = NEW_CALL($1, $3, $4)

Definition at line 1397 of file parse.y.

return tOP_ASGN

Definition at line 7639 of file parse.y.

error top_stmt

Initial value:
{
$$ = newline_node($1)

Definition at line 902 of file parse.y.

case return tREGEXP_BEG

Definition at line 7617 of file parse.y.

tSTAR

Initial value:
{
$$ = NEW_MASGN($1, -1)

Definition at line 1538 of file parse.y.

return tSYMBEG

Definition at line 7613 of file parse.y.