diff options
Diffstat (limited to 'parse.y')
| -rw-r--r-- | parse.y | 3108 |
1 files changed, 1513 insertions, 1595 deletions
@@ -9,8 +9,6 @@ **********************************************************************/ -%require "3.0" - %{ #if !YYPURE @@ -78,7 +76,7 @@ syntax_error_new(void) } #endif -static NODE *reg_named_capture_assign(struct parser_params* p, VALUE regexp, const YYLTYPE *loc); +static NODE *reg_named_capture_assign(struct parser_params* p, VALUE regexp, const YYLTYPE *loc, rb_parser_assignable_func assignable); #define compile_callback rb_suppress_tracing #endif /* !UNIVERSAL_PARSER */ @@ -276,7 +274,7 @@ parse_isdigit(int c) static inline int parse_isalnum(int c) { - return parse_isalpha(c) || parse_isdigit(c); + return ISALPHA(c) || ISDIGIT(c); } #undef ISALNUM @@ -285,7 +283,7 @@ parse_isalnum(int c) static inline int parse_isxdigit(int c) { - return parse_isdigit(c) || ('A' <= c && c <= 'F') || ('a' <= c && c <= 'f'); + return ISDIGIT(c) || ('A' <= c && c <= 'F') || ('a' <= c && c <= 'f'); } #undef ISXDIGIT @@ -316,12 +314,15 @@ struct lex_context { unsigned int in_argdef: 1; unsigned int in_def: 1; unsigned int in_class: 1; + unsigned int has_trailing_semicolon: 1; BITFIELD(enum rb_parser_shareability, shareable_constant_value, 2); BITFIELD(enum rescue_context, in_rescue, 2); + unsigned int cant_return: 1; + unsigned int in_alt_pattern: 1; + unsigned int capture_in_pattern: 1; }; typedef struct RNode_DEF_TEMP rb_node_def_temp_t; -typedef struct RNode_EXITS rb_node_exits_t; #if defined(__GNUC__) && !defined(__clang__) // Suppress "parameter passing for argument of type 'struct @@ -439,6 +440,12 @@ struct local_vars { NODE *it; }; +typedef struct rb_locations_lambda_body_t { + NODE *node; + YYLTYPE opening_loc; + YYLTYPE closing_loc; +} rb_locations_lambda_body_t; + enum { ORDINAL_PARAM = -1, NO_PARAM = 0, @@ -474,7 +481,7 @@ typedef struct parser_string_buffer { parser_string_buffer_elem_t *last; } parser_string_buffer_t; -#define AFTER_HEREDOC_WITHOUT_TERMINTOR ((rb_parser_string_t *)1) +#define AFTER_HEREDOC_WITHOUT_TERMINATOR ((rb_parser_string_t *)1) /* Structure of Lexer Buffer: @@ -539,11 +546,11 @@ struct parser_params { int end_col; } delayed; - ID cur_arg; - rb_ast_t *ast; int node_id; + st_table *warn_duplicate_keys_table; + int max_numparam; ID it_id; @@ -709,10 +716,11 @@ after_pop_stack(int len, struct parser_params *p) #define VALID_SYMNAME_P(s, l, enc, type) (rb_enc_symname_type(s, l, enc, (1U<<(type))) == (int)(type)) #ifndef RIPPER -static inline bool -end_with_newline_p(struct parser_params *p, VALUE str) +static inline int +char_at_end(struct parser_params *p, VALUE str, int when_empty) { - return RSTRING_LEN(str) > 0 && RSTRING_END(str)[-1] == '\n'; + long len = RSTRING_LEN(str); + return len > 0 ? (unsigned char)RSTRING_PTR(str)[len-1] : when_empty; } #endif @@ -764,8 +772,6 @@ string_buffer_append(struct parser_params *p, rb_parser_string_t *str) buf->last->buf[buf->last->used++] = str; } -static void rb_parser_string_free(rb_parser_t *p, rb_parser_string_t *str); - static void string_buffer_free(struct parser_params *p) { @@ -964,7 +970,6 @@ parser_token2char(struct parser_params *p, enum yytokentype tok) TOKEN2CHAR(tASSOC); TOKEN2CHAR(tLPAREN); TOKEN2CHAR(tLPAREN_ARG); - TOKEN2CHAR(tRPAREN); TOKEN2CHAR(tLBRACK); TOKEN2CHAR(tLBRACE); TOKEN2CHAR(tLBRACE_ARG); @@ -1058,28 +1063,28 @@ rb_discard_node(struct parser_params *p, NODE *n) rb_ast_delete_node(p->ast, n); } -static rb_node_scope_t *rb_node_scope_new(struct parser_params *p, rb_node_args_t *nd_args, NODE *nd_body, const YYLTYPE *loc); -static rb_node_scope_t *rb_node_scope_new2(struct parser_params *p, rb_ast_id_table_t *nd_tbl, rb_node_args_t *nd_args, NODE *nd_body, const YYLTYPE *loc); +static rb_node_scope_t *rb_node_scope_new(struct parser_params *p, rb_node_args_t *nd_args, NODE *nd_body, NODE *nd_parent, const YYLTYPE *loc); +static rb_node_scope_t *rb_node_scope_new2(struct parser_params *p, rb_ast_id_table_t *nd_tbl, rb_node_args_t *nd_args, NODE *nd_body, NODE *nd_parent, const YYLTYPE *loc); static rb_node_block_t *rb_node_block_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc); -static rb_node_if_t *rb_node_if_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, NODE *nd_else, const YYLTYPE *loc); -static rb_node_unless_t *rb_node_unless_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, NODE *nd_else, const YYLTYPE *loc); -static rb_node_case_t *rb_node_case_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, const YYLTYPE *loc); -static rb_node_case2_t *rb_node_case2_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc); -static rb_node_case3_t *rb_node_case3_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, const YYLTYPE *loc); -static rb_node_when_t *rb_node_when_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc); -static rb_node_in_t *rb_node_in_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc); -static rb_node_while_t *rb_node_while_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, long nd_state, const YYLTYPE *loc); -static rb_node_until_t *rb_node_until_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, long nd_state, const YYLTYPE *loc); +static rb_node_if_t *rb_node_if_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, NODE *nd_else, const YYLTYPE *loc, const YYLTYPE* if_keyword_loc, const YYLTYPE* then_keyword_loc, const YYLTYPE* end_keyword_loc); +static rb_node_unless_t *rb_node_unless_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, NODE *nd_else, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *then_keyword_loc, const YYLTYPE *end_keyword_loc); +static rb_node_case_t *rb_node_case_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *case_keyword_loc, const YYLTYPE *end_keyword_loc); +static rb_node_case2_t *rb_node_case2_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *case_keyword_loc, const YYLTYPE *end_keyword_loc); +static rb_node_case3_t *rb_node_case3_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *case_keyword_loc, const YYLTYPE *end_keyword_loc); +static rb_node_when_t *rb_node_when_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *then_keyword_loc); +static rb_node_in_t *rb_node_in_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc, const YYLTYPE *in_keyword_loc, const YYLTYPE *then_keyword_loc, const YYLTYPE *operator_loc); +static rb_node_while_t *rb_node_while_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, long nd_state, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *closing_loc); +static rb_node_until_t *rb_node_until_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, long nd_state, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *closing_loc); static rb_node_iter_t *rb_node_iter_new(struct parser_params *p, rb_node_args_t *nd_args, NODE *nd_body, const YYLTYPE *loc); -static rb_node_for_t *rb_node_for_new(struct parser_params *p, NODE *nd_iter, NODE *nd_body, const YYLTYPE *loc); +static rb_node_for_t *rb_node_for_new(struct parser_params *p, NODE *nd_iter, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *for_keyword_loc, const YYLTYPE *in_keyword_loc, const YYLTYPE *do_keyword_loc, const YYLTYPE *end_keyword_loc); static rb_node_for_masgn_t *rb_node_for_masgn_new(struct parser_params *p, NODE *nd_var, const YYLTYPE *loc); static rb_node_retry_t *rb_node_retry_new(struct parser_params *p, const YYLTYPE *loc); static rb_node_begin_t *rb_node_begin_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc); static rb_node_rescue_t *rb_node_rescue_new(struct parser_params *p, NODE *nd_head, NODE *nd_resq, NODE *nd_else, const YYLTYPE *loc); -static rb_node_resbody_t *rb_node_resbody_new(struct parser_params *p, NODE *nd_args, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc); +static rb_node_resbody_t *rb_node_resbody_new(struct parser_params *p, NODE *nd_args, NODE *nd_exc_var, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc); static rb_node_ensure_t *rb_node_ensure_new(struct parser_params *p, NODE *nd_head, NODE *nd_ensr, const YYLTYPE *loc); -static rb_node_and_t *rb_node_and_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc); -static rb_node_or_t *rb_node_or_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc); +static rb_node_and_t *rb_node_and_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc, const YYLTYPE *operator_loc); +static rb_node_or_t *rb_node_or_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc, const YYLTYPE *operator_loc); static rb_node_masgn_t *rb_node_masgn_new(struct parser_params *p, NODE *nd_head, NODE *nd_args, const YYLTYPE *loc); static rb_node_lasgn_t *rb_node_lasgn_new(struct parser_params *p, ID nd_vid, NODE *nd_value, const YYLTYPE *loc); static rb_node_dasgn_t *rb_node_dasgn_new(struct parser_params *p, ID nd_vid, NODE *nd_value, const YYLTYPE *loc); @@ -1087,8 +1092,8 @@ static rb_node_gasgn_t *rb_node_gasgn_new(struct parser_params *p, ID nd_vid, NO static rb_node_iasgn_t *rb_node_iasgn_new(struct parser_params *p, ID nd_vid, NODE *nd_value, const YYLTYPE *loc); static rb_node_cdecl_t *rb_node_cdecl_new(struct parser_params *p, ID nd_vid, NODE *nd_value, NODE *nd_else, enum rb_parser_shareability shareability, const YYLTYPE *loc); static rb_node_cvasgn_t *rb_node_cvasgn_new(struct parser_params *p, ID nd_vid, NODE *nd_value, const YYLTYPE *loc); -static rb_node_op_asgn1_t *rb_node_op_asgn1_new(struct parser_params *p, NODE *nd_recv, ID nd_mid, NODE *index, NODE *rvalue, const YYLTYPE *loc); -static rb_node_op_asgn2_t *rb_node_op_asgn2_new(struct parser_params *p, NODE *nd_recv, NODE *nd_value, ID nd_vid, ID nd_mid, bool nd_aid, const YYLTYPE *loc); +static rb_node_op_asgn1_t *rb_node_op_asgn1_new(struct parser_params *p, NODE *nd_recv, ID nd_mid, NODE *index, NODE *rvalue, const YYLTYPE *loc, const YYLTYPE *call_operator_loc, const YYLTYPE *opening_loc, const YYLTYPE *closing_loc, const YYLTYPE *binary_operator_loc); +static rb_node_op_asgn2_t *rb_node_op_asgn2_new(struct parser_params *p, NODE *nd_recv, NODE *nd_value, ID nd_vid, ID nd_mid, bool nd_aid, const YYLTYPE *loc, const YYLTYPE *call_operator_loc, const YYLTYPE *message_loc, const YYLTYPE *binary_operator_loc); static rb_node_op_asgn_or_t *rb_node_op_asgn_or_new(struct parser_params *p, NODE *nd_head, NODE *nd_value, const YYLTYPE *loc); static rb_node_op_asgn_and_t *rb_node_op_asgn_and_new(struct parser_params *p, NODE *nd_head, NODE *nd_value, const YYLTYPE *loc); static rb_node_op_cdecl_t *rb_node_op_cdecl_new(struct parser_params *p, NODE *nd_head, NODE *nd_value, ID nd_aid, enum rb_parser_shareability shareability, const YYLTYPE *loc); @@ -1097,14 +1102,14 @@ static rb_node_opcall_t *rb_node_opcall_new(struct parser_params *p, NODE *nd_re static rb_node_fcall_t *rb_node_fcall_new(struct parser_params *p, ID nd_mid, NODE *nd_args, const YYLTYPE *loc); static rb_node_vcall_t *rb_node_vcall_new(struct parser_params *p, ID nd_mid, const YYLTYPE *loc); static rb_node_qcall_t *rb_node_qcall_new(struct parser_params *p, NODE *nd_recv, ID nd_mid, NODE *nd_args, const YYLTYPE *loc); -static rb_node_super_t *rb_node_super_new(struct parser_params *p, NODE *nd_args, const YYLTYPE *loc); +static rb_node_super_t *rb_node_super_new(struct parser_params *p, NODE *nd_args, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *lparen_loc, const YYLTYPE *rparen_loc); static rb_node_zsuper_t * rb_node_zsuper_new(struct parser_params *p, const YYLTYPE *loc); static rb_node_list_t *rb_node_list_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc); static rb_node_list_t *rb_node_list_new2(struct parser_params *p, NODE *nd_head, long nd_alen, NODE *nd_next, const YYLTYPE *loc); static rb_node_zlist_t *rb_node_zlist_new(struct parser_params *p, const YYLTYPE *loc); static rb_node_hash_t *rb_node_hash_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc); -static rb_node_return_t *rb_node_return_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc); -static rb_node_yield_t *rb_node_yield_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc); +static rb_node_return_t *rb_node_return_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc, const YYLTYPE *keyword_loc); +static rb_node_yield_t *rb_node_yield_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *lparen_loc, const YYLTYPE *rparen_loc); static rb_node_lvar_t *rb_node_lvar_new(struct parser_params *p, ID nd_vid, const YYLTYPE *loc); static rb_node_dvar_t *rb_node_dvar_new(struct parser_params *p, ID nd_vid, const YYLTYPE *loc); static rb_node_gvar_t *rb_node_gvar_new(struct parser_params *p, ID nd_vid, const YYLTYPE *loc); @@ -1124,8 +1129,8 @@ static rb_node_dstr_t *rb_node_dstr_new0(struct parser_params *p, rb_parser_stri static rb_node_dstr_t *rb_node_dstr_new(struct parser_params *p, rb_parser_string_t *string, const YYLTYPE *loc); static rb_node_xstr_t *rb_node_xstr_new(struct parser_params *p, rb_parser_string_t *string, const YYLTYPE *loc); static rb_node_dxstr_t *rb_node_dxstr_new(struct parser_params *p, rb_parser_string_t *string, long nd_alen, NODE *nd_next, const YYLTYPE *loc); -static rb_node_evstr_t *rb_node_evstr_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc); -static rb_node_regx_t *rb_node_regx_new(struct parser_params *p, rb_parser_string_t *string, int options, const YYLTYPE *loc); +static rb_node_evstr_t *rb_node_evstr_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *opening_loc, const YYLTYPE *closing_loc); +static rb_node_regx_t *rb_node_regx_new(struct parser_params *p, rb_parser_string_t *string, int options, const YYLTYPE *loc, const YYLTYPE *opening_loc, const YYLTYPE *content_loc, const YYLTYPE *closing_loc); static rb_node_once_t *rb_node_once_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc); static rb_node_args_t *rb_node_args_new(struct parser_params *p, const YYLTYPE *loc); static rb_node_args_aux_t *rb_node_args_aux_new(struct parser_params *p, ID nd_pid, int nd_plen, const YYLTYPE *loc); @@ -1134,31 +1139,31 @@ static rb_node_kw_arg_t *rb_node_kw_arg_new(struct parser_params *p, NODE *nd_bo static rb_node_postarg_t *rb_node_postarg_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc); static rb_node_argscat_t *rb_node_argscat_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, const YYLTYPE *loc); static rb_node_argspush_t *rb_node_argspush_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, const YYLTYPE *loc); -static rb_node_splat_t *rb_node_splat_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc); -static rb_node_block_pass_t *rb_node_block_pass_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc); +static rb_node_splat_t *rb_node_splat_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc, const YYLTYPE *operator_loc); +static rb_node_block_pass_t *rb_node_block_pass_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *operator_loc); static rb_node_defn_t *rb_node_defn_new(struct parser_params *p, ID nd_mid, NODE *nd_defn, const YYLTYPE *loc); static rb_node_defs_t *rb_node_defs_new(struct parser_params *p, NODE *nd_recv, ID nd_mid, NODE *nd_defn, const YYLTYPE *loc); -static rb_node_alias_t *rb_node_alias_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc); -static rb_node_valias_t *rb_node_valias_new(struct parser_params *p, ID nd_alias, ID nd_orig, const YYLTYPE *loc); +static rb_node_alias_t *rb_node_alias_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc, const YYLTYPE *keyword_loc); +static rb_node_valias_t *rb_node_valias_new(struct parser_params *p, ID nd_alias, ID nd_orig, const YYLTYPE *loc, const YYLTYPE *keyword_loc); static rb_node_undef_t *rb_node_undef_new(struct parser_params *p, NODE *nd_undef, const YYLTYPE *loc); -static rb_node_class_t *rb_node_class_new(struct parser_params *p, NODE *nd_cpath, NODE *nd_body, NODE *nd_super, const YYLTYPE *loc); -static rb_node_module_t *rb_node_module_new(struct parser_params *p, NODE *nd_cpath, NODE *nd_body, const YYLTYPE *loc); -static rb_node_sclass_t *rb_node_sclass_new(struct parser_params *p, NODE *nd_recv, NODE *nd_body, const YYLTYPE *loc); -static rb_node_colon2_t *rb_node_colon2_new(struct parser_params *p, NODE *nd_head, ID nd_mid, const YYLTYPE *loc); -static rb_node_colon3_t *rb_node_colon3_new(struct parser_params *p, ID nd_mid, const YYLTYPE *loc); -static rb_node_dot2_t *rb_node_dot2_new(struct parser_params *p, NODE *nd_beg, NODE *nd_end, const YYLTYPE *loc); -static rb_node_dot3_t *rb_node_dot3_new(struct parser_params *p, NODE *nd_beg, NODE *nd_end, const YYLTYPE *loc); +static rb_node_class_t *rb_node_class_new(struct parser_params *p, NODE *nd_cpath, NODE *nd_body, NODE *nd_super, const YYLTYPE *loc, const YYLTYPE *class_keyword_loc, const YYLTYPE *inheritance_operator_loc, const YYLTYPE *end_keyword_loc); +static rb_node_module_t *rb_node_module_new(struct parser_params *p, NODE *nd_cpath, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *module_keyword_loc, const YYLTYPE *end_keyword_loc); +static rb_node_sclass_t *rb_node_sclass_new(struct parser_params *p, NODE *nd_recv, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *class_keyword_loc, const YYLTYPE *operator_loc, const YYLTYPE *end_keyword_loc); +static rb_node_colon2_t *rb_node_colon2_new(struct parser_params *p, NODE *nd_head, ID nd_mid, const YYLTYPE *loc, const YYLTYPE *delimiter_loc, const YYLTYPE *name_loc); +static rb_node_colon3_t *rb_node_colon3_new(struct parser_params *p, ID nd_mid, const YYLTYPE *loc, const YYLTYPE *delimiter_loc, const YYLTYPE *name_loc); +static rb_node_dot2_t *rb_node_dot2_new(struct parser_params *p, NODE *nd_beg, NODE *nd_end, const YYLTYPE *loc, const YYLTYPE *operator_loc); +static rb_node_dot3_t *rb_node_dot3_new(struct parser_params *p, NODE *nd_beg, NODE *nd_end, const YYLTYPE *loc, const YYLTYPE *operator_loc); static rb_node_self_t *rb_node_self_new(struct parser_params *p, const YYLTYPE *loc); static rb_node_nil_t *rb_node_nil_new(struct parser_params *p, const YYLTYPE *loc); static rb_node_true_t *rb_node_true_new(struct parser_params *p, const YYLTYPE *loc); static rb_node_false_t *rb_node_false_new(struct parser_params *p, const YYLTYPE *loc); static rb_node_errinfo_t *rb_node_errinfo_new(struct parser_params *p, const YYLTYPE *loc); -static rb_node_defined_t *rb_node_defined_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc); -static rb_node_postexe_t *rb_node_postexe_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc); +static rb_node_defined_t *rb_node_defined_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc, const YYLTYPE *keyword_loc); +static rb_node_postexe_t *rb_node_postexe_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *opening_loc, const YYLTYPE *closing_loc); static rb_node_sym_t *rb_node_sym_new(struct parser_params *p, VALUE str, const YYLTYPE *loc); static rb_node_dsym_t *rb_node_dsym_new(struct parser_params *p, rb_parser_string_t *string, long nd_alen, NODE *nd_next, const YYLTYPE *loc); static rb_node_attrasgn_t *rb_node_attrasgn_new(struct parser_params *p, NODE *nd_recv, ID nd_mid, NODE *nd_args, const YYLTYPE *loc); -static rb_node_lambda_t *rb_node_lambda_new(struct parser_params *p, rb_node_args_t *nd_args, NODE *nd_body, const YYLTYPE *loc); +static rb_node_lambda_t *rb_node_lambda_new(struct parser_params *p, rb_node_args_t *nd_args, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *operator_loc, const YYLTYPE *opening_loc, const YYLTYPE *closing_loc); static rb_node_aryptn_t *rb_node_aryptn_new(struct parser_params *p, NODE *pre_args, NODE *rest_arg, NODE *post_args, const YYLTYPE *loc); static rb_node_hshptn_t *rb_node_hshptn_new(struct parser_params *p, NODE *nd_pconst, NODE *nd_pkwargs, NODE *nd_pkwrestarg, const YYLTYPE *loc); static rb_node_fndptn_t *rb_node_fndptn_new(struct parser_params *p, NODE *pre_rest_arg, NODE *args, NODE *post_rest_arg, const YYLTYPE *loc); @@ -1166,28 +1171,28 @@ static rb_node_line_t *rb_node_line_new(struct parser_params *p, const YYLTYPE * static rb_node_file_t *rb_node_file_new(struct parser_params *p, VALUE str, const YYLTYPE *loc); static rb_node_error_t *rb_node_error_new(struct parser_params *p, const YYLTYPE *loc); -#define NEW_SCOPE(a,b,loc) (NODE *)rb_node_scope_new(p,a,b,loc) -#define NEW_SCOPE2(t,a,b,loc) (NODE *)rb_node_scope_new2(p,t,a,b,loc) +#define NEW_SCOPE(a,b,c,loc) (NODE *)rb_node_scope_new(p,a,b,c,loc) +#define NEW_SCOPE2(t,a,b,c,loc) (NODE *)rb_node_scope_new2(p,t,a,b,c,loc) #define NEW_BLOCK(a,loc) (NODE *)rb_node_block_new(p,a,loc) -#define NEW_IF(c,t,e,loc) (NODE *)rb_node_if_new(p,c,t,e,loc) -#define NEW_UNLESS(c,t,e,loc) (NODE *)rb_node_unless_new(p,c,t,e,loc) -#define NEW_CASE(h,b,loc) (NODE *)rb_node_case_new(p,h,b,loc) -#define NEW_CASE2(b,loc) (NODE *)rb_node_case2_new(p,b,loc) -#define NEW_CASE3(h,b,loc) (NODE *)rb_node_case3_new(p,h,b,loc) -#define NEW_WHEN(c,t,e,loc) (NODE *)rb_node_when_new(p,c,t,e,loc) -#define NEW_IN(c,t,e,loc) (NODE *)rb_node_in_new(p,c,t,e,loc) -#define NEW_WHILE(c,b,n,loc) (NODE *)rb_node_while_new(p,c,b,n,loc) -#define NEW_UNTIL(c,b,n,loc) (NODE *)rb_node_until_new(p,c,b,n,loc) +#define NEW_IF(c,t,e,loc,ik_loc,tk_loc,ek_loc) (NODE *)rb_node_if_new(p,c,t,e,loc,ik_loc,tk_loc,ek_loc) +#define NEW_UNLESS(c,t,e,loc,k_loc,t_loc,e_loc) (NODE *)rb_node_unless_new(p,c,t,e,loc,k_loc,t_loc,e_loc) +#define NEW_CASE(h,b,loc,ck_loc,ek_loc) (NODE *)rb_node_case_new(p,h,b,loc,ck_loc,ek_loc) +#define NEW_CASE2(b,loc,ck_loc,ek_loc) (NODE *)rb_node_case2_new(p,b,loc,ck_loc,ek_loc) +#define NEW_CASE3(h,b,loc,ck_loc,ek_loc) (NODE *)rb_node_case3_new(p,h,b,loc,ck_loc,ek_loc) +#define NEW_WHEN(c,t,e,loc,k_loc,t_loc) (NODE *)rb_node_when_new(p,c,t,e,loc,k_loc,t_loc) +#define NEW_IN(c,t,e,loc,ik_loc,tk_loc,o_loc) (NODE *)rb_node_in_new(p,c,t,e,loc,ik_loc,tk_loc,o_loc) +#define NEW_WHILE(c,b,n,loc,k_loc,c_loc) (NODE *)rb_node_while_new(p,c,b,n,loc,k_loc,c_loc) +#define NEW_UNTIL(c,b,n,loc,k_loc,c_loc) (NODE *)rb_node_until_new(p,c,b,n,loc,k_loc,c_loc) #define NEW_ITER(a,b,loc) (NODE *)rb_node_iter_new(p,a,b,loc) -#define NEW_FOR(i,b,loc) (NODE *)rb_node_for_new(p,i,b,loc) +#define NEW_FOR(i,b,loc,f_loc,i_loc,d_loc,e_loc) (NODE *)rb_node_for_new(p,i,b,loc,f_loc,i_loc,d_loc,e_loc) #define NEW_FOR_MASGN(v,loc) (NODE *)rb_node_for_masgn_new(p,v,loc) #define NEW_RETRY(loc) (NODE *)rb_node_retry_new(p,loc) #define NEW_BEGIN(b,loc) (NODE *)rb_node_begin_new(p,b,loc) #define NEW_RESCUE(b,res,e,loc) (NODE *)rb_node_rescue_new(p,b,res,e,loc) -#define NEW_RESBODY(a,ex,n,loc) (NODE *)rb_node_resbody_new(p,a,ex,n,loc) +#define NEW_RESBODY(a,v,ex,n,loc) (NODE *)rb_node_resbody_new(p,a,v,ex,n,loc) #define NEW_ENSURE(b,en,loc) (NODE *)rb_node_ensure_new(p,b,en,loc) -#define NEW_AND(f,s,loc) (NODE *)rb_node_and_new(p,f,s,loc) -#define NEW_OR(f,s,loc) (NODE *)rb_node_or_new(p,f,s,loc) +#define NEW_AND(f,s,loc,op_loc) (NODE *)rb_node_and_new(p,f,s,loc,op_loc) +#define NEW_OR(f,s,loc,op_loc) (NODE *)rb_node_or_new(p,f,s,loc,op_loc) #define NEW_MASGN(l,r,loc) rb_node_masgn_new(p,l,r,loc) #define NEW_LASGN(v,val,loc) (NODE *)rb_node_lasgn_new(p,v,val,loc) #define NEW_DASGN(v,val,loc) (NODE *)rb_node_dasgn_new(p,v,val,loc) @@ -1195,8 +1200,8 @@ static rb_node_error_t *rb_node_error_new(struct parser_params *p, const YYLTYPE #define NEW_IASGN(v,val,loc) (NODE *)rb_node_iasgn_new(p,v,val,loc) #define NEW_CDECL(v,val,path,share,loc) (NODE *)rb_node_cdecl_new(p,v,val,path,share,loc) #define NEW_CVASGN(v,val,loc) (NODE *)rb_node_cvasgn_new(p,v,val,loc) -#define NEW_OP_ASGN1(r,id,idx,rval,loc) (NODE *)rb_node_op_asgn1_new(p,r,id,idx,rval,loc) -#define NEW_OP_ASGN2(r,t,i,o,val,loc) (NODE *)rb_node_op_asgn2_new(p,r,val,i,o,t,loc) +#define NEW_OP_ASGN1(r,id,idx,rval,loc,c_op_loc,o_loc,c_loc,b_op_loc) (NODE *)rb_node_op_asgn1_new(p,r,id,idx,rval,loc,c_op_loc,o_loc,c_loc,b_op_loc) +#define NEW_OP_ASGN2(r,t,i,o,val,loc,c_op_loc,m_loc,b_op_loc) (NODE *)rb_node_op_asgn2_new(p,r,val,i,o,t,loc,c_op_loc,m_loc,b_op_loc) #define NEW_OP_ASGN_OR(i,val,loc) (NODE *)rb_node_op_asgn_or_new(p,i,val,loc) #define NEW_OP_ASGN_AND(i,val,loc) (NODE *)rb_node_op_asgn_and_new(p,i,val,loc) #define NEW_OP_CDECL(v,op,val,share,loc) (NODE *)rb_node_op_cdecl_new(p,v,val,op,share,loc) @@ -1205,14 +1210,14 @@ static rb_node_error_t *rb_node_error_new(struct parser_params *p, const YYLTYPE #define NEW_FCALL(m,a,loc) rb_node_fcall_new(p,m,a,loc) #define NEW_VCALL(m,loc) (NODE *)rb_node_vcall_new(p,m,loc) #define NEW_QCALL0(r,m,a,loc) (NODE *)rb_node_qcall_new(p,r,m,a,loc) -#define NEW_SUPER(a,loc) (NODE *)rb_node_super_new(p,a,loc) +#define NEW_SUPER(a,loc,k_loc,l_loc,r_loc) (NODE *)rb_node_super_new(p,a,loc,k_loc,l_loc,r_loc) #define NEW_ZSUPER(loc) (NODE *)rb_node_zsuper_new(p,loc) #define NEW_LIST(a,loc) (NODE *)rb_node_list_new(p,a,loc) #define NEW_LIST2(h,l,n,loc) (NODE *)rb_node_list_new2(p,h,l,n,loc) #define NEW_ZLIST(loc) (NODE *)rb_node_zlist_new(p,loc) #define NEW_HASH(a,loc) (NODE *)rb_node_hash_new(p,a,loc) -#define NEW_RETURN(s,loc) (NODE *)rb_node_return_new(p,s,loc) -#define NEW_YIELD(a,loc) (NODE *)rb_node_yield_new(p,a,loc) +#define NEW_RETURN(s,loc,k_loc) (NODE *)rb_node_return_new(p,s,loc,k_loc) +#define NEW_YIELD(a,loc,k_loc,l_loc,r_loc) (NODE *)rb_node_yield_new(p,a,loc,k_loc,l_loc,r_loc) #define NEW_LVAR(v,loc) (NODE *)rb_node_lvar_new(p,v,loc) #define NEW_DVAR(v,loc) (NODE *)rb_node_dvar_new(p,v,loc) #define NEW_GVAR(v,loc) (NODE *)rb_node_gvar_new(p,v,loc) @@ -1232,8 +1237,8 @@ static rb_node_error_t *rb_node_error_new(struct parser_params *p, const YYLTYPE #define NEW_DSTR(s,loc) (NODE *)rb_node_dstr_new(p,s,loc) #define NEW_XSTR(s,loc) (NODE *)rb_node_xstr_new(p,s,loc) #define NEW_DXSTR(s,l,n,loc) (NODE *)rb_node_dxstr_new(p,s,l,n,loc) -#define NEW_EVSTR(n,loc) (NODE *)rb_node_evstr_new(p,n,loc) -#define NEW_REGX(str,opts,loc) (NODE *)rb_node_regx_new(p,str,opts,loc) +#define NEW_EVSTR(n,loc,o_loc,c_loc) (NODE *)rb_node_evstr_new(p,n,loc,o_loc,c_loc) +#define NEW_REGX(str,opts,loc,o_loc,ct_loc,c_loc) (NODE *)rb_node_regx_new(p,str,opts,loc,o_loc,ct_loc,c_loc) #define NEW_ONCE(b,loc) (NODE *)rb_node_once_new(p,b,loc) #define NEW_ARGS(loc) rb_node_args_new(p,loc) #define NEW_ARGS_AUX(r,b,loc) rb_node_args_aux_new(p,r,b,loc) @@ -1242,31 +1247,31 @@ static rb_node_error_t *rb_node_error_new(struct parser_params *p, const YYLTYPE #define NEW_POSTARG(i,v,loc) (NODE *)rb_node_postarg_new(p,i,v,loc) #define NEW_ARGSCAT(a,b,loc) (NODE *)rb_node_argscat_new(p,a,b,loc) #define NEW_ARGSPUSH(a,b,loc) (NODE *)rb_node_argspush_new(p,a,b,loc) -#define NEW_SPLAT(a,loc) (NODE *)rb_node_splat_new(p,a,loc) -#define NEW_BLOCK_PASS(b,loc) rb_node_block_pass_new(p,b,loc) +#define NEW_SPLAT(a,loc,op_loc) (NODE *)rb_node_splat_new(p,a,loc,op_loc) +#define NEW_BLOCK_PASS(b,loc,o_loc) rb_node_block_pass_new(p,b,loc,o_loc) #define NEW_DEFN(i,s,loc) (NODE *)rb_node_defn_new(p,i,s,loc) #define NEW_DEFS(r,i,s,loc) (NODE *)rb_node_defs_new(p,r,i,s,loc) -#define NEW_ALIAS(n,o,loc) (NODE *)rb_node_alias_new(p,n,o,loc) -#define NEW_VALIAS(n,o,loc) (NODE *)rb_node_valias_new(p,n,o,loc) +#define NEW_ALIAS(n,o,loc,k_loc) (NODE *)rb_node_alias_new(p,n,o,loc,k_loc) +#define NEW_VALIAS(n,o,loc,k_loc) (NODE *)rb_node_valias_new(p,n,o,loc,k_loc) #define NEW_UNDEF(i,loc) (NODE *)rb_node_undef_new(p,i,loc) -#define NEW_CLASS(n,b,s,loc) (NODE *)rb_node_class_new(p,n,b,s,loc) -#define NEW_MODULE(n,b,loc) (NODE *)rb_node_module_new(p,n,b,loc) -#define NEW_SCLASS(r,b,loc) (NODE *)rb_node_sclass_new(p,r,b,loc) -#define NEW_COLON2(c,i,loc) (NODE *)rb_node_colon2_new(p,c,i,loc) -#define NEW_COLON3(i,loc) (NODE *)rb_node_colon3_new(p,i,loc) -#define NEW_DOT2(b,e,loc) (NODE *)rb_node_dot2_new(p,b,e,loc) -#define NEW_DOT3(b,e,loc) (NODE *)rb_node_dot3_new(p,b,e,loc) +#define NEW_CLASS(n,b,s,loc,ck_loc,io_loc,ek_loc) (NODE *)rb_node_class_new(p,n,b,s,loc,ck_loc,io_loc,ek_loc) +#define NEW_MODULE(n,b,loc,mk_loc,ek_loc) (NODE *)rb_node_module_new(p,n,b,loc,mk_loc,ek_loc) +#define NEW_SCLASS(r,b,loc,ck_loc,op_loc,ek_loc) (NODE *)rb_node_sclass_new(p,r,b,loc,ck_loc,op_loc,ek_loc) +#define NEW_COLON2(c,i,loc,d_loc,n_loc) (NODE *)rb_node_colon2_new(p,c,i,loc,d_loc,n_loc) +#define NEW_COLON3(i,loc,d_loc,n_loc) (NODE *)rb_node_colon3_new(p,i,loc,d_loc,n_loc) +#define NEW_DOT2(b,e,loc,op_loc) (NODE *)rb_node_dot2_new(p,b,e,loc,op_loc) +#define NEW_DOT3(b,e,loc,op_loc) (NODE *)rb_node_dot3_new(p,b,e,loc,op_loc) #define NEW_SELF(loc) (NODE *)rb_node_self_new(p,loc) #define NEW_NIL(loc) (NODE *)rb_node_nil_new(p,loc) #define NEW_TRUE(loc) (NODE *)rb_node_true_new(p,loc) #define NEW_FALSE(loc) (NODE *)rb_node_false_new(p,loc) #define NEW_ERRINFO(loc) (NODE *)rb_node_errinfo_new(p,loc) -#define NEW_DEFINED(e,loc) (NODE *)rb_node_defined_new(p,e,loc) -#define NEW_POSTEXE(b,loc) (NODE *)rb_node_postexe_new(p,b,loc) +#define NEW_DEFINED(e,loc,k_loc) (NODE *)rb_node_defined_new(p,e,loc, k_loc) +#define NEW_POSTEXE(b,loc,k_loc,o_loc,c_loc) (NODE *)rb_node_postexe_new(p,b,loc,k_loc,o_loc,c_loc) #define NEW_SYM(str,loc) (NODE *)rb_node_sym_new(p,str,loc) #define NEW_DSYM(s,l,n,loc) (NODE *)rb_node_dsym_new(p,s,l,n,loc) #define NEW_ATTRASGN(r,m,a,loc) (NODE *)rb_node_attrasgn_new(p,r,m,a,loc) -#define NEW_LAMBDA(a,b,loc) (NODE *)rb_node_lambda_new(p,a,b,loc) +#define NEW_LAMBDA(a,b,loc,op_loc,o_loc,c_loc) (NODE *)rb_node_lambda_new(p,a,b,loc,op_loc,o_loc,c_loc) #define NEW_ARYPTN(pre,r,post,loc) (NODE *)rb_node_aryptn_new(p,pre,r,post,loc) #define NEW_HSHPTN(c,kw,kwrest,loc) (NODE *)rb_node_hshptn_new(p,c,kw,kwrest,loc) #define NEW_FNDPTN(pre,a,post,loc) (NODE *)rb_node_fndptn_new(p,pre,a,post,loc) @@ -1305,7 +1310,6 @@ struct RNode_DEF_TEMP { ID nd_mid; struct { - ID cur_arg; int max_numparam; NODE *numparam_save; struct lex_context ctxt; @@ -1314,15 +1318,15 @@ struct RNode_DEF_TEMP { #define RNODE_DEF_TEMP(node) ((struct RNode_DEF_TEMP *)(node)) -static rb_node_break_t *rb_node_break_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc); -static rb_node_next_t *rb_node_next_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc); -static rb_node_redo_t *rb_node_redo_new(struct parser_params *p, const YYLTYPE *loc); +static rb_node_break_t *rb_node_break_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc, const YYLTYPE *keyword_loc); +static rb_node_next_t *rb_node_next_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc, const YYLTYPE *keyword_loc); +static rb_node_redo_t *rb_node_redo_new(struct parser_params *p, const YYLTYPE *loc, const YYLTYPE *keyword_loc); static rb_node_def_temp_t *rb_node_def_temp_new(struct parser_params *p, const YYLTYPE *loc); static rb_node_def_temp_t *def_head_save(struct parser_params *p, rb_node_def_temp_t *n); -#define NEW_BREAK(s,loc) (NODE *)rb_node_break_new(p,s,loc) -#define NEW_NEXT(s,loc) (NODE *)rb_node_next_new(p,s,loc) -#define NEW_REDO(loc) (NODE *)rb_node_redo_new(p,loc) +#define NEW_BREAK(s,loc,k_loc) (NODE *)rb_node_break_new(p,s,loc,k_loc) +#define NEW_NEXT(s,loc,k_loc) (NODE *)rb_node_next_new(p,s,loc,k_loc) +#define NEW_REDO(loc,k_loc) (NODE *)rb_node_redo_new(p,loc,k_loc) #define NEW_DEF_TEMP(loc) rb_node_def_temp_new(p,loc) /* Make a new internal node, which should not be appeared in the @@ -1389,19 +1393,17 @@ last_expr_node(NODE *expr) static NODE* cond(struct parser_params *p, NODE *node, const YYLTYPE *loc); static NODE* method_cond(struct parser_params *p, NODE *node, const YYLTYPE *loc); -#define new_nil(loc) NEW_NIL(loc) static NODE *new_nil_at(struct parser_params *p, const rb_code_position_t *pos); -static NODE *new_if(struct parser_params*,NODE*,NODE*,NODE*,const YYLTYPE*); -static NODE *new_unless(struct parser_params*,NODE*,NODE*,NODE*,const YYLTYPE*); +static NODE *new_if(struct parser_params*,NODE*,NODE*,NODE*,const YYLTYPE*,const YYLTYPE*,const YYLTYPE*,const YYLTYPE*); +static NODE *new_unless(struct parser_params*,NODE*,NODE*,NODE*,const YYLTYPE*,const YYLTYPE*,const YYLTYPE*,const YYLTYPE*); static NODE *logop(struct parser_params*,ID,NODE*,NODE*,const YYLTYPE*,const YYLTYPE*); static NODE *newline_node(NODE*); static void fixpos(NODE*,NODE*); -static int value_expr_gen(struct parser_params*,NODE*); +static int value_expr(struct parser_params*,NODE*); static void void_expr(struct parser_params*,NODE*); static NODE *remove_begin(NODE*); -#define value_expr(node) value_expr_gen(p, (node)) static NODE *void_stmts(struct parser_params*,NODE*); static void reduce_nodes(struct parser_params*,NODE**); static void block_dup_check(struct parser_params*,NODE*,NODE*); @@ -1413,7 +1415,7 @@ static NODE *arg_append(struct parser_params*,NODE*,NODE*,const YYLTYPE*); static NODE *last_arg_append(struct parser_params *p, NODE *args, NODE *last_arg, const YYLTYPE *loc); static NODE *rest_arg_append(struct parser_params *p, NODE *args, NODE *rest_arg, const YYLTYPE *loc); static NODE *literal_concat(struct parser_params*,NODE*,NODE*,const YYLTYPE*); -static NODE *new_evstr(struct parser_params*,NODE*,const YYLTYPE*); +static NODE *new_evstr(struct parser_params*,NODE*,const YYLTYPE*,const YYLTYPE*,const YYLTYPE*); static NODE *new_dstr(struct parser_params*,NODE*,const YYLTYPE*); static NODE *str2dstr(struct parser_params*,NODE*); static NODE *evstr2dstr(struct parser_params*,NODE*); @@ -1440,9 +1442,9 @@ static rb_node_kw_arg_t *new_kw_arg(struct parser_params *p, NODE *k, const YYLT static rb_node_args_t *args_with_numbered(struct parser_params*,rb_node_args_t*,int,ID); static NODE* negate_lit(struct parser_params*, NODE*); +static void no_blockarg(struct parser_params*,NODE*); static NODE *ret_args(struct parser_params*,NODE*); static NODE *arg_blk_pass(NODE*,rb_node_block_pass_t*); -static NODE *new_yield(struct parser_params*,NODE*,const YYLTYPE*); static NODE *dsym_node(struct parser_params*,NODE*,const YYLTYPE*); static NODE *gettable(struct parser_params*,ID,const YYLTYPE*); @@ -1451,12 +1453,12 @@ static NODE *assignable(struct parser_params*,ID,NODE*,const YYLTYPE*); static NODE *aryset(struct parser_params*,NODE*,NODE*,const YYLTYPE*); static NODE *attrset(struct parser_params*,NODE*,ID,ID,const YYLTYPE*); -static void rb_backref_error(struct parser_params*,NODE*); +static VALUE rb_backref_error(struct parser_params*,NODE*); static NODE *node_assign(struct parser_params*,NODE*,NODE*,struct lex_context,const YYLTYPE*); static NODE *new_op_assign(struct parser_params *p, NODE *lhs, ID op, NODE *rhs, struct lex_context, const YYLTYPE *loc); -static NODE *new_ary_op_assign(struct parser_params *p, NODE *ary, NODE *args, ID op, NODE *rhs, const YYLTYPE *args_loc, const YYLTYPE *loc); -static NODE *new_attr_op_assign(struct parser_params *p, NODE *lhs, ID atype, ID attr, ID op, NODE *rhs, const YYLTYPE *loc); +static NODE *new_ary_op_assign(struct parser_params *p, NODE *ary, NODE *args, ID op, NODE *rhs, const YYLTYPE *args_loc, const YYLTYPE *loc, const YYLTYPE *call_operator_loc, const YYLTYPE *opening_loc, const YYLTYPE *closing_loc, const YYLTYPE *binary_operator_loc); +static NODE *new_attr_op_assign(struct parser_params *p, NODE *lhs, ID atype, ID attr, ID op, NODE *rhs, const YYLTYPE *loc, const YYLTYPE *call_operator_loc, const YYLTYPE *message_loc, const YYLTYPE *binary_operator_loc); static NODE *new_const_op_assign(struct parser_params *p, NODE *lhs, ID op, NODE *rhs, struct lex_context, const YYLTYPE *loc); static NODE *new_bodystmt(struct parser_params *p, NODE *head, NODE *rescue, NODE *rescue_else, NODE *ensure, const YYLTYPE *loc); @@ -1468,9 +1470,9 @@ static rb_node_kw_arg_t *kwd_append(rb_node_kw_arg_t*, rb_node_kw_arg_t*); static NODE *new_hash(struct parser_params *p, NODE *hash, const YYLTYPE *loc); static NODE *new_unique_key_hash(struct parser_params *p, NODE *hash, const YYLTYPE *loc); -static NODE *new_defined(struct parser_params *p, NODE *expr, const YYLTYPE *loc); +static NODE *new_defined(struct parser_params *p, NODE *expr, const YYLTYPE *loc, const YYLTYPE *keyword_loc); -static NODE *new_regexp(struct parser_params *, NODE *, int, const YYLTYPE *); +static NODE *new_regexp(struct parser_params *, NODE *, int, const YYLTYPE *, const YYLTYPE *, const YYLTYPE *, const YYLTYPE *); #define make_list(list, loc) ((list) ? (nd_set_loc(list, loc), list) : NEW_ZLIST(loc)) @@ -1484,18 +1486,17 @@ static rb_ast_id_table_t *local_tbl(struct parser_params*); static VALUE reg_compile(struct parser_params*, rb_parser_string_t*, int); static void reg_fragment_setenc(struct parser_params*, rb_parser_string_t*, int); -#define reg_fragment_check rb_parser_reg_fragment_check -int reg_fragment_check(struct parser_params*, rb_parser_string_t*, int); static int literal_concat0(struct parser_params *p, rb_parser_string_t *head, rb_parser_string_t *tail); static NODE *heredoc_dedent(struct parser_params*,NODE*); static void check_literal_when(struct parser_params *p, NODE *args, const YYLTYPE *loc); +static rb_locations_lambda_body_t* new_locations_lambda_body(struct parser_params *p, NODE *node, const YYLTYPE *loc, const YYLTYPE *opening_loc, const YYLTYPE *closing_loc); + #ifdef RIPPER #define get_value(idx) (rb_ary_entry(p->s_value_stack, idx)) #define set_value(val) (p->s_lvalue = val) -static VALUE backref_error(struct parser_params*, NODE *, VALUE); static VALUE assign_error(struct parser_params *p, const char *mesg, VALUE a); static int id_is_var(struct parser_params *p, ID id); #endif @@ -1516,9 +1517,10 @@ YYLTYPE *rb_parser_set_location(struct parser_params *p, YYLTYPE *yylloc); void ruby_show_error_line(struct parser_params *p, VALUE errbuf, const YYLTYPE *yylloc, int lineno, rb_parser_string_t *str); RUBY_SYMBOL_EXPORT_END +static void flush_string_content(struct parser_params *p, rb_encoding *enc, size_t back); static void error_duplicate_pattern_variable(struct parser_params *p, ID id, const YYLTYPE *loc); static void error_duplicate_pattern_key(struct parser_params *p, ID id, const YYLTYPE *loc); -static ID formal_argument(struct parser_params*, ID); +static VALUE formal_argument_error(struct parser_params*, ID); static ID shadowing_lvar(struct parser_params*,ID); static void new_bv(struct parser_params*,ID); @@ -1572,7 +1574,7 @@ static void numparam_pop(struct parser_params *p, NODE *prev_inner); #define CASE_LABELS_ENABLED_P(case_labels) (case_labels && case_labels != CHECK_LITERAL_WHEN) #define yytnamerr(yyres, yystr) (YYSIZE_T)rb_yytnamerr(p, yyres, yystr) -size_t rb_yytnamerr(struct parser_params *p, char *yyres, const char *yystr); +RUBY_FUNC_EXPORTED size_t rb_yytnamerr(struct parser_params *p, char *yyres, const char *yystr); #define TOKEN2ID(tok) ( \ tTOKEN_LOCAL_BEGIN<(tok)&&(tok)<tTOKEN_LOCAL_END ? TOKEN2LOCALID(tok) : \ @@ -1601,18 +1603,16 @@ static VALUE ripper_dispatch5(struct parser_params*,ID,VALUE,VALUE,VALUE,VALUE,V static VALUE ripper_dispatch7(struct parser_params*,ID,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE); void ripper_error(struct parser_params *p); -#define dispatch0(n) ripper_dispatch0(p, TOKEN_PASTE(ripper_id_, n)) -#define dispatch1(n,a) ripper_dispatch1(p, TOKEN_PASTE(ripper_id_, n), (a)) -#define dispatch2(n,a,b) ripper_dispatch2(p, TOKEN_PASTE(ripper_id_, n), (a), (b)) -#define dispatch3(n,a,b,c) ripper_dispatch3(p, TOKEN_PASTE(ripper_id_, n), (a), (b), (c)) -#define dispatch4(n,a,b,c,d) ripper_dispatch4(p, TOKEN_PASTE(ripper_id_, n), (a), (b), (c), (d)) -#define dispatch5(n,a,b,c,d,e) ripper_dispatch5(p, TOKEN_PASTE(ripper_id_, n), (a), (b), (c), (d), (e)) -#define dispatch7(n,a,b,c,d,e,f,g) ripper_dispatch7(p, TOKEN_PASTE(ripper_id_, n), (a), (b), (c), (d), (e), (f), (g)) +#define dispatch0(n) ripper_dispatch0(p, RIPPER_ID(n)) +#define dispatch1(n,a) ripper_dispatch1(p, RIPPER_ID(n), (a)) +#define dispatch2(n,a,b) ripper_dispatch2(p, RIPPER_ID(n), (a), (b)) +#define dispatch3(n,a,b,c) ripper_dispatch3(p, RIPPER_ID(n), (a), (b), (c)) +#define dispatch4(n,a,b,c,d) ripper_dispatch4(p, RIPPER_ID(n), (a), (b), (c), (d)) +#define dispatch5(n,a,b,c,d,e) ripper_dispatch5(p, RIPPER_ID(n), (a), (b), (c), (d), (e)) +#define dispatch7(n,a,b,c,d,e,f,g) ripper_dispatch7(p, RIPPER_ID(n), (a), (b), (c), (d), (e), (f), (g)) #define yyparse ripper_yyparse -static VALUE ripper_formal_argument(struct parser_params *p, ID id, VALUE lhs); - static VALUE aryptn_pre_args(struct parser_params *p, VALUE pre_arg, VALUE pre_args) { @@ -1634,11 +1634,11 @@ aryptn_pre_args(struct parser_params *p, VALUE pre_arg, VALUE pre_args) #define KWD2EID(t, v) keyword_##t static NODE * -new_scope_body(struct parser_params *p, rb_node_args_t *args, NODE *body, const YYLTYPE *loc) +new_scope_body(struct parser_params *p, rb_node_args_t *args, NODE *body, NODE *parent, const YYLTYPE *loc) { body = remove_begin(body); reduce_nodes(p, &body); - NODE *n = NEW_SCOPE(args, body, loc); + NODE *n = NEW_SCOPE(args, body, parent, loc); nd_set_line(n, loc->end_pos.lineno); set_line_body(body, loc->beg_pos.lineno); return n; @@ -1649,7 +1649,7 @@ rescued_expr(struct parser_params *p, NODE *arg, NODE *rescue, const YYLTYPE *arg_loc, const YYLTYPE *mod_loc, const YYLTYPE *res_loc) { YYLTYPE loc = code_loc_gen(mod_loc, res_loc); - rescue = NEW_RESBODY(0, remove_begin(rescue), 0, &loc); + rescue = NEW_RESBODY(0, 0, remove_begin(rescue), 0, &loc); loc.beg_pos = arg_loc->beg_pos; return NEW_RESCUE(arg, rescue, 0, &loc); } @@ -1671,7 +1671,6 @@ restore_defun(struct parser_params *p, rb_node_def_temp_t *temp) { /* See: def_name action */ struct lex_context ctxt = temp->save.ctxt; - p->cur_arg = temp->save.cur_arg; p->ctxt.in_def = ctxt.in_def; p->ctxt.shareable_constant_value = ctxt.shareable_constant_value; p->ctxt.in_rescue = ctxt.in_rescue; @@ -1702,12 +1701,17 @@ endless_method_name(struct parser_params *p, ID mid, const YYLTYPE *loc) #define begin_definition(k, loc_beg, loc_end) \ do { \ if (!(p->ctxt.in_class = (k)[0] != 0)) { \ + /* singleton class */ \ + p->ctxt.cant_return = !p->ctxt.in_def; \ p->ctxt.in_def = 0; \ } \ else if (p->ctxt.in_def) { \ YYLTYPE loc = code_loc_gen(loc_beg, loc_end); \ yyerror1(&loc, k " definition in method body"); \ } \ + else { \ + p->ctxt.cant_return = 1; \ + } \ local_push(p, 0); \ } while (0) @@ -1747,7 +1751,6 @@ extern const ID id_warn, id_warning, id_gets, id_assoc; # define WARN_I(i) INT2NUM(i) # define WARN_ID(i) rb_id2str(i) # define PRIsWARN PRIsVALUE -# define rb_warn0L_experimental(l,fmt) WARN_CALL(WARN_ARGS_L(l, fmt, 1)) # define WARN_ARGS(fmt,n) p->value, id_warn, n, rb_usascii_str_new_lit(fmt) # define WARN_ARGS_L(l,fmt,n) WARN_ARGS(fmt,n) # ifdef HAVE_VA_ARGS_MACRO @@ -1772,7 +1775,6 @@ extern const ID id_warn, id_warning, id_gets, id_assoc; # define WARN_ARGS(fmt,n) WARN_ARGS_L(p->ruby_sourceline,fmt,n) # define WARN_ARGS_L(l,fmt,n) p->ruby_sourcefile, (l), (fmt) # define WARN_CALL rb_compile_warn -# define rb_warn0L_experimental(l,fmt) rb_category_compile_warn(RB_WARN_CATEGORY_EXPERIMENTAL, WARN_ARGS_L(l, fmt, 1)) # define WARNING_ARGS(fmt,n) WARN_ARGS(fmt,n) # define WARNING_ARGS_L(l,fmt,n) WARN_ARGS_L(l,fmt,n) # define WARNING_CALL rb_compile_warning @@ -1780,13 +1782,6 @@ PRINTF_ARGS(static void parser_compile_error(struct parser_params*, const rb_cod # define compile_error(p, ...) parser_compile_error(p, NULL, __VA_ARGS__) #endif -struct RNode_EXITS { - NODE node; - - NODE *nd_chain; /* Assume NODE_BREAK, NODE_NEXT, NODE_REDO have nd_chain here */ - NODE *nd_end; -}; - #define RNODE_EXITS(node) ((rb_node_exits_t*)(node)) static NODE * @@ -1799,14 +1794,14 @@ add_block_exit(struct parser_params *p, NODE *node) switch (nd_type(node)) { case NODE_BREAK: case NODE_NEXT: case NODE_REDO: break; default: - compile_error(p, "unexpected node: %s", parser_node_name(nd_type(node))); + compile_error(p, "add_block_exit: unexpected node: %s", parser_node_name(nd_type(node))); return node; } if (!p->ctxt.in_defined) { rb_node_exits_t *exits = p->exits; if (exits) { - RNODE_EXITS(exits->nd_end)->nd_chain = node; - exits->nd_end = node; + RNODE_EXITS(exits->nd_stts)->nd_chain = node; + exits->nd_stts = node; } } return node; @@ -1818,7 +1813,7 @@ init_block_exit(struct parser_params *p) rb_node_exits_t *old = p->exits; rb_node_exits_t *exits = NODE_NEW_INTERNAL(NODE_EXITS, rb_node_exits_t); exits->nd_chain = 0; - exits->nd_end = RNODE(exits); + exits->nd_stts = RNODE(exits); p->exits = exits; return old; } @@ -1842,7 +1837,7 @@ clear_block_exit(struct parser_params *p, bool error) { rb_node_exits_t *exits = p->exits; if (!exits) return; - if (error && !compile_for_eval) { + if (error) { for (NODE *e = RNODE(exits); (e = RNODE_EXITS(e)->nd_chain) != 0; ) { switch (nd_type(e)) { case NODE_BREAK: @@ -1861,7 +1856,7 @@ clear_block_exit(struct parser_params *p, bool error) } end_checks:; } - exits->nd_end = RNODE(exits); + exits->nd_stts = RNODE(exits); exits->nd_chain = 0; } @@ -1890,7 +1885,7 @@ get_nd_value(struct parser_params *p, NODE *node) case NODE_CDECL: return RNODE_CDECL(node)->nd_value; default: - compile_error(p, "unexpected node: %s", parser_node_name(nd_type(node))); + compile_error(p, "get_nd_value: unexpected node: %s", parser_node_name(nd_type(node))); return 0; } } @@ -1921,7 +1916,7 @@ set_nd_value(struct parser_params *p, NODE *node, NODE *rhs) RNODE_CVASGN(node)->nd_value = rhs; break; default: - compile_error(p, "unexpected node: %s", parser_node_name(nd_type(node))); + compile_error(p, "set_nd_value: unexpected node: %s", parser_node_name(nd_type(node))); break; } } @@ -1943,7 +1938,7 @@ get_nd_vid(struct parser_params *p, NODE *node) case NODE_CVASGN: return RNODE_CVASGN(node)->nd_vid; default: - compile_error(p, "unexpected node: %s", parser_node_name(nd_type(node))); + compile_error(p, "get_nd_vid: unexpected node: %s", parser_node_name(nd_type(node))); return 0; } } @@ -1970,7 +1965,7 @@ get_nd_args(struct parser_params *p, NODE *node) case NODE_NEXT: return 0; default: - compile_error(p, "unexpected node: %s", parser_node_name(nd_type(node))); + compile_error(p, "get_nd_args: unexpected node: %s", parser_node_name(nd_type(node))); return 0; } } @@ -2010,10 +2005,10 @@ parser_memhash(const void *ptr, long len) ((ptrvar) = str->ptr, \ (lenvar) = str->len) -static inline bool -parser_string_end_with_newline_p(struct parser_params *p, rb_parser_string_t *str) +static inline int +parser_string_char_at_end(struct parser_params *p, rb_parser_string_t *str, int when_empty) { - return PARSER_STRING_LEN(str) > 0 && PARSER_STRING_END(str)[-1] == '\n'; + return PARSER_STRING_LEN(str) > 0 ? (unsigned char)PARSER_STRING_END(str)[-1] : when_empty; } static rb_parser_string_t * @@ -2054,15 +2049,15 @@ rb_str_to_parser_string(rb_parser_t *p, VALUE str) RB_GC_GUARD(str); return ret; } -#endif -static void +void rb_parser_string_free(rb_parser_t *p, rb_parser_string_t *str) { if (!str) return; xfree(PARSER_STRING_PTR(str)); xfree(str); } +#endif static st_index_t rb_parser_str_hash(rb_parser_string_t *str) @@ -2209,8 +2204,7 @@ rb_parser_enc_associate(struct parser_params *p, rb_parser_string_t *str, rb_enc { if (rb_parser_str_get_encoding(str) == enc) return str; - if (!PARSER_ENC_CODERANGE_ASCIIONLY(str) || - !rb_enc_asciicompat(enc)) { + if (!PARSER_ENC_CODERANGE_ASCIIONLY(str)) { PARSER_ENC_CODERANGE_CLEAR(str); } rb_parser_string_set_encoding(str, enc); @@ -2223,30 +2217,25 @@ rb_parser_is_ascii_string(struct parser_params *p, rb_parser_string_t *str) return rb_parser_enc_str_coderange(p, str) == RB_PARSER_ENC_CODERANGE_7BIT; } -static int -rb_parser_enc_str_asciionly_p(struct parser_params *p, rb_parser_string_t *str) +static rb_encoding * +rb_parser_enc_compatible(struct parser_params *p, rb_parser_string_t *str1, rb_parser_string_t *str2) { - rb_encoding *enc = rb_parser_str_get_encoding(str); + rb_encoding *enc1 = rb_parser_str_get_encoding(str1); + rb_encoding *enc2 = rb_parser_str_get_encoding(str2); - if (!rb_enc_asciicompat(enc)) - return FALSE; - else if (rb_parser_is_ascii_string(p, str)) - return TRUE; - return FALSE; -} + if (enc1 == NULL || enc2 == NULL) + return 0; -static rb_encoding * -rb_parser_enc_compatible_latter(struct parser_params *p, rb_parser_string_t *str1, rb_parser_string_t *str2, rb_encoding *enc1, rb_encoding *enc2) -{ - int cr1, cr2; + if (enc1 == enc2) { + return enc1; + } if (PARSER_STRING_LEN(str2) == 0) return enc1; if (PARSER_STRING_LEN(str1) == 0) - return (rb_enc_asciicompat(enc1) && rb_parser_enc_str_asciionly_p(p, str2)) ? enc1 : enc2; - if (!rb_enc_asciicompat(enc1) || !rb_enc_asciicompat(enc2)) { - return 0; - } + return rb_parser_is_ascii_string(p, str2) ? enc1 : enc2; + + int cr1, cr2; cr1 = rb_parser_enc_str_coderange(p, str1); cr2 = rb_parser_enc_str_coderange(p, str2); @@ -2267,22 +2256,6 @@ rb_parser_enc_compatible_latter(struct parser_params *p, rb_parser_string_t *str return 0; } -static rb_encoding * -rb_parser_enc_compatible(struct parser_params *p, rb_parser_string_t *str1, rb_parser_string_t *str2) -{ - rb_encoding *enc1 = rb_parser_str_get_encoding(str1); - rb_encoding *enc2 = rb_parser_str_get_encoding(str2); - - if (enc1 == NULL || enc2 == NULL) - return 0; - - if (enc1 == enc2) { - return enc1; - } - - return rb_parser_enc_compatible_latter(p, str1, str2, enc1, enc2); -} - static void rb_parser_str_modify(rb_parser_string_t *str) { @@ -2350,6 +2323,9 @@ rb_parser_str_buf_cat(struct parser_params *p, rb_parser_string_t *str, const ch return str; } +#define parser_str_cat(str, ptr, len) rb_parser_str_buf_cat(p, str, ptr, len) +#define parser_str_cat_cstr(str, lit) rb_parser_str_buf_cat(p, str, lit, strlen(lit)) + static rb_parser_string_t * rb_parser_enc_cr_str_buf_cat(struct parser_params *p, rb_parser_string_t *str, const char *ptr, long len, rb_encoding *ptr_enc, int ptr_cr, int *ptr_cr_ret) @@ -2415,7 +2391,7 @@ rb_parser_enc_cr_str_buf_cat(struct parser_params *p, rb_parser_string_t *str, c if (len < 0) { compile_error(p, "negative string size (or size too big)"); } - rb_parser_str_buf_cat(p, str, ptr, len); + parser_str_cat(str, ptr, len); PARSER_ENCODING_CODERANGE_SET(str, res_enc, res_cr); return str; @@ -2493,7 +2469,6 @@ rb_parser_string_hash_cmp(rb_parser_string_t *str1, rb_parser_string_t *str2) memcmp(ptr1, ptr2, len1) != 0); } -#ifndef RIPPER static void rb_parser_ary_extend(rb_parser_t *p, rb_parser_ary_t *ary, long len) { @@ -2509,7 +2484,7 @@ rb_parser_ary_extend(rb_parser_t *p, rb_parser_ary_t *ary, long len) /* * Do not call this directly. - * Use rb_parser_ary_new_capa_for_script_line() or rb_parser_ary_new_capa_for_ast_token() instead. + * Use rb_parser_ary_new_capa_for_XXX() instead. */ static rb_parser_ary_t * parser_ary_new_capa(rb_parser_t *p, long len) @@ -2518,6 +2493,7 @@ parser_ary_new_capa(rb_parser_t *p, long len) rb_bug("negative array size (or size too big): %ld", len); } rb_parser_ary_t *ary = xcalloc(1, sizeof(rb_parser_ary_t)); + ary->data_type = 0; ary->len = 0; ary->capa = len; if (0 < len) { @@ -2529,6 +2505,7 @@ parser_ary_new_capa(rb_parser_t *p, long len) return ary; } +#ifndef RIPPER static rb_parser_ary_t * rb_parser_ary_new_capa_for_script_line(rb_parser_t *p, long len) { @@ -2544,10 +2521,19 @@ rb_parser_ary_new_capa_for_ast_token(rb_parser_t *p, long len) ary->data_type = PARSER_ARY_DATA_AST_TOKEN; return ary; } +#endif + +static rb_parser_ary_t * +rb_parser_ary_new_capa_for_node(rb_parser_t *p, long len) +{ + rb_parser_ary_t *ary = parser_ary_new_capa(p, len); + ary->data_type = PARSER_ARY_DATA_NODE; + return ary; +} /* * Do not call this directly. - * Use rb_parser_ary_push_script_line() or rb_parser_ary_push_ast_token() instead. + * Use rb_parser_ary_push_XXX() instead. */ static rb_parser_ary_t * parser_ary_push(rb_parser_t *p, rb_parser_ary_t *ary, rb_parser_ary_data val) @@ -2559,6 +2545,7 @@ parser_ary_push(rb_parser_t *p, rb_parser_ary_t *ary, rb_parser_ary_data val) return ary; } +#ifndef RIPPER static rb_parser_ary_t * rb_parser_ary_push_ast_token(rb_parser_t *p, rb_parser_ary_t *ary, rb_parser_ast_token_t *val) { @@ -2576,7 +2563,18 @@ rb_parser_ary_push_script_line(rb_parser_t *p, rb_parser_ary_t *ary, rb_parser_s } return parser_ary_push(p, ary, val); } +#endif + +static rb_parser_ary_t * +rb_parser_ary_push_node(rb_parser_t *p, rb_parser_ary_t *ary, NODE *val) +{ + if (ary->data_type != PARSER_ARY_DATA_NODE) { + rb_bug("unexpected rb_parser_ary_data_type: %d", ary->data_type); + } + return parser_ary_push(p, ary, val); +} +#ifndef RIPPER static void rb_parser_ast_token_free(rb_parser_t *p, rb_parser_ast_token_t *token) { @@ -2598,11 +2596,15 @@ rb_parser_ary_free(rb_parser_t *p, rb_parser_ary_t *ary) case PARSER_ARY_DATA_SCRIPT_LINE: foreach_ary(data) {rb_parser_string_free(p, *data);} break; + case PARSER_ARY_DATA_NODE: + /* Do nothing because nodes are freed when rb_ast_t is freed */ + break; default: rb_bug("unexpected rb_parser_ary_data_type: %d", ary->data_type); break; } # undef foreach_ary + xfree(ary->data); xfree(ary); } @@ -2676,6 +2678,7 @@ rb_parser_ary_free(rb_parser_t *p, rb_parser_ary_t *ary) rb_node_masgn_t *node_masgn; rb_node_def_temp_t *node_def_temp; rb_node_exits_t *node_exits; + struct rb_locations_lambda_body_t *locations_lambda_body; ID id; int num; st_table *tbl; @@ -2755,14 +2758,15 @@ rb_parser_ary_free(rb_parser_t *p, rb_parser_ary_t *ary) %token <num> tREGEXP_END %token <num> tDUMNY_END "dummy end" -%type <node> singleton strings string string1 xstring regexp +%type <node> singleton singleton_expr strings string string1 xstring regexp %type <node> string_contents xstring_contents regexp_contents string_content %type <node> words symbols symbol_list qwords qsymbols word_list qword_list qsym_list word %type <node> literal numeric simple_numeric ssym dsym symbol cpath %type <node_def_temp> defn_head defs_head k_def %type <node_exits> block_open k_while k_until k_for allow_exits -%type <node> top_compstmt top_stmts top_stmt begin_block endless_arg endless_command -%type <node> bodystmt compstmt stmts stmt_or_begin stmt expr arg primary command command_call method_call +%type <node> top_stmts top_stmt begin_block endless_arg endless_command +%type <node> bodystmt stmts stmt_or_begin stmt expr arg ternary primary +%type <node> command command_call command_call_value method_call %type <node> expr_value expr_value_do arg_value primary_value rel_expr %type <node_fcall> fcall %type <node> if_tail opt_else case_body case_args cases opt_rescue exc_list exc_var opt_ensure @@ -2776,23 +2780,23 @@ rb_parser_ary_free(rb_parser_t *p, rb_parser_ary_t *ary) %type <node> command_asgn mrhs mrhs_arg superclass block_call block_command %type <node_args> f_arglist f_opt_paren_args f_paren_args f_args %type <node_args_aux> f_arg f_arg_item -%type <node> f_marg f_marg_list f_rest_marg +%type <node> f_marg f_rest_marg %type <node_masgn> f_margs %type <node> assoc_list assocs assoc undef_list backref string_dvar for_var -%type <node_args> block_param opt_block_param block_param_def -%type <node_kw_arg> f_kw f_block_kw -%type <id> bv_decls opt_bv_decl bvar -%type <node> lambda lambda_body brace_body do_body +%type <node_args> block_param opt_block_param_def block_param_def opt_block_param +%type <id> do bv_decls opt_bv_decl bvar +%type <node> lambda brace_body do_body +%type <locations_lambda_body> lambda_body %type <node_args> f_larglist %type <node> brace_block cmd_brace_block do_block lhs none fitem -%type <node> mlhs_head mlhs_item mlhs_node mlhs_post +%type <node> mlhs_head mlhs_item mlhs_node %type <node_masgn> mlhs mlhs_basic mlhs_inner %type <node> p_case_body p_cases p_top_expr p_top_expr_body %type <node> p_expr p_as p_alt p_expr_basic p_find %type <node> p_args p_args_head p_args_tail p_args_post p_arg p_rest %type <node> p_value p_primitive p_variable p_var_ref p_expr_ref p_const %type <node> p_kwargs p_kwarg p_kw -%type <id> keyword_variable user_variable sym operation operation2 operation3 +%type <id> keyword_variable user_variable sym operation2 operation3 %type <id> cname fname op f_rest_arg f_block_arg opt_f_block_arg f_norm_arg f_bad_arg %type <id> f_kwrest f_label f_arg_asgn call_op call_op2 reswords relop dot_or_colon %type <id> p_kwrest p_kwnorest p_any_kwrest p_kw_label @@ -2841,7 +2845,6 @@ rb_parser_ary_free(rb_parser_t *p, rb_parser_ary_t *ary) %token tASSOC "=>" %token tLPAREN "(" %token tLPAREN_ARG "( arg" -%token tRPAREN ")" %token tLBRACK "[" %token tLBRACE "{" %token tLBRACE_ARG "{ arg" @@ -2896,59 +2899,262 @@ rb_parser_ary_free(rb_parser_t *p, rb_parser_ary_t *ary) %token tLAST_TOKEN /* + * inlining rules + */ +%rule %inline ident_or_const + : tIDENTIFIER + | tCONSTANT + ; + +%rule %inline user_or_keyword_variable + : user_variable + | keyword_variable + ; + +/* * parameterizing rules */ -%rule f_opt(value) <node_opt_arg>: f_arg_asgn f_eq value - { - p->cur_arg = 0; - p->ctxt.in_argdef = 1; - $$ = NEW_OPT_ARG(assignable(p, $1, $3, &@$), &@$); - /*% ripper: [$:$, $:3] %*/ - } - ; - -%rule f_optarg(value) <node_opt_arg>: f_opt(value) - { - $$ = $1; - /*% ripper: rb_ary_new3(1, $:1) %*/ - } - | f_optarg(value) ',' f_opt(value) - { - $$ = opt_arg_append($1, $3); - /*% ripper: rb_ary_push($:1, $:3) %*/ - } - ; - -%rule f_kwarg(kw) <node_kw_arg>: kw - { - $$ = $1; - /*% ripper: rb_ary_new3(1, $:1) %*/ - } - | f_kwarg(kw) ',' kw - { - $$ = kwd_append($1, $3); - /*% ripper: rb_ary_push($:1, $:3) %*/ - } - ; - -%rule opt_args_tail(tail) <node_args>: ',' tail - { - $$ = $2; - /*% ripper: $:2 %*/ - } - | /* none */ - { - $$ = new_args_tail(p, 0, 0, 0, &@0); - /*% ripper: [Qnil, Qnil, Qnil] %*/ - } - ; - -%rule words(begin, word_list): begin ' '+ word_list tSTRING_END - { - $$ = make_list($3, &@$); - /*% ripper: array!($:3) %*/ - } - ; +%rule asgn(rhs) <node> + : lhs '=' lex_ctxt rhs + { + $$ = node_assign(p, (NODE *)$lhs, $rhs, $lex_ctxt, &@$); + /*% ripper: assign!($:1, $:4) %*/ + } + ; + +%rule args_tail_basic(value) <node_args> + : f_kwarg(value) ',' f_kwrest opt_f_block_arg + { + $$ = new_args_tail(p, $1, $3, $4, &@3); + /*% ripper: [$:1, $:3, $:4] %*/ + } + | f_kwarg(value) opt_f_block_arg + { + $$ = new_args_tail(p, $1, 0, $2, &@1); + /*% ripper: [$:1, Qnil, $:2] %*/ + } + | f_any_kwrest opt_f_block_arg + { + $$ = new_args_tail(p, 0, $1, $2, &@1); + /*% ripper: [Qnil, $:1, $:2] %*/ + } + | f_block_arg + { + $$ = new_args_tail(p, 0, 0, $1, &@1); + /*% ripper: [Qnil, Qnil, $:1] %*/ + } + ; + +%rule def_endless_method(bodystmt) <node> + : defn_head[head] f_opt_paren_args[args] '=' bodystmt + { + endless_method_name(p, $head->nd_mid, &@head); + restore_defun(p, $head); + ($$ = $head->nd_def)->nd_loc = @$; + $bodystmt = new_scope_body(p, $args, $bodystmt, $$, &@$); + RNODE_DEFN($$)->nd_defn = $bodystmt; + /*% ripper: bodystmt!($:bodystmt, Qnil, Qnil, Qnil) %*/ + /*% ripper: def!($:head, $:args, $:$) %*/ + local_pop(p); + } + | defs_head[head] f_opt_paren_args[args] '=' bodystmt + { + endless_method_name(p, $head->nd_mid, &@head); + restore_defun(p, $head); + ($$ = $head->nd_def)->nd_loc = @$; + $bodystmt = new_scope_body(p, $args, $bodystmt, $$, &@$); + RNODE_DEFS($$)->nd_defn = $bodystmt; + /*% ripper: bodystmt!($:bodystmt, Qnil, Qnil, Qnil) %*/ + /*% ripper: defs!(*$:head[0..2], $:args, $:$) %*/ + local_pop(p); + } + ; + +%rule compstmt(stmts) <node> + : stmts terms? + { + void_stmts(p, $$ = $stmts); + } + ; + +%rule f_opt(value) <node_opt_arg> + : f_arg_asgn f_eq value + { + p->ctxt.in_argdef = 1; + $$ = NEW_OPT_ARG(assignable(p, $f_arg_asgn, $value, &@$), &@$); + /*% ripper: [$:$, $:3] %*/ + } + ; + +%rule f_opt_arg(value) <node_opt_arg> + : f_opt(value) + { + $$ = $f_opt; + /*% ripper: rb_ary_new3(1, $:1) %*/ + } + | f_opt_arg(value) ',' f_opt(value) + { + $$ = opt_arg_append($f_opt_arg, $f_opt); + /*% ripper: rb_ary_push($:1, $:3) %*/ + } + ; + +%rule f_kw(value) <node_kw_arg> + : f_label value + { + p->ctxt.in_argdef = 1; + $$ = new_kw_arg(p, assignable(p, $f_label, $value, &@$), &@$); + /*% ripper: [$:$, $:value] %*/ + } + | f_label + { + p->ctxt.in_argdef = 1; + $$ = new_kw_arg(p, assignable(p, $f_label, NODE_SPECIAL_REQUIRED_KEYWORD, &@$), &@$); + /*% ripper: [$:$, 0] %*/ + } + ; + +%rule f_kwarg(value) <node_kw_arg> + : f_kw(value) + { + $$ = $f_kw; + /*% ripper: rb_ary_new3(1, $:1) %*/ + } + | f_kwarg(value) ',' f_kw(value) + { + $$ = kwd_append($f_kwarg, $f_kw); + /*% ripper: rb_ary_push($:1, $:3) %*/ + } + ; + +%rule mlhs_items(item) <node> + : item + { + $$ = NEW_LIST($1, &@$); + /*% ripper: mlhs_add!(mlhs_new!, $:1) %*/ + } + | mlhs_items(item) ',' item + { + $$ = list_append(p, $1, $3); + /*% ripper: mlhs_add!($:1, $:3) %*/ + } + ; + +%rule op_asgn(rhs) <node> + : var_lhs tOP_ASGN lex_ctxt rhs + { + $$ = new_op_assign(p, $var_lhs, $tOP_ASGN, $rhs, $lex_ctxt, &@$); + /*% ripper: opassign!($:1, $:2, $:4) %*/ + } + | primary_value '['[lbracket] opt_call_args rbracket tOP_ASGN lex_ctxt rhs + { + $$ = new_ary_op_assign(p, $primary_value, $opt_call_args, $tOP_ASGN, $rhs, &@opt_call_args, &@$, &NULL_LOC, &@lbracket, &@rbracket, &@tOP_ASGN); + /*% ripper: opassign!(aref_field!($:1, $:3), $:5, $:7) %*/ + } + | primary_value call_op tIDENTIFIER tOP_ASGN lex_ctxt rhs + { + $$ = new_attr_op_assign(p, $primary_value, $call_op, $tIDENTIFIER, $tOP_ASGN, $rhs, &@$, &@call_op, &@tIDENTIFIER, &@tOP_ASGN); + /*% ripper: opassign!(field!($:1, $:2, $:3), $:4, $:6) %*/ + } + | primary_value call_op tCONSTANT tOP_ASGN lex_ctxt rhs + { + $$ = new_attr_op_assign(p, $primary_value, $call_op, $tCONSTANT, $tOP_ASGN, $rhs, &@$, &@call_op, &@tCONSTANT, &@tOP_ASGN); + /*% ripper: opassign!(field!($:1, $:2, $:3), $:4, $:6) %*/ + } + | primary_value tCOLON2 tIDENTIFIER tOP_ASGN lex_ctxt rhs + { + $$ = new_attr_op_assign(p, $primary_value, idCOLON2, $tIDENTIFIER, $tOP_ASGN, $rhs, &@$, &@tCOLON2, &@tIDENTIFIER, &@tOP_ASGN); + /*% ripper: opassign!(field!($:1, $:2, $:3), $:4, $:6) %*/ + } + | primary_value tCOLON2 tCONSTANT tOP_ASGN lex_ctxt rhs + { + YYLTYPE loc = code_loc_gen(&@primary_value, &@tCONSTANT); + $$ = new_const_op_assign(p, NEW_COLON2($primary_value, $tCONSTANT, &loc, &@tCOLON2, &@tCONSTANT), $tOP_ASGN, $rhs, $lex_ctxt, &@$); + /*% ripper: opassign!(const_path_field!($:1, $:3), $:4, $:6) %*/ + } + | tCOLON3 tCONSTANT tOP_ASGN lex_ctxt rhs + { + YYLTYPE loc = code_loc_gen(&@tCOLON3, &@tCONSTANT); + $$ = new_const_op_assign(p, NEW_COLON3($tCONSTANT, &loc, &@tCOLON3, &@tCONSTANT), $tOP_ASGN, $rhs, $lex_ctxt, &@$); + /*% ripper: opassign!(top_const_field!($:2), $:3, $:5) %*/ + } + | backref tOP_ASGN lex_ctxt rhs + { + VALUE MAYBE_UNUSED(e) = rb_backref_error(p, $backref); + $$ = NEW_ERROR(&@$); + /*% ripper[error]: assign_error!(?e, opassign!(var_field!($:1), $:2, $:4)) %*/ + } + ; + +%rule opt_args_tail(tail) <node_args> + : ',' tail + { + $$ = $tail; + /*% ripper: $:2 %*/ + } + | /* none */ + { + $$ = new_args_tail(p, 0, 0, 0, &@0); + /*% ripper: [Qnil, Qnil, Qnil] %*/ + } + ; + +%rule range_expr(range) <node> + : range tDOT2 range + { + value_expr(p, $1); + value_expr(p, $3); + $$ = NEW_DOT2($1, $3, &@$, &@2); + /*% ripper: dot2!($:1, $:3) %*/ + } + | range tDOT3 range + { + value_expr(p, $1); + value_expr(p, $3); + $$ = NEW_DOT3($1, $3, &@$, &@2); + /*% ripper: dot3!($:1, $:3) %*/ + } + | range tDOT2 + { + value_expr(p, $1); + $$ = NEW_DOT2($1, new_nil_at(p, &@2.end_pos), &@$, &@2); + /*% ripper: dot2!($:1, Qnil) %*/ + } + | range tDOT3 + { + value_expr(p, $1); + $$ = NEW_DOT3($1, new_nil_at(p, &@2.end_pos), &@$, &@2); + /*% ripper: dot3!($:1, Qnil) %*/ + } + | tBDOT2 range + { + value_expr(p, $2); + $$ = NEW_DOT2(new_nil_at(p, &@1.beg_pos), $2, &@$, &@1); + /*% ripper: dot2!(Qnil, $:2) %*/ + } + | tBDOT3 range + { + value_expr(p, $2); + $$ = NEW_DOT3(new_nil_at(p, &@1.beg_pos), $2, &@$, &@1); + /*% ripper: dot3!(Qnil, $:2) %*/ + } + ; + +%rule value_expr(value) <node> + : value + { + value_expr(p, $1); + $$ = $1; + } + ; + +%rule words(begin, word_list) <node> + : begin ' '+ word_list tSTRING_END + { + $$ = make_list($word_list, &@$); + /*% ripper: array!($:3) %*/ + } + ; %% program : { @@ -2957,7 +3163,7 @@ program : { /* jumps are possible in the top-level loop. */ if (!ifndef_ripper(p->do_loop) + 0) init_block_exit(p); } - top_compstmt + compstmt(top_stmts) { if ($2 && !compile_for_eval) { NODE *node = $2; @@ -2971,18 +3177,12 @@ program : { node = remove_begin(node); void_expr(p, node); } - p->eval_tree = NEW_SCOPE(0, block_append(p, p->eval_tree, $2), &@$); + p->eval_tree = NEW_SCOPE(0, block_append(p, p->eval_tree, $2), NULL, &@$); /*% ripper[final]: program!($:2) %*/ local_pop(p); } ; -top_compstmt : top_stmts terms? - { - $$ = void_stmts(p, $1); - } - ; - top_stmts : none { $$ = NEW_BEGIN(0, &@$); @@ -3014,7 +3214,7 @@ top_stmt : stmt block_open : '{' {$$ = init_block_exit(p);}; -begin_block : block_open top_compstmt '}' +begin_block : block_open compstmt(top_stmts) '}' { restore_block_exit(p, $block_open); p->eval_tree_begin = block_append(p, p->eval_tree_begin, @@ -3024,7 +3224,7 @@ begin_block : block_open top_compstmt '}' } ; -bodystmt : compstmt[body] +bodystmt : compstmt(stmts)[body] lex_ctxt[ctxt] opt_rescue k_else @@ -3032,7 +3232,7 @@ bodystmt : compstmt[body] if (!$opt_rescue) yyerror1(&@k_else, "else without rescue is useless"); next_rescue_context(&p->ctxt, &$ctxt, after_else); } - compstmt[elsebody] + compstmt(stmts)[elsebody] { next_rescue_context(&p->ctxt, &$ctxt, after_ensure); } @@ -3041,7 +3241,7 @@ bodystmt : compstmt[body] $$ = new_bodystmt(p, $body, $opt_rescue, $elsebody, $opt_ensure, &@$); /*% ripper: bodystmt!($:body, $:opt_rescue, $:elsebody, $:opt_ensure) %*/ } - | compstmt[body] + | compstmt(stmts)[body] lex_ctxt[ctxt] opt_rescue { @@ -3054,12 +3254,6 @@ bodystmt : compstmt[body] } ; -compstmt : stmts terms? - { - $$ = void_stmts(p, $1); - } - ; - stmts : none { $$ = NEW_BEGIN(0, &@$); @@ -3078,9 +3272,6 @@ stmts : none ; stmt_or_begin : stmt - { - $$ = $1; - } | keyword_BEGIN { yyerror1(&@1, "BEGIN is permitted only at toplevel"); @@ -3102,12 +3293,12 @@ k_END : keyword_END lex_ctxt stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem { - $$ = NEW_ALIAS($2, $4, &@$); + $$ = NEW_ALIAS($2, $4, &@$, &@1); /*% ripper: alias!($:2, $:4) %*/ } | keyword_alias tGVAR tGVAR { - $$ = NEW_VALIAS($2, $3, &@$); + $$ = NEW_VALIAS($2, $3, &@$, &@1); /*% ripper: var_alias!($:2, $:3) %*/ } | keyword_alias tGVAR tBACK_REF @@ -3115,7 +3306,7 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem char buf[2]; buf[0] = '$'; buf[1] = (char)RNODE_BACK_REF($3)->nd_nth; - $$ = NEW_VALIAS($2, rb_intern2(buf, 2), &@$); + $$ = NEW_VALIAS($2, rb_intern2(buf, 2), &@$, &@1); /*% ripper: var_alias!($:2, $:3) %*/ } | keyword_alias tGVAR tNTH_REF @@ -3129,18 +3320,20 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem } | keyword_undef undef_list { + nd_set_first_loc($2, @1.beg_pos); + RNODE_UNDEF($2)->keyword_loc = @1; $$ = $2; /*% ripper: undef!($:2) %*/ } | stmt modifier_if expr_value { - $$ = new_if(p, $3, remove_begin($1), 0, &@$); + $$ = new_if(p, $3, remove_begin($1), 0, &@$, &@2, &NULL_LOC, &NULL_LOC); fixpos($$, $3); /*% ripper: if_mod!($:3, $:1) %*/ } | stmt modifier_unless expr_value { - $$ = new_unless(p, $3, remove_begin($1), 0, &@$); + $$ = new_unless(p, $3, remove_begin($1), 0, &@$, &@2, &NULL_LOC, &NULL_LOC); fixpos($$, $3); /*% ripper: unless_mod!($:3, $:1) %*/ } @@ -3148,10 +3341,10 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem { clear_block_exit(p, false); if ($1 && nd_type_p($1, NODE_BEGIN)) { - $$ = NEW_WHILE(cond(p, $3, &@3), RNODE_BEGIN($1)->nd_body, 0, &@$); + $$ = NEW_WHILE(cond(p, $3, &@3), RNODE_BEGIN($1)->nd_body, 0, &@$, &@2, &NULL_LOC); } else { - $$ = NEW_WHILE(cond(p, $3, &@3), $1, 1, &@$); + $$ = NEW_WHILE(cond(p, $3, &@3), $1, 1, &@$, &@2, &NULL_LOC); } /*% ripper: while_mod!($:3, $:1) %*/ } @@ -3159,10 +3352,10 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem { clear_block_exit(p, false); if ($1 && nd_type_p($1, NODE_BEGIN)) { - $$ = NEW_UNTIL(cond(p, $3, &@3), RNODE_BEGIN($1)->nd_body, 0, &@$); + $$ = NEW_UNTIL(cond(p, $3, &@3), RNODE_BEGIN($1)->nd_body, 0, &@$, &@2, &NULL_LOC); } else { - $$ = NEW_UNTIL(cond(p, $3, &@3), $1, 1, &@$); + $$ = NEW_UNTIL(cond(p, $3, &@3), $1, 1, &@$, &@2, &NULL_LOC); } /*% ripper: until_mod!($:3, $:1) %*/ } @@ -3171,11 +3364,11 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem p->ctxt.in_rescue = $3.in_rescue; NODE *resq; YYLTYPE loc = code_loc_gen(&@2, &@4); - resq = NEW_RESBODY(0, remove_begin($4), 0, &loc); + resq = NEW_RESBODY(0, 0, remove_begin($4), 0, &loc); $$ = NEW_RESCUE(remove_begin($1), resq, 0, &@$); /*% ripper: rescue_mod!($:1, $:4) %*/ } - | k_END allow_exits '{' compstmt '}' + | k_END allow_exits '{' compstmt(stmts) '}' { if (p->ctxt.in_def) { rb_warn0("END in method; use at_exit"); @@ -3183,29 +3376,25 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem restore_block_exit(p, $allow_exits); p->ctxt = $k_END; { - NODE *scope = NEW_SCOPE2(0 /* tbl */, 0 /* args */, $compstmt /* body */, &@$); - $$ = NEW_POSTEXE(scope, &@$); + NODE *scope = NEW_SCOPE2(0 /* tbl */, 0 /* args */, $compstmt /* body */, NULL /* parent */, &@$); + $$ = NEW_POSTEXE(scope, &@$, &@1, &@3, &@5); + RNODE_SCOPE(scope)->nd_parent = $$; } /*% ripper: END!($:compstmt) %*/ } | command_asgn - | mlhs '=' lex_ctxt command_call + | mlhs '=' lex_ctxt command_call_value { - value_expr($4); $$ = node_assign(p, (NODE *)$1, $4, $3, &@$); /*% ripper: massign!($:1, $:4) %*/ } - | lhs '=' lex_ctxt mrhs - { - $$ = node_assign(p, $1, $4, $3, &@$); - /*% ripper: assign!($:1, $:4) %*/ - } + | asgn(mrhs) | mlhs '=' lex_ctxt mrhs_arg modifier_rescue after_rescue stmt[resbody] { p->ctxt.in_rescue = $3.in_rescue; YYLTYPE loc = code_loc_gen(&@modifier_rescue, &@resbody); - $resbody = NEW_RESBODY(0, remove_begin($resbody), 0, &loc); + $resbody = NEW_RESBODY(0, 0, remove_begin($resbody), 0, &loc); loc.beg_pos = @mrhs_arg.beg_pos; $mrhs_arg = NEW_RESCUE($mrhs_arg, $resbody, 0, &loc); $$ = node_assign(p, (NODE *)$mlhs, $mrhs_arg, $lex_ctxt, &@$); @@ -3224,73 +3413,9 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem } ; -command_asgn : lhs '=' lex_ctxt command_rhs - { - $$ = node_assign(p, $1, $4, $3, &@$); - /*% ripper: assign!($:1, $:4) %*/ - } - | var_lhs tOP_ASGN lex_ctxt command_rhs - { - $$ = new_op_assign(p, $1, $2, $4, $3, &@$); - /*% ripper: opassign!($:1, $:2, $:4) %*/ - } - | primary_value '[' opt_call_args rbracket tOP_ASGN lex_ctxt command_rhs - { - $$ = new_ary_op_assign(p, $1, $3, $5, $7, &@3, &@$); - /*% ripper: opassign!(aref_field!($:1, $:3), $:5, $:7) %*/ - - } - | primary_value call_op tIDENTIFIER tOP_ASGN lex_ctxt command_rhs - { - $$ = new_attr_op_assign(p, $1, $2, $3, $4, $6, &@$); - /*% ripper: opassign!(field!($:1, $:2, $:3), $:4, $:6) %*/ - } - | primary_value call_op tCONSTANT tOP_ASGN lex_ctxt command_rhs - { - $$ = new_attr_op_assign(p, $1, $2, $3, $4, $6, &@$); - /*% ripper: opassign!(field!($:1, $:2, $:3), $:4, $:6) %*/ - } - | primary_value tCOLON2 tCONSTANT tOP_ASGN lex_ctxt command_rhs - { - YYLTYPE loc = code_loc_gen(&@1, &@3); - $$ = new_const_op_assign(p, NEW_COLON2($1, $3, &loc), $4, $6, $5, &@$); - /*% ripper: opassign!(const_path_field!($:1, $:3), $:4, $:6) %*/ - } - | primary_value tCOLON2 tIDENTIFIER tOP_ASGN lex_ctxt command_rhs - { - $$ = new_attr_op_assign(p, $1, idCOLON2, $3, $4, $6, &@$); - /*% ripper: opassign!(field!($:1, $:2, $:3), $:4, $:6) %*/ - } - | defn_head[head] f_opt_paren_args[args] '=' endless_command[bodystmt] - { - endless_method_name(p, $head->nd_mid, &@head); - restore_defun(p, $head); - $bodystmt = new_scope_body(p, $args, $bodystmt, &@$); - ($$ = $head->nd_def)->nd_loc = @$; - RNODE_DEFN($$)->nd_defn = $bodystmt; - /*% ripper: bodystmt!($:bodystmt, Qnil, Qnil, Qnil) %*/ - /*% ripper: def!($:head, $:args, $:$) %*/ - local_pop(p); - } - | defs_head[head] f_opt_paren_args[args] '=' endless_command[bodystmt] - { - endless_method_name(p, $head->nd_mid, &@head); - restore_defun(p, $head); - $bodystmt = new_scope_body(p, $args, $bodystmt, &@$); - ($$ = $head->nd_def)->nd_loc = @$; - RNODE_DEFS($$)->nd_defn = $bodystmt; - /*% ripper: bodystmt!($:bodystmt, Qnil, Qnil, Qnil) %*/ - /*% ripper: defs!(*$:head[0..2], $:args, $:$) %*/ - local_pop(p); - } - | backref tOP_ASGN lex_ctxt command_rhs - { - /*%%%*/ - rb_backref_error(p, $1); - /*% %*/ - $$ = NEW_ERROR(&@$); - /*% ripper[error]: backref_error(p, $1, opassign!(var_field!($:1), $:2, $:4)) %*/ - } +command_asgn : asgn(command_rhs) + | op_asgn(command_rhs) + | def_endless_method(endless_command) ; endless_command : command @@ -3307,17 +3432,12 @@ endless_command : command } ; -command_rhs : command_call %prec tOP_ASGN - { - value_expr($1); - $$ = $1; - } - | command_call modifier_rescue after_rescue stmt +command_rhs : command_call_value %prec tOP_ASGN + | command_call_value modifier_rescue after_rescue stmt { p->ctxt.in_rescue = $3.in_rescue; YYLTYPE loc = code_loc_gen(&@2, &@4); - value_expr($1); - $$ = NEW_RESCUE($1, NEW_RESBODY(0, remove_begin($4), 0, &loc), 0, &@$); + $$ = NEW_RESCUE($1, NEW_RESBODY(0, 0, remove_begin($4), 0, &loc), 0, &@$); /*% ripper: rescue_mod!($:1, $:4) %*/ } | command_asgn @@ -3346,7 +3466,7 @@ expr : command_call } | arg tASSOC { - value_expr($arg); + value_expr(p, $arg); } p_in_kwarg[ctxt] p_pvtbl p_pktbl p_top_expr_body[body] @@ -3354,12 +3474,14 @@ expr : command_call pop_pktbl(p, $p_pktbl); pop_pvtbl(p, $p_pvtbl); p->ctxt.in_kwarg = $ctxt.in_kwarg; - $$ = NEW_CASE3($arg, NEW_IN($body, 0, 0, &@body), &@$); + p->ctxt.in_alt_pattern = $ctxt.in_alt_pattern; + p->ctxt.capture_in_pattern = $ctxt.capture_in_pattern; + $$ = NEW_CASE3($arg, NEW_IN($body, 0, 0, &@body, &NULL_LOC, &NULL_LOC, &@2), &@$, &NULL_LOC, &NULL_LOC); /*% ripper: case!($:arg, in!($:body, Qnil, Qnil)) %*/ } | arg keyword_in { - value_expr($arg); + value_expr(p, $arg); } p_in_kwarg[ctxt] p_pvtbl p_pktbl p_top_expr_body[body] @@ -3367,7 +3489,9 @@ expr : command_call pop_pktbl(p, $p_pktbl); pop_pvtbl(p, $p_pvtbl); p->ctxt.in_kwarg = $ctxt.in_kwarg; - $$ = NEW_CASE3($arg, NEW_IN($body, NEW_TRUE(&@body), NEW_FALSE(&@body), &@body), &@$); + p->ctxt.in_alt_pattern = $ctxt.in_alt_pattern; + p->ctxt.capture_in_pattern = $ctxt.capture_in_pattern; + $$ = NEW_CASE3($arg, NEW_IN($body, NEW_TRUE(&@body), NEW_FALSE(&@body), &@body, &@keyword_in, &NULL_LOC, &NULL_LOC), &@$, &NULL_LOC, &NULL_LOC); /*% ripper: case!($:arg, in!($:body, Qnil, Qnil)) %*/ } | arg %prec tLBRACE_ARG @@ -3375,13 +3499,12 @@ expr : command_call def_name : fname { - ID fname = $1; - numparam_name(p, fname); + numparam_name(p, $fname); local_push(p, 0); - p->cur_arg = 0; p->ctxt.in_def = 1; p->ctxt.in_rescue = before_rescue; - $$ = $1; + p->ctxt.cant_return = 0; + $$ = $fname; } ; @@ -3397,7 +3520,6 @@ defn_head : k_def def_name defs_head : k_def singleton dot_or_colon { SET_LEX_STATE(EXPR_FNAME); - p->ctxt.in_argdef = 1; } def_name { @@ -3409,11 +3531,7 @@ defs_head : k_def singleton dot_or_colon } ; -expr_value : expr - { - value_expr($1); - $$ = $1; - } +expr_value : value_expr(expr) | error { $$ = NEW_ERROR(&@$); @@ -3431,6 +3549,9 @@ command_call : command | block_command ; +command_call_value : value_expr(command_call) + ; + block_command : block_call | block_call call_op2 operation2 command_args { @@ -3498,33 +3619,33 @@ command : fcall command_args %prec tLOWEST } | keyword_super command_args { - $$ = NEW_SUPER($2, &@$); + $$ = NEW_SUPER($2, &@$, &@1, &NULL_LOC, &NULL_LOC); fixpos($$, $2); /*% ripper: super!($:2) %*/ } | k_yield command_args { - $$ = new_yield(p, $2, &@$); + $$ = NEW_YIELD($2, &@$, &@1, &NULL_LOC, &NULL_LOC); fixpos($$, $2); /*% ripper: yield!($:2) %*/ } | k_return call_args { - $$ = NEW_RETURN(ret_args(p, $2), &@$); + $$ = NEW_RETURN(ret_args(p, $2), &@$, &@1); /*% ripper: return!($:2) %*/ } | keyword_break call_args { NODE *args = 0; args = ret_args(p, $2); - $$ = add_block_exit(p, NEW_BREAK(args, &@$)); + $$ = add_block_exit(p, NEW_BREAK(args, &@$, &@1)); /*% ripper: break!($:2) %*/ } | keyword_next call_args { NODE *args = 0; args = ret_args(p, $2); - $$ = add_block_exit(p, NEW_NEXT(args, &@$)); + $$ = add_block_exit(p, NEW_NEXT(args, &@$, &@1)); /*% ripper: next!($:2) %*/ } ; @@ -3560,7 +3681,7 @@ mlhs_basic : mlhs_head $$ = NEW_MASGN($1, $3, &@$); /*% ripper: mlhs_add_star!($:1, $:3) %*/ } - | mlhs_head tSTAR mlhs_node ',' mlhs_post + | mlhs_head tSTAR mlhs_node ',' mlhs_items(mlhs_item) { $$ = NEW_MASGN($1, NEW_POSTARG($3,$5,&@$), &@$); /*% ripper: mlhs_add_post!(mlhs_add_star!($:1, $:3), $:5) %*/ @@ -3570,7 +3691,7 @@ mlhs_basic : mlhs_head $$ = NEW_MASGN($1, NODE_SPECIAL_NO_NAME_REST, &@$); /*% ripper: mlhs_add_star!($:1, Qnil) %*/ } - | mlhs_head tSTAR ',' mlhs_post + | mlhs_head tSTAR ',' mlhs_items(mlhs_item) { $$ = NEW_MASGN($1, NEW_POSTARG(NODE_SPECIAL_NO_NAME_REST, $4, &@$), &@$); /*% ripper: mlhs_add_post!(mlhs_add_star!($:1, Qnil), $:4) %*/ @@ -3580,7 +3701,7 @@ mlhs_basic : mlhs_head $$ = NEW_MASGN(0, $2, &@$); /*% ripper: mlhs_add_star!(mlhs_new!, $:2) %*/ } - | tSTAR mlhs_node ',' mlhs_post + | tSTAR mlhs_node ',' mlhs_items(mlhs_item) { $$ = NEW_MASGN(0, NEW_POSTARG($2,$4,&@$), &@$); /*% ripper: mlhs_add_post!(mlhs_add_star!(mlhs_new!, $:2), $:4) %*/ @@ -3590,7 +3711,7 @@ mlhs_basic : mlhs_head $$ = NEW_MASGN(0, NODE_SPECIAL_NO_NAME_REST, &@$); /*% ripper: mlhs_add_star!(mlhs_new!, Qnil) %*/ } - | tSTAR ',' mlhs_post + | tSTAR ',' mlhs_items(mlhs_item) { $$ = NEW_MASGN(0, NEW_POSTARG(NODE_SPECIAL_NO_NAME_REST, $3, &@$), &@$); /*% ripper: mlhs_add_post!(mlhs_add_star!(mlhs_new!, Qnil), $:3) %*/ @@ -3617,24 +3738,8 @@ mlhs_head : mlhs_item ',' } ; -mlhs_post : mlhs_item - { - $$ = NEW_LIST($1, &@$); - /*% ripper: mlhs_add!(mlhs_new!, $:1) %*/ - } - | mlhs_post ',' mlhs_item - { - $$ = list_append(p, $1, $3); - /*% ripper: mlhs_add!($:1, $:3) %*/ - } - ; -mlhs_node : user_variable - { - /*% ripper: var_field!($:1) %*/ - $$ = assignable(p, $1, 0, &@$); - } - | keyword_variable +mlhs_node : user_or_keyword_variable { /*% ripper: var_field!($:1) %*/ $$ = assignable(p, $1, 0, &@$); @@ -3644,7 +3749,7 @@ mlhs_node : user_variable $$ = aryset(p, $1, $3, &@$); /*% ripper: aref_field!($:1, $:3) %*/ } - | primary_value call_op tIDENTIFIER + | primary_value call_op ident_or_const { anddot_multiple_assignment_check(p, &@2, $2); $$ = attrset(p, $1, $2, $3, &@$); @@ -3655,38 +3760,25 @@ mlhs_node : user_variable $$ = attrset(p, $1, idCOLON2, $3, &@$); /*% ripper: const_path_field!($:1, $:3) %*/ } - | primary_value call_op tCONSTANT - { - anddot_multiple_assignment_check(p, &@2, $2); - $$ = attrset(p, $1, $2, $3, &@$); - /*% ripper: field!($:1, $:2, $:3) %*/ - } | primary_value tCOLON2 tCONSTANT { /*% ripper: const_path_field!($:1, $:3) %*/ - $$ = const_decl(p, NEW_COLON2($1, $3, &@$), &@$); + $$ = const_decl(p, NEW_COLON2($1, $3, &@$, &@2, &@3), &@$); } | tCOLON3 tCONSTANT { /*% ripper: top_const_field!($:2) %*/ - $$ = const_decl(p, NEW_COLON3($2, &@$), &@$); + $$ = const_decl(p, NEW_COLON3($2, &@$, &@1, &@2), &@$); } | backref { - /*%%%*/ - rb_backref_error(p, $1); - /*% %*/ + VALUE MAYBE_UNUSED(e) = rb_backref_error(p, $1); $$ = NEW_ERROR(&@$); - /*% ripper[error]: backref_error(p, $1, var_field!($:1)) %*/ + /*% ripper[error]: assign_error!(?e, var_field!($:1)) %*/ } ; -lhs : user_variable - { - /*% ripper: var_field!($:1) %*/ - $$ = assignable(p, $1, 0, &@$); - } - | keyword_variable +lhs : user_or_keyword_variable { /*% ripper: var_field!($:1) %*/ $$ = assignable(p, $1, 0, &@$); @@ -3696,7 +3788,7 @@ lhs : user_variable $$ = aryset(p, $1, $3, &@$); /*% ripper: aref_field!($:1, $:3) %*/ } - | primary_value call_op tIDENTIFIER + | primary_value call_op ident_or_const { $$ = attrset(p, $1, $2, $3, &@$); /*% ripper: field!($:1, $:2, $:3) %*/ @@ -3706,28 +3798,21 @@ lhs : user_variable $$ = attrset(p, $1, idCOLON2, $3, &@$); /*% ripper: field!($:1, $:2, $:3) %*/ } - | primary_value call_op tCONSTANT - { - $$ = attrset(p, $1, $2, $3, &@$); - /*% ripper: field!($:1, $:2, $:3) %*/ - } | primary_value tCOLON2 tCONSTANT { /*% ripper: const_path_field!($:1, $:3) %*/ - $$ = const_decl(p, NEW_COLON2($1, $3, &@$), &@$); + $$ = const_decl(p, NEW_COLON2($1, $3, &@$, &@2, &@3), &@$); } | tCOLON3 tCONSTANT { /*% ripper: top_const_field!($:2) %*/ - $$ = const_decl(p, NEW_COLON3($2, &@$), &@$); + $$ = const_decl(p, NEW_COLON3($2, &@$, &@1, &@2), &@$); } | backref { - /*%%%*/ - rb_backref_error(p, $1); - /*% %*/ + VALUE MAYBE_UNUSED(e) = rb_backref_error(p, $1); $$ = NEW_ERROR(&@$); - /*% ripper[error]: backref_error(p, $1, var_field!($:1)) %*/ + /*% ripper[error]: assign_error!(?e, var_field!($:1)) %*/ } ; @@ -3744,24 +3829,22 @@ cname : tIDENTIFIER cpath : tCOLON3 cname { - $$ = NEW_COLON3($2, &@$); + $$ = NEW_COLON3($2, &@$, &@1, &@2); /*% ripper: top_const_ref!($:2) %*/ } | cname { - $$ = NEW_COLON2(0, $1, &@$); + $$ = NEW_COLON2(0, $1, &@$, &NULL_LOC, &@1); /*% ripper: const_ref!($:1) %*/ } | primary_value tCOLON2 cname { - $$ = NEW_COLON2($1, $3, &@$); + $$ = NEW_COLON2($1, $3, &@$, &@2, &@3); /*% ripper: const_path_ref!($:1, $:3) %*/ } ; -fname : tIDENTIFIER - | tCONSTANT - | tFID +fname : operation | op { SET_LEX_STATE(EXPR_ENDFN); @@ -3785,8 +3868,8 @@ undef_list : fitem } | undef_list ',' {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem { - NODE *undef = NEW_UNDEF($4, &@4); - $$ = block_append(p, $1, undef); + nd_set_last_loc($1, @4.end_pos); + rb_parser_ary_push_node(p, RNODE_UNDEF($1)->nd_undefs, $4); /*% ripper: rb_ary_push($:1, $:4) %*/ } ; @@ -3837,94 +3920,9 @@ reswords : keyword__LINE__ | keyword__FILE__ | keyword__ENCODING__ | keyword_while | keyword_until ; -arg : lhs '=' lex_ctxt arg_rhs - { - $$ = node_assign(p, $1, $4, $3, &@$); - /*% ripper: assign!($:1, $:4) %*/ - } - | var_lhs tOP_ASGN lex_ctxt arg_rhs - { - $$ = new_op_assign(p, $1, $2, $4, $3, &@$); - /*% ripper: opassign!($:1, $:2, $:4) %*/ - } - | primary_value '[' opt_call_args rbracket tOP_ASGN lex_ctxt arg_rhs - { - $$ = new_ary_op_assign(p, $1, $3, $5, $7, &@3, &@$); - /*% ripper: opassign!(aref_field!($:1, $:3), $:5, $:7) %*/ - } - | primary_value call_op tIDENTIFIER tOP_ASGN lex_ctxt arg_rhs - { - $$ = new_attr_op_assign(p, $1, $2, $3, $4, $6, &@$); - /*% ripper: opassign!(field!($:1, $:2, $:3), $:4, $:6) %*/ - } - | primary_value call_op tCONSTANT tOP_ASGN lex_ctxt arg_rhs - { - $$ = new_attr_op_assign(p, $1, $2, $3, $4, $6, &@$); - /*% ripper: opassign!(field!($:1, $:2, $:3), $:4, $:6) %*/ - } - | primary_value tCOLON2 tIDENTIFIER tOP_ASGN lex_ctxt arg_rhs - { - $$ = new_attr_op_assign(p, $1, idCOLON2, $3, $4, $6, &@$); - /*% ripper: opassign!(field!($:1, $:2, $:3), $:4, $:6) %*/ - } - | primary_value tCOLON2 tCONSTANT tOP_ASGN lex_ctxt arg_rhs - { - YYLTYPE loc = code_loc_gen(&@1, &@3); - $$ = new_const_op_assign(p, NEW_COLON2($1, $3, &loc), $4, $6, $5, &@$); - /*% ripper: opassign!(const_path_field!($:1, $:3), $:4, $:6) %*/ - } - | tCOLON3 tCONSTANT tOP_ASGN lex_ctxt arg_rhs - { - YYLTYPE loc = code_loc_gen(&@1, &@2); - $$ = new_const_op_assign(p, NEW_COLON3($2, &loc), $3, $5, $4, &@$); - /*% ripper: opassign!(top_const_field!($:2), $:3, $:5) %*/ - } - | backref tOP_ASGN lex_ctxt arg_rhs - { - rb_backref_error(p, $1); - /*%%%*/ - $$ = NEW_ERROR(&@$); - /*% %*/ - /*% ripper[error]: backref_error(p, $1, opassign!(var_field!($:1), $:2, $:4)) %*/ - } - | arg tDOT2 arg - { - value_expr($1); - value_expr($3); - $$ = NEW_DOT2($1, $3, &@$); - /*% ripper: dot2!($:1, $:3) %*/ - } - | arg tDOT3 arg - { - value_expr($1); - value_expr($3); - $$ = NEW_DOT3($1, $3, &@$); - /*% ripper: dot3!($:1, $:3) %*/ - } - | arg tDOT2 - { - value_expr($1); - $$ = NEW_DOT2($1, new_nil_at(p, &@2.end_pos), &@$); - /*% ripper: dot2!($:1, Qnil) %*/ - } - | arg tDOT3 - { - value_expr($1); - $$ = NEW_DOT3($1, new_nil_at(p, &@2.end_pos), &@$); - /*% ripper: dot3!($:1, Qnil) %*/ - } - | tBDOT2 arg - { - value_expr($2); - $$ = NEW_DOT2(new_nil_at(p, &@1.beg_pos), $2, &@$); - /*% ripper: dot2!(Qnil, $:2) %*/ - } - | tBDOT3 arg - { - value_expr($2); - $$ = NEW_DOT3(new_nil_at(p, &@1.beg_pos), $2, &@$); - /*% ripper: dot3!(Qnil, $:2) %*/ - } +arg : asgn(arg_rhs) + | op_asgn(arg_rhs) + | range_expr(arg) | arg '+' arg { $$ = call_bin_op(p, $1, '+', $3, &@2, &@$); @@ -4049,42 +4047,22 @@ arg : lhs '=' lex_ctxt arg_rhs | keyword_defined '\n'? begin_defined arg { p->ctxt.in_defined = $3.in_defined; - $$ = new_defined(p, $4, &@$); + $$ = new_defined(p, $4, &@$, &@1); + p->ctxt.has_trailing_semicolon = $3.has_trailing_semicolon; /*% ripper: defined!($:4) %*/ } - | arg '?' arg '\n'? ':' arg + | def_endless_method(endless_arg) + | ternary + | primary + ; + +ternary : arg '?' arg '\n'? ':' arg { - value_expr($1); - $$ = new_if(p, $1, $3, $6, &@$); + value_expr(p, $1); + $$ = new_if(p, $1, $3, $6, &@$, &NULL_LOC, &@5, &NULL_LOC); fixpos($$, $1); /*% ripper: ifop!($:1, $:3, $:6) %*/ } - | defn_head[head] f_opt_paren_args[args] '=' endless_arg[bodystmt] - { - endless_method_name(p, $head->nd_mid, &@head); - restore_defun(p, $head); - $bodystmt = new_scope_body(p, $args, $bodystmt, &@$); - ($$ = $head->nd_def)->nd_loc = @$; - RNODE_DEFN($$)->nd_defn = $bodystmt; - /*% ripper: bodystmt!($:bodystmt, Qnil, Qnil, Qnil) %*/ - /*% ripper: def!($:head, $:args, $:$) %*/ - local_pop(p); - } - | defs_head[head] f_opt_paren_args[args] '=' endless_arg[bodystmt] - { - endless_method_name(p, $head->nd_mid, &@head); - restore_defun(p, $head); - $bodystmt = new_scope_body(p, $args, $bodystmt, &@$); - ($$ = $head->nd_def)->nd_loc = @$; - RNODE_DEFS($$)->nd_defn = $bodystmt; - /*% ripper: bodystmt!($:bodystmt, Qnil, Qnil, Qnil) %*/ - /*% ripper: defs!(*$:head[0..2], $:args, $:$) %*/ - local_pop(p); - } - | primary - { - $$ = $1; - } ; endless_arg : arg %prec modifier_rescue @@ -4140,18 +4118,11 @@ after_rescue : lex_ctxt } ; -arg_value : arg - { - value_expr($1); - $$ = $1; - } +arg_value : value_expr(arg) ; aref_args : none | args trailer - { - $$ = $1; - } | args ',' assocs trailer { $$ = $3 ? arg_append(p, $1, new_hash(p, $3, &@3), &@$) : $1; @@ -4166,13 +4137,13 @@ aref_args : none arg_rhs : arg %prec tOP_ASGN { - value_expr($1); + value_expr(p, $1); $$ = $1; } | arg modifier_rescue after_rescue arg { p->ctxt.in_rescue = $3.in_rescue; - value_expr($1); + value_expr(p, $1); $$ = rescued_expr(p, $1, $4, &@1, &@2, &@4); /*% ripper: rescue_mod!($:1, $:4) %*/ } @@ -4215,9 +4186,6 @@ opt_paren_args : none opt_call_args : none | call_args | args ',' - { - $$ = $1; - } | args ',' assocs ',' { $$ = $3 ? arg_append(p, $1, new_hash(p, $3, &@3), &@$) : $1; @@ -4230,9 +4198,13 @@ opt_call_args : none } ; -call_args : command +call_args : value_expr(command) + { + $$ = NEW_LIST($1, &@$); + /*% ripper: args_add!(args_new!, $:1) %*/ + } + | def_endless_method(endless_command) { - value_expr($1); $$ = NEW_LIST($1, &@$); /*% ripper: args_add!(args_new!, $:1) %*/ } @@ -4297,13 +4269,13 @@ command_args : { block_arg : tAMPER arg_value { - $$ = NEW_BLOCK_PASS($2, &@$); + $$ = NEW_BLOCK_PASS($2, &@$, &@1); /*% ripper: $:2 %*/ } | tAMPER { forwarding_arg_check(p, idFWD_BLOCK, idFWD_ALL, "block"); - $$ = NEW_BLOCK_PASS(NEW_LVAR(idFWD_BLOCK, &@1), &@$); + $$ = NEW_BLOCK_PASS(NEW_LVAR(idFWD_BLOCK, &@1), &@$, &@1); /*% ripper: Qnil %*/ } ; @@ -4323,36 +4295,36 @@ opt_block_arg : ',' block_arg /* value */ args : arg_value { - $$ = NEW_LIST($1, &@$); - /*% ripper: args_add!(args_new!, $:1) %*/ + $$ = NEW_LIST($arg_value, &@$); + /*% ripper: args_add!(args_new!, $:arg_value) %*/ } | arg_splat { - $$ = NEW_SPLAT($arg_splat, &@$); + $$ = $arg_splat; /*% ripper: args_add_star!(args_new!, $:arg_splat) %*/ } - | args ',' arg_value + | args[non_last_args] ',' arg_value { - $$ = last_arg_append(p, $1, $3, &@$); - /*% ripper: args_add!($:1, $:3) %*/ + $$ = last_arg_append(p, $non_last_args, $arg_value, &@$); + /*% ripper: args_add!($:non_last_args, $:arg_value) %*/ } - | args ',' arg_splat + | args[non_last_args] ',' arg_splat { - $$ = rest_arg_append(p, $1, $3, &@$); - /*% ripper: args_add_star!($:1, $:3) %*/ + $$ = rest_arg_append(p, $non_last_args, RNODE_SPLAT($arg_splat)->nd_head, &@$); + /*% ripper: args_add_star!($:non_last_args, $:arg_splat) %*/ } ; /* value */ arg_splat : tSTAR arg_value { - $$ = $2; - /*% ripper: $:2 %*/ + $$ = NEW_SPLAT($arg_value, &@$, &@tSTAR); + /*% ripper: $:arg_value %*/ } | tSTAR /* none */ { forwarding_arg_check(p, idFWD_REST, idFWD_ALL, "rest"); - $$ = NEW_LVAR(idFWD_REST, &@1); + $$ = NEW_SPLAT(NEW_LVAR(idFWD_REST, &@tSTAR), &@$, &@tSTAR); /*% ripper: Qnil %*/ } ; @@ -4365,22 +4337,23 @@ mrhs_arg : mrhs /* value */ mrhs : args ',' arg_value { - $$ = last_arg_append(p, $1, $3, &@$); - /*% ripper: mrhs_add!(mrhs_new_from_args!($:1), $:3) %*/ + $$ = last_arg_append(p, $args, $arg_value, &@$); + /*% ripper: mrhs_add!(mrhs_new_from_args!($:args), $:arg_value) %*/ } | args ',' tSTAR arg_value { - $$ = rest_arg_append(p, $1, $4, &@$); - /*% ripper: mrhs_add_star!(mrhs_new_from_args!($:1), $:4) %*/ + $$ = rest_arg_append(p, $args, $arg_value, &@$); + /*% ripper: mrhs_add_star!(mrhs_new_from_args!($:args), $:arg_value) %*/ } | tSTAR arg_value { - $$ = NEW_SPLAT($2, &@$); - /*% ripper: mrhs_add_star!(mrhs_new!, $:2) %*/ + $$ = NEW_SPLAT($arg_value, &@$, &@tSTAR); + /*% ripper: mrhs_add_star!(mrhs_new!, $:arg_value) %*/ } ; -primary : literal +%rule %inline inline_primary + : literal | strings | xstring | regexp @@ -4388,335 +4361,349 @@ primary : literal | qwords | symbols | qsymbols - | var_ref - | backref - | tFID - { - $$ = (NODE *)NEW_FCALL($1, 0, &@$); - /*% ripper: method_add_arg!(fcall!($:1), args_new!) %*/ - } - | k_begin - { - CMDARG_PUSH(0); - } - bodystmt - k_end - { - CMDARG_POP(); - set_line_body($3, @1.end_pos.lineno); - $$ = NEW_BEGIN($3, &@$); - nd_set_line($$, @1.end_pos.lineno); - /*% ripper: begin!($:3) %*/ - } - | tLPAREN_ARG compstmt {SET_LEX_STATE(EXPR_ENDARG);} ')' - { - if (nd_type_p($2, NODE_SELF)) RNODE_SELF($2)->nd_state = 0; - $$ = $2; - /*% ripper: paren!($:2) %*/ - } - | tLPAREN compstmt ')' - { - if (nd_type_p($2, NODE_SELF)) RNODE_SELF($2)->nd_state = 0; - $$ = NEW_BLOCK($2, &@$); - /*% ripper: paren!($:2) %*/ - } - | primary_value tCOLON2 tCONSTANT - { - $$ = NEW_COLON2($1, $3, &@$); - /*% ripper: const_path_ref!($:1, $:3) %*/ - } - | tCOLON3 tCONSTANT - { - $$ = NEW_COLON3($2, &@$); - /*% ripper: top_const_ref!($:2) %*/ - } - | tLBRACK aref_args ']' - { - $$ = make_list($2, &@$); - /*% ripper: array!($:2) %*/ - } - | tLBRACE assoc_list '}' - { - $$ = new_hash(p, $2, &@$); - RNODE_HASH($$)->nd_brace = TRUE; - /*% ripper: hash!($:2) %*/ - } - | k_return - { - $$ = NEW_RETURN(0, &@$); - /*% ripper: return0! %*/ - } - | k_yield '(' call_args rparen - { - $$ = new_yield(p, $3, &@$); - /*% ripper: yield!(paren!($:3)) %*/ - } - | k_yield '(' rparen - { - $$ = NEW_YIELD(0, &@$); - /*% ripper: yield!(paren!(args_new!)) %*/ - } - | k_yield - { - $$ = NEW_YIELD(0, &@$); - /*% ripper: yield0! %*/ - } - | keyword_defined '\n'? '(' begin_defined expr rparen - { - p->ctxt.in_defined = $4.in_defined; - $$ = new_defined(p, $5, &@$); - /*% ripper: defined!($:5) %*/ - } - | keyword_not '(' expr rparen - { - $$ = call_uni_op(p, method_cond(p, $3, &@3), METHOD_NOT, &@1, &@$); - /*% ripper: unary!(ID2VAL(idNOT), $:3) %*/ - } - | keyword_not '(' rparen - { - $$ = call_uni_op(p, method_cond(p, new_nil(&@2), &@2), METHOD_NOT, &@1, &@$); - /*% ripper: unary!(ID2VAL(idNOT), Qnil) %*/ - } - | fcall brace_block - { - $$ = method_add_block(p, (NODE *)$1, $2, &@$); - /*% ripper: method_add_block!(method_add_arg!(fcall!($:1), args_new!), $:2) %*/ - } - | method_call - | method_call brace_block - { - block_dup_check(p, get_nd_args(p, $1), $2); - $$ = method_add_block(p, $1, $2, &@$); - /*% ripper: method_add_block!($:1, $:2) %*/ - } - | lambda - | k_if expr_value then - compstmt - if_tail - k_end - { - $$ = new_if(p, $2, $4, $5, &@$); - fixpos($$, $2); - /*% ripper: if!($:2, $:4, $:5) %*/ - } - | k_unless expr_value then - compstmt - opt_else - k_end - { - $$ = new_unless(p, $2, $4, $5, &@$); - fixpos($$, $2); - /*% ripper: unless!($:2, $:4, $:5) %*/ - } - | k_while expr_value_do - compstmt - k_end - { - restore_block_exit(p, $1); - $$ = NEW_WHILE(cond(p, $2, &@2), $3, 1, &@$); - fixpos($$, $2); - /*% ripper: while!($:2, $:3) %*/ - } - | k_until expr_value_do - compstmt - k_end - { - restore_block_exit(p, $1); - $$ = NEW_UNTIL(cond(p, $2, &@2), $3, 1, &@$); - fixpos($$, $2); - /*% ripper: until!($:2, $:3) %*/ - } - | k_case expr_value terms? - { - $$ = p->case_labels; - p->case_labels = CHECK_LITERAL_WHEN; - }<labels> - case_body - k_end - { - if (CASE_LABELS_ENABLED_P(p->case_labels)) st_free_table(p->case_labels); - p->case_labels = $4; - $$ = NEW_CASE($2, $5, &@$); - fixpos($$, $2); - /*% ripper: case!($:2, $:5) %*/ - } - | k_case terms? - { - $$ = p->case_labels; - p->case_labels = 0; - }<labels> - case_body - k_end - { - if (p->case_labels) st_free_table(p->case_labels); - p->case_labels = $3; - $$ = NEW_CASE2($4, &@$); - /*% ripper: case!(Qnil, $:4) %*/ - } - | k_case expr_value terms? - p_case_body - k_end - { - $$ = NEW_CASE3($2, $4, &@$); - /*% ripper: case!($:2, $:4) %*/ - } - | k_for for_var keyword_in expr_value_do - compstmt - k_end - { - restore_block_exit(p, $1); - /* - * for a, b, c in e - * #=> - * e.each{|*x| a, b, c = x} - * - * for a in e - * #=> - * e.each{|x| a, = x} - */ - ID id = internal_id(p); - rb_node_args_aux_t *m = NEW_ARGS_AUX(0, 0, &NULL_LOC); - rb_node_args_t *args; - NODE *scope, *internal_var = NEW_DVAR(id, &@2); - rb_ast_id_table_t *tbl = rb_ast_new_local_table(p->ast, 1); - tbl->ids[0] = id; /* internal id */ - - switch (nd_type($2)) { - case NODE_LASGN: - case NODE_DASGN: /* e.each {|internal_var| a = internal_var; ... } */ - set_nd_value(p, $2, internal_var); - id = 0; - m->nd_plen = 1; - m->nd_next = $2; - break; - case NODE_MASGN: /* e.each {|*internal_var| a, b, c = (internal_var.length == 1 && Array === (tmp = internal_var[0]) ? tmp : internal_var); ... } */ - m->nd_next = node_assign(p, $2, NEW_FOR_MASGN(internal_var, &@2), NO_LEX_CTXT, &@2); - break; - default: /* e.each {|*internal_var| @a, B, c[1], d.attr = internal_val; ... } */ - m->nd_next = node_assign(p, (NODE *)NEW_MASGN(NEW_LIST($2, &@2), 0, &@2), internal_var, NO_LEX_CTXT, &@2); - } - /* {|*internal_id| <m> = internal_id; ... } */ - args = new_args(p, m, 0, id, 0, new_args_tail(p, 0, 0, 0, &@2), &@2); - scope = NEW_SCOPE2(tbl, args, $5, &@$); - $$ = NEW_FOR($4, scope, &@$); - fixpos($$, $2); - /*% ripper: for!($:2, $:4, $:5) %*/ - } - | k_class cpath superclass - { - begin_definition("class", &@k_class, &@cpath); - } - bodystmt - k_end - { - $$ = NEW_CLASS($cpath, $bodystmt, $superclass, &@$); - nd_set_line(RNODE_CLASS($$)->nd_body, @k_end.end_pos.lineno); - set_line_body($bodystmt, @superclass.end_pos.lineno); - nd_set_line($$, @superclass.end_pos.lineno); - /*% ripper: class!($:cpath, $:superclass, $:bodystmt) %*/ - local_pop(p); - p->ctxt.in_class = $k_class.in_class; - p->ctxt.shareable_constant_value = $k_class.shareable_constant_value; - } - | k_class tLSHFT expr_value - { - begin_definition("", &@k_class, &@tLSHFT); - } - term - bodystmt - k_end - { - $$ = NEW_SCLASS($expr_value, $bodystmt, &@$); - nd_set_line(RNODE_SCLASS($$)->nd_body, @k_end.end_pos.lineno); - set_line_body($bodystmt, nd_line($expr_value)); - fixpos($$, $expr_value); - /*% ripper: sclass!($:expr_value, $:bodystmt) %*/ - local_pop(p); - p->ctxt.in_def = $k_class.in_def; - p->ctxt.in_class = $k_class.in_class; - p->ctxt.shareable_constant_value = $k_class.shareable_constant_value; - } - | k_module cpath - { - begin_definition("module", &@k_module, &@cpath); - } - bodystmt - k_end - { - $$ = NEW_MODULE($cpath, $bodystmt, &@$); - nd_set_line(RNODE_MODULE($$)->nd_body, @k_end.end_pos.lineno); - set_line_body($bodystmt, @cpath.end_pos.lineno); - nd_set_line($$, @cpath.end_pos.lineno); - /*% ripper: module!($:cpath, $:bodystmt) %*/ - local_pop(p); - p->ctxt.in_class = $k_module.in_class; - p->ctxt.shareable_constant_value = $k_module.shareable_constant_value; - } - | defn_head[head] - f_arglist[args] - { - push_end_expect_token_locations(p, &@head.beg_pos); - } - bodystmt - k_end - { - restore_defun(p, $head); - $bodystmt = new_scope_body(p, $args, $bodystmt, &@$); - ($$ = $head->nd_def)->nd_loc = @$; - RNODE_DEFN($$)->nd_defn = $bodystmt; - /*% ripper: def!($:head, $:args, $:bodystmt) %*/ - local_pop(p); - } - | defs_head[head] - f_arglist[args] - { - push_end_expect_token_locations(p, &@head.beg_pos); - } - bodystmt - k_end - { - restore_defun(p, $head); - $bodystmt = new_scope_body(p, $args, $bodystmt, &@$); - ($$ = $head->nd_def)->nd_loc = @$; - RNODE_DEFS($$)->nd_defn = $bodystmt; - /*% ripper: defs!(*$:head[0..2], $:args, $:bodystmt) %*/ - local_pop(p); - } - | keyword_break - { - $$ = add_block_exit(p, NEW_BREAK(0, &@$)); - /*% ripper: break!(args_new!) %*/ - } - | keyword_next - { - $$ = add_block_exit(p, NEW_NEXT(0, &@$)); - /*% ripper: next!(args_new!) %*/ - } - | keyword_redo - { - $$ = add_block_exit(p, NEW_REDO(&@$)); - /*% ripper: redo! %*/ - } - | keyword_retry - { - if (!p->ctxt.in_defined) { - switch (p->ctxt.in_rescue) { - case before_rescue: yyerror1(&@1, "Invalid retry without rescue"); break; - case after_rescue: /* ok */ break; - case after_else: yyerror1(&@1, "Invalid retry after else"); break; - case after_ensure: yyerror1(&@1, "Invalid retry after ensure"); break; - } - } - $$ = NEW_RETRY(&@$); - /*% ripper: retry! %*/ - } ; -primary_value : primary - { - value_expr($1); - $$ = $1; +primary : inline_primary + | var_ref + | backref + | tFID + { + $$ = (NODE *)NEW_FCALL($1, 0, &@$); + /*% ripper: method_add_arg!(fcall!($:1), args_new!) %*/ + } + | k_begin + { + CMDARG_PUSH(0); + } + bodystmt + k_end + { + CMDARG_POP(); + set_line_body($3, @1.end_pos.lineno); + $$ = NEW_BEGIN($3, &@$); + nd_set_line($$, @1.end_pos.lineno); + /*% ripper: begin!($:3) %*/ + } + | tLPAREN_ARG compstmt(stmts) {SET_LEX_STATE(EXPR_ENDARG);} ')' + { + if (nd_type_p($2, NODE_SELF)) RNODE_SELF($2)->nd_state = 0; + $$ = $2; + /*% ripper: paren!($:2) %*/ + } + | tLPAREN compstmt(stmts) ')' + { + if (nd_type_p($2, NODE_SELF)) RNODE_SELF($2)->nd_state = 0; + $$ = NEW_BLOCK($2, &@$); + /*% ripper: paren!($:2) %*/ + } + | primary_value tCOLON2 tCONSTANT + { + $$ = NEW_COLON2($1, $3, &@$, &@2, &@3); + /*% ripper: const_path_ref!($:1, $:3) %*/ + } + | tCOLON3 tCONSTANT + { + $$ = NEW_COLON3($2, &@$, &@1, &@2); + /*% ripper: top_const_ref!($:2) %*/ + } + | tLBRACK aref_args ']' + { + $$ = make_list($2, &@$); + /*% ripper: array!($:2) %*/ + } + | tLBRACE assoc_list '}' + { + $$ = new_hash(p, $2, &@$); + RNODE_HASH($$)->nd_brace = TRUE; + /*% ripper: hash!($:2) %*/ + } + | k_return + { + $$ = NEW_RETURN(0, &@$, &@1); + /*% ripper: return0! %*/ + } + | k_yield '(' call_args rparen + { + $$ = NEW_YIELD($3, &@$, &@1, &@2, &@4); + /*% ripper: yield!(paren!($:3)) %*/ + } + | k_yield '(' rparen + { + $$ = NEW_YIELD(0, &@$, &@1, &@2, &@3); + /*% ripper: yield!(paren!(args_new!)) %*/ + } + | k_yield + { + $$ = NEW_YIELD(0, &@$, &@1, &NULL_LOC, &NULL_LOC); + /*% ripper: yield0! %*/ + } + | keyword_defined '\n'? '(' begin_defined expr rparen + { + p->ctxt.in_defined = $4.in_defined; + $$ = new_defined(p, $5, &@$, &@1); + p->ctxt.has_trailing_semicolon = $4.has_trailing_semicolon; + /*% ripper: defined!($:5) %*/ + } + | keyword_not '(' expr rparen + { + $$ = call_uni_op(p, method_cond(p, $3, &@3), METHOD_NOT, &@1, &@$); + /*% ripper: unary!(ID2VAL(idNOT), $:3) %*/ + } + | keyword_not '(' rparen + { + $$ = call_uni_op(p, method_cond(p, NEW_NIL(&@2), &@2), METHOD_NOT, &@1, &@$); + /*% ripper: unary!(ID2VAL(idNOT), Qnil) %*/ + } + | fcall brace_block + { + $$ = method_add_block(p, (NODE *)$1, $2, &@$); + /*% ripper: method_add_block!(method_add_arg!(fcall!($:1), args_new!), $:2) %*/ + } + | method_call + | method_call brace_block + { + block_dup_check(p, get_nd_args(p, $1), $2); + $$ = method_add_block(p, $1, $2, &@$); + /*% ripper: method_add_block!($:1, $:2) %*/ + } + | lambda + | k_if expr_value then + compstmt(stmts) + if_tail + k_end + { + if ($5 && nd_type_p($5, NODE_IF)) + RNODE_IF($5)->end_keyword_loc = @6; + + $$ = new_if(p, $2, $4, $5, &@$, &@1, &@3, &@6); + fixpos($$, $2); + /*% ripper: if!($:2, $:4, $:5) %*/ + } + | k_unless expr_value then + compstmt(stmts) + opt_else + k_end + { + $$ = new_unless(p, $2, $4, $5, &@$, &@1, &@3, &@6); + fixpos($$, $2); + /*% ripper: unless!($:2, $:4, $:5) %*/ + } + | k_while expr_value_do + compstmt(stmts) + k_end + { + restore_block_exit(p, $1); + $$ = NEW_WHILE(cond(p, $2, &@2), $3, 1, &@$, &@1, &@4); + fixpos($$, $2); + /*% ripper: while!($:2, $:3) %*/ + } + | k_until expr_value_do + compstmt(stmts) + k_end + { + restore_block_exit(p, $1); + $$ = NEW_UNTIL(cond(p, $2, &@2), $3, 1, &@$, &@1, &@4); + fixpos($$, $2); + /*% ripper: until!($:2, $:3) %*/ + } + | k_case expr_value terms? + { + $$ = p->case_labels; + p->case_labels = CHECK_LITERAL_WHEN; + }<labels> + case_body + k_end + { + if (CASE_LABELS_ENABLED_P(p->case_labels)) st_free_table(p->case_labels); + p->case_labels = $4; + $$ = NEW_CASE($2, $5, &@$, &@1, &@6); + fixpos($$, $2); + /*% ripper: case!($:2, $:5) %*/ + } + | k_case terms? + { + $$ = p->case_labels; + p->case_labels = 0; + }<labels> + case_body + k_end + { + if (p->case_labels) st_free_table(p->case_labels); + p->case_labels = $3; + $$ = NEW_CASE2($4, &@$, &@1, &@5); + /*% ripper: case!(Qnil, $:4) %*/ + } + | k_case expr_value terms? + p_case_body + k_end + { + $$ = NEW_CASE3($2, $4, &@$, &@1, &@5); + /*% ripper: case!($:2, $:4) %*/ + } + | k_for for_var keyword_in + {COND_PUSH(1);} expr_value do {COND_POP();} + compstmt(stmts) + k_end + { + restore_block_exit(p, $k_for); + /* + * for a, b, c in e + * #=> + * e.each{|*x| a, b, c = x} + * + * for a in e + * #=> + * e.each{|x| a, = x} + */ + ID id = internal_id(p); + rb_node_args_aux_t *m = NEW_ARGS_AUX(0, 0, &NULL_LOC); + rb_node_args_t *args; + NODE *scope, *internal_var = NEW_DVAR(id, &@for_var); + rb_ast_id_table_t *tbl = rb_ast_new_local_table(p->ast, 1); + tbl->ids[0] = id; /* internal id */ + + switch (nd_type($for_var)) { + case NODE_LASGN: + case NODE_DASGN: /* e.each {|internal_var| a = internal_var; ... } */ + set_nd_value(p, $for_var, internal_var); + id = 0; + m->nd_plen = 1; + m->nd_next = $for_var; + break; + case NODE_MASGN: /* e.each {|*internal_var| a, b, c = (internal_var.length == 1 && Array === (tmp = internal_var[0]) ? tmp : internal_var); ... } */ + m->nd_next = node_assign(p, $for_var, NEW_FOR_MASGN(internal_var, &@for_var), NO_LEX_CTXT, &@for_var); + break; + default: /* e.each {|*internal_var| @a, B, c[1], d.attr = internal_val; ... } */ + m->nd_next = node_assign(p, (NODE *)NEW_MASGN(NEW_LIST($for_var, &@for_var), 0, &@for_var), internal_var, NO_LEX_CTXT, &@for_var); + } + /* {|*internal_id| <m> = internal_id; ... } */ + args = new_args(p, m, 0, id, 0, new_args_tail(p, 0, 0, 0, &@for_var), &@for_var); + scope = NEW_SCOPE2(tbl, args, $compstmt, NULL, &@$); + YYLTYPE do_keyword_loc = $do == keyword_do_cond ? @do : NULL_LOC; + $$ = NEW_FOR($5, scope, &@$, &@k_for, &@keyword_in, &do_keyword_loc, &@k_end); + RNODE_SCOPE(scope)->nd_parent = $$; + fixpos($$, $for_var); + /*% ripper: for!($:for_var, $:expr_value, $:compstmt) %*/ + } + | k_class cpath superclass + { + begin_definition("class", &@k_class, &@cpath); + } + bodystmt + k_end + { + YYLTYPE inheritance_operator_loc = NULL_LOC; + if ($superclass) { + inheritance_operator_loc = @superclass; + inheritance_operator_loc.end_pos.column = inheritance_operator_loc.beg_pos.column + 1; + } + $$ = NEW_CLASS($cpath, $bodystmt, $superclass, &@$, &@k_class, &inheritance_operator_loc, &@k_end); + nd_set_line(RNODE_CLASS($$)->nd_body, @k_end.end_pos.lineno); + set_line_body($bodystmt, @superclass.end_pos.lineno); + nd_set_line($$, @superclass.end_pos.lineno); + /*% ripper: class!($:cpath, $:superclass, $:bodystmt) %*/ + local_pop(p); + p->ctxt.in_class = $k_class.in_class; + p->ctxt.cant_return = $k_class.cant_return; + p->ctxt.shareable_constant_value = $k_class.shareable_constant_value; + } + | k_class tLSHFT expr_value + { + begin_definition("", &@k_class, &@tLSHFT); + } + term + bodystmt + k_end + { + $$ = NEW_SCLASS($expr_value, $bodystmt, &@$, &@k_class, &@tLSHFT, &@k_end); + nd_set_line(RNODE_SCLASS($$)->nd_body, @k_end.end_pos.lineno); + set_line_body($bodystmt, nd_line($expr_value)); + fixpos($$, $expr_value); + /*% ripper: sclass!($:expr_value, $:bodystmt) %*/ + local_pop(p); + p->ctxt.in_def = $k_class.in_def; + p->ctxt.in_class = $k_class.in_class; + p->ctxt.cant_return = $k_class.cant_return; + p->ctxt.shareable_constant_value = $k_class.shareable_constant_value; + } + | k_module cpath + { + begin_definition("module", &@k_module, &@cpath); + } + bodystmt + k_end + { + $$ = NEW_MODULE($cpath, $bodystmt, &@$, &@k_module, &@k_end); + nd_set_line(RNODE_MODULE($$)->nd_body, @k_end.end_pos.lineno); + set_line_body($bodystmt, @cpath.end_pos.lineno); + nd_set_line($$, @cpath.end_pos.lineno); + /*% ripper: module!($:cpath, $:bodystmt) %*/ + local_pop(p); + p->ctxt.in_class = $k_module.in_class; + p->ctxt.cant_return = $k_module.cant_return; + p->ctxt.shareable_constant_value = $k_module.shareable_constant_value; + } + | defn_head[head] + f_arglist[args] + { + push_end_expect_token_locations(p, &@head.beg_pos); + } + bodystmt + k_end + { + restore_defun(p, $head); + ($$ = $head->nd_def)->nd_loc = @$; + $bodystmt = new_scope_body(p, $args, $bodystmt, $$, &@$); + RNODE_DEFN($$)->nd_defn = $bodystmt; + /*% ripper: def!($:head, $:args, $:bodystmt) %*/ + local_pop(p); + } + | defs_head[head] + f_arglist[args] + { + push_end_expect_token_locations(p, &@head.beg_pos); + } + bodystmt + k_end + { + restore_defun(p, $head); + ($$ = $head->nd_def)->nd_loc = @$; + $bodystmt = new_scope_body(p, $args, $bodystmt, $$, &@$); + RNODE_DEFS($$)->nd_defn = $bodystmt; + /*% ripper: defs!(*$:head[0..2], $:args, $:bodystmt) %*/ + local_pop(p); + } + | keyword_break + { + $$ = add_block_exit(p, NEW_BREAK(0, &@$, &@1)); + /*% ripper: break!(args_new!) %*/ + } + | keyword_next + { + $$ = add_block_exit(p, NEW_NEXT(0, &@$, &@1)); + /*% ripper: next!(args_new!) %*/ + } + | keyword_redo + { + $$ = add_block_exit(p, NEW_REDO(&@$, &@1)); + /*% ripper: redo! %*/ + } + | keyword_retry + { + if (!p->ctxt.in_defined) { + switch (p->ctxt.in_rescue) { + case before_rescue: yyerror1(&@1, "Invalid retry without rescue"); break; + case after_rescue: /* ok */ break; + case after_else: yyerror1(&@1, "Invalid retry after else"); break; + case after_ensure: yyerror1(&@1, "Invalid retry after ensure"); break; + } } + $$ = NEW_RETRY(&@$); + /*% ripper: retry! %*/ + } + ; + +primary_value : value_expr(primary) ; k_begin : keyword_begin @@ -4878,7 +4865,7 @@ k_end : keyword_end k_return : keyword_return { - if (p->ctxt.in_class && !p->ctxt.in_def && !dyna_in_block(p)) + if (p->ctxt.cant_return && !dyna_in_block(p)) yyerror1(&@1, "Invalid return in class/module body"); } ; @@ -4896,22 +4883,22 @@ then : term ; do : term - | keyword_do_cond + | keyword_do_cond { $$ = keyword_do_cond; } ; if_tail : opt_else | k_elsif expr_value then - compstmt + compstmt(stmts) if_tail { - $$ = new_if(p, $2, $4, $5, &@$); + $$ = new_if(p, $2, $4, $5, &@$, &@1, &@3, &NULL_LOC); fixpos($$, $2); /*% ripper: elsif!($:2, $:4, $:5) %*/ } ; opt_else : none - | k_else compstmt + | k_else compstmt(stmts) { $$ = $2; /*% ripper: else!($:2) %*/ @@ -4934,29 +4921,18 @@ f_marg : f_norm_arg } ; -f_marg_list : f_marg - { - $$ = NEW_LIST($1, &@$); - /*% ripper: mlhs_add!(mlhs_new!, $:1) %*/ - } - | f_marg_list ',' f_marg - { - $$ = list_append(p, $1, $3); - /*% ripper: mlhs_add!($:1, $:3) %*/ - } - ; -f_margs : f_marg_list +f_margs : mlhs_items(f_marg) { $$ = NEW_MASGN($1, 0, &@$); /*% ripper: $:1 %*/ } - | f_marg_list ',' f_rest_marg + | mlhs_items(f_marg) ',' f_rest_marg { $$ = NEW_MASGN($1, $3, &@$); /*% ripper: mlhs_add_star!($:1, $:3) %*/ } - | f_marg_list ',' f_rest_marg ',' f_marg_list + | mlhs_items(f_marg) ',' f_rest_marg ',' mlhs_items(f_marg) { $$ = NEW_MASGN($1, NEW_POSTARG($3, $5, &@$), &@$); /*% ripper: mlhs_add_post!(mlhs_add_star!($:1, $:3), $:5) %*/ @@ -4966,7 +4942,7 @@ f_margs : f_marg_list $$ = NEW_MASGN(0, $1, &@$); /*% ripper: mlhs_add_star!(mlhs_new!, $:1) %*/ } - | f_rest_marg ',' f_marg_list + | f_rest_marg ',' mlhs_items(f_marg) { $$ = NEW_MASGN(0, NEW_POSTARG($1, $3, &@$), &@$); /*% ripper: mlhs_add_post!(mlhs_add_star!(mlhs_new!, $:1), $:3) %*/ @@ -4996,26 +4972,7 @@ f_any_kwrest : f_kwrest f_eq : {p->ctxt.in_argdef = 0;} '='; -block_args_tail : f_kwarg(f_block_kw) ',' f_kwrest opt_f_block_arg - { - $$ = new_args_tail(p, $1, $3, $4, &@3); - /*% ripper: [$:1, $:3, $:4] %*/ - } - | f_kwarg(f_block_kw) opt_f_block_arg - { - $$ = new_args_tail(p, $1, 0, $2, &@1); - /*% ripper: [$:1, Qnil, $:2] %*/ - } - | f_any_kwrest opt_f_block_arg - { - $$ = new_args_tail(p, 0, $1, $2, &@1); - /*% ripper: [Qnil, $:1, $:2] %*/ - } - | f_block_arg - { - $$ = new_args_tail(p, 0, 0, $1, &@1); - /*% ripper: [Qnil, Qnil, $:1] %*/ - } +block_args_tail : args_tail_basic(primary_value) ; excessed_comma : ',' @@ -5026,22 +4983,22 @@ excessed_comma : ',' } ; -block_param : f_arg ',' f_optarg(primary_value) ',' f_rest_arg opt_args_tail(block_args_tail) +block_param : f_arg ',' f_opt_arg(primary_value) ',' f_rest_arg opt_args_tail(block_args_tail) { $$ = new_args(p, $1, $3, $5, 0, $6, &@$); /*% ripper: params!($:1, $:3, $:5, Qnil, *$:6[0..2]) %*/ } - | f_arg ',' f_optarg(primary_value) ',' f_rest_arg ',' f_arg opt_args_tail(block_args_tail) + | f_arg ',' f_opt_arg(primary_value) ',' f_rest_arg ',' f_arg opt_args_tail(block_args_tail) { $$ = new_args(p, $1, $3, $5, $7, $8, &@$); /*% ripper: params!($:1, $:3, $:5, $:7, *$:8[0..2]) %*/ } - | f_arg ',' f_optarg(primary_value) opt_args_tail(block_args_tail) + | f_arg ',' f_opt_arg(primary_value) opt_args_tail(block_args_tail) { $$ = new_args(p, $1, $3, 0, 0, $4, &@$); /*% ripper: params!($:1, $:3, Qnil, Qnil, *$:4[0..2]) %*/ } - | f_arg ',' f_optarg(primary_value) ',' f_arg opt_args_tail(block_args_tail) + | f_arg ',' f_opt_arg(primary_value) ',' f_arg opt_args_tail(block_args_tail) { $$ = new_args(p, $1, $3, 0, $5, $6, &@$); /*% ripper: params!($:1, $:3, Qnil, $:5, *$:6[0..2]) %*/ @@ -5067,22 +5024,22 @@ block_param : f_arg ',' f_optarg(primary_value) ',' f_rest_arg opt_args_tail(blo $$ = new_args(p, $1, 0, 0, 0, $2, &@$); /*% ripper: params!($:1, Qnil, Qnil, Qnil, *$:2[0..2]) %*/ } - | f_optarg(primary_value) ',' f_rest_arg opt_args_tail(block_args_tail) + | f_opt_arg(primary_value) ',' f_rest_arg opt_args_tail(block_args_tail) { $$ = new_args(p, 0, $1, $3, 0, $4, &@$); /*% ripper: params!(Qnil, $:1, $:3, Qnil, *$:4[0..2]) %*/ } - | f_optarg(primary_value) ',' f_rest_arg ',' f_arg opt_args_tail(block_args_tail) + | f_opt_arg(primary_value) ',' f_rest_arg ',' f_arg opt_args_tail(block_args_tail) { $$ = new_args(p, 0, $1, $3, $5, $6, &@$); /*% ripper: params!(Qnil, $:1, $:3, $:5, *$:6[0..2]) %*/ } - | f_optarg(primary_value) opt_args_tail(block_args_tail) + | f_opt_arg(primary_value) opt_args_tail(block_args_tail) { $$ = new_args(p, 0, $1, 0, 0, $2, &@$); /*% ripper: params!(Qnil, $:1, Qnil, Qnil, *$:2[0..2]) %*/ } - | f_optarg(primary_value) ',' f_arg opt_args_tail(block_args_tail) + | f_opt_arg(primary_value) ',' f_arg opt_args_tail(block_args_tail) { $$ = new_args(p, 0, $1, 0, $3, $4, &@$); /*% ripper: params!(Qnil, $:1, Qnil, $:3, *$:4[0..2]) %*/ @@ -5104,24 +5061,15 @@ block_param : f_arg ',' f_optarg(primary_value) ',' f_rest_arg opt_args_tail(blo } ; -opt_block_param : none - | block_param_def - { - p->command_start = TRUE; - } - ; +opt_block_param_def : none + | block_param_def + { + p->command_start = TRUE; + } + ; -block_param_def : '|' opt_bv_decl '|' - { - p->cur_arg = 0; - p->max_numparam = ORDINAL_PARAM; - p->ctxt.in_argdef = 0; - $$ = 0; - /*% ripper: block_var!(params!(Qnil,Qnil,Qnil,Qnil,Qnil,Qnil,Qnil), $:2) %*/ - } - | '|' block_param opt_bv_decl '|' +block_param_def : '|' opt_block_param opt_bv_decl '|' { - p->cur_arg = 0; p->max_numparam = ORDINAL_PARAM; p->ctxt.in_argdef = 0; $$ = $2; @@ -5129,6 +5077,13 @@ block_param_def : '|' opt_bv_decl '|' } ; +opt_block_param : /* none */ + { + $$ = 0; + /*% ripper: params!(Qnil,Qnil,Qnil,Qnil,Qnil,Qnil,Qnil) %*/ + } + | block_param + ; opt_bv_decl : '\n'? { @@ -5154,9 +5109,6 @@ bvar : tIDENTIFIER /*% ripper: $:1 %*/ } | f_bad_arg - { - $$ = 0; - } ; max_numparam : { @@ -5170,7 +5122,7 @@ numparam : { } ; -it_id : { +it_id : { $$ = p->it_id; p->it_id = 0; } @@ -5180,7 +5132,6 @@ lambda : tLAMBDA[lpar] { token_info_push(p, "->", &@1); $$ = dyna_push(p); - p->lex.lpar_beg = p->lex.paren_nest; }[dyna]<vars> max_numparam numparam it_id allow_exits f_larglist[args] @@ -5198,11 +5149,12 @@ lambda : tLAMBDA[lpar] CMDARG_POP(); $args = args_with_numbered(p, $args, max_numparam, it_id); { - YYLTYPE loc = code_loc_gen(&@args, &@body); - $$ = NEW_LAMBDA($args, $body, &loc); + YYLTYPE loc = code_loc_gen(&@lpar, &@body); + $$ = NEW_LAMBDA($args, $body->node, &loc, &@lpar, &$body->opening_loc, &$body->closing_loc); nd_set_line(RNODE_LAMBDA($$)->nd_body, @body.end_pos.lineno); nd_set_line($$, @args.end_pos.lineno); nd_set_first_loc($$, @1.beg_pos); + xfree($body); } /*% ripper: lambda!($:args, $:body) %*/ numparam_pop(p, $numparam); @@ -5213,7 +5165,7 @@ lambda : tLAMBDA[lpar] f_larglist : '(' f_args opt_bv_decl ')' { p->ctxt.in_argdef = 0; - $$ = $2; + $$ = $f_args; p->max_numparam = ORDINAL_PARAM; /*% ripper: paren!($:2) %*/ } @@ -5222,14 +5174,14 @@ f_larglist : '(' f_args opt_bv_decl ')' p->ctxt.in_argdef = 0; if (!args_info_empty_p(&$1->nd_ainfo)) p->max_numparam = ORDINAL_PARAM; - $$ = $1; + $$ = $f_args; } ; -lambda_body : tLAMBEG compstmt '}' +lambda_body : tLAMBEG compstmt(stmts) '}' { token_info_pop(p, "}", &@3); - $$ = $2; + $$ = new_locations_lambda_body(p, $2, &@2, &@1, &@3); /*% ripper: $:2 %*/ } | keyword_do_LAMBDA @@ -5238,7 +5190,7 @@ lambda_body : tLAMBEG compstmt '}' } bodystmt k_end { - $$ = $3; + $$ = new_locations_lambda_body(p, $3, &@3, &@1, &@4); /*% ripper: $:3 %*/ } ; @@ -5275,19 +5227,21 @@ block_call : command do_block } | block_call call_op2 operation2 opt_paren_args brace_block { - bool has_args = $5 != 0; - if (NODE_EMPTY_ARGS_P($5)) $5 = 0; + if (NODE_EMPTY_ARGS_P($4)) $4 = 0; $$ = new_command_qcall(p, $2, $1, $3, $4, $5, &@3, &@$); - /*% ripper: command_call!($:1, $:2, $:3, $:4) %*/ - if (has_args) { - /*% ripper: method_add_block!($:$, $:5) %*/ - } + /*% ripper: method_add_block!(command_call!($:1, $:2, $:3, $:4), $:5) %*/ } | block_call call_op2 operation2 command_args do_block { $$ = new_command_qcall(p, $2, $1, $3, $4, $5, &@3, &@$); /*% ripper: method_add_block!(command_call!($:1, $:2, $:3, $:4), $:5) %*/ } + | block_call call_op2 paren_args + { + $$ = new_qcall(p, $2, $1, idCall, $3, &@2, &@$); + nd_set_line($$, @2.end_pos.lineno); + /*% ripper: method_add_arg!(call!($:1, $:2, ID2VAL(idCall)), $:3) %*/ + } ; method_call : fcall paren_args @@ -5319,21 +5273,20 @@ method_call : fcall paren_args $$ = new_qcall(p, idCOLON2, $1, $3, 0, &@3, &@$); /*% ripper: call!($:1, $:2, $:3) %*/ } - | primary_value call_op paren_args + | primary_value call_op2 paren_args { $$ = new_qcall(p, $2, $1, idCall, $3, &@2, &@$); nd_set_line($$, @2.end_pos.lineno); /*% ripper: method_add_arg!(call!($:1, $:2, ID2VAL(idCall)), $:3) %*/ } - | primary_value tCOLON2 paren_args - { - $$ = new_qcall(p, idCOLON2, $1, idCall, $3, &@2, &@$); - nd_set_line($$, @2.end_pos.lineno); - /*% ripper: method_add_arg!(call!($:1, $:2, ID2VAL(idCall)), $:3) %*/ - } | keyword_super paren_args { - $$ = NEW_SUPER($2, &@$); + rb_code_location_t lparen_loc = @2; + rb_code_location_t rparen_loc = @2; + lparen_loc.end_pos.column = lparen_loc.beg_pos.column + 1; + rparen_loc.beg_pos.column = rparen_loc.end_pos.column - 1; + + $$ = NEW_SUPER($2, &@$, &@1, &lparen_loc, &rparen_loc); /*% ripper: super!($:2) %*/ } | keyword_super @@ -5365,7 +5318,7 @@ brace_block : '{' brace_body '}' brace_body : {$$ = dyna_push(p);}[dyna]<vars> max_numparam numparam it_id allow_exits - opt_block_param[args] compstmt + opt_block_param_def[args] compstmt(stmts) { int max_numparam = p->max_numparam; ID it_id = p->it_id; @@ -5385,7 +5338,7 @@ do_body : { CMDARG_PUSH(0); }[dyna]<vars> max_numparam numparam it_id allow_exits - opt_block_param[args] bodystmt + opt_block_param_def[args] bodystmt { int max_numparam = p->max_numparam; ID it_id = p->it_id; @@ -5403,33 +5356,33 @@ do_body : { case_args : arg_value { - check_literal_when(p, $1, &@1); - $$ = NEW_LIST($1, &@$); - /*% ripper: args_add!(args_new!, $:1) %*/ + check_literal_when(p, $arg_value, &@arg_value); + $$ = NEW_LIST($arg_value, &@$); + /*% ripper: args_add!(args_new!, $:arg_value) %*/ } | tSTAR arg_value { - $$ = NEW_SPLAT($2, &@$); - /*% ripper: args_add_star!(args_new!, $:2) %*/ + $$ = NEW_SPLAT($arg_value, &@$, &@tSTAR); + /*% ripper: args_add_star!(args_new!, $:arg_value) %*/ } - | case_args ',' arg_value + | case_args[non_last_args] ',' arg_value { - check_literal_when(p, $3, &@3); - $$ = last_arg_append(p, $1, $3, &@$); - /*% ripper: args_add!($:1, $:3) %*/ + check_literal_when(p, $arg_value, &@arg_value); + $$ = last_arg_append(p, $non_last_args, $arg_value, &@$); + /*% ripper: args_add!($:non_last_args, $:arg_value) %*/ } - | case_args ',' tSTAR arg_value + | case_args[non_last_args] ',' tSTAR arg_value { - $$ = rest_arg_append(p, $1, $4, &@$); - /*% ripper: args_add_star!($:1, $:4) %*/ + $$ = rest_arg_append(p, $non_last_args, $arg_value, &@$); + /*% ripper: args_add_star!($:non_last_args, $:arg_value) %*/ } ; case_body : k_when case_args then - compstmt + compstmt(stmts) cases { - $$ = NEW_WHEN($2, $4, $5, &@$); + $$ = NEW_WHEN($2, $4, $5, &@$, &@1, &@3); fixpos($$, $2); /*% ripper: when!($:2, $:4, $:5) %*/ } @@ -5447,6 +5400,8 @@ p_in_kwarg : { SET_LEX_STATE(EXPR_BEG|EXPR_LABEL); p->command_start = FALSE; p->ctxt.in_kwarg = 1; + p->ctxt.in_alt_pattern = 0; + p->ctxt.capture_in_pattern = 0; } ; @@ -5457,11 +5412,13 @@ p_case_body : keyword_in pop_pktbl(p, $p_pktbl); pop_pvtbl(p, $p_pvtbl); p->ctxt.in_kwarg = $ctxt.in_kwarg; + p->ctxt.in_alt_pattern = $ctxt.in_alt_pattern; + p->ctxt.capture_in_pattern = $ctxt.capture_in_pattern; } - compstmt + compstmt(stmts) p_cases[cases] { - $$ = NEW_IN($expr, $compstmt, $cases, &@$); + $$ = NEW_IN($expr, $compstmt, $cases, &@$, &@keyword_in, &@then, &NULL_LOC); /*% ripper: in!($:expr, $:compstmt, $:cases) %*/ } ; @@ -5473,13 +5430,13 @@ p_cases : opt_else p_top_expr : p_top_expr_body | p_top_expr_body modifier_if expr_value { - $$ = new_if(p, $3, $1, 0, &@$); + $$ = new_if(p, $3, $1, 0, &@$, &@2, &NULL_LOC, &NULL_LOC); fixpos($$, $3); /*% ripper: if_mod!($:3, $:1) %*/ } | p_top_expr_body modifier_unless expr_value { - $$ = new_unless(p, $3, $1, 0, &@$); + $$ = new_unless(p, $3, $1, 0, &@$, &@2, &NULL_LOC, &NULL_LOC); fixpos($$, $3); /*% ripper: unless_mod!($:3, $:1) %*/ } @@ -5528,10 +5485,18 @@ p_as : p_expr tASSOC p_variable | p_alt ; -p_alt : p_alt '|' p_expr_basic +p_alt : p_alt[left] '|'[alt] { - $$ = NEW_OR($1, $3, &@$); - /*% ripper: binary!($:1, ID2VAL(idOr), $:3) %*/ + p->ctxt.in_alt_pattern = 1; + } + p_expr_basic[right] + { + if (p->ctxt.capture_in_pattern) { + yyerror1(&@alt, "alternative pattern after variable capture"); + } + p->ctxt.in_alt_pattern = 0; + $$ = NEW_OR($left, $right, &@$, &@alt); + /*% ripper: binary!($:left, ID2VAL(idOr), $:right) %*/ } | p_expr_basic ; @@ -5677,9 +5642,6 @@ p_args : p_expr ; p_args_head : p_arg ',' - { - $$ = $1; - } | p_args_head p_arg ',' { $$ = list_concat($1, $2); @@ -5827,57 +5789,13 @@ p_any_kwrest : p_kwrest ; p_value : p_primitive - | p_primitive tDOT2 p_primitive - { - value_expr($1); - value_expr($3); - $$ = NEW_DOT2($1, $3, &@$); - /*% ripper: dot2!($:1, $:3) %*/ - } - | p_primitive tDOT3 p_primitive - { - value_expr($1); - value_expr($3); - $$ = NEW_DOT3($1, $3, &@$); - /*% ripper: dot3!($:1, $:3) %*/ - } - | p_primitive tDOT2 - { - value_expr($1); - $$ = NEW_DOT2($1, new_nil_at(p, &@2.end_pos), &@$); - /*% ripper: dot2!($:1, Qnil) %*/ - } - | p_primitive tDOT3 - { - value_expr($1); - $$ = NEW_DOT3($1, new_nil_at(p, &@2.end_pos), &@$); - /*% ripper: dot3!($:1, Qnil) %*/ - } + | range_expr(p_primitive) | p_var_ref | p_expr_ref | p_const - | tBDOT2 p_primitive - { - value_expr($2); - $$ = NEW_DOT2(new_nil_at(p, &@1.beg_pos), $2, &@$); - /*% ripper: dot2!(Qnil, $:2) %*/ - } - | tBDOT3 p_primitive - { - value_expr($2); - $$ = NEW_DOT3(new_nil_at(p, &@1.beg_pos), $2, &@$); - /*% ripper: dot3!(Qnil, $:2) %*/ - } ; -p_primitive : literal - | strings - | xstring - | regexp - | words - | qwords - | symbols - | qsymbols +p_primitive : inline_primary | keyword_variable { if (!($$ = gettable(p, $1, &@$))) $$ = NEW_ERROR(&@$); @@ -5922,12 +5840,12 @@ p_expr_ref : '^' tLPAREN expr_value rparen p_const : tCOLON3 cname { - $$ = NEW_COLON3($2, &@$); + $$ = NEW_COLON3($2, &@$, &@1, &@2); /*% ripper: top_const_ref!($:2) %*/ } | p_const tCOLON2 cname { - $$ = NEW_COLON2($1, $3, &@$); + $$ = NEW_COLON2($1, $3, &@$, &@2, &@3); /*% ripper: const_path_ref!($:1, $:3) %*/ } | tCONSTANT @@ -5938,16 +5856,15 @@ p_const : tCOLON3 cname ; opt_rescue : k_rescue exc_list exc_var then - compstmt + compstmt(stmts) opt_rescue { - NODE *body = $5; + NODE *err = $3; if ($3) { - NODE *err = NEW_ERRINFO(&@3); + err = NEW_ERRINFO(&@3); err = node_assign(p, $3, err, NO_LEX_CTXT, &@3); - body = block_append(p, err, body); } - $$ = NEW_RESBODY($2, body, $6, &@$); + $$ = NEW_RESBODY($2, $3, $5, $6, &@$); if ($2) { fixpos($$, $2); } @@ -5982,10 +5899,11 @@ exc_var : tASSOC lhs | none ; -opt_ensure : k_ensure compstmt +opt_ensure : k_ensure stmts terms? { p->ctxt.in_rescue = $1.in_rescue; $$ = $2; + void_expr(p, void_stmts(p, $$)); /*% ripper: ensure!($:2) %*/ } | none @@ -5997,14 +5915,12 @@ literal : numeric strings : string { - NODE *node = $1; - if (!node) { - node = NEW_STR(STRING_NEW0(), &@$); + if (!$1) { + $$ = NEW_STR(STRING_NEW0(), &@$); } else { - node = evstr2dstr(p, node); + $$ = evstr2dstr(p, $1); } - $$ = node; /*% ripper: $:1 %*/ } ; @@ -6045,12 +5961,12 @@ xstring : tXSTRING_BEG xstring_contents tSTRING_END regexp : tREGEXP_BEG regexp_contents tREGEXP_END { - $$ = new_regexp(p, $2, $3, &@$); + $$ = new_regexp(p, $2, $3, &@$, &@1, &@2, &@3); /*% ripper: regexp_literal!($:2, $:3) %*/ } ; -words : words(tWORDS_BEG, word_list) <node> +words : words(tWORDS_BEG, word_list) ; word_list : /* none */ @@ -6074,7 +5990,7 @@ word : string_content } ; -symbols : words(tSYMBOLS_BEG, symbol_list) <node> +symbols : words(tSYMBOLS_BEG, symbol_list) ; symbol_list : /* none */ @@ -6089,10 +6005,10 @@ symbol_list : /* none */ } ; -qwords : words(tQWORDS_BEG, qword_list) <node> +qwords : words(tQWORDS_BEG, qword_list) ; -qsymbols : words(tQSYMBOLS_BEG, qsym_list) <node> +qsymbols : words(tQSYMBOLS_BEG, qsym_list) ; qword_list : /* none */ @@ -6119,11 +6035,9 @@ qsym_list : /* none */ } ; -string_contents : /* none */ +string_contents : /* none */ { $$ = 0; - /*%%%*/ - /*% %*/ /*% ripper: string_content! %*/ } | string_contents string_content @@ -6145,7 +6059,7 @@ xstring_contents: /* none */ } ; -regexp_contents: /* none */ +regexp_contents : /* none */ { $$ = 0; /*% ripper: regexp_new! %*/ @@ -6188,7 +6102,7 @@ string_content : tSTRING_CONTENT string_dvar { p->lex.strterm = $2; - $$ = NEW_EVSTR($3, &@$); + $$ = NEW_EVSTR($3, &@$, &@1, &NULL_LOC); nd_set_line($$, @3.end_pos.lineno); /*% ripper: string_dvar!($:3) %*/ } @@ -6209,7 +6123,7 @@ string_content : tSTRING_CONTENT $$ = p->heredoc_indent; p->heredoc_indent = 0; }[indent]<num> - compstmt string_dend + compstmt(stmts) string_dend { COND_POP(); CMDARG_POP(); @@ -6219,7 +6133,7 @@ string_content : tSTRING_CONTENT p->heredoc_indent = $indent; p->heredoc_line_indent = -1; if ($compstmt) nd_unset_fl_newline($compstmt); - $$ = new_evstr(p, $compstmt, &@$); + $$ = new_evstr(p, $compstmt, &@$, &@state, &@string_dend); /*% ripper: string_embexpr!($:compstmt) %*/ } ; @@ -6283,13 +6197,12 @@ simple_numeric : tINTEGER | tIMAGINARY ; -nonlocal_var : tIVAR +nonlocal_var : tIVAR | tGVAR | tCVAR ; -user_variable : tIDENTIFIER - | tCONSTANT +user_variable : ident_or_const | nonlocal_var ; @@ -6319,12 +6232,7 @@ var_ref : user_variable } ; -var_lhs : user_variable - { - /*% ripper: var_field!($:1) %*/ - $$ = assignable(p, $1, 0, &@$); - } - | keyword_variable +var_lhs : user_or_keyword_variable { /*% ripper: var_field!($:1) %*/ $$ = assignable(p, $1, 0, &@$); @@ -6345,11 +6253,7 @@ superclass : '<' $$ = $3; /*% ripper: $:3 %*/ } - | /* none */ - { - $$ = 0; - /*% ripper: Qnil %*/ - } + | none ; f_opt_paren_args: f_paren_args @@ -6390,51 +6294,40 @@ f_arglist : f_paren_args } ; -args_tail : f_kwarg(f_kw) ',' f_kwrest opt_f_block_arg - { - $$ = new_args_tail(p, $1, $3, $4, &@3); - /*% ripper: [$:1, $:3, $:4] %*/ - } - | f_kwarg(f_kw) opt_f_block_arg - { - $$ = new_args_tail(p, $1, 0, $2, &@1); - /*% ripper: [$:1, Qnil, $:2] %*/ - } - | f_any_kwrest opt_f_block_arg - { - $$ = new_args_tail(p, 0, $1, $2, &@1); - /*% ripper: [Qnil, $:1, $:2] %*/ - } - | f_block_arg - { - $$ = new_args_tail(p, 0, 0, $1, &@1); - /*% ripper: [Qnil, Qnil, $:1] %*/ - } +args_tail : args_tail_basic(arg_value) | args_forward { - add_forwarding_args(p); - $$ = new_args_tail(p, 0, $1, arg_FWD_BLOCK, &@1); + ID fwd = $args_forward; + if (lambda_beginning_p() || + (p->lex.lpar_beg >= 0 && p->lex.lpar_beg+1 == p->lex.paren_nest)) { + yyerror0("unexpected ... in lambda argument"); + fwd = 0; + } + else { + add_forwarding_args(p); + } + $$ = new_args_tail(p, 0, fwd, arg_FWD_BLOCK, &@1); $$->nd_ainfo.forwarding = 1; /*% ripper: [Qnil, $:1, Qnil] %*/ } ; -f_args : f_arg ',' f_optarg(arg_value) ',' f_rest_arg opt_args_tail(args_tail) +f_args : f_arg ',' f_opt_arg(arg_value) ',' f_rest_arg opt_args_tail(args_tail) { $$ = new_args(p, $1, $3, $5, 0, $6, &@$); /*% ripper: params!($:1, $:3, $:5, Qnil, *$:6[0..2]) %*/ } - | f_arg ',' f_optarg(arg_value) ',' f_rest_arg ',' f_arg opt_args_tail(args_tail) + | f_arg ',' f_opt_arg(arg_value) ',' f_rest_arg ',' f_arg opt_args_tail(args_tail) { $$ = new_args(p, $1, $3, $5, $7, $8, &@$); /*% ripper: params!($:1, $:3, $:5, $:7, *$:8[0..2]) %*/ } - | f_arg ',' f_optarg(arg_value) opt_args_tail(args_tail) + | f_arg ',' f_opt_arg(arg_value) opt_args_tail(args_tail) { $$ = new_args(p, $1, $3, 0, 0, $4, &@$); /*% ripper: params!($:1, $:3, Qnil, Qnil, *$:4[0..2]) %*/ } - | f_arg ',' f_optarg(arg_value) ',' f_arg opt_args_tail(args_tail) + | f_arg ',' f_opt_arg(arg_value) ',' f_arg opt_args_tail(args_tail) { $$ = new_args(p, $1, $3, 0, $5, $6, &@$); /*% ripper: params!($:1, $:3, Qnil, $:5, *$:6[0..2]) %*/ @@ -6454,22 +6347,22 @@ f_args : f_arg ',' f_optarg(arg_value) ',' f_rest_arg opt_args_tail(args_tail) $$ = new_args(p, $1, 0, 0, 0, $2, &@$); /*% ripper: params!($:1, Qnil, Qnil, Qnil, *$:2[0..2]) %*/ } - | f_optarg(arg_value) ',' f_rest_arg opt_args_tail(args_tail) + | f_opt_arg(arg_value) ',' f_rest_arg opt_args_tail(args_tail) { $$ = new_args(p, 0, $1, $3, 0, $4, &@$); /*% ripper: params!(Qnil, $:1, $:3, Qnil, *$:4[0..2]) %*/ } - | f_optarg(arg_value) ',' f_rest_arg ',' f_arg opt_args_tail(args_tail) + | f_opt_arg(arg_value) ',' f_rest_arg ',' f_arg opt_args_tail(args_tail) { $$ = new_args(p, 0, $1, $3, $5, $6, &@$); /*% ripper: params!(Qnil, $:1, $:3, $:5, *$:6[0..2]) %*/ } - | f_optarg(arg_value) opt_args_tail(args_tail) + | f_opt_arg(arg_value) opt_args_tail(args_tail) { $$ = new_args(p, 0, $1, 0, 0, $2, &@$); /*% ripper: params!(Qnil, $:1, Qnil, Qnil, *$:2[0..2]) %*/ } - | f_optarg(arg_value) ',' f_arg opt_args_tail(args_tail) + | f_opt_arg(arg_value) ',' f_arg opt_args_tail(args_tail) { $$ = new_args(p, 0, $1, 0, $3, $4, &@$); /*% ripper: params!(Qnil, $:1, Qnil, $:3, *$:4[0..2]) %*/ @@ -6499,11 +6392,7 @@ f_args : f_arg ',' f_optarg(arg_value) ',' f_rest_arg opt_args_tail(args_tail) args_forward : tBDOT3 { -#ifdef FORWARD_ARGS_WITH_RUBY2_KEYWORDS - $$ = 0; -#else $$ = idFWD_KWREST; -#endif /*% ripper: args_forward! %*/ } ; @@ -6549,25 +6438,23 @@ f_bad_arg : tCONSTANT f_norm_arg : f_bad_arg | tIDENTIFIER { - formal_argument(p, $1); + VALUE e = formal_argument_error(p, $$ = $1); + if (e) { + /*% ripper[error]: param_error!(?e, $:1) %*/ + } p->max_numparam = ORDINAL_PARAM; - $$ = $1; - /*% ripper: ripper_formal_argument(p, $1, $:1) %*/ } ; f_arg_asgn : f_norm_arg { - ID id = $1; - arg_var(p, id); - p->cur_arg = id; + arg_var(p, $1); $$ = $1; } ; f_arg_item : f_arg_asgn { - p->cur_arg = 0; $$ = NEW_ARGS_AUX($1, 1, &NULL_LOC); /*% ripper: $:1 %*/ } @@ -6605,42 +6492,21 @@ f_arg : f_arg_item f_label : tLABEL { - arg_var(p, formal_argument(p, $1)); - p->cur_arg = $1; + VALUE e = formal_argument_error(p, $$ = $1); + if (e) { + $$ = 0; + /*% ripper[error]: param_error!(?e, $:1) %*/ + } + /* + * Workaround for Prism::ParseTest#test_filepath for + * "unparser/corpus/literal/def.txt" + * + * See the discussion on https://github.com/ruby/ruby/pull/9923 + */ + arg_var(p, ifdef_ripper(0, $1)); + /*% ripper: $:1 %*/ p->max_numparam = ORDINAL_PARAM; p->ctxt.in_argdef = 0; - $$ = $1; - /*% ripper: ripper_formal_argument(p, $1, $:1) %*/ - } - ; - -f_kw : f_label arg_value - { - p->cur_arg = 0; - p->ctxt.in_argdef = 1; - $$ = new_kw_arg(p, assignable(p, $1, $2, &@$), &@$); - /*% ripper: [$:$, $:2] %*/ - } - | f_label - { - p->cur_arg = 0; - p->ctxt.in_argdef = 1; - $$ = new_kw_arg(p, assignable(p, $1, NODE_SPECIAL_REQUIRED_KEYWORD, &@$), &@$); - /*% ripper: [$:$, 0] %*/ - } - ; - -f_block_kw : f_label primary_value - { - p->ctxt.in_argdef = 1; - $$ = new_kw_arg(p, assignable(p, $1, $2, &@$), &@$); - /*% ripper: [$:$, $:2] %*/ - } - | f_label - { - p->ctxt.in_argdef = 1; - $$ = new_kw_arg(p, assignable(p, $1, NODE_SPECIAL_REQUIRED_KEYWORD, &@$), &@$); - /*% ripper: [$:$, 0] %*/ } ; @@ -6710,20 +6576,12 @@ opt_f_block_arg : ',' f_block_arg /*% ripper: $:2 %*/ } | none - { - $$ = 0; - /*% ripper: Qnil %*/ - } ; -singleton : var_ref - { - value_expr($1); - $$ = $1; - } - | '(' {SET_LEX_STATE(EXPR_BEG);} expr rparen + +singleton : value_expr(singleton_expr) { - NODE *expr = last_expr_node($3); + NODE *expr = last_expr_node($1); switch (nd_type(expr)) { case NODE_STR: case NODE_DSTR: @@ -6745,9 +6603,21 @@ singleton : var_ref yyerror1(&expr->nd_loc, "can't define singleton method for literals"); break; default: - value_expr($3); break; } + $$ = $1; + } + ; + +singleton_expr : var_ref + | '(' + { + SET_LEX_STATE(EXPR_BEG); + p->ctxt.in_argdef = 0; + } + expr rparen + { + p->ctxt.in_argdef = 1; $$ = $3; /*% ripper: paren!($:3) %*/ } @@ -6825,10 +6695,9 @@ assoc : arg_value tASSOC arg_value } ; -operation : tIDENTIFIER - | tCONSTANT - | tFID - ; +%rule %inline operation : ident_or_const + | tFID + ; operation2 : operation | op @@ -6864,7 +6733,14 @@ trailer : '\n'? | ',' ; -term : ';' {yyerrok;token_flush(p);} +term : ';' + { + yyerrok; + token_flush(p); + if (p->ctxt.in_defined) { + p->ctxt.has_trailing_semicolon = 1; + } + } | '\n' { @$.end_pos = @$.beg_pos; @@ -6879,6 +6755,7 @@ terms : term none : /* none */ { $$ = 0; + /*% ripper: Qnil %*/ } ; %% @@ -6893,11 +6770,7 @@ static void tokaddmbc(struct parser_params *p, int c, rb_encoding *enc); static enum yytokentype parse_string(struct parser_params*,rb_strterm_literal_t*); static enum yytokentype here_document(struct parser_params*,rb_strterm_heredoc_t*); -#ifndef RIPPER -#define set_parser_s_value(x) (void)(x) -#else -#define set_parser_s_value(x) (p->s_value = (x)) -#endif +#define set_parser_s_value(x) (ifdef_ripper(p->s_value = (x), (void)0)) # define set_yylval_node(x) { \ YYLTYPE _cur_loc; \ @@ -6907,8 +6780,8 @@ static enum yytokentype here_document(struct parser_params*,rb_strterm_heredoc_t } # define set_yylval_str(x) \ do { \ - set_yylval_node(NEW_STR(rb_str_to_parser_string(p, x), &_cur_loc)); \ - set_parser_s_value(x); \ + set_yylval_node(NEW_STR(x, &_cur_loc)); \ + set_parser_s_value(rb_str_new_mutable_parser_string(x)); \ } while(0) # define set_yylval_num(x) { \ yylval.num = (x); \ @@ -6969,14 +6842,13 @@ rb_parser_str_escape(struct parser_params *p, rb_parser_string_t *str) const char *prev = ptr; char charbuf[5] = {'\\', 'x', 0, 0, 0}; rb_parser_string_t * result = rb_parser_string_new(p, 0, 0); - int asciicompat = rb_enc_asciicompat(enc); while (ptr < pend) { unsigned int c; const char *cc; int n = rb_enc_precise_mbclen(ptr, pend, enc); if (!MBCLEN_CHARFOUND_P(n)) { - if (ptr > prev) rb_parser_str_buf_cat(p, result, prev, ptr - prev); + if (ptr > prev) parser_str_cat(result, prev, ptr - prev); n = rb_enc_mbminlen(enc); if (pend < ptr + n) n = (int)(pend - ptr); @@ -6985,7 +6857,7 @@ rb_parser_str_escape(struct parser_params *p, rb_parser_string_t *str) charbuf[2] = (c < 10) ? '0' + c : 'A' + c - 10; c = *ptr & 0x0f; charbuf[3] = (c < 10) ? '0' + c : 'A' + c - 10; - rb_parser_str_buf_cat(p, result, charbuf, 4); + parser_str_cat(result, charbuf, 4); prev = ++ptr; } continue; @@ -6995,22 +6867,22 @@ rb_parser_str_escape(struct parser_params *p, rb_parser_string_t *str) ptr += n; cc = escaped_char(c); if (cc) { - if (ptr - n > prev) rb_parser_str_buf_cat(p, result, prev, ptr - n - prev); - rb_parser_str_buf_cat(p, result, cc, strlen(cc)); + if (ptr - n > prev) parser_str_cat(result, prev, ptr - n - prev); + parser_str_cat_cstr(result, cc); prev = ptr; } - else if (asciicompat && rb_enc_isascii(c, enc) && ISPRINT(c)) { + else if (rb_enc_isascii(c, enc) && ISPRINT(c)) { } else { if (ptr - n > prev) { - rb_parser_str_buf_cat(p, result, prev, ptr - n - prev); + parser_str_cat(result, prev, ptr - n - prev); prev = ptr - n; } - rb_parser_str_buf_cat(p, result, prev, ptr - prev); + parser_str_cat(result, prev, ptr - prev); prev = ptr; } } - if (ptr > prev) rb_parser_str_buf_cat(p, result, prev, ptr - prev); + if (ptr > prev) parser_str_cat(result, prev, ptr - prev); return result; } @@ -7067,7 +6939,8 @@ parser_dispatch_delayed_token(struct parser_params *p, enum yytokentype t, int l if (p->keep_tokens) { /* p->delayed.token is freed by rb_parser_tokens_free */ parser_append_tokens(p, p->delayed.token, t, line); - } else { + } + else { rb_parser_string_free(p, p->delayed.token); } @@ -7130,6 +7003,16 @@ is_identchar(struct parser_params *p, const char *ptr, const char *MAYBE_UNUSED( return rb_enc_isalnum((unsigned char)*ptr, enc) || *ptr == '_' || !ISASCII(*ptr); } +static inline bool +peek_word_at(struct parser_params *p, const char *str, size_t len, int at) +{ + const char *ptr = p->lex.pcur + at; + if (lex_eol_ptr_n_p(p, ptr, len-1)) return false; + if (memcmp(ptr, str, len)) return false; + if (lex_eol_ptr_n_p(p, ptr, len)) return true; + return !is_identchar(p, ptr+len, p->lex.pend, p->enc); +} + static inline int parser_is_identchar(struct parser_params *p) { @@ -7181,10 +7064,11 @@ token_info_pop(struct parser_params *p, const char *token, const rb_code_locatio token_info *ptinfo_beg = p->token_info; if (!ptinfo_beg) return; - p->token_info = ptinfo_beg->next; /* indentation check of matched keywords (begin..end, if..end, etc.) */ token_info_warn(p, token, ptinfo_beg, 1, loc); + + p->token_info = ptinfo_beg->next; ruby_sized_xfree(ptinfo_beg, sizeof(*ptinfo_beg)); } @@ -7334,7 +7218,7 @@ ruby_show_error_line(struct parser_params *p, VALUE errbuf, const YYLTYPE *yyllo } if (RTEST(errbuf)) { mesg = rb_attr_get(errbuf, idMesg); - if (RSTRING_LEN(mesg) > 0 && *(RSTRING_END(mesg)-1) != '\n') + if (char_at_end(p, mesg, '\n') != '\n') rb_str_cat_cstr(mesg, "\n"); } else { @@ -7673,21 +7557,24 @@ enum string_type { str_dsym = (STR_FUNC_SYMBOL|STR_FUNC_EXPAND) }; -static VALUE +static rb_parser_string_t * parser_str_new(struct parser_params *p, const char *ptr, long len, rb_encoding *enc, int func, rb_encoding *enc0) { - VALUE str; + rb_parser_string_t *pstr; - str = rb_enc_str_new(ptr, len, enc); - if (!(func & STR_FUNC_REGEXP) && rb_enc_asciicompat(enc)) { - if (is_ascii_string(str)) { + pstr = rb_parser_encoding_string_new(p, ptr, len, enc); + + if (!(func & STR_FUNC_REGEXP)) { + if (rb_parser_is_ascii_string(p, pstr)) { } else if (rb_is_usascii_enc((void *)enc0) && enc != rb_utf8_encoding()) { - rb_enc_associate(str, rb_ascii8bit_encoding()); + /* everything is valid in ASCII-8BIT */ + enc = rb_ascii8bit_encoding(); + PARSER_ENCODING_CODERANGE_SET(pstr, enc, RB_PARSER_ENC_CODERANGE_VALID); } } - return str; + return pstr; } static int @@ -7719,16 +7606,15 @@ new_heredoc(struct parser_params *p) #define peekc(p) peekc_n(p, 0) #define peekc_n(p,n) (lex_eol_n_p(p, n) ? -1 : (unsigned char)(p)->lex.pcur[n]) +#define add_delayed_token(p, tok, end) parser_add_delayed_token(p, tok, end, __LINE__) static void -add_delayed_token(struct parser_params *p, const char *tok, const char *end, int line) +parser_add_delayed_token(struct parser_params *p, const char *tok, const char *end, int line) { -#ifndef RIPPER debug_token_line(p, "add_delayed_token", line); -#endif if (tok < end) { if (has_delayed_token(p)) { - bool next_line = parser_string_end_with_newline_p(p, p->delayed.token); + bool next_line = parser_string_char_at_end(p, p->delayed.token, 0) == '\n'; int end_line = (next_line ? 1 : 0) + p->delayed.end_line; int end_col = (next_line ? 0 : p->delayed.end_col); if (end_line != p->ruby_sourceline || end_col != tok - p->lex.pbeg) { @@ -7741,7 +7627,7 @@ add_delayed_token(struct parser_params *p, const char *tok, const char *end, int p->delayed.beg_line = p->ruby_sourceline; p->delayed.beg_col = rb_long2int(tok - p->lex.pbeg); } - rb_parser_str_buf_cat(p, p->delayed.token, tok, end - tok); + parser_str_cat(p->delayed.token, tok, end - tok); p->delayed.end_line = p->ruby_sourceline; p->delayed.end_col = rb_long2int(end - p->lex.pbeg); p->lex.ptok = end; @@ -7784,11 +7670,11 @@ nextline(struct parser_params *p, int set_encoding) #endif p->cr_seen = FALSE; } - else if (str == AFTER_HEREDOC_WITHOUT_TERMINTOR) { + else if (str == AFTER_HEREDOC_WITHOUT_TERMINATOR) { /* after here-document without terminator */ goto end_of_input; } - add_delayed_token(p, p->lex.ptok, p->lex.pend, __LINE__); + add_delayed_token(p, p->lex.ptok, p->lex.pend); if (p->heredoc_end > 0) { p->ruby_sourceline = p->heredoc_end; p->heredoc_end = 0; @@ -7814,7 +7700,7 @@ nextc0(struct parser_params *p, int set_encoding) { int c; - if (UNLIKELY(lex_eol_p(p) || p->eofp || p->lex.nextline > AFTER_HEREDOC_WITHOUT_TERMINTOR)) { + if (UNLIKELY(lex_eol_p(p) || p->eofp || p->lex.nextline > AFTER_HEREDOC_WITHOUT_TERMINATOR)) { if (nextline(p, set_encoding)) return -1; } c = (unsigned char)*p->lex.pcur++; @@ -7901,6 +7787,7 @@ tok_hex(struct parser_params *p, size_t *numlen) c = (int)ruby_scan_hex(p->lex.pcur, 2, numlen); if (!*numlen) { + flush_string_content(p, p->enc, rb_strlen_lit("\\x")); yyerror0("invalid hex escape"); dispatch_scan_event(p, tSTRING_CONTENT); return 0; @@ -7943,27 +7830,33 @@ escaped_control_code(int c) static int tokadd_codepoint(struct parser_params *p, rb_encoding **encp, - int regexp_literal, int wide) + int regexp_literal, const char *begin) { + const int wide = !begin; size_t numlen; int codepoint = (int)ruby_scan_hex(p->lex.pcur, wide ? p->lex.pend - p->lex.pcur : 4, &numlen); + p->lex.pcur += numlen; if (p->lex.strterm == NULL || strterm_is_heredoc(p->lex.strterm) || (p->lex.strterm->u.literal.func != str_regexp)) { + if (!begin) begin = p->lex.pcur; if (wide ? (numlen == 0 || numlen > 6) : (numlen < 4)) { - literal_flush(p, p->lex.pcur); + flush_string_content(p, rb_utf8_encoding(), p->lex.pcur - begin); yyerror0("invalid Unicode escape"); + dispatch_scan_event(p, tSTRING_CONTENT); return wide && numlen > 0; } if (codepoint > 0x10ffff) { - literal_flush(p, p->lex.pcur); + flush_string_content(p, rb_utf8_encoding(), p->lex.pcur - begin); yyerror0("invalid Unicode codepoint (too large)"); + dispatch_scan_event(p, tSTRING_CONTENT); return wide; } if ((codepoint & 0xfffff800) == 0xd800) { - literal_flush(p, p->lex.pcur); + flush_string_content(p, rb_utf8_encoding(), p->lex.pcur - begin); yyerror0("invalid Unicode codepoint"); + dispatch_scan_event(p, tSTRING_CONTENT); return wide; } } @@ -8051,7 +7944,7 @@ tokadd_utf8(struct parser_params *p, rb_encoding **encp, if (second == multiple_codepoints) second = p->lex.pcur; if (regexp_literal) tokadd(p, last); - if (!tokadd_codepoint(p, encp, regexp_literal, TRUE)) { + if (!tokadd_codepoint(p, encp, regexp_literal, NULL)) { break; } while (ISSPACE(c = peekc(p))) { @@ -8064,8 +7957,9 @@ tokadd_utf8(struct parser_params *p, rb_encoding **encp, if (c != close_brace) { unterminated: - token_flush(p); + flush_string_content(p, rb_utf8_encoding(), 0); yyerror0("unterminated Unicode escape"); + dispatch_scan_event(p, tSTRING_CONTENT); return; } if (second && second != multiple_codepoints) { @@ -8083,7 +7977,7 @@ tokadd_utf8(struct parser_params *p, rb_encoding **encp, } } else { /* handle \uxxxx form */ - if (!tokadd_codepoint(p, encp, regexp_literal, FALSE)) { + if (!tokadd_codepoint(p, encp, regexp_literal, p->lex.pcur - rb_strlen_lit("\\u"))) { token_flush(p); return; } @@ -8094,7 +7988,7 @@ tokadd_utf8(struct parser_params *p, rb_encoding **encp, #define ESCAPE_META 2 static int -read_escape(struct parser_params *p, int flags) +read_escape(struct parser_params *p, int flags, const char *begin) { int c; size_t numlen; @@ -8153,7 +8047,7 @@ read_escape(struct parser_params *p, int flags) nextc(p); goto eof; } - return read_escape(p, flags|ESCAPE_META) | 0x80; + return read_escape(p, flags|ESCAPE_META, begin) | 0x80; } else if (c == -1) goto eof; else if (!ISASCII(c)) { @@ -8186,7 +8080,7 @@ read_escape(struct parser_params *p, int flags) nextc(p); goto eof; } - c = read_escape(p, flags|ESCAPE_CONTROL); + c = read_escape(p, flags|ESCAPE_CONTROL, begin); } else if (c == '?') return 0177; @@ -8221,11 +8115,16 @@ read_escape(struct parser_params *p, int flags) eof: case -1: + flush_string_content(p, p->enc, p->lex.pcur - begin); yyerror0("Invalid escape character syntax"); dispatch_scan_event(p, tSTRING_CONTENT); return '\0'; default: + if (!ISASCII(c)) { + tokskip_mbchar(p); + goto eof; + } return c; } } @@ -8242,6 +8141,7 @@ tokadd_escape(struct parser_params *p) { int c; size_t numlen; + const char *begin = p->lex.pcur; switch (c = nextc(p)) { case '\n': @@ -8267,6 +8167,7 @@ tokadd_escape(struct parser_params *p) eof: case -1: + flush_string_content(p, p->enc, p->lex.pcur - begin); yyerror0("Invalid escape character syntax"); token_flush(p); return -1; @@ -8537,7 +8438,7 @@ tokadd_string(struct parser_params *p, case 'C': case 'M': { pushback(p, c); - c = read_escape(p, 0); + c = read_escape(p, 0, p->lex.pcur - 1); char *t = tokspace(p, rb_strlen_lit("\\x00")); *t++ = '\\'; @@ -8563,7 +8464,7 @@ tokadd_string(struct parser_params *p, else if (func & STR_FUNC_EXPAND) { pushback(p, c); if (func & STR_FUNC_ESCAPE) tokadd(p, '\\'); - c = read_escape(p, 0); + c = read_escape(p, 0, p->lex.pcur - 1); } else if ((func & STR_FUNC_QWORDS) && ISSPACE(c)) { /* ignore backslashed spaces in %w */ @@ -8613,8 +8514,9 @@ tokadd_string(struct parser_params *p, #define NEW_STRTERM(func, term, paren) new_strterm(p, func, term, paren) static void -flush_string_content(struct parser_params *p, rb_encoding *enc) +flush_string_content(struct parser_params *p, rb_encoding *enc, size_t back) { + p->lex.pcur -= back; if (has_delayed_token(p)) { ptrdiff_t len = p->lex.pcur - p->lex.ptok; if (len > 0) { @@ -8626,9 +8528,9 @@ flush_string_content(struct parser_params *p, rb_encoding *enc) p->lex.ptok = p->lex.pcur; } dispatch_scan_event(p, tSTRING_CONTENT); + p->lex.pcur += back; } -RUBY_FUNC_EXPORTED const uint_least32_t ruby_global_name_punct_bits[(0x7e - 0x20 + 31) / 32]; /* this can be shared with ripper, since it's independent from struct * parser_params. */ #ifndef RIPPER @@ -8725,7 +8627,7 @@ parse_string(struct parser_params *p, rb_strterm_literal_t *quote) int c, space = 0; rb_encoding *enc = p->enc; rb_encoding *base_enc = 0; - VALUE lit; + rb_parser_string_t *lit; if (func & STR_FUNC_TERM) { if (func & STR_FUNC_QWORDS) nextc(p); /* delayed term */ @@ -8747,14 +8649,14 @@ parse_string(struct parser_params *p, rb_strterm_literal_t *quote) if (func & STR_FUNC_QWORDS) { quote->func |= STR_FUNC_TERM; pushback(p, c); /* dispatch the term at tSTRING_END */ - add_delayed_token(p, p->lex.ptok, p->lex.pcur, __LINE__); + add_delayed_token(p, p->lex.ptok, p->lex.pcur); return ' '; } return parser_string_term(p, func); } if (space) { if (!ISSPACE(c)) pushback(p, c); - add_delayed_token(p, p->lex.ptok, p->lex.pcur, __LINE__); + add_delayed_token(p, p->lex.ptok, p->lex.pcur); return ' '; } newtok(p); @@ -8794,7 +8696,7 @@ parse_string(struct parser_params *p, rb_strterm_literal_t *quote) tokfix(p); lit = STR_NEW3(tok(p), toklen(p), enc, func); set_yylval_str(lit); - flush_string_content(p, enc); + flush_string_content(p, enc, 0); return tSTRING_CONTENT; } @@ -8898,7 +8800,7 @@ heredoc_restore(struct parser_params *p, rb_strterm_heredoc_t *here) p->lex.ptok = p->lex.pbeg + here->offset - here->quote; p->heredoc_end = p->ruby_sourceline; p->ruby_sourceline = (int)here->sourceline; - if (p->eofp) p->lex.nextline = AFTER_HEREDOC_WITHOUT_TERMINTOR; + if (p->eofp) p->lex.nextline = AFTER_HEREDOC_WITHOUT_TERMINATOR; p->eofp = 0; xfree(term); } @@ -9101,21 +9003,6 @@ set_number_literal(struct parser_params *p, enum yytokentype type, int suffix, i return type; } -#ifdef RIPPER -static void -dispatch_heredoc_end(struct parser_params *p) -{ - VALUE str; - if (has_delayed_token(p)) - dispatch_delayed_token(p, tSTRING_CONTENT); - str = STR_NEW(p->lex.ptok, p->lex.pend - p->lex.ptok); - ripper_dispatch1(p, ripper_token2eventid(tHEREDOC_END), str); - RUBY_SET_YYLLOC_FROM_STRTERM_HEREDOC(*p->yylloc); - lex_goto_eol(p); - token_flush(p); -} - -#else #define dispatch_heredoc_end(p) parser_dispatch_heredoc_end(p, __LINE__) static void parser_dispatch_heredoc_end(struct parser_params *p, int line) @@ -9123,17 +9010,21 @@ parser_dispatch_heredoc_end(struct parser_params *p, int line) if (has_delayed_token(p)) dispatch_delayed_token(p, tSTRING_CONTENT); +#ifdef RIPPER + VALUE str = STR_NEW(p->lex.ptok, p->lex.pend - p->lex.ptok); + ripper_dispatch1(p, ripper_token2eventid(tHEREDOC_END), str); +#else if (p->keep_tokens) { rb_parser_string_t *str = rb_parser_encoding_string_new(p, p->lex.ptok, p->lex.pend - p->lex.ptok, p->enc); RUBY_SET_YYLLOC_OF_HEREDOC_END(*p->yylloc); parser_append_tokens(p, str, tHEREDOC_END, line); } +#endif RUBY_SET_YYLLOC_FROM_STRTERM_HEREDOC(*p->yylloc); lex_goto_eol(p); token_flush(p); } -#endif static enum yytokentype here_document(struct parser_params *p, rb_strterm_heredoc_t *here) @@ -9141,7 +9032,7 @@ here_document(struct parser_params *p, rb_strterm_heredoc_t *here) int c, func, indent = 0; const char *eos, *ptr, *ptr_end; long len; - VALUE str = 0; + rb_parser_string_t *str = 0; rb_encoding *enc = p->enc; rb_encoding *base_enc = 0; int bol; @@ -9159,9 +9050,9 @@ here_document(struct parser_params *p, rb_strterm_heredoc_t *here) if (!has_delayed_token(p)) { dispatch_scan_event(p, tSTRING_CONTENT); } - else { + else if (p->delayed.end_line + 1 == p->ruby_sourceline) { if ((len = p->lex.pcur - p->lex.ptok) > 0) { - if (!(func & STR_FUNC_REGEXP) && rb_enc_asciicompat(enc)) { + if (!(func & STR_FUNC_REGEXP)) { int cr = ENC_CODERANGE_UNKNOWN; rb_str_coderange_scan_restartable(p->lex.ptok, p->lex.pcur, enc, &cr); if (cr != ENC_CODERANGE_7BIT && @@ -9174,6 +9065,10 @@ here_document(struct parser_params *p, rb_strterm_heredoc_t *here) } dispatch_delayed_token(p, tSTRING_CONTENT); } + else { + dispatch_delayed_token(p, tSTRING_CONTENT); + dispatch_scan_event(p, tSTRING_CONTENT); + } lex_goto_eol(p); #endif heredoc_restore(p, &p->lex.strterm->u.heredoc); @@ -9227,16 +9122,17 @@ here_document(struct parser_params *p, rb_strterm_heredoc_t *here) } if (str) - rb_str_cat(str, ptr, ptr_end - ptr); + parser_str_cat(str, ptr, ptr_end - ptr); else - str = STR_NEW(ptr, ptr_end - ptr); - if (!lex_eol_ptr_p(p, ptr_end)) rb_str_cat(str, "\n", 1); + str = rb_parser_encoding_string_new(p, ptr, ptr_end - ptr, enc); + if (!lex_eol_ptr_p(p, ptr_end)) parser_str_cat_cstr(str, "\n"); lex_goto_eol(p); if (p->heredoc_indent > 0) { goto flush_str; } if (nextc(p) == -1) { if (str) { + rb_parser_string_free(p, str); str = 0; } goto error; @@ -9274,7 +9170,7 @@ here_document(struct parser_params *p, rb_strterm_heredoc_t *here) #ifndef RIPPER if (bol) nd_set_fl_newline(yylval.node); #endif - flush_string_content(p, enc); + flush_string_content(p, enc, 0); return tSTRING_CONTENT; } tokadd(p, nextc(p)); @@ -9324,72 +9220,35 @@ arg_ambiguous(struct parser_params *p, char c) return TRUE; } -static ID -formal_argument(struct parser_params *p, ID id) +/* returns true value if formal argument error; + * Qtrue, or error message if ripper */ +static VALUE +formal_argument_error(struct parser_params *p, ID id) { switch (id_type(id)) { case ID_LOCAL: break; -#define ERR(mesg) yyerror0(mesg) - case ID_CONST: - ERR("formal argument cannot be a constant"); - return 0; - case ID_INSTANCE: - ERR("formal argument cannot be an instance variable"); - return 0; - case ID_GLOBAL: - ERR("formal argument cannot be a global variable"); - return 0; - case ID_CLASS: - ERR("formal argument cannot be a class variable"); - return 0; - default: - ERR("formal argument must be local variable"); - return 0; -#undef ERR - } - shadowing_lvar(p, id); - -/* - * Workaround for Prism::ParseTest#test_filepath for "unparser/corpus/literal/def.txt" - * - * See the discussion on https://github.com/ruby/ruby/pull/9923 - */ #ifndef RIPPER - return id; +# define ERR(mesg) (yyerror0(mesg), Qtrue) #else - return 0; +# define ERR(mesg) WARN_S(mesg) #endif -} - -#ifdef RIPPER -static VALUE -ripper_formal_argument(struct parser_params *p, ID id, VALUE lhs) -{ - switch (id_type(id)) { - case ID_LOCAL: - break; -#define ERR(mesg) (dispatch2(param_error, WARN_S(mesg), lhs), ripper_error(p)) case ID_CONST: - ERR("formal argument cannot be a constant"); - break; + return ERR("formal argument cannot be a constant"); case ID_INSTANCE: - ERR("formal argument cannot be an instance variable"); - break; + return ERR("formal argument cannot be an instance variable"); case ID_GLOBAL: - ERR("formal argument cannot be a global variable"); - break; + return ERR("formal argument cannot be a global variable"); case ID_CLASS: - ERR("formal argument cannot be a class variable"); - break; + return ERR("formal argument cannot be a class variable"); default: - ERR("formal argument must be local variable"); - break; + return ERR("formal argument must be local variable"); #undef ERR } - return lhs; + shadowing_lvar(p, id); + + return Qfalse; } -#endif static int lvar_defined(struct parser_params *p, ID id) @@ -9443,6 +9302,10 @@ parser_set_encode(struct parser_params *p, const char *name) rb_ary_unshift(excargs[2], rb_sprintf("%"PRIsVALUE":%d", p->ruby_sourcefile_string, p->ruby_sourceline)); VALUE exc = rb_make_exception(3, excargs); ruby_show_error_line(p, exc, &(YYLTYPE)RUBY_INIT_YYLLOC(), p->ruby_sourceline, p->lex.lastline); + + rb_ast_free(p->ast); + p->ast = NULL; + rb_exc_raise(exc); } enc = rb_enc_from_index(idx); @@ -10075,7 +9938,8 @@ parse_qmark(struct parser_params *p, int space_seen) { rb_encoding *enc; register int c; - VALUE lit; + rb_parser_string_t *lit; + const char *start = p->lex.pcur; if (IS_END()) { SET_LEX_STATE(EXPR_VALUE); @@ -10100,13 +9964,11 @@ parse_qmark(struct parser_params *p, int space_seen) } newtok(p); enc = p->enc; - if (!parser_isascii(p)) { - if (tokadd_mbchar(p, c) == -1) return 0; - } - else if ((rb_enc_isalnum(c, p->enc) || c == '_') && - !lex_eol_p(p) && is_identchar(p, p->lex.pcur, p->lex.pend, p->enc)) { + int w = parser_precise_mbclen(p, start); + if (is_identchar(p, start, p->lex.pend, p->enc) && + !(lex_eol_ptr_n_p(p, start, w) || !is_identchar(p, start + w, p->lex.pend, p->enc))) { if (space_seen) { - const char *start = p->lex.pcur - 1, *ptr = start; + const char *ptr = start; do { int n = parser_precise_mbclen(p, ptr); if (n < 0) return -1; @@ -10124,17 +9986,17 @@ parse_qmark(struct parser_params *p, int space_seen) enc = rb_utf8_encoding(); tokadd_utf8(p, &enc, -1, 0, 0); } - else if (!ISASCII(c = peekc(p))) { + else if (!ISASCII(c = peekc(p)) && c != -1) { nextc(p); if (tokadd_mbchar(p, c) == -1) return 0; } else { - c = read_escape(p, 0); + c = read_escape(p, 0, p->lex.pcur - rb_strlen_lit("?\\")); tokadd(p, c); } } else { - tokadd(p, c); + if (tokadd_mbchar(p, c) == -1) return 0; } tokfix(p); lit = STR_NEW3(tok(p), toklen(p), enc, 0); @@ -10338,7 +10200,7 @@ parse_gvar(struct parser_params *p, const enum lex_state_e last_state) return '$'; } gvar: - set_yylval_name(TOK_INTERN()); + tokenize_ident(p); return tGVAR; case '&': /* $&: last match */ @@ -10505,7 +10367,7 @@ parse_ident(struct parser_params *p, int c, int cmd_state) if (IS_LABEL_SUFFIX(0)) { SET_LEX_STATE(EXPR_ARG|EXPR_LABELED); nextc(p); - set_yylval_name(TOK_INTERN()); + tokenize_ident(p); return tLABEL; } } @@ -10722,7 +10584,24 @@ parser_yylex(struct parser_params *p) token_flush(p); } goto retry; + case 'a': + if (peek_word_at(p, "nd", 2, 0)) goto leading_logical; + goto bol; + case 'o': + if (peek_word_at(p, "r", 1, 0)) goto leading_logical; + goto bol; + case '|': + if (peek(p, '|')) goto leading_logical; + goto bol; case '&': + if (peek(p, '&')) { + leading_logical: + pushback(p, c); + dispatch_delayed_token(p, tIGNORED_NL); + cmd_state = FALSE; + goto retry; + } + /* fall through */ case '.': { dispatch_delayed_token(p, tIGNORED_NL); if (peek(p, '.') == (c == '&')) { @@ -10731,11 +10610,15 @@ parser_yylex(struct parser_params *p) goto retry; } } + bol: default: p->ruby_sourceline--; p->lex.nextline = p->lex.lastline; set_lastline(p, prevline); case -1: /* EOF no decrement*/ + if (c == -1 && space_seen) { + dispatch_scan_event(p, tSP); + } lex_goto_eol(p); if (c != -1) { token_flush(p); @@ -11049,6 +10932,7 @@ parser_yylex(struct parser_params *p) if (c == '>') { SET_LEX_STATE(EXPR_ENDFN); yylval.num = p->lex.lpar_beg; + p->lex.lpar_beg = p->lex.paren_nest; return tLAMBDA; } if (IS_BEG() || (IS_SPCARG(c) && arg_ambiguous(p, '-'))) { @@ -11068,17 +10952,13 @@ parser_yylex(struct parser_params *p) SET_LEX_STATE(EXPR_BEG); if ((c = nextc(p)) == '.') { if ((c = nextc(p)) == '.') { - if (p->ctxt.in_argdef) { + if (p->ctxt.in_argdef || IS_LABEL_POSSIBLE()) { SET_LEX_STATE(EXPR_ENDARG); return tBDOT3; } if (p->lex.paren_nest == 0 && looking_at_eol_p(p)) { rb_warn0("... at EOL, should be parenthesized?"); } - else if (p->lex.lpar_beg >= 0 && p->lex.lpar_beg+1 == p->lex.paren_nest) { - if (IS_lex_state_for(last_state, EXPR_LABEL)) - return tDOT3; - } return is_beg ? tBDOT3 : tDOT3; } pushback(p, c); @@ -11381,24 +11261,26 @@ node_newnode(struct parser_params *p, enum node_type type, size_t size, size_t a #define NODE_NEWNODE(node_type, type, loc) (type *)(node_newnode(p, node_type, sizeof(type), RUBY_ALIGNOF(type), loc)) static rb_node_scope_t * -rb_node_scope_new(struct parser_params *p, rb_node_args_t *nd_args, NODE *nd_body, const YYLTYPE *loc) +rb_node_scope_new(struct parser_params *p, rb_node_args_t *nd_args, NODE *nd_body, NODE *nd_parent, const YYLTYPE *loc) { rb_ast_id_table_t *nd_tbl; nd_tbl = local_tbl(p); rb_node_scope_t *n = NODE_NEWNODE(NODE_SCOPE, rb_node_scope_t, loc); n->nd_tbl = nd_tbl; n->nd_body = nd_body; + n->nd_parent = nd_parent; n->nd_args = nd_args; return n; } static rb_node_scope_t * -rb_node_scope_new2(struct parser_params *p, rb_ast_id_table_t *nd_tbl, rb_node_args_t *nd_args, NODE *nd_body, const YYLTYPE *loc) +rb_node_scope_new2(struct parser_params *p, rb_ast_id_table_t *nd_tbl, rb_node_args_t *nd_args, NODE *nd_body, NODE *nd_parent, const YYLTYPE *loc) { rb_node_scope_t *n = NODE_NEWNODE(NODE_SCOPE, rb_node_scope_t, loc); n->nd_tbl = nd_tbl; n->nd_body = nd_body; + n->nd_parent = nd_parent; n->nd_args = nd_args; return n; @@ -11437,11 +11319,15 @@ rb_node_block_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc) } static rb_node_for_t * -rb_node_for_new(struct parser_params *p, NODE *nd_iter, NODE *nd_body, const YYLTYPE *loc) +rb_node_for_new(struct parser_params *p, NODE *nd_iter, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *for_keyword_loc, const YYLTYPE *in_keyword_loc, const YYLTYPE *do_keyword_loc, const YYLTYPE *end_keyword_loc) { rb_node_for_t *n = NODE_NEWNODE(NODE_FOR, rb_node_for_t, loc); n->nd_body = nd_body; n->nd_iter = nd_iter; + n->for_keyword_loc = *for_keyword_loc; + n->in_keyword_loc = *in_keyword_loc; + n->do_keyword_loc = *do_keyword_loc; + n->end_keyword_loc = *end_keyword_loc; return n; } @@ -11484,10 +11370,11 @@ rb_node_rescue_new(struct parser_params *p, NODE *nd_head, NODE *nd_resq, NODE * } static rb_node_resbody_t * -rb_node_resbody_new(struct parser_params *p, NODE *nd_args, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc) +rb_node_resbody_new(struct parser_params *p, NODE *nd_args, NODE *nd_exc_var, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc) { rb_node_resbody_t *n = NODE_NEWNODE(NODE_RESBODY, rb_node_resbody_t, loc); n->nd_args = nd_args; + n->nd_exc_var = nd_exc_var; n->nd_body = nd_body; n->nd_next = nd_next; @@ -11505,97 +11392,122 @@ rb_node_ensure_new(struct parser_params *p, NODE *nd_head, NODE *nd_ensr, const } static rb_node_and_t * -rb_node_and_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc) +rb_node_and_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc, const YYLTYPE *operator_loc) { rb_node_and_t *n = NODE_NEWNODE(NODE_AND, rb_node_and_t, loc); n->nd_1st = nd_1st; n->nd_2nd = nd_2nd; + n->operator_loc = *operator_loc; return n; } static rb_node_or_t * -rb_node_or_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc) +rb_node_or_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc, const YYLTYPE *operator_loc) { rb_node_or_t *n = NODE_NEWNODE(NODE_OR, rb_node_or_t, loc); n->nd_1st = nd_1st; n->nd_2nd = nd_2nd; + n->operator_loc = *operator_loc; return n; } static rb_node_return_t * -rb_node_return_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc) +rb_node_return_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc, const YYLTYPE *keyword_loc) { rb_node_return_t *n = NODE_NEWNODE(NODE_RETURN, rb_node_return_t, loc); n->nd_stts = nd_stts; + n->keyword_loc = *keyword_loc; return n; } static rb_node_yield_t * -rb_node_yield_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc) +rb_node_yield_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *lparen_loc, const YYLTYPE *rparen_loc) { + if (nd_head) no_blockarg(p, nd_head); + rb_node_yield_t *n = NODE_NEWNODE(NODE_YIELD, rb_node_yield_t, loc); n->nd_head = nd_head; + n->keyword_loc = *keyword_loc; + n->lparen_loc = *lparen_loc; + n->rparen_loc = *rparen_loc; return n; } static rb_node_if_t * -rb_node_if_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, NODE *nd_else, const YYLTYPE *loc) +rb_node_if_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, NODE *nd_else, const YYLTYPE *loc, const YYLTYPE* if_keyword_loc, const YYLTYPE* then_keyword_loc, const YYLTYPE* end_keyword_loc) { rb_node_if_t *n = NODE_NEWNODE(NODE_IF, rb_node_if_t, loc); n->nd_cond = nd_cond; n->nd_body = nd_body; n->nd_else = nd_else; + n->if_keyword_loc = *if_keyword_loc; + n->then_keyword_loc = *then_keyword_loc; + n->end_keyword_loc = *end_keyword_loc; return n; } static rb_node_unless_t * -rb_node_unless_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, NODE *nd_else, const YYLTYPE *loc) +rb_node_unless_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, NODE *nd_else, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *then_keyword_loc, const YYLTYPE *end_keyword_loc) { rb_node_unless_t *n = NODE_NEWNODE(NODE_UNLESS, rb_node_unless_t, loc); n->nd_cond = nd_cond; n->nd_body = nd_body; n->nd_else = nd_else; + n->keyword_loc = *keyword_loc; + n->then_keyword_loc = *then_keyword_loc; + n->end_keyword_loc = *end_keyword_loc; return n; } static rb_node_class_t * -rb_node_class_new(struct parser_params *p, NODE *nd_cpath, NODE *nd_body, NODE *nd_super, const YYLTYPE *loc) +rb_node_class_new(struct parser_params *p, NODE *nd_cpath, NODE *nd_body, NODE *nd_super, const YYLTYPE *loc, const YYLTYPE *class_keyword_loc, const YYLTYPE *inheritance_operator_loc, const YYLTYPE *end_keyword_loc) { /* Keep the order of node creation */ - NODE *scope = NEW_SCOPE(0, nd_body, loc); + NODE *scope = NEW_SCOPE(0, nd_body, NULL, loc); rb_node_class_t *n = NODE_NEWNODE(NODE_CLASS, rb_node_class_t, loc); + RNODE_SCOPE(scope)->nd_parent = &n->node; n->nd_cpath = nd_cpath; n->nd_body = scope; n->nd_super = nd_super; + n->class_keyword_loc = *class_keyword_loc; + n->inheritance_operator_loc = *inheritance_operator_loc; + n->end_keyword_loc = *end_keyword_loc; return n; } static rb_node_sclass_t * -rb_node_sclass_new(struct parser_params *p, NODE *nd_recv, NODE *nd_body, const YYLTYPE *loc) +rb_node_sclass_new(struct parser_params *p, NODE *nd_recv, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *class_keyword_loc, const YYLTYPE *operator_loc, const YYLTYPE *end_keyword_loc) { /* Keep the order of node creation */ - NODE *scope = NEW_SCOPE(0, nd_body, loc); + NODE *scope = NEW_SCOPE(0, nd_body, NULL, loc); rb_node_sclass_t *n = NODE_NEWNODE(NODE_SCLASS, rb_node_sclass_t, loc); + RNODE_SCOPE(scope)->nd_parent = &n->node; n->nd_recv = nd_recv; n->nd_body = scope; + n->class_keyword_loc = *class_keyword_loc; + n->operator_loc = *operator_loc; + n->end_keyword_loc = *end_keyword_loc; return n; } static rb_node_module_t * -rb_node_module_new(struct parser_params *p, NODE *nd_cpath, NODE *nd_body, const YYLTYPE *loc) +rb_node_module_new(struct parser_params *p, NODE *nd_cpath, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *module_keyword_loc, const YYLTYPE *end_keyword_loc) { /* Keep the order of node creation */ - NODE *scope = NEW_SCOPE(0, nd_body, loc); + NODE *scope = NEW_SCOPE(0, nd_body, NULL, loc); rb_node_module_t *n = NODE_NEWNODE(NODE_MODULE, rb_node_module_t, loc); + RNODE_SCOPE(scope)->nd_parent = &n->node; n->nd_cpath = nd_cpath; n->nd_body = scope; + n->module_keyword_loc = *module_keyword_loc; + n->end_keyword_loc = *end_keyword_loc; return n; } @@ -11604,8 +11516,9 @@ static rb_node_iter_t * rb_node_iter_new(struct parser_params *p, rb_node_args_t *nd_args, NODE *nd_body, const YYLTYPE *loc) { /* Keep the order of node creation */ - NODE *scope = NEW_SCOPE(nd_args, nd_body, loc); + NODE *scope = NEW_SCOPE(nd_args, nd_body, NULL, loc); rb_node_iter_t *n = NODE_NEWNODE(NODE_ITER, rb_node_iter_t, loc); + RNODE_SCOPE(scope)->nd_parent = &n->node; n->nd_body = scope; n->nd_iter = 0; @@ -11613,125 +11526,151 @@ rb_node_iter_new(struct parser_params *p, rb_node_args_t *nd_args, NODE *nd_body } static rb_node_lambda_t * -rb_node_lambda_new(struct parser_params *p, rb_node_args_t *nd_args, NODE *nd_body, const YYLTYPE *loc) +rb_node_lambda_new(struct parser_params *p, rb_node_args_t *nd_args, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *operator_loc, const YYLTYPE *opening_loc, const YYLTYPE *closing_loc) { /* Keep the order of node creation */ - NODE *scope = NEW_SCOPE(nd_args, nd_body, loc); - rb_node_lambda_t *n = NODE_NEWNODE(NODE_LAMBDA, rb_node_lambda_t, loc); + NODE *scope = NEW_SCOPE(nd_args, nd_body, NULL, loc); + YYLTYPE lambda_loc = code_loc_gen(operator_loc, closing_loc); + rb_node_lambda_t *n = NODE_NEWNODE(NODE_LAMBDA, rb_node_lambda_t, &lambda_loc); + RNODE_SCOPE(scope)->nd_parent = &n->node; n->nd_body = scope; + n->operator_loc = *operator_loc; + n->opening_loc = *opening_loc; + n->closing_loc = *closing_loc; return n; } static rb_node_case_t * -rb_node_case_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, const YYLTYPE *loc) +rb_node_case_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *case_keyword_loc, const YYLTYPE *end_keyword_loc) { rb_node_case_t *n = NODE_NEWNODE(NODE_CASE, rb_node_case_t, loc); n->nd_head = nd_head; n->nd_body = nd_body; + n->case_keyword_loc = *case_keyword_loc; + n->end_keyword_loc = *end_keyword_loc; return n; } static rb_node_case2_t * -rb_node_case2_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc) +rb_node_case2_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *case_keyword_loc, const YYLTYPE *end_keyword_loc) { rb_node_case2_t *n = NODE_NEWNODE(NODE_CASE2, rb_node_case2_t, loc); n->nd_head = 0; n->nd_body = nd_body; + n->case_keyword_loc = *case_keyword_loc; + n->end_keyword_loc = *end_keyword_loc; return n; } static rb_node_case3_t * -rb_node_case3_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, const YYLTYPE *loc) +rb_node_case3_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *case_keyword_loc, const YYLTYPE *end_keyword_loc) { rb_node_case3_t *n = NODE_NEWNODE(NODE_CASE3, rb_node_case3_t, loc); n->nd_head = nd_head; n->nd_body = nd_body; + n->case_keyword_loc = *case_keyword_loc; + n->end_keyword_loc = *end_keyword_loc; return n; } static rb_node_when_t * -rb_node_when_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc) +rb_node_when_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *then_keyword_loc) { rb_node_when_t *n = NODE_NEWNODE(NODE_WHEN, rb_node_when_t, loc); n->nd_head = nd_head; n->nd_body = nd_body; n->nd_next = nd_next; + n->keyword_loc = *keyword_loc; + n->then_keyword_loc = *then_keyword_loc; return n; } static rb_node_in_t * -rb_node_in_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc) +rb_node_in_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc, const YYLTYPE *in_keyword_loc, const YYLTYPE *then_keyword_loc, const YYLTYPE *operator_loc) { rb_node_in_t *n = NODE_NEWNODE(NODE_IN, rb_node_in_t, loc); n->nd_head = nd_head; n->nd_body = nd_body; n->nd_next = nd_next; + n->in_keyword_loc = *in_keyword_loc; + n->then_keyword_loc = *then_keyword_loc; + n->operator_loc = *operator_loc; return n; } static rb_node_while_t * -rb_node_while_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, long nd_state, const YYLTYPE *loc) +rb_node_while_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, long nd_state, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *closing_loc) { rb_node_while_t *n = NODE_NEWNODE(NODE_WHILE, rb_node_while_t, loc); n->nd_cond = nd_cond; n->nd_body = nd_body; n->nd_state = nd_state; + n->keyword_loc = *keyword_loc; + n->closing_loc = *closing_loc; return n; } static rb_node_until_t * -rb_node_until_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, long nd_state, const YYLTYPE *loc) +rb_node_until_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, long nd_state, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *closing_loc) { rb_node_until_t *n = NODE_NEWNODE(NODE_UNTIL, rb_node_until_t, loc); n->nd_cond = nd_cond; n->nd_body = nd_body; n->nd_state = nd_state; + n->keyword_loc = *keyword_loc; + n->closing_loc = *closing_loc; return n; } static rb_node_colon2_t * -rb_node_colon2_new(struct parser_params *p, NODE *nd_head, ID nd_mid, const YYLTYPE *loc) +rb_node_colon2_new(struct parser_params *p, NODE *nd_head, ID nd_mid, const YYLTYPE *loc, const YYLTYPE *delimiter_loc, const YYLTYPE *name_loc) { rb_node_colon2_t *n = NODE_NEWNODE(NODE_COLON2, rb_node_colon2_t, loc); n->nd_head = nd_head; n->nd_mid = nd_mid; + n->delimiter_loc = *delimiter_loc; + n->name_loc = *name_loc; return n; } static rb_node_colon3_t * -rb_node_colon3_new(struct parser_params *p, ID nd_mid, const YYLTYPE *loc) +rb_node_colon3_new(struct parser_params *p, ID nd_mid, const YYLTYPE *loc, const YYLTYPE *delimiter_loc, const YYLTYPE *name_loc) { rb_node_colon3_t *n = NODE_NEWNODE(NODE_COLON3, rb_node_colon3_t, loc); n->nd_mid = nd_mid; + n->delimiter_loc = *delimiter_loc; + n->name_loc = *name_loc; return n; } static rb_node_dot2_t * -rb_node_dot2_new(struct parser_params *p, NODE *nd_beg, NODE *nd_end, const YYLTYPE *loc) +rb_node_dot2_new(struct parser_params *p, NODE *nd_beg, NODE *nd_end, const YYLTYPE *loc, const YYLTYPE *operator_loc) { rb_node_dot2_t *n = NODE_NEWNODE(NODE_DOT2, rb_node_dot2_t, loc); n->nd_beg = nd_beg; n->nd_end = nd_end; + n->operator_loc = *operator_loc; return n; } static rb_node_dot3_t * -rb_node_dot3_new(struct parser_params *p, NODE *nd_beg, NODE *nd_end, const YYLTYPE *loc) +rb_node_dot3_new(struct parser_params *p, NODE *nd_beg, NODE *nd_end, const YYLTYPE *loc, const YYLTYPE *operator_loc) { rb_node_dot3_t *n = NODE_NEWNODE(NODE_DOT3, rb_node_dot3_t, loc); n->nd_beg = nd_beg; n->nd_end = nd_end; + n->operator_loc = *operator_loc; return n; } @@ -11770,10 +11709,14 @@ rb_node_false_new(struct parser_params *p, const YYLTYPE *loc) } static rb_node_super_t * -rb_node_super_new(struct parser_params *p, NODE *nd_args, const YYLTYPE *loc) +rb_node_super_new(struct parser_params *p, NODE *nd_args, const YYLTYPE *loc, + const YYLTYPE *keyword_loc, const YYLTYPE *lparen_loc, const YYLTYPE *rparen_loc) { rb_node_super_t *n = NODE_NEWNODE(NODE_SUPER, rb_node_super_t, loc); n->nd_args = nd_args; + n->keyword_loc = *keyword_loc; + n->lparen_loc = *lparen_loc; + n->rparen_loc = *rparen_loc; return n; } @@ -11910,19 +11853,23 @@ rb_node_cvasgn_new(struct parser_params *p, ID nd_vid, NODE *nd_value, const YYL } static rb_node_op_asgn1_t * -rb_node_op_asgn1_new(struct parser_params *p, NODE *nd_recv, ID nd_mid, NODE *index, NODE *rvalue, const YYLTYPE *loc) +rb_node_op_asgn1_new(struct parser_params *p, NODE *nd_recv, ID nd_mid, NODE *index, NODE *rvalue, const YYLTYPE *loc, const YYLTYPE *call_operator_loc, const YYLTYPE *opening_loc, const YYLTYPE *closing_loc, const YYLTYPE *binary_operator_loc) { rb_node_op_asgn1_t *n = NODE_NEWNODE(NODE_OP_ASGN1, rb_node_op_asgn1_t, loc); n->nd_recv = nd_recv; n->nd_mid = nd_mid; n->nd_index = index; n->nd_rvalue = rvalue; + n->call_operator_loc = *call_operator_loc; + n->opening_loc = *opening_loc; + n->closing_loc = *closing_loc; + n->binary_operator_loc = *binary_operator_loc; return n; } static rb_node_op_asgn2_t * -rb_node_op_asgn2_new(struct parser_params *p, NODE *nd_recv, NODE *nd_value, ID nd_vid, ID nd_mid, bool nd_aid, const YYLTYPE *loc) +rb_node_op_asgn2_new(struct parser_params *p, NODE *nd_recv, NODE *nd_value, ID nd_vid, ID nd_mid, bool nd_aid, const YYLTYPE *loc, const YYLTYPE *call_operator_loc, const YYLTYPE *message_loc, const YYLTYPE *binary_operator_loc) { rb_node_op_asgn2_t *n = NODE_NEWNODE(NODE_OP_ASGN2, rb_node_op_asgn2_t, loc); n->nd_recv = nd_recv; @@ -11930,6 +11877,9 @@ rb_node_op_asgn2_new(struct parser_params *p, NODE *nd_recv, NODE *nd_value, ID n->nd_vid = nd_vid; n->nd_mid = nd_mid; n->nd_aid = nd_aid; + n->call_operator_loc = *call_operator_loc; + n->message_loc = *message_loc; + n->binary_operator_loc = *binary_operator_loc; return n; } @@ -12140,20 +12090,25 @@ rb_node_dsym_new(struct parser_params *p, rb_parser_string_t *string, long nd_al } static rb_node_evstr_t * -rb_node_evstr_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc) +rb_node_evstr_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *opening_loc, const YYLTYPE *closing_loc) { rb_node_evstr_t *n = NODE_NEWNODE(NODE_EVSTR, rb_node_evstr_t, loc); n->nd_body = nd_body; + n->opening_loc = *opening_loc; + n->closing_loc = *closing_loc; return n; } static rb_node_regx_t * -rb_node_regx_new(struct parser_params *p, rb_parser_string_t *string, int options, const YYLTYPE *loc) +rb_node_regx_new(struct parser_params *p, rb_parser_string_t *string, int options, const YYLTYPE *loc, const YYLTYPE *opening_loc, const YYLTYPE *content_loc, const YYLTYPE *closing_loc) { rb_node_regx_t *n = NODE_NEWNODE(NODE_REGX, rb_node_regx_t, loc); n->string = string; n->options = options & RE_OPTION_MASK; + n->opening_loc = *opening_loc; + n->content_loc = *content_loc; + n->closing_loc = *closing_loc; return n; } @@ -12290,40 +12245,45 @@ rb_node_argspush_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, cons } static rb_node_splat_t * -rb_node_splat_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc) +rb_node_splat_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc, const YYLTYPE *operator_loc) { rb_node_splat_t *n = NODE_NEWNODE(NODE_SPLAT, rb_node_splat_t, loc); n->nd_head = nd_head; + n->operator_loc = *operator_loc; return n; } static rb_node_block_pass_t * -rb_node_block_pass_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc) +rb_node_block_pass_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *operator_loc) { rb_node_block_pass_t *n = NODE_NEWNODE(NODE_BLOCK_PASS, rb_node_block_pass_t, loc); + n->forwarding = 0; n->nd_head = 0; n->nd_body = nd_body; + n->operator_loc = *operator_loc; return n; } static rb_node_alias_t * -rb_node_alias_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc) +rb_node_alias_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc, const YYLTYPE *keyword_loc) { rb_node_alias_t *n = NODE_NEWNODE(NODE_ALIAS, rb_node_alias_t, loc); n->nd_1st = nd_1st; n->nd_2nd = nd_2nd; + n->keyword_loc = *keyword_loc; return n; } static rb_node_valias_t * -rb_node_valias_new(struct parser_params *p, ID nd_alias, ID nd_orig, const YYLTYPE *loc) +rb_node_valias_new(struct parser_params *p, ID nd_alias, ID nd_orig, const YYLTYPE *loc, const YYLTYPE *keyword_loc) { rb_node_valias_t *n = NODE_NEWNODE(NODE_VALIAS, rb_node_valias_t, loc); n->nd_alias = nd_alias; n->nd_orig = nd_orig; + n->keyword_loc = *keyword_loc; return n; } @@ -12332,7 +12292,9 @@ static rb_node_undef_t * rb_node_undef_new(struct parser_params *p, NODE *nd_undef, const YYLTYPE *loc) { rb_node_undef_t *n = NODE_NEWNODE(NODE_UNDEF, rb_node_undef_t, loc); - n->nd_undef = nd_undef; + n->nd_undefs = rb_parser_ary_new_capa_for_node(p, 1); + n->keyword_loc = NULL_LOC; + rb_parser_ary_push_node(p, n->nd_undefs, nd_undef); return n; } @@ -12346,19 +12308,23 @@ rb_node_errinfo_new(struct parser_params *p, const YYLTYPE *loc) } static rb_node_defined_t * -rb_node_defined_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc) +rb_node_defined_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc, const YYLTYPE *keyword_loc) { rb_node_defined_t *n = NODE_NEWNODE(NODE_DEFINED, rb_node_defined_t, loc); n->nd_head = nd_head; + n->keyword_loc = *keyword_loc; return n; } static rb_node_postexe_t * -rb_node_postexe_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc) +rb_node_postexe_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *opening_loc, const YYLTYPE *closing_loc) { rb_node_postexe_t *n = NODE_NEWNODE(NODE_POSTEXE, rb_node_postexe_t, loc); n->nd_body = nd_body; + n->keyword_loc = *keyword_loc; + n->opening_loc = *opening_loc; + n->closing_loc = *closing_loc; return n; } @@ -12468,30 +12434,33 @@ rb_node_error_new(struct parser_params *p, const YYLTYPE *loc) } static rb_node_break_t * -rb_node_break_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc) +rb_node_break_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc, const YYLTYPE *keyword_loc) { rb_node_break_t *n = NODE_NEWNODE(NODE_BREAK, rb_node_break_t, loc); n->nd_stts = nd_stts; n->nd_chain = 0; + n->keyword_loc = *keyword_loc; return n; } static rb_node_next_t * -rb_node_next_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc) +rb_node_next_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc, const YYLTYPE *keyword_loc) { rb_node_next_t *n = NODE_NEWNODE(NODE_NEXT, rb_node_next_t, loc); n->nd_stts = nd_stts; n->nd_chain = 0; + n->keyword_loc = *keyword_loc; return n; } static rb_node_redo_t * -rb_node_redo_new(struct parser_params *p, const YYLTYPE *loc) +rb_node_redo_new(struct parser_params *p, const YYLTYPE *loc, const YYLTYPE *keyword_loc) { rb_node_redo_t *n = NODE_NEWNODE(NODE_REDO, rb_node_redo_t, loc); n->nd_chain = 0; + n->keyword_loc = *keyword_loc; return n; } @@ -12500,7 +12469,6 @@ static rb_node_def_temp_t * rb_node_def_temp_new(struct parser_params *p, const YYLTYPE *loc) { rb_node_def_temp_t *n = NODE_NEWNODE((enum node_type)NODE_DEF_TEMP, rb_node_def_temp_t, loc); - n->save.cur_arg = p->cur_arg; n->save.numparam_save = 0; n->save.max_numparam = 0; n->save.ctxt = p->ctxt; @@ -12799,12 +12767,16 @@ str2dstr(struct parser_params *p, NODE *node) } static NODE * -str2regx(struct parser_params *p, NODE *node, int options) +str2regx(struct parser_params *p, NODE *node, int options, const YYLTYPE *loc, const YYLTYPE *opening_loc, const YYLTYPE *content_loc, const YYLTYPE *closing_loc) { NODE *new_node = (NODE *)NODE_NEW_INTERNAL(NODE_REGX, rb_node_regx_t); nd_copy_flag(new_node, node); RNODE_REGX(new_node)->string = RNODE_STR(node)->string; RNODE_REGX(new_node)->options = options; + nd_set_loc(new_node, loc); + RNODE_REGX(new_node)->opening_loc = *opening_loc; + RNODE_REGX(new_node)->content_loc = *content_loc; + RNODE_REGX(new_node)->closing_loc = *closing_loc; RNODE_STR(node)->string = 0; return new_node; @@ -12820,7 +12792,7 @@ evstr2dstr(struct parser_params *p, NODE *node) } static NODE * -new_evstr(struct parser_params *p, NODE *node, const YYLTYPE *loc) +new_evstr(struct parser_params *p, NODE *node, const YYLTYPE *loc, const YYLTYPE *opening_loc, const YYLTYPE *closing_loc) { NODE *head = node; @@ -12834,7 +12806,7 @@ new_evstr(struct parser_params *p, NODE *node, const YYLTYPE *loc) return node; } } - return NEW_EVSTR(head, loc); + return NEW_EVSTR(head, loc, opening_loc, closing_loc); } static NODE * @@ -12849,8 +12821,8 @@ call_bin_op(struct parser_params *p, NODE *recv, ID id, NODE *arg1, const YYLTYPE *op_loc, const YYLTYPE *loc) { NODE *expr; - value_expr(recv); - value_expr(arg1); + value_expr(p, recv); + value_expr(p, arg1); expr = NEW_OPCALL(recv, id, NEW_LIST(arg1, &arg1->nd_loc), loc); nd_set_line(expr, op_loc->beg_pos.lineno); return expr; @@ -12860,7 +12832,7 @@ static NODE * call_uni_op(struct parser_params *p, NODE *recv, ID id, const YYLTYPE *op_loc, const YYLTYPE *loc) { NODE *opcall; - value_expr(recv); + value_expr(p, recv); opcall = NEW_OPCALL(recv, id, 0, loc); nd_set_line(opcall, op_loc->beg_pos.lineno); return opcall; @@ -12885,6 +12857,16 @@ new_command_qcall(struct parser_params* p, ID atype, NODE *recv, ID mid, NODE *a return ret; } +static rb_locations_lambda_body_t* +new_locations_lambda_body(struct parser_params* p, NODE *node, const YYLTYPE *loc, const YYLTYPE *opening_loc, const YYLTYPE *closing_loc) +{ + rb_locations_lambda_body_t *body = xcalloc(1, sizeof(rb_locations_lambda_body_t)); + body->node = node; + body->opening_loc = *opening_loc; + body->closing_loc = *closing_loc; + return body; +} + #define nd_once_body(node) (nd_type_p((node), NODE_ONCE) ? RNODE_ONCE(node)->nd_body : node) static NODE* @@ -12900,8 +12882,8 @@ match_op(struct parser_params *p, NODE *node1, NODE *node2, const YYLTYPE *op_lo NODE *n; int line = op_loc->beg_pos.lineno; - value_expr(node1); - value_expr(node2); + value_expr(p, node1); + value_expr(p, node2); if ((n = last_expr_once_body(node1)) != 0) { switch (nd_type(n)) { @@ -12917,7 +12899,7 @@ match_op(struct parser_params *p, NODE *node1, NODE *node2, const YYLTYPE *op_lo const VALUE lit = rb_node_regx_string_val(n); if (!NIL_P(lit)) { NODE *match = NEW_MATCH2(node1, node2, loc); - RNODE_MATCH2(match)->nd_args = reg_named_capture_assign(p, lit, loc); + RNODE_MATCH2(match)->nd_args = reg_named_capture_assign(p, lit, loc, assignable); nd_set_line(match, line); return match; } @@ -12961,10 +12943,10 @@ numparam_nested_p(struct parser_params *p) NODE *inner = local->numparam.inner; if (outer || inner) { NODE *used = outer ? outer : inner; - compile_error(p, "numbered parameter is already used in\n" - "%s:%d: %s block here", - p->ruby_sourcefile, nd_line(used), - outer ? "outer" : "inner"); + compile_error(p, "numbered parameter is already used in %s block\n" + "%s:%d: numbered parameter is already used here", + outer ? "outer" : "inner", + p->ruby_sourcefile, nd_line(used)); parser_show_error_line(p, &used->nd_loc); return 1; } @@ -12976,8 +12958,8 @@ numparam_used_p(struct parser_params *p) { NODE *numparam = p->lvtbl->numparam.current; if (numparam) { - compile_error(p, "numbered parameter is already used in\n" - "%s:%d: current block here", + compile_error(p, "'it' is not allowed when a numbered parameter is already used\n" + "%s:%d: numbered parameter is already used here", p->ruby_sourcefile, nd_line(numparam)); parser_show_error_line(p, &numparam->nd_loc); return 1; @@ -12990,8 +12972,8 @@ it_used_p(struct parser_params *p) { NODE *it = p->lvtbl->it; if (it) { - compile_error(p, "'it' is already used in\n" - "%s:%d: current block here", + compile_error(p, "numbered parameters are not allowed when 'it' is already used\n" + "%s:%d: 'it' is already used here", p->ruby_sourcefile, nd_line(it)); parser_show_error_line(p, &it->nd_loc); return 1; @@ -13031,19 +13013,11 @@ gettable(struct parser_params *p, ID id, const YYLTYPE *loc) case ID_LOCAL: if (dyna_in_block(p) && dvar_defined_ref(p, id, &vidp)) { if (NUMPARAM_ID_P(id) && (numparam_nested_p(p) || it_used_p(p))) return 0; - if (id == p->cur_arg) { - compile_error(p, "circular argument reference - %"PRIsWARN, rb_id2str(id)); - return 0; - } if (vidp) *vidp |= LVAR_USED; node = NEW_DVAR(id, loc); return node; } if (local_id_ref(p, id, &vidp)) { - if (id == p->cur_arg) { - compile_error(p, "circular argument reference - %"PRIsWARN, rb_id2str(id)); - return 0; - } if (vidp) *vidp |= LVAR_USED; node = NEW_LVAR(id, loc); return node; @@ -13062,14 +13036,14 @@ gettable(struct parser_params *p, ID id, const YYLTYPE *loc) } # endif /* method call without arguments */ - if (dyna_in_block(p) && id == rb_intern("it") && !(DVARS_TERMINAL_P(p->lvtbl->args) || DVARS_TERMINAL_P(p->lvtbl->args->prev))) { + if (dyna_in_block(p) && id == idIt && !(DVARS_TERMINAL_P(p->lvtbl->args) || DVARS_TERMINAL_P(p->lvtbl->args->prev))) { if (numparam_used_p(p)) return 0; if (p->max_numparam == ORDINAL_PARAM) { compile_error(p, "ordinary parameter is defined"); return 0; } if (!p->it_id) { - p->it_id = internal_id(p); + p->it_id = idItImplicit; vtable_add(p->lvtbl->args, p->it_id); } NODE *node = NEW_DVAR(p->it_id, loc); @@ -13116,8 +13090,11 @@ kwd_append(rb_node_kw_arg_t *kwlist, rb_node_kw_arg_t *kw) } static NODE * -new_defined(struct parser_params *p, NODE *expr, const YYLTYPE *loc) +new_defined(struct parser_params *p, NODE *expr, const YYLTYPE *loc, const YYLTYPE *keyword_loc) { + int had_trailing_semicolon = p->ctxt.has_trailing_semicolon; + p->ctxt.has_trailing_semicolon = 0; + NODE *n = expr; while (n) { if (nd_type_p(n, NODE_BEGIN)) { @@ -13130,7 +13107,13 @@ new_defined(struct parser_params *p, NODE *expr, const YYLTYPE *loc) break; } } - return NEW_DEFINED(n, loc); + + if (had_trailing_semicolon && !nd_type_p(expr, NODE_BLOCK)) { + NODE *block = NEW_BLOCK(expr, loc); + return NEW_DEFINED(block, loc, keyword_loc); + } + + return NEW_DEFINED(n, loc, keyword_loc); } static NODE* @@ -13165,17 +13148,31 @@ symbol_append(struct parser_params *p, NODE *symbols, NODE *symbol) return list_append(p, symbols, symbol); } -static NODE * -new_regexp(struct parser_params *p, NODE *node, int options, const YYLTYPE *loc) +static void +dregex_fragment_setenc(struct parser_params *p, rb_node_dregx_t *const dreg, int options) { - struct RNode_LIST *list; - NODE *prev; + if (dreg->string) { + reg_fragment_setenc(p, dreg->string, options); + } + for (struct RNode_LIST *list = dreg->nd_next; list; list = RNODE_LIST(list->nd_next)) { + NODE *frag = list->nd_head; + if (nd_type_p(frag, NODE_STR)) { + reg_fragment_setenc(p, RNODE_STR(frag)->string, options); + } + else if (nd_type_p(frag, NODE_DSTR)) { + dregex_fragment_setenc(p, RNODE_DSTR(frag), options); + } + } +} +static NODE * +new_regexp(struct parser_params *p, NODE *node, int options, const YYLTYPE *loc, const YYLTYPE *opening_loc, const YYLTYPE *content_loc, const YYLTYPE *closing_loc) +{ if (!node) { /* Check string is valid regex */ rb_parser_string_t *str = STRING_NEW0(); reg_compile(p, str, options); - node = NEW_REGX(str, options, loc); + node = NEW_REGX(str, options, loc, opening_loc, content_loc, closing_loc); return node; } switch (nd_type(node)) { @@ -13183,7 +13180,7 @@ new_regexp(struct parser_params *p, NODE *node, int options, const YYLTYPE *loc) { /* Check string is valid regex */ reg_compile(p, RNODE_STR(node)->string, options); - node = str2regx(p, node, options); + node = str2regx(p, node, options, loc, opening_loc, content_loc, closing_loc); } break; default: @@ -13194,35 +13191,8 @@ new_regexp(struct parser_params *p, NODE *node, int options, const YYLTYPE *loc) nd_set_loc(node, loc); rb_node_dregx_t *const dreg = RNODE_DREGX(node); dreg->as.nd_cflag = options & RE_OPTION_MASK; - if (dreg->string) reg_fragment_check(p, dreg->string, options); - prev = node; - for (list = dreg->nd_next; list; list = RNODE_LIST(list->nd_next)) { - NODE *frag = list->nd_head; - enum node_type type = nd_type(frag); - if (type == NODE_STR || (type == NODE_DSTR && !RNODE_DSTR(frag)->nd_next)) { - rb_parser_string_t *tail = RNODE_STR(frag)->string; - if (reg_fragment_check(p, tail, options) && prev && RNODE_DREGX(prev)->string) { - rb_parser_string_t *lit = prev == node ? dreg->string : RNODE_STR(RNODE_LIST(prev)->nd_head)->string; - if (!literal_concat0(p, lit, tail)) { - return NEW_NIL(loc); /* dummy node on error */ - } - rb_parser_str_resize(p, tail, 0); - RNODE_LIST(prev)->nd_next = list->nd_next; - rb_discard_node(p, list->nd_head); - rb_discard_node(p, (NODE *)list); - list = RNODE_LIST(prev); - } - else { - prev = (NODE *)list; - } - } - else { - prev = 0; - } - } - if (!dreg->nd_next) { - /* Check string is valid regex */ - reg_compile(p, dreg->string, options); + if (dreg->nd_next) { + dregex_fragment_setenc(p, dreg, options); } if (options & RE_OPTION_ONCE) { node = NEW_ONCE(node, loc); @@ -13693,35 +13663,23 @@ attrset(struct parser_params *p, NODE *recv, ID atype, ID id, const YYLTYPE *loc return NEW_ATTRASGN(recv, id, 0, loc); } -static void -rb_backref_error(struct parser_params *p, NODE *node) -{ - switch (nd_type(node)) { - case NODE_NTH_REF: - compile_error(p, "Can't set variable $%ld", RNODE_NTH_REF(node)->nd_nth); - break; - case NODE_BACK_REF: - compile_error(p, "Can't set variable $%c", (int)RNODE_BACK_REF(node)->nd_nth); - break; - } -} - -#ifdef RIPPER static VALUE -backref_error(struct parser_params *p, NODE *node, VALUE expr) +rb_backref_error(struct parser_params *p, NODE *node) { - VALUE mesg = rb_str_new_cstr("Can't set variable "); +#ifndef RIPPER +# define ERR(...) (compile_error(p, __VA_ARGS__), Qtrue) +#else +# define ERR(...) rb_sprintf(__VA_ARGS__) +#endif switch (nd_type(node)) { case NODE_NTH_REF: - rb_str_catf(mesg, "$%ld", RNODE_NTH_REF(node)->nd_nth); - break; + return ERR("Can't set variable $%ld", RNODE_NTH_REF(node)->nd_nth); case NODE_BACK_REF: - rb_str_catf(mesg, "$%c", (int)RNODE_BACK_REF(node)->nd_nth); - break; + return ERR("Can't set variable $%c", (int)RNODE_BACK_REF(node)->nd_nth); } - return dispatch2(assign_error, mesg, expr); +#undef ERR + UNREACHABLE_RETURN(Qfalse); /* only called on syntax error */ } -#endif static NODE * arg_append(struct parser_params *p, NODE *node1, NODE *node2, const YYLTYPE *loc) @@ -13965,7 +13923,7 @@ value_expr_check(struct parser_params *p, NODE *node) } static int -value_expr_gen(struct parser_params *p, NODE *node) +value_expr(struct parser_params *p, NODE *node) { NODE *void_node = value_expr_check(p, node); if (void_node) { @@ -14068,6 +14026,7 @@ void_expr(struct parser_params *p, NODE *node) } } +/* warns useless use of block and returns the last statement node */ static NODE * void_stmts(struct parser_params *p, NODE *node) { @@ -14080,7 +14039,7 @@ void_stmts(struct parser_params *p, NODE *node) void_expr(p, RNODE_BLOCK(node)->nd_head); node = RNODE_BLOCK(node)->nd_next; } - return n; + return RNODE_BLOCK(node)->nd_head; } static NODE * @@ -14108,16 +14067,12 @@ reduce_nodes(struct parser_params *p, NODE **body) (reduce_nodes(p, &type(node)->n1), body = &type(node)->n2, 1)) while (node) { - int newline = (int)(nd_fl_newline(node)); + int newline = (int)nd_fl_newline(node); switch (nd_type(node)) { end: case NODE_NIL: *body = 0; return; - case NODE_RETURN: - *body = node = RNODE_RETURN(node)->nd_stts; - if (newline && node) nd_set_fl_newline(node); - continue; case NODE_BEGIN: *body = node = RNODE_BEGIN(node)->nd_body; if (newline && node) nd_set_fl_newline(node); @@ -14237,7 +14192,7 @@ range_op(struct parser_params *p, NODE *node, const YYLTYPE *loc) if (node == 0) return 0; type = nd_type(node); - value_expr(node); + value_expr(p, node); if (type == NODE_INTEGER) { if (!e_option_supplied(p)) rb_warn0L(nd_line(node), "integer literal in flip-flop"); ID lineno = rb_intern("$."); @@ -14315,13 +14270,7 @@ cond0(struct parser_params *p, NODE *node, enum cond_type type, const YYLTYPE *l break; case NODE_LINE: - SWITCH_BY_COND_TYPE(type, warning, ""); - break; - case NODE_ENCODING: - SWITCH_BY_COND_TYPE(type, warning, ""); - break; - case NODE_INTEGER: case NODE_FLOAT: case NODE_RATIONAL: @@ -14357,22 +14306,22 @@ new_nil_at(struct parser_params *p, const rb_code_position_t *pos) } static NODE* -new_if(struct parser_params *p, NODE *cc, NODE *left, NODE *right, const YYLTYPE *loc) +new_if(struct parser_params *p, NODE *cc, NODE *left, NODE *right, const YYLTYPE *loc, const YYLTYPE* if_keyword_loc, const YYLTYPE* then_keyword_loc, const YYLTYPE* end_keyword_loc) { if (!cc) return right; cc = cond0(p, cc, COND_IN_COND, loc, true); - return newline_node(NEW_IF(cc, left, right, loc)); + return newline_node(NEW_IF(cc, left, right, loc, if_keyword_loc, then_keyword_loc, end_keyword_loc)); } static NODE* -new_unless(struct parser_params *p, NODE *cc, NODE *left, NODE *right, const YYLTYPE *loc) +new_unless(struct parser_params *p, NODE *cc, NODE *left, NODE *right, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *then_keyword_loc, const YYLTYPE *end_keyword_loc) { if (!cc) return right; cc = cond0(p, cc, COND_IN_COND, loc, true); - return newline_node(NEW_UNLESS(cc, left, right, loc)); + return newline_node(NEW_UNLESS(cc, left, right, loc, keyword_loc, then_keyword_loc, end_keyword_loc)); } -#define NEW_AND_OR(type, f, s, loc) (type == NODE_AND ? NEW_AND(f,s,loc) : NEW_OR(f,s,loc)) +#define NEW_AND_OR(type, f, s, loc, op_loc) (type == NODE_AND ? NEW_AND(f,s,loc,op_loc) : NEW_OR(f,s,loc,op_loc)) static NODE* logop(struct parser_params *p, ID id, NODE *left, NODE *right, @@ -14380,18 +14329,18 @@ logop(struct parser_params *p, ID id, NODE *left, NODE *right, { enum node_type type = id == idAND || id == idANDOP ? NODE_AND : NODE_OR; NODE *op; - value_expr(left); + value_expr(p, left); if (left && nd_type_p(left, type)) { NODE *node = left, *second; while ((second = RNODE_AND(node)->nd_2nd) != 0 && nd_type_p(second, type)) { node = second; } - RNODE_AND(node)->nd_2nd = NEW_AND_OR(type, second, right, loc); + RNODE_AND(node)->nd_2nd = NEW_AND_OR(type, second, right, loc, op_loc); nd_set_line(RNODE_AND(node)->nd_2nd, op_loc->beg_pos.lineno); left->nd_loc.end_pos = loc->end_pos; return left; } - op = NEW_AND_OR(type, left, right, loc); + op = NEW_AND_OR(type, left, right, loc, op_loc); nd_set_line(op, op_loc->beg_pos.lineno); return op; } @@ -14418,14 +14367,6 @@ ret_args(struct parser_params *p, NODE *node) return node; } -static NODE * -new_yield(struct parser_params *p, NODE *node, const YYLTYPE *loc) -{ - if (node) no_blockarg(p, node); - - return NEW_YIELD(node, loc); -} - static NODE* negate_lit(struct parser_params *p, NODE* node) { @@ -14496,12 +14437,6 @@ new_args(struct parser_params *p, rb_node_args_aux_t *pre_args, rb_node_opt_arg_ args->opt_args = opt_args; -#ifdef FORWARD_ARGS_WITH_RUBY2_KEYWORDS - args->ruby2_keywords = args->forwarding; -#else - args->ruby2_keywords = 0; -#endif - nd_set_loc(RNODE(tail), loc); return tail; @@ -14730,7 +14665,7 @@ static void warn_duplicate_keys(struct parser_params *p, NODE *hash) { /* See https://bugs.ruby-lang.org/issues/20331 for discussion about what is warned. */ - st_table *literal_keys = st_init_table_with_size(&literal_type, RNODE_LIST(hash)->as.nd_alen / 2); + p->warn_duplicate_keys_table = st_init_table_with_size(&literal_type, RNODE_LIST(hash)->as.nd_alen / 2); while (hash && RNODE_LIST(hash)->nd_next) { NODE *head = RNODE_LIST(hash)->nd_head; NODE *value = RNODE_LIST(hash)->nd_next; @@ -14746,16 +14681,17 @@ warn_duplicate_keys(struct parser_params *p, NODE *hash) if (nd_type_st_key_enable_p(head)) { key = (st_data_t)head; - if (st_delete(literal_keys, &key, &data)) { + if (st_delete(p->warn_duplicate_keys_table, &key, &data)) { rb_warn2L(nd_line((NODE *)data), "key %+"PRIsWARN" is duplicated and overwritten on line %d", nd_value(p, head), WARN_I(nd_line(head))); } - st_insert(literal_keys, (st_data_t)key, (st_data_t)hash); + st_insert(p->warn_duplicate_keys_table, (st_data_t)key, (st_data_t)hash); } hash = next; } - st_free_table(literal_keys); + st_free_table(p->warn_duplicate_keys_table); + p->warn_duplicate_keys_table = NULL; } static NODE * @@ -14774,7 +14710,11 @@ error_duplicate_pattern_variable(struct parser_params *p, ID id, const YYLTYPE * if (st_is_member(p->pvtbl, id)) { yyerror1(loc, "duplicated variable name"); } + else if (p->ctxt.in_alt_pattern && id) { + yyerror1(loc, "variable capture in alternative pattern"); + } else { + p->ctxt.capture_in_pattern = 1; st_insert(p->pvtbl, (st_data_t)id, 0); } } @@ -14831,24 +14771,26 @@ new_op_assign(struct parser_params *p, NODE *lhs, ID op, NODE *rhs, struct lex_c static NODE * new_ary_op_assign(struct parser_params *p, NODE *ary, - NODE *args, ID op, NODE *rhs, const YYLTYPE *args_loc, const YYLTYPE *loc) + NODE *args, ID op, NODE *rhs, const YYLTYPE *args_loc, const YYLTYPE *loc, + const YYLTYPE *call_operator_loc, const YYLTYPE *opening_loc, const YYLTYPE *closing_loc, const YYLTYPE *binary_operator_loc) { NODE *asgn; aryset_check(p, args); args = make_list(args, args_loc); - asgn = NEW_OP_ASGN1(ary, op, args, rhs, loc); + asgn = NEW_OP_ASGN1(ary, op, args, rhs, loc, call_operator_loc, opening_loc, closing_loc, binary_operator_loc); fixpos(asgn, ary); return asgn; } static NODE * new_attr_op_assign(struct parser_params *p, NODE *lhs, - ID atype, ID attr, ID op, NODE *rhs, const YYLTYPE *loc) + ID atype, ID attr, ID op, NODE *rhs, const YYLTYPE *loc, + const YYLTYPE *call_operator_loc, const YYLTYPE *message_loc, const YYLTYPE *binary_operator_loc) { NODE *asgn; - asgn = NEW_OP_ASGN2(lhs, CALL_Q_P(atype), attr, op, rhs, loc); + asgn = NEW_OP_ASGN2(lhs, CALL_Q_P(atype), attr, op, rhs, loc, call_operator_loc, message_loc, binary_operator_loc); fixpos(asgn, lhs); return asgn; } @@ -15104,9 +15046,7 @@ static void add_forwarding_args(struct parser_params *p) { arg_var(p, idFWD_REST); -#ifndef FORWARD_ARGS_WITH_RUBY2_KEYWORDS arg_var(p, idFWD_KWREST); -#endif arg_var(p, idFWD_BLOCK); arg_var(p, idFWD_ALL); } @@ -15149,14 +15089,11 @@ static NODE * new_args_forward_call(struct parser_params *p, NODE *leading, const YYLTYPE *loc, const YYLTYPE *argsloc) { NODE *rest = NEW_LVAR(idFWD_REST, loc); -#ifndef FORWARD_ARGS_WITH_RUBY2_KEYWORDS NODE *kwrest = list_append(p, NEW_LIST(0, loc), NEW_LVAR(idFWD_KWREST, loc)); -#endif - rb_node_block_pass_t *block = NEW_BLOCK_PASS(NEW_LVAR(idFWD_BLOCK, loc), loc); - NODE *args = leading ? rest_arg_append(p, leading, rest, argsloc) : NEW_SPLAT(rest, loc); -#ifndef FORWARD_ARGS_WITH_RUBY2_KEYWORDS - args = arg_append(p, args, new_hash(p, kwrest, loc), loc); -#endif + rb_node_block_pass_t *block = NEW_BLOCK_PASS(NEW_LVAR(idFWD_BLOCK, loc), argsloc, &NULL_LOC); + NODE *args = leading ? rest_arg_append(p, leading, rest, argsloc) : NEW_SPLAT(rest, loc, &NULL_LOC); + block->forwarding = TRUE; + args = arg_append(p, args, new_hash(p, kwrest, loc), argsloc); return arg_blk_pass(args, block); } @@ -15376,13 +15313,7 @@ rb_reg_fragment_setenc(struct parser_params* p, rb_parser_string_t *str, int opt rb_parser_enc_associate(p, str, rb_ascii8bit_encoding()); } else if (rb_is_usascii_enc(p->enc)) { - if (!rb_parser_is_ascii_string(p, str)) { - /* raise in re.c */ - rb_parser_enc_associate(p, str, rb_usascii_encoding()); - } - else { - rb_parser_enc_associate(p, str, rb_ascii8bit_encoding()); - } + rb_parser_enc_associate(p, str, rb_ascii8bit_encoding()); } return 0; @@ -15398,30 +15329,13 @@ reg_fragment_setenc(struct parser_params* p, rb_parser_string_t *str, int option if (c) reg_fragment_enc_error(p, str, c); } -#ifndef RIPPER -int -reg_fragment_check(struct parser_params* p, rb_parser_string_t *str, int options) -{ - VALUE err, str2; - reg_fragment_setenc(p, str, options); - /* TODO */ - str2 = rb_str_new_parser_string(str); - err = rb_reg_check_preprocess(str2); - if (err != Qnil) { - err = rb_obj_as_string(err); - compile_error(p, "%"PRIsVALUE, err); - return 0; - } - return 1; -} -#endif - #ifndef UNIVERSAL_PARSER typedef struct { struct parser_params* parser; rb_encoding *enc; NODE *succ_block; const YYLTYPE *loc; + rb_parser_assignable_func assignable; } reg_named_capture_assign_t; static int @@ -15434,11 +15348,11 @@ reg_named_capture_assign_iter(const OnigUChar *name, const OnigUChar *name_end, long len = name_end - name; const char *s = (const char *)name; - return rb_reg_named_capture_assign_iter_impl(p, s, len, enc, &arg->succ_block, arg->loc); + return rb_reg_named_capture_assign_iter_impl(p, s, len, enc, &arg->succ_block, arg->loc, arg->assignable); } static NODE * -reg_named_capture_assign(struct parser_params* p, VALUE regexp, const YYLTYPE *loc) +reg_named_capture_assign(struct parser_params* p, VALUE regexp, const YYLTYPE *loc, rb_parser_assignable_func assignable) { reg_named_capture_assign_t arg; @@ -15446,6 +15360,7 @@ reg_named_capture_assign(struct parser_params* p, VALUE regexp, const YYLTYPE *l arg.enc = rb_enc_get(regexp); arg.succ_block = 0; arg.loc = loc; + arg.assignable = assignable; onig_foreach_name(RREGEXP_PTR(regexp), reg_named_capture_assign_iter, &arg); if (!arg.succ_block) return 0; @@ -15454,9 +15369,15 @@ reg_named_capture_assign(struct parser_params* p, VALUE regexp, const YYLTYPE *l #endif #ifndef RIPPER +NODE * +rb_parser_assignable(struct parser_params *p, ID id, NODE *val, const YYLTYPE *loc) +{ + return assignable(p, id, val, loc); +} + int rb_reg_named_capture_assign_iter_impl(struct parser_params *p, const char *s, long len, - rb_encoding *enc, NODE **succ_block, const rb_code_location_t *loc) + rb_encoding *enc, NODE **succ_block, const rb_code_location_t *loc, rb_parser_assignable_func assignable) { ID var; NODE *node, *succ; @@ -15554,7 +15475,7 @@ parser_append_options(struct parser_params *p, NODE *node) irs = list_append(p, irs, NEW_HASH(chomp, LOC)); } - node = NEW_WHILE((NODE *)NEW_FCALL(idGets, irs, LOC), node, 1, LOC); + node = NEW_WHILE((NODE *)NEW_FCALL(idGets, irs, LOC), node, 1, LOC, &NULL_LOC, &NULL_LOC); } return node; @@ -15636,6 +15557,14 @@ rb_ruby_parser_free(void *ptr) struct parser_params *p = (struct parser_params*)ptr; struct local_vars *local, *prev; + if (p->ast) { + rb_ast_free(p->ast); + } + + if (p->warn_duplicate_keys_table) { + st_free_table(p->warn_duplicate_keys_table); + } + #ifndef RIPPER if (p->tokens) { rb_parser_ary_free(p, p->tokens); @@ -15668,6 +15597,9 @@ rb_ruby_parser_free(void *ptr) st_free_table(p->case_labels); } + xfree(p->lex.strterm); + p->lex.strterm = 0; + xfree(ptr); } @@ -15876,23 +15808,9 @@ rb_ruby_ripper_parse0(rb_parser_t *p) } int -rb_ruby_ripper_dedent_string(rb_parser_t *p, VALUE string, int width) +rb_ruby_ripper_dedent_string(rb_parser_t *p, rb_parser_string_t *string, int width) { - char *str; - long len; - int i; - - RSTRING_GETMEM(string, str, len); - i = dedent_string_column(str, len, width); - if (!i) return 0; - - rb_str_modify(string); - str = RSTRING_PTR(string); - if (RSTRING_LEN(string) != len) - rb_fatal("literal string changed: %+"PRIsVALUE, string); - MEMMOVE(str, str + i, char, len - i); - rb_str_set_len(string, len - i); - return i; + return dedent_string(p, string, width); } int @@ -15959,7 +15877,7 @@ rb_parser_printf(struct parser_params *p, const char *fmt, ...) va_start(ap, fmt); rb_str_vcatf(mesg, fmt, ap); va_end(ap); - if (end_with_newline_p(p, mesg)) { + if (char_at_end(p, mesg, 0) == '\n') { rb_io_write(p->debug_output, mesg); p->debug_buffer = Qnil; } @@ -16005,7 +15923,7 @@ count_char(const char *str, int c) * * "\"`class' keyword\"" => "`class' keyword" */ -RUBY_FUNC_EXPORTED size_t +size_t rb_yytnamerr(struct parser_params *p, char *yyres, const char *yystr) { if (*yystr == '"') { |
