summaryrefslogtreecommitdiff
path: root/parse.y
diff options
context:
space:
mode:
Diffstat (limited to 'parse.y')
-rw-r--r--parse.y199
1 files changed, 153 insertions, 46 deletions
diff --git a/parse.y b/parse.y
index f15684fb99..8f88b978eb 100644
--- a/parse.y
+++ b/parse.y
@@ -532,6 +532,10 @@ mlhs_node : variable
{
$$ = attrset($1, $3);
}
+ | primary tCOLON2 tIDENTIFIER
+ {
+ $$ = attrset($1, $3);
+ }
| backref
{
rb_backref_error($1);
@@ -550,6 +554,10 @@ lhs : variable
{
$$ = attrset($1, $3);
}
+ | primary tCOLON2 tIDENTIFIER
+ {
+ $$ = attrset($1, $3);
+ }
| backref
{
rb_backref_error($1);
@@ -683,6 +691,17 @@ arg : lhs '=' arg
$$ = NEW_OP_ASGN2($1, $3, $4, $5);
fixpos($$, $1);
}
+ | primary tCOLON2 tIDENTIFIER tOP_ASGN arg
+ {
+ if ($4 == tOROP) {
+ $4 = 0;
+ }
+ else if ($4 == tANDOP) {
+ $4 = 1;
+ }
+ $$ = NEW_OP_ASGN2($1, $3, $4, $5);
+ fixpos($$, $1);
+ }
| backref tOP_ASGN arg
{
rb_backref_error($1);
@@ -968,15 +987,6 @@ primary : literal
{
$$ = NEW_LIT($1);
}
- | primary tCOLON2 tCONSTANT
- {
- value_expr($1);
- $$ = NEW_COLON2($1, $3);
- }
- | tCOLON3 cname
- {
- $$ = NEW_COLON3($2);
- }
| string
| tXSTRING
{
@@ -986,6 +996,43 @@ primary : literal
| tDREGEXP
| var_ref
| backref
+ | tFID
+ {
+ $$ = NEW_VCALL($1);
+ }
+ | kBEGIN
+ compstmt
+ rescue
+ opt_else
+ ensure
+ kEND
+ {
+ if (!$3 && !$4 && !$5)
+ $$ = NEW_BEGIN($2);
+ else {
+ if ($3) $2 = NEW_RESCUE($2, $3, $4);
+ else if ($4) {
+ rb_warn("else without rescue is useless");
+ $2 = block_append($2, $4);
+ }
+ if ($5) $2 = NEW_ENSURE($2, $5);
+ $$ = $2;
+ }
+ fixpos($$, $2);
+ }
+ | tLPAREN compstmt ')'
+ {
+ $$ = $2;
+ }
+ | primary tCOLON2 tCONSTANT
+ {
+ value_expr($1);
+ $$ = NEW_COLON2($1, $3);
+ }
+ | tCOLON3 cname
+ {
+ $$ = NEW_COLON3($2);
+ }
| primary '[' aref_args ']'
{
value_expr($1);
@@ -1040,10 +1087,6 @@ primary : literal
in_defined = 0;
$$ = NEW_DEFINED($5);
}
- | tFID
- {
- $$ = NEW_VCALL($1);
- }
| operation brace_block
{
$2->nd_iter = NEW_FCALL($1, 0);
@@ -1109,30 +1152,6 @@ primary : literal
$$ = NEW_FOR($2, $5, $8);
fixpos($$, $2);
}
- | kBEGIN
- compstmt
- rescue
- opt_else
- ensure
- kEND
- {
- if (!$3 && !$4 && !$5)
- $$ = NEW_BEGIN($2);
- else {
- if ($3) $2 = NEW_RESCUE($2, $3, $4);
- else if ($4) {
- rb_warn("else without rescue is useless");
- $2 = block_append($2, $4);
- }
- if ($5) $2 = NEW_ENSURE($2, $5);
- $$ = $2;
- }
- fixpos($$, $2);
- }
- | tLPAREN compstmt ')'
- {
- $$ = $2;
- }
| kCLASS cname superclass
{
if (cur_mid || in_single)
@@ -2400,11 +2419,80 @@ parse_qstring(term, paren)
}
static int
-parse_quotedword(term, paren)
+parse_quotedwords(term, paren)
int term, paren;
{
- if (parse_qstring(term, paren) == 0) return 0;
- yylval.node = NEW_CALL(NEW_STR(yylval.val), rb_intern("split"), 0);
+ NODE *qwords = 0;
+ int strstart;
+ int c;
+ int nest = 0;
+
+ strstart = ruby_sourceline;
+ newtok();
+
+ while ((c = nextc()) == ' ')
+ ; /* skip preceding spaces */
+ pushback(c);
+ while ((c = nextc()) != term || nest > 0) {
+ if (c == -1) {
+ ruby_sourceline = strstart;
+ rb_compile_error("unterminated string meets end of file");
+ return 0;
+ }
+ if (ismbchar(c)) {
+ int i, len = mbclen(c)-1;
+
+ for (i = 0; i < len; i++) {
+ tokadd(c);
+ c = nextc();
+ }
+ }
+ else if (c == '\\') {
+ c = nextc();
+ switch (c) {
+ case '\n':
+ continue;
+ case '\\':
+ c = '\\';
+ break;
+ case ' ':
+ tokadd(' ');
+ break;
+ default:
+ tokadd('\\');
+ }
+ }
+ else if (c == ' ') {
+ NODE *str;
+
+ tokfix();
+ str = NEW_STR(rb_str_new(tok(), toklen()));
+ newtok();
+ if (!qwords) qwords = NEW_LIST(str);
+ else list_append(qwords, str);
+ while ((c = nextc()) == ' ')
+ ; /* skip continuous spaces */
+ pushback(c);
+ continue;
+ }
+ if (paren) {
+ if (c == paren) nest++;
+ if (c == term && nest-- == 0) break;
+ }
+ tokadd(c);
+ }
+
+ tokfix();
+ if (toklen() > 0) {
+ NODE *str;
+
+ str = NEW_STR(rb_str_new(tok(), toklen()));
+ if (!qwords) qwords = NEW_LIST(str);
+ else list_append(qwords, str);
+ }
+ if (!qwords) qwords = NEW_ZARRAY();
+ yylval.node = qwords;
+ lex_state = EXPR_END;
return tDSTRING;
}
@@ -2814,6 +2902,8 @@ yylex()
if (lex_state == EXPR_BEG || lex_state == EXPR_MID ||
(lex_state == EXPR_ARG && space_seen && !ISSPACE(c))) {
pushback(c);
+ if (lex_state == EXPR_ARG) arg_ambiguous();
+ if (ISDIGIT(c)) goto start_num;
lex_state = EXPR_BEG;
return tUPLUS;
}
@@ -2837,8 +2927,13 @@ yylex()
}
if (lex_state == EXPR_BEG || lex_state == EXPR_MID ||
(lex_state == EXPR_ARG && space_seen && !ISSPACE(c))) {
+ if (lex_state == EXPR_ARG) arg_ambiguous();
lex_state = EXPR_BEG;
pushback(c);
+ if (ISDIGIT(c)) {
+ c = '-';
+ goto start_num;
+ }
return tUMINUS;
}
lex_state = EXPR_BEG;
@@ -3072,6 +3167,12 @@ yylex()
lex_state = EXPR_BEG;
}
else {
+ if (lex_state == EXPR_ARG) {
+ if (space_seen) {
+ arg_ambiguous();
+ c = tLPAREN;
+ }
+ }
lex_state = EXPR_BEG;
}
return c;
@@ -3147,7 +3248,7 @@ yylex()
return parse_qstring(term, paren);
case 'w':
- return parse_quotedword(term, paren);
+ return parse_quotedwords(term, paren);
case 'x':
return parse_string('`', term, paren);
@@ -3766,15 +3867,18 @@ assignable(id, val)
yyerror("Can't assign to __LINE__");
}
else if (is_local_id(id)) {
- if (rb_dvar_defined(id)) {
+ if (rb_dvar_curr(id)) {
+ lhs = NEW_DASGN_CURR(id, val);
+ }
+ else if (rb_dvar_defined(id)) {
lhs = NEW_DASGN(id, val);
}
else if (local_id(id) || !dyna_in_block()) {
lhs = NEW_LASGN(id, val);
}
else{
- rb_dvar_push(id, 0);
- lhs = NEW_DASGN_PUSH(id, val);
+ rb_dvar_push(id, Qnil);
+ lhs = NEW_DASGN_CURR(id, val);
}
}
else if (is_global_id(id)) {
@@ -3871,7 +3975,7 @@ node_assign(lhs, rhs)
case NODE_IASGN:
case NODE_LASGN:
case NODE_DASGN:
- case NODE_DASGN_PUSH:
+ case NODE_DASGN_CURR:
case NODE_MASGN:
case NODE_CASGN:
case NODE_CDECL:
@@ -4354,8 +4458,11 @@ top_local_setup()
static struct RVarmap*
dyna_push()
{
+ struct RVarmap* vars = ruby_dyna_vars;
+
+ rb_dvar_push(0, 0);
lvtbl->dlev++;
- return ruby_dyna_vars;
+ return vars;
}
static void