summaryrefslogtreecommitdiff
path: root/parse.y
diff options
context:
space:
mode:
Diffstat (limited to 'parse.y')
-rw-r--r--parse.y152
1 files changed, 84 insertions, 68 deletions
diff --git a/parse.y b/parse.y
index 8e7dfecf0e..2b5a692558 100644
--- a/parse.y
+++ b/parse.y
@@ -758,7 +758,8 @@ static void token_info_pop(struct parser_params*, const char *token, const rb_co
static void token_info_warn(struct parser_params *p, const char *token, token_info *ptinfo_beg, int same, const rb_code_location_t *loc);
%}
-%pure-parser
+%expect 0
+%define api.pure
%lex-param {struct parser_params *p}
%parse-param {struct parser_params *p}
%initial-action
@@ -1211,7 +1212,6 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem
command_asgn : lhs '=' command_rhs
{
/*%%%*/
- value_expr($3);
$$ = node_assign(p, $1, $3, &@$);
/*% %*/
/*% ripper: assign!($1, $3) %*/
@@ -1219,7 +1219,6 @@ command_asgn : lhs '=' command_rhs
| var_lhs tOP_ASGN command_rhs
{
/*%%%*/
- value_expr($3);
$$ = new_op_assign(p, $1, $2, $3, &@$);
/*% %*/
/*% ripper: opassign!($1, $2, $3) %*/
@@ -1227,7 +1226,6 @@ command_asgn : lhs '=' command_rhs
| primary_value '[' opt_call_args rbracket tOP_ASGN command_rhs
{
/*%%%*/
- value_expr($6);
$$ = new_ary_op_assign(p, $1, $3, $5, $6, &@3, &@$);
/*% %*/
/*% ripper: opassign!(aref_field!($1, escape_Qundef($3)), $5, $6) %*/
@@ -1236,7 +1234,6 @@ command_asgn : lhs '=' command_rhs
| primary_value call_op tIDENTIFIER tOP_ASGN command_rhs
{
/*%%%*/
- value_expr($5);
$$ = new_attr_op_assign(p, $1, $2, $3, $4, $5, &@$);
/*% %*/
/*% ripper: opassign!(field!($1, $2, $3), $4, $5) %*/
@@ -1244,7 +1241,6 @@ command_asgn : lhs '=' command_rhs
| primary_value call_op tCONSTANT tOP_ASGN command_rhs
{
/*%%%*/
- value_expr($5);
$$ = new_attr_op_assign(p, $1, $2, $3, $4, $5, &@$);
/*% %*/
/*% ripper: opassign!(field!($1, $2, $3), $4, $5) %*/
@@ -1260,7 +1256,6 @@ command_asgn : lhs '=' command_rhs
| primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_rhs
{
/*%%%*/
- value_expr($5);
$$ = new_attr_op_assign(p, $1, ID2VAL(idCOLON2), $3, $4, $5, &@$);
/*% %*/
/*% ripper: opassign!(field!($1, ID2VAL(idCOLON2), $3), $4, $5) %*/
@@ -4446,7 +4441,7 @@ none : /* none */
# define yylval (*p->lval)
static int regx_options(struct parser_params*);
-static int tokadd_string(struct parser_params*,int,int,int,long*,rb_encoding**);
+static int tokadd_string(struct parser_params*,int,int,int,long*,rb_encoding**,rb_encoding**);
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*);
@@ -4941,7 +4936,7 @@ yycompile(VALUE vparser, struct parser_params *p, VALUE fname, int line)
p->ruby_sourcefile = "(none)";
}
else {
- p->ruby_sourcefile_string = rb_str_new_frozen(fname);
+ p->ruby_sourcefile_string = rb_fstring(fname);
p->ruby_sourcefile = StringValueCStr(fname);
}
p->ruby_sourceline = line - 1;
@@ -5659,32 +5654,38 @@ parser_update_heredoc_indent(struct parser_params *p, int c)
return FALSE;
}
+static void
+parser_mixed_error(struct parser_params *p, rb_encoding *enc1, rb_encoding *enc2)
+{
+ static const char mixed_msg[] = "%s mixed within %s source";
+ const char *n1 = rb_enc_name(enc1), *n2 = rb_enc_name(enc2);
+ const size_t len = sizeof(mixed_msg) - 4 + strlen(n1) + strlen(n2);
+ char *errbuf = ALLOCA_N(char, len);
+ snprintf(errbuf, len, mixed_msg, n1, n2);
+ yyerror0(errbuf);
+}
+
+static void
+parser_mixed_escape(struct parser_params *p, const char *beg, rb_encoding *enc1, rb_encoding *enc2)
+{
+ const char *pos = p->lex.pcur;
+ p->lex.pcur = beg;
+ parser_mixed_error(p, enc1, enc2);
+ p->lex.pcur = pos;
+}
+
static int
tokadd_string(struct parser_params *p,
int func, int term, int paren, long *nest,
- rb_encoding **encp)
+ rb_encoding **encp, rb_encoding **enc)
{
int c;
- rb_encoding *enc = 0;
- char *errbuf = 0;
- static const char mixed_msg[] = "%s mixed within %s source";
+ bool erred = false;
-#define mixed_error(enc1, enc2) if (!errbuf) { \
- size_t len = sizeof(mixed_msg) - 4; \
- len += strlen(rb_enc_name(enc1)); \
- len += strlen(rb_enc_name(enc2)); \
- errbuf = ALLOCA_N(char, len); \
- snprintf(errbuf, len, mixed_msg, \
- rb_enc_name(enc1), \
- rb_enc_name(enc2)); \
- yyerror0(errbuf); \
- }
-#define mixed_escape(beg, enc1, enc2) do { \
- const char *pos = p->lex.pcur; \
- p->lex.pcur = (beg); \
- mixed_error((enc1), (enc2)); \
- p->lex.pcur = pos; \
- } while (0)
+#define mixed_error(enc1, enc2) \
+ (void)(erred || (parser_mixed_error(p, enc1, enc2), erred = true))
+#define mixed_escape(beg, enc1, enc2) \
+ (void)(erred || (parser_mixed_escape(p, beg, enc1, enc2), erred = true))
while ((c = nextc(p)) != -1) {
if (p->heredoc_indent > 0) {
@@ -5734,7 +5735,7 @@ tokadd_string(struct parser_params *p,
tokadd(p, '\\');
break;
}
- if (!parser_tokadd_utf8(p, &enc, term,
+ if (!parser_tokadd_utf8(p, enc, term,
func & STR_FUNC_SYMBOL,
func & STR_FUNC_REGEXP)) {
return -1;
@@ -5753,17 +5754,17 @@ tokadd_string(struct parser_params *p,
continue;
}
pushback(p, c);
- if ((c = tokadd_escape(p, &enc)) < 0)
+ if ((c = tokadd_escape(p, enc)) < 0)
return -1;
- if (enc && enc != *encp) {
- mixed_escape(p->lex.ptok+2, enc, *encp);
+ if (*enc && *enc != *encp) {
+ mixed_escape(p->lex.ptok+2, *enc, *encp);
}
continue;
}
else if (func & STR_FUNC_EXPAND) {
pushback(p, c);
if (func & STR_FUNC_ESCAPE) tokadd(p, '\\');
- c = read_escape(p, 0, &enc);
+ c = read_escape(p, 0, enc);
}
else if ((func & STR_FUNC_QWORDS) && ISSPACE(c)) {
/* ignore backslashed spaces in %w */
@@ -5777,11 +5778,11 @@ tokadd_string(struct parser_params *p,
}
else if (!parser_isascii(p)) {
non_ascii:
- if (!enc) {
- enc = *encp;
+ if (!*enc) {
+ *enc = *encp;
}
- else if (enc != *encp) {
- mixed_error(enc, *encp);
+ else if (*enc != *encp) {
+ mixed_error(*enc, *encp);
continue;
}
if (tokadd_mbchar(p, c) == -1) return -1;
@@ -5792,18 +5793,18 @@ tokadd_string(struct parser_params *p,
break;
}
if (c & 0x80) {
- if (!enc) {
- enc = *encp;
+ if (!*enc) {
+ *enc = *encp;
}
- else if (enc != *encp) {
- mixed_error(enc, *encp);
+ else if (*enc != *encp) {
+ mixed_error(*enc, *encp);
continue;
}
}
tokadd(p, c);
}
terminate:
- if (enc) *encp = enc;
+ if (*enc) *encp = *enc;
return c;
}
@@ -5936,6 +5937,7 @@ parse_string(struct parser_params *p, rb_strterm_literal_t *quote)
int paren = (int)quote->u2.paren;
int c, space = 0;
rb_encoding *enc = p->enc;
+ rb_encoding *base_enc = 0;
VALUE lit;
if (func & STR_FUNC_TERM) {
@@ -5976,7 +5978,7 @@ parse_string(struct parser_params *p, rb_strterm_literal_t *quote)
}
pushback(p, c);
if (tokadd_string(p, func, term, paren, &quote->u0.nest,
- &enc) == -1) {
+ &enc, &base_enc) == -1) {
if (p->eofp) {
#ifndef RIPPER
# define unterminated_literal(mesg) yyerror0(mesg)
@@ -6341,6 +6343,7 @@ here_document(struct parser_params *p, rb_strterm_heredoc_t *here)
long len;
VALUE str = 0;
rb_encoding *enc = p->enc;
+ rb_encoding *base_enc = 0;
int bol;
eos = RSTRING_PTR(here->term);
@@ -6452,7 +6455,8 @@ here_document(struct parser_params *p, rb_strterm_heredoc_t *here)
}
do {
pushback(p, c);
- if ((c = tokadd_string(p, func, '\n', 0, NULL, &enc)) == -1) {
+ enc = p->enc;
+ if ((c = tokadd_string(p, func, '\n', 0, NULL, &enc, &base_enc)) == -1) {
if (p->eofp) goto error;
goto restore;
}
@@ -8310,16 +8314,17 @@ yylex(YYSTYPE *lval, YYLTYPE *yylloc, struct parser_params *p)
p->lval = lval;
lval->val = Qundef;
t = parser_yylex(p);
- if (has_delayed_token(p))
- dispatch_delayed_token(p, t);
- else if (t != 0)
- dispatch_scan_event(p, t);
if (p->lex.strterm && (p->lex.strterm->flags & STRTERM_HEREDOC))
RUBY_SET_YYLLOC_FROM_STRTERM_HEREDOC(*yylloc);
else
RUBY_SET_YYLLOC(*yylloc);
+ if (has_delayed_token(p))
+ dispatch_delayed_token(p, t);
+ else if (t != 0)
+ dispatch_scan_event(p, t);
+
return t;
}
@@ -9134,7 +9139,7 @@ parser_token_value_print(struct parser_params *p, enum yytokentype type, const Y
#ifndef RIPPER
v = rb_id2str(valp->id);
#else
- v = valp->val;
+ v = valp->node->nd_rval;
#endif
rb_parser_printf(p, "%"PRIsVALUE, v);
break;
@@ -9475,10 +9480,10 @@ node_assign(struct parser_params *p, NODE *lhs, NODE *rhs, const YYLTYPE *loc)
return lhs;
}
-static int
-value_expr_gen(struct parser_params *p, NODE *node)
+static NODE *
+value_expr_check(struct parser_params *p, NODE *node)
{
- int cond = 0;
+ NODE *void_node = 0, *vn;
if (!node) {
rb_warning0("empty expression");
@@ -9490,9 +9495,7 @@ value_expr_gen(struct parser_params *p, NODE *node)
case NODE_NEXT:
case NODE_REDO:
case NODE_RETRY:
- if (!cond) yyerror1(&node->nd_loc, "void value expression");
- /* or "control never reach"? */
- return FALSE;
+ return void_node ? void_node : node;
case NODE_BLOCK:
while (node->nd_next) {
@@ -9515,14 +9518,15 @@ value_expr_gen(struct parser_params *p, NODE *node)
node = node->nd_body;
break;
}
- if (!value_expr(node->nd_body)) return FALSE;
+ vn = value_expr_check(p, node->nd_body);
+ if (!vn) return NULL;
+ if (!void_node) void_node = vn;
node = node->nd_else;
break;
case NODE_AND:
case NODE_OR:
- cond = 1;
- node = node->nd_2nd;
+ node = node->nd_1st;
break;
case NODE_LASGN:
@@ -9530,13 +9534,25 @@ value_expr_gen(struct parser_params *p, NODE *node)
case NODE_DASGN_CURR:
case NODE_MASGN:
mark_lvar_used(p, node);
- return TRUE;
+ return NULL;
default:
- return TRUE;
+ return NULL;
}
}
+ return NULL;
+}
+
+static int
+value_expr_gen(struct parser_params *p, NODE *node)
+{
+ NODE *void_node = value_expr_check(p, node);
+ if (void_node) {
+ yyerror1(&void_node->nd_loc, "void value expression");
+ /* or "control never reach"? */
+ return FALSE;
+ }
return TRUE;
}
@@ -9852,10 +9868,8 @@ cond0(struct parser_params *p, NODE *node, int method_op, const YYLTYPE *loc)
case NODE_DOT3:
node->nd_beg = range_op(p, node->nd_beg, loc);
node->nd_end = range_op(p, node->nd_end, loc);
- if (nd_type(node) == NODE_DOT2 || nd_type(node) == NODE_DOT3) {
- nd_set_type(node, nd_type(node) == NODE_DOT2 ? NODE_FLIP2 : NODE_FLIP3);
- parser_warn(p, node, "flip-flop is deprecated");
- }
+ if (nd_type(node) == NODE_DOT2) nd_set_type(node,NODE_FLIP2);
+ else if (nd_type(node) == NODE_DOT3) nd_set_type(node, NODE_FLIP3);
if (!method_op && !e_option_supplied(p)) {
int b = literal_node(node->nd_beg);
int e = literal_node(node->nd_end);
@@ -10670,12 +10684,13 @@ reg_named_capture_assign_iter(const OnigUChar *name, const OnigUChar *name_end,
NODE *node, *succ;
if (!len) return ST_CONTINUE;
- if (len < MAX_WORD_LENGTH && rb_reserved_word(s, (int)len))
- return ST_CONTINUE;
if (rb_enc_symname_type(s, len, enc, (1U<<ID_LOCAL)) != ID_LOCAL)
return ST_CONTINUE;
var = intern_cstr(s, len, enc);
+ if (len < MAX_WORD_LENGTH && rb_reserved_word(s, (int)len)) {
+ if (!lvar_defined(p, var)) return ST_CONTINUE;
+ }
node = node_assign(p, assignable(p, var, 0, arg->loc), NEW_LIT(ID2SYM(var), arg->loc), arg->loc);
succ = arg->succ_block;
if (!succ) succ = NEW_BEGIN(0, arg->loc);
@@ -10810,8 +10825,9 @@ rb_init_parse(void)
static ID
internal_id(struct parser_params *p)
{
+ const ID max_id = RB_ID_SERIAL_MAX & ~0xffff;
ID id = (ID)vtable_size(p->lvtbl->args) + (ID)vtable_size(p->lvtbl->vars);
- id += ((tLAST_TOKEN - ID_INTERNAL) >> ID_SCOPE_SHIFT) + 1;
+ id = max_id - id;
return ID_STATIC_SYM | ID_INTERNAL | (id << ID_SCOPE_SHIFT);
}