summaryrefslogtreecommitdiff
path: root/parse.y
diff options
context:
space:
mode:
Diffstat (limited to 'parse.y')
-rw-r--r--parse.y510
1 files changed, 377 insertions, 133 deletions
diff --git a/parse.y b/parse.y
index 350c83a7ca..50e6db2b39 100644
--- a/parse.y
+++ b/parse.y
@@ -56,7 +56,7 @@ static enum lex_state {
EXPR_BEG, /* ignore newline, +/- is a sign. */
EXPR_MID, /* newline significant, +/- is a sign. */
EXPR_END, /* newline significant, +/- is a operator. */
- EXPR_ARG, /* newline significant, +/- is a sign(meybe). */
+ EXPR_ARG, /* newline significant, +/- may be a sign. */
EXPR_FNAME, /* ignore newline, +/- is a operator. */
} lex_state;
@@ -68,16 +68,17 @@ static int value_expr();
static NODE *cond();
static NODE *logop();
+static NODE *newline_node();
+static void fixpos();
+
static NODE *block_append();
static NODE *list_append();
static NODE *list_concat();
-static NODE *list_copy();
-static NODE *expand_op();
static NODE *call_op();
static int in_defined = 0;
static NODE *gettable();
-static NODE *asignable();
+static NODE *assignable();
static NODE *aryset();
static NODE *attrset();
static void backref_error();
@@ -154,7 +155,7 @@ static void top_local_setup();
%type <val> literal numeric
%type <node> compexpr exprs expr arg primary command_call method_call
%type <node> if_tail opt_else case_body cases rescue ensure iterator
-%type <node> call_args call_args0 args args2 opt_args var_ref
+%type <node> call_args call_args0 ret_args args mrhs opt_args var_ref
%type <node> superclass f_arglist f_args f_optarg f_opt
%type <node> array assoc_list assocs assoc undef_list
%type <node> iter_var opt_iter_var iter_block iter_do_block
@@ -214,12 +215,15 @@ program : {
lex_state = EXPR_BEG;
top_local_init();
NEW_CREF0(); /* initialize constant c-ref */
+ if ((VALUE)the_class == cObject) class_nest = 0;
+ else class_nest = 1;
}
compexpr
{
eval_tree = block_append(eval_tree, $2);
top_local_setup();
cur_cref = 0;
+ class_nest = 0;
}
compexpr : exprs opt_terms
@@ -229,16 +233,19 @@ exprs : /* none */
$$ = 0;
}
| expr
+ {
+ $$ = newline_node($1);
+ }
| exprs terms expr
{
- $$ = block_append($1, $3);
+ $$ = block_append($1, newline_node($3));
}
| error expr
{
$$ = $2;
}
-expr : mlhs '=' args2
+expr : mlhs '=' mrhs
{
value_expr($3);
$1->nd_value = $3;
@@ -248,14 +255,14 @@ expr : mlhs '=' args2
{
$$ = NEW_HASH($1);
}
- | RETURN args2
+ | RETURN ret_args
{
value_expr($2);
if (!cur_mid && !in_single)
yyerror("return appeared outside of method");
$$ = NEW_RET($2);
}
- | YIELD args2
+ | YIELD ret_args
{
value_expr($2);
$$ = NEW_YIELD($2);
@@ -265,11 +272,40 @@ expr : mlhs '=' args2
{
$2->nd_iter = $1;
$$ = $2;
+ fixpos($$, $2);
}
| ALIAS fname {lex_state = EXPR_FNAME;} fname
{
+ if (cur_mid || in_single)
+ yyerror("alias within method");
$$ = NEW_ALIAS($2, $4);
}
+ | ALIAS GVAR GVAR
+ {
+ if (cur_mid || in_single)
+ yyerror("alias within method");
+ $$ = NEW_VALIAS($2, $3);
+ }
+ | ALIAS GVAR BACK_REF
+ {
+ char buf[3];
+
+ if (cur_mid || in_single)
+ yyerror("alias within method");
+ sprintf(buf, "$%c", $3->nd_nth);
+ $$ = NEW_VALIAS($2, rb_intern(buf));
+ }
+ | ALIAS GVAR NTH_REF
+ {
+ yyerror("can't make alias for the number variables");
+ $$ = 0;
+ }
+ | UNDEF undef_list
+ {
+ if (cur_mid || in_single)
+ yyerror("undef within method");
+ $$ = $2;
+ }
| expr IF_MOD expr
{
value_expr($3);
@@ -323,21 +359,20 @@ expr : mlhs '=' args2
command_call : operation call_args0
{
$$ = NEW_FCALL($1, $2);
+ fixpos($$, $2);
}
| primary '.' operation call_args0
{
value_expr($1);
$$ = NEW_CALL($1, $3, $4);
+ fixpos($$, $1);
}
| SUPER call_args0
{
if (!cur_mid && !in_single && !in_defined)
yyerror("super called outside of method");
$$ = NEW_SUPER($2);
- }
- | UNDEF undef_list
- {
- $$ = $2;
+ fixpos($$, $2);
}
mlhs : mlhs_head
@@ -374,7 +409,7 @@ mlhs_tail : lhs
lhs : variable
{
- $$ = asignable($1, 0);
+ $$ = assignable($1, 0);
}
| primary '[' opt_args opt_nl ']'
{
@@ -384,6 +419,10 @@ lhs : variable
{
$$ = attrset($1, $3, 0);
}
+ | primary '.' CONSTANT
+ {
+ $$ = attrset($1, $3, 0);
+ }
| backref
{
backref_error($1);
@@ -445,15 +484,23 @@ op : DOT2 { $$ = DOT2; }
arg : variable '=' arg
{
value_expr($3);
- $$ = asignable($1, $3);
+ $$ = assignable($1, $3);
+ fixpos($$, $3);
}
| primary '[' opt_args opt_nl ']' '=' arg
{
$$ = aryset($1, $3, $7);
+ fixpos($$, $7);
}
| primary '.' IDENTIFIER '=' arg
{
$$ = attrset($1, $3, $5);
+ fixpos($$, $5);
+ }
+ | primary '.' CONSTANT '=' arg
+ {
+ $$ = attrset($1, $3, $5);
+ fixpos($$, $5);
}
| backref '=' arg
{
@@ -466,18 +513,22 @@ arg : variable '=' arg
value_expr($3);
if (is_local_id($1)&&!local_id($1)&&dyna_in_block())
dyna_var_asgn($1, TRUE);
- $$ = asignable($1, call_op(gettable($1), $2, 1, $3));
+ $$ = assignable($1, call_op(gettable($1), $2, 1, $3));
+ fixpos($$, $3);
}
| primary '[' opt_args opt_nl ']' OP_ASGN arg
{
NODE *args = NEW_LIST($7);
- if ($3) list_concat(args, $3);
+ list_append($3, NEW_NIL());
+ list_concat(args, $3);
$$ = NEW_OP_ASGN1($1, $6, args);
+ fixpos($$, $7);
}
| primary '.' IDENTIFIER OP_ASGN arg
{
$$ = NEW_OP_ASGN2($1, $3, $4, $5);
+ fixpos($$, $5);
}
| backref OP_ASGN arg
{
@@ -570,10 +621,12 @@ arg : variable '=' arg
}
| arg MATCH arg
{
+ local_cnt('~');
$$ = NEW_CALL($1, MATCH, NEW_LIST($3));
}
| arg NMATCH arg
{
+ local_cnt('~');
$$ = NEW_NOT(NEW_CALL($1, MATCH, NEW_LIST($3)));
}
| '!' arg
@@ -601,10 +654,10 @@ arg : variable '=' arg
{
$$ = logop(NODE_OR, $1, $3);
}
- | DEFINED {in_defined = 1;} arg
+ | DEFINED opt_nl {in_defined = 1;} arg
{
in_defined = 0;
- $$ = NEW_DEFINED($3);
+ $$ = NEW_DEFINED($4);
}
| primary
{
@@ -627,10 +680,6 @@ call_args0 : args
{
$$ = NEW_LIST(NEW_HASH($1));
}
- | args ',' command_call
- {
- $$ = list_append($1, $3);
- }
| args ',' assocs
{
$$ = list_append($1, NEW_HASH($3));
@@ -666,7 +715,25 @@ args : arg
$$ = list_append($1, $3);
}
-args2 : args
+mrhs : args
+ {
+ if ($1 && $1->nd_next == 0) {
+ $$ = $1->nd_head;
+ }
+ else {
+ $$ = $1;
+ }
+ }
+ | args ',' STAR arg
+ {
+ $$ = call_op($1, '+', 1, $4);
+ }
+ | STAR arg
+ {
+ $$ = $2;
+ }
+
+ret_args : call_args0
{
if ($1 && $1->nd_next == 0) {
$$ = $1->nd_head;
@@ -732,13 +799,26 @@ primary : literal
{
$$ = NEW_HASH($2);
}
+ | RETURN '(' ret_args ')'
+ {
+ if (!cur_mid && !in_single)
+ yyerror("return appeared outside of method");
+ value_expr($3);
+ $$ = NEW_RET($3);
+ }
+ | RETURN '(' ')'
+ {
+ if (!cur_mid && !in_single)
+ yyerror("return appeared outside of method");
+ $$ = NEW_RET(0);
+ }
| RETURN
{
if (!cur_mid && !in_single)
yyerror("return appeared outside of method");
$$ = NEW_RET(0);
}
- | YIELD '(' args2 ')'
+ | YIELD '(' ret_args ')'
{
value_expr($3);
$$ = NEW_YIELD($3);
@@ -750,11 +830,11 @@ primary : literal
| YIELD
{
$$ = NEW_YIELD(0);
- }
- | DEFINED '(' {in_defined = 1;} expr ')'
+ }
+ | DEFINED opt_nl '(' {in_defined = 1;} expr ')'
{
in_defined = 0;
- $$ = NEW_DEFINED($4);
+ $$ = NEW_DEFINED($5);
}
| FID
{
@@ -770,6 +850,7 @@ primary : literal
{
$2->nd_iter = $1;
$$ = $2;
+ fixpos($$, $1);
}
| IF expr then
compexpr
@@ -778,6 +859,7 @@ primary : literal
{
value_expr($2);
$$ = NEW_IF(cond($2), $4, $5);
+ fixpos($$, $2);
}
| UNLESS expr then
compexpr
@@ -786,16 +868,19 @@ primary : literal
{
value_expr($2);
$$ = NEW_UNLESS(cond($2), $4, $5);
+ fixpos($$, $2);
}
| WHILE expr term compexpr END
{
value_expr($2);
$$ = NEW_WHILE(cond($2), $4, 1);
+ fixpos($$, $2);
}
| UNTIL expr term compexpr END
{
value_expr($2);
$$ = NEW_UNTIL(cond($2), $4, 1);
+ fixpos($$, $2);
}
| CASE compexpr
case_body
@@ -803,11 +888,13 @@ primary : literal
{
value_expr($2);
$$ = NEW_CASE($2, $3);
+ fixpos($$, $2);
}
| FOR iter_var IN expr term compexpr END
{
value_expr($2);
$$ = NEW_FOR($2, $4, $6);
+ fixpos($$, $2);
}
| BEGIN
compexpr
@@ -822,6 +909,7 @@ primary : literal
if ($4) $2 = NEW_ENSURE($2, $4);
$$ = $2;
}
+ fixpos($$, $2);
}
| LPAREN compexpr ')'
{
@@ -840,6 +928,25 @@ primary : literal
END
{
$$ = NEW_CLASS($2, $5, $3);
+ fixpos($$, $3);
+ local_pop();
+ cref_pop();
+ class_nest--;
+ }
+ | CLASS LSHFT expr term
+ {
+ if (cur_mid || in_single)
+ yyerror("class definition in method body");
+
+ class_nest++;
+ cref_push();
+ local_push();
+ }
+ compexpr
+ END
+ {
+ $$ = NEW_SCLASS($3, $6);
+ fixpos($$, $3);
local_pop();
cref_pop();
class_nest--;
@@ -856,6 +963,7 @@ primary : literal
END
{
$$ = NEW_MODULE($2, $4);
+ fixpos($$, $4);
local_pop();
cref_pop();
class_nest--;
@@ -872,6 +980,7 @@ primary : literal
END
{
$$ = NEW_DEFN($2, $4, $5, class_nest?0:1);
+ fixpos($$, $4);
local_pop();
cur_mid = 0;
}
@@ -887,6 +996,7 @@ primary : literal
END
{
$$ = NEW_DEFS($2, $5, $7, $8);
+ fixpos($$, $2);
local_pop();
in_single--;
}
@@ -902,6 +1012,7 @@ if_tail : opt_else
{
value_expr($2);
$$ = NEW_IF(cond($2), $4, $5);
+ fixpos($$, $2);
}
opt_else : /* none */
@@ -942,6 +1053,7 @@ iter_do_block : DO
END
{
$$ = NEW_ITER($3, 0, $4);
+ fixpos($$, $3?$3:$4);
dyna_pop($<vars>2);
}
@@ -953,6 +1065,7 @@ iter_block : '{'
compexpr '}'
{
$$ = NEW_ITER($3, 0, $4);
+ fixpos($$, $3?$3:$4);
dyna_pop($<vars>2);
}
@@ -974,11 +1087,13 @@ iterator : IDENTIFIER
method_call : operation '(' call_args ')'
{
$$ = NEW_FCALL($1, $3);
+ fixpos($$, $3);
}
| primary '.' operation '(' call_args ')'
{
value_expr($1);
$$ = NEW_CALL($1, $3, $5);
+ fixpos($$, $1);
}
| primary '.' operation
{
@@ -989,6 +1104,7 @@ method_call : operation '(' call_args ')'
{
value_expr($1);
$$ = NEW_CALL($1, $3, $5);
+ fixpos($$, $1);
}
case_body : WHEN args then
@@ -1005,6 +1121,7 @@ rescue : RESCUE opt_args term compexpr
rescue
{
$$ = NEW_RESBODY($2, $4, $5);
+ fixpos($$, $2?$2:$4);
}
| /* none */
{
@@ -1131,12 +1248,13 @@ f_opt : IDENTIFIER '=' arg
{
if (!is_local_id($1))
yyerror("formal argument must be local variable");
- $$ = asignable($1, $3);
+ $$ = assignable($1, $3);
}
f_optarg : f_opt
{
$$ = NEW_BLOCK($1);
+ $$->nd_end = $$;
}
| f_optarg ',' f_opt
{
@@ -1298,6 +1416,8 @@ yyerror(msg)
static int newline_seen;
+int rb_in_compile = 0;
+
static NODE*
yycompile(f)
char *f;
@@ -1307,7 +1427,9 @@ yycompile(f)
newline_seen = 0;
sourcefile = strdup(f);
eval_tree = 0;
+ rb_in_compile = 1;
n = yyparse();
+ rb_in_compile = 0;
if (n == 0) return eval_tree;
return 0;
@@ -1340,7 +1462,7 @@ compile_file(f, file, start)
return yycompile(f);
}
-int
+static int
nextc()
{
int c;
@@ -1357,7 +1479,7 @@ nextc()
return -1;
}
}
- c = *lex_p++;
+ c = (unsigned char)*lex_p++;
return c;
}
@@ -1375,7 +1497,7 @@ pushback(c)
#define toklen() tokidx
#define toklast() (tokidx>0?tokenbuf[tokidx-1]:0)
-char*
+static char*
newtok()
{
tokidx = 0;
@@ -1384,12 +1506,13 @@ newtok()
tokenbuf = ALLOC_N(char, 60);
}
if (toksiz > 1024) {
+ toksiz = 60;
REALLOC_N(tokenbuf, char, 60);
}
return tokenbuf;
}
-void
+static void
tokadd(c)
char c;
{
@@ -1432,18 +1555,19 @@ read_escape()
case '0': case '1': case '2': case '3': /* octal constant */
case '4': case '5': case '6': case '7':
- pushback(c);
{
char buf[3];
int i;
+ pushback(c);
for (i=0; i<3; i++) {
- buf[i] = nextc();
- if (buf[i] == -1) goto eof;
- if (buf[i] < '0' || '7' < buf[i]) {
- pushback(buf[i]);
+ c = nextc();
+ if (c == -1) goto eof;
+ if (c < '0' || '7' < c) {
+ pushback(c);
break;
}
+ buf[i] = c;
}
c = scan_oct(buf, i+1, &i);
}
@@ -1514,11 +1638,11 @@ parse_regx(term)
int term;
{
register int c;
+ char kcode = 0;
+ int once = 0;
int casefold = 0;
int in_brack = 0;
int re_start = sourceline;
- int once = 0;
- int quote = 0;
NODE *list = 0;
newtok();
@@ -1604,19 +1728,29 @@ parse_regx(term)
regx_end:
for (;;) {
- c = nextc();
- if (c == 'i') {
+ switch (c = nextc()) {
+ case 'i':
casefold = 1;
- }
- else if (c == 'o') {
+ break;
+ case 'o':
once = 1;
- }
- else {
- pushback(c);
break;
+ case 'n':
+ kcode = 2;
+ break;
+ case 'e':
+ kcode = 4;
+ break;
+ case 's':
+ kcode = 6;
+ break;
+ default:
+ pushback(c);
+ goto end_options;
}
}
+ end_options:
tokfix();
lex_state = EXPR_END;
if (list) {
@@ -1625,12 +1759,12 @@ parse_regx(term)
list_append(list, NEW_STR(ss));
}
nd_set_type(list, once?NODE_DREGX_ONCE:NODE_DREGX);
- list->nd_cflag = casefold;
+ list->nd_cflag = kcode | casefold;
yylval.node = list;
return DREGEXP;
}
else {
- yylval.val = reg_new(tok(), toklen(), casefold);
+ yylval.val = reg_new(tok(), toklen(), kcode | casefold);
return REGEXP;
}
}
@@ -1715,14 +1849,12 @@ static int
parse_qstring(term)
int term;
{
- int quote = 0;
int strstart;
int c;
strstart = sourceline;
newtok();
while ((c = nextc()) != term) {
- qstr_retry:
if (c == -1) {
sourceline = strstart;
Error("unterminated string meets end of file");
@@ -1811,6 +1943,10 @@ arg_ambiguous()
Warning("ambiguous first argument; make sure");
}
+#ifndef atof
+double atof();
+#endif
+
static int
yylex()
{
@@ -1819,7 +1955,7 @@ yylex()
struct kwtable *low = kwtable, *mid, *high = LAST(kwtable);
if (newline_seen) {
- sourceline++;
+ sourceline+=newline_seen;
newline_seen = 0;
}
@@ -1848,6 +1984,27 @@ retry:
}
/* fall through */
case '\n':
+ /* skip embedded rd document */
+ if ((c = nextc()) == '=' &&
+ strncmp(lex_p, "begin", 5) == 0 &&
+ (lex_p[5] == '\n' || lex_p[5] == '\r')) {
+ for (;;) {
+ if (c == -1) return 0;
+ c = nextc();
+ if (c != '\n') continue;
+ c = nextc();
+ if (c != '=') continue;
+ if (strncmp(lex_p, "end", 3) == 0 &&
+ (lex_p[3] == '\n' || lex_p[3] == '\r')) {
+ lex_p += 3; /* sizeof "end" */
+ break;
+ }
+ }
+ }
+ else {
+ pushback(c);
+ }
+
if (lex_state == EXPR_BEG || lex_state == EXPR_FNAME) {
sourceline++;
goto retry;
@@ -1877,7 +2034,7 @@ retry:
lex_state = EXPR_BEG;
return STAR;
}
- if (lex_state == EXPR_BEG) {
+ if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
return STAR;
}
lex_state = EXPR_BEG;
@@ -1895,6 +2052,25 @@ retry:
return '!';
case '=':
+ if (lex_p == lex_pbeg + 1) {
+ /* skip embedded rd document */
+ if (strncmp(lex_p, "begin", 5) == 0 && isspace(lex_p[5])) {
+ lex_p = lex_pend;
+ for (;;) {
+ if (c == -1) return 0;
+ c = nextc();
+ if (c != '\n') continue;
+ c = nextc();
+ if (c != '=') continue;
+ if (strncmp(lex_p, "end", 3) == 0 && isspace(lex_p[3])) {
+ lex_p = lex_pend;
+ break;
+ }
+ }
+ goto retry;
+ }
+ }
+
lex_state = EXPR_BEG;
if ((c = nextc()) == '=') {
if ((c = nextc()) == '=') {
@@ -2085,11 +2261,16 @@ retry:
is_float = seen_point = seen_e = 0;
lex_state = EXPR_END;
newtok();
+ if (c == '-' || c == '+') {
+ tokadd(c);
+ c = nextc();
+ }
if (c == '0') {
c = nextc();
if (c == 'x' || c == 'X') {
/* hexadecimal */
while (c = nextc()) {
+ if (c == '_') continue;
if (!isxdigit(c)) break;
tokadd(c);
}
@@ -2102,7 +2283,8 @@ retry:
/* octal */
do {
tokadd(c);
- c = nextc();
+ while ((c = nextc()) == '_')
+ ;
} while (c >= '0' && c <= '9');
pushback(c);
tokfix();
@@ -2121,10 +2303,6 @@ retry:
return INTEGER;
}
}
- if (c == '-' || c == '+') {
- tokadd(c);
- c = nextc();
- }
for (;;) {
switch (c) {
@@ -2178,8 +2356,6 @@ retry:
pushback(c);
tokfix();
if (is_float) {
- double atof();
-
yylval.val = float_new(atof(tok()));
return FLOAT;
}
@@ -2248,7 +2424,7 @@ retry:
}
}
lex_state = EXPR_BEG;
- return c;
+ return '~';
case '(':
if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
@@ -2311,7 +2487,16 @@ retry:
quotation:
if (!isalnum(c)) {
term = c;
- c = '"';
+ switch (c) {
+ case '\'':
+ c = 'q'; break;
+ case '/':
+ c = 'r'; break;
+ case '`':
+ c = 'x'; break;
+ default:
+ c = 'Q';break;
+ }
}
else {
term = nextc();
@@ -2387,6 +2572,15 @@ retry:
yylval.id = rb_intern(tok());
return GVAR;
+ case '-':
+ tokadd('$');
+ tokadd(c);
+ c = nextc();
+ tokadd(c);
+ tokfix();
+ yylval.id = rb_intern(tok());
+ return GVAR;
+
case '&': /* $&: last match */
case '`': /* $`: string before last match */
case '\'': /* $': string after last match */
@@ -2468,11 +2662,10 @@ retry:
/* See if it is a reserved word. */
while (low <= high) {
mid = low + (high - low)/2;
- if (( c = strcmp(mid->name, tok())) == 0) {
+ if ((c = strcmp(mid->name, tok())) == 0) {
enum lex_state state = lex_state;
lex_state = mid->state;
- if (state != EXPR_BEG
- && state != EXPR_BEG) {
+ if (state != EXPR_BEG) {
if (mid->id == IF) return IF_MOD;
if (mid->id == UNLESS) return UNLESS_MOD;
if (mid->id == WHILE) return WHILE_MOD;
@@ -2512,6 +2705,7 @@ retry:
result = IDENTIFIER;
}
}
+ tokfix();
yylval.id = rb_intern(tok());
return result;
}
@@ -2525,7 +2719,6 @@ str_extend(list, term)
int c;
VALUE ss;
NODE *node;
- ID id;
int nest;
c = nextc();
@@ -2579,6 +2772,7 @@ str_extend(list, term)
if (c == term) {
list_append(list, NEW_STR(str_new2("#$")));
pushback(c);
+ newtok();
return list;
}
switch (c) {
@@ -2618,7 +2812,6 @@ str_extend(list, term)
switch (c) {
case -1:
if (nest > 0) {
- bad_sub:
Error("bad substitution in string");
newtok();
return list;
@@ -2647,7 +2840,6 @@ str_extend(list, term)
newtok();
return list;
}
- add_char:
default:
tokadd(c);
break;
@@ -2665,11 +2857,11 @@ str_extend(list, term)
}
NODE*
-newnode(type, a0, a1, a2)
+node_newnode(type, a0, a1, a2)
enum node_type type;
NODE *a0, *a1, *a2;
{
- NODE *n = (NODE*)newobj();
+ NODE *n = (NODE*)rb_newobj();
n->flags |= T_NODE;
nd_set_type(n, type);
@@ -2690,41 +2882,79 @@ nodetype(node) /* for debug */
return (enum node_type)nd_type(node);
}
+int
+nodeline(node)
+ NODE *node;
+{
+ return nd_line(node);
+}
+
+static NODE*
+newline_node(node)
+ NODE *node;
+{
+ NODE *nl = 0;
+ if (node) {
+ nl = NEW_NEWLINE(node);
+ fixpos(nl, node);
+ nl->nd_nth = nd_line(node);
+ }
+ return nl;
+}
+
+static void
+fixpos(node, orig)
+ NODE *node, *orig;
+{
+ if (!node) return;
+ if (!orig) return;
+ node->file = orig->file;
+ nd_set_line(node, nd_line(orig));
+}
+
static NODE*
block_append(head, tail)
NODE *head, *tail;
{
extern int verbose;
- NODE *last;
+ NODE *end;
if (tail == 0) return head;
if (head == 0) return tail;
- if (nd_type(head) != NODE_BLOCK)
- head = last = NEW_BLOCK(head);
+ if (nd_type(head) != NODE_BLOCK) {
+ end = NEW_BLOCK(head);
+ end->nd_end = end;
+ fixpos(end, head);
+ head = end;
+ }
else {
- last = head;
- while (last->nd_next) {
- last = last->nd_next;
- }
+ end = head->nd_end;
}
if (verbose) {
- switch (nd_type(last->nd_head)) {
+ NODE *nd = end->nd_head;
+ newline:
+ switch (nd_type(nd)) {
case NODE_RETURN:
Warning("statement not reached");
break;
+ case NODE_NEWLINE:
+ nd = nd->nd_next;
+ goto newline;
+
default:
break;
}
}
-
+
if (nd_type(tail) != NODE_BLOCK) {
tail = NEW_BLOCK(tail);
+ tail->nd_end = tail;
}
- last->nd_next = tail;
- head->nd_alen += tail->nd_alen;
+ end->nd_next = tail;
+ head->nd_end = tail->nd_end;
return head;
}
@@ -2792,7 +3022,7 @@ gettable(id)
if (local_id(id)) return NEW_LVAR(id);
if (dyna_var_defined(id)) return NEW_DVAR(id);
/* method call without arguments */
- return NEW_FCALL(id, 0);
+ return NEW_VCALL(id);
}
else if (is_global_id(id)) {
return NEW_GVAR(id);
@@ -2808,7 +3038,7 @@ gettable(id)
}
static NODE*
-asignable(id, val)
+assignable(id, val)
ID id;
NODE *val;
{
@@ -2818,11 +3048,12 @@ asignable(id, val)
yyerror("Can't change the value of self");
}
else if (id == NIL) {
- yyerror("Can't asign to nil");
+ yyerror("Can't assign to nil");
}
else if (is_local_id(id)) {
- if (local_id(id) || !dyna_in_block())
+ if (local_id(id) || !dyna_in_block()) {
lhs = NEW_LASGN(id, val);
+ }
else{
dyna_var_asgn(id, TRUE);
lhs = NEW_DASGN(id, val);
@@ -2836,7 +3067,7 @@ asignable(id, val)
}
else if (is_const_id(id)) {
if (cur_mid || in_single)
- yyerror("dynamic constant asignment");
+ yyerror("dynamic constant assignment");
lhs = NEW_CASGN(id, val);
}
else {
@@ -2918,6 +3149,9 @@ value_expr(node)
case NODE_IF:
return value_expr(node->nd_body) && value_expr(node->nd_else);
+ case NODE_NEWLINE:
+ return value_expr(node->nd_next);
+
default:
return TRUE;
}
@@ -2934,6 +3168,8 @@ cond0(node)
switch (type) {
case NODE_DREGX:
case NODE_DREGX_ONCE:
+ local_cnt('_');
+ local_cnt('~');
return call_op(NEW_GVAR(rb_intern("$_")),MATCH,1,node);
case NODE_DOT2:
@@ -2946,6 +3182,8 @@ cond0(node)
case NODE_LIT:
if (TYPE(node->nd_lit) == T_REGEXP) {
+ local_cnt('_');
+ local_cnt('~');
return NEW_MATCH(node);
}
default:
@@ -2966,26 +3204,28 @@ cond(node)
case NODE_GASGN:
case NODE_IASGN:
case NODE_CASGN:
- Warning("asignment in condition");
+ Warning("assignment in condition");
break;
+ case NODE_NEWLINE:
+ node->nd_next = cond0(node->nd_next);
+ return node;
+ default:
+ break;
}
- node = cond0(node);
- if (type == NODE_CALL && node->nd_mid == '!') {
- if (node->nd_args || node->nd_recv == 0) {
- Bug("method `!' called with wrong # of operand");
- }
- node->nd_recv = cond0(node->nd_recv);
- }
- return node;
+ return cond0(node);
}
static NODE*
cond2(node)
NODE *node;
{
+ enum node_type type;
+
node = cond(node);
- if (nd_type(node) == NODE_LIT && FIXNUM_P(node->nd_lit)) {
+ type = nd_type(node);
+ if (type == NODE_NEWLINE) node = node->nd_next;
+ if (type == NODE_LIT && FIXNUM_P(node->nd_lit)) {
return call_op(node,EQ,1,NEW_GVAR(rb_intern("$.")));
}
return node;
@@ -2998,13 +3238,14 @@ logop(type, left, right)
{
value_expr(left);
- return newnode(type, cond(left), cond(right));
+ return node_newnode(type, cond(left), cond(right));
}
st_table *new_idhash();
static struct local_vars {
ID *tbl;
+ int nofree;
int cnt;
int dlev;
struct local_vars *prev;
@@ -3017,6 +3258,7 @@ local_push()
local = ALLOC(struct local_vars);
local->prev = lvtbl;
+ local->nofree = 0;
local->cnt = 0;
local->tbl = 0;
local->dlev = 0;
@@ -3029,13 +3271,17 @@ local_pop()
struct local_vars *local = lvtbl;
lvtbl = local->prev;
- if (local->tbl) local->tbl[0] = local->cnt;
+ if (local->tbl) {
+ local->tbl[0] = local->cnt;
+ if (!local->nofree) free(local->tbl);
+ }
free(local);
}
static ID*
local_tbl()
{
+ lvtbl->nofree = 1;
return lvtbl->tbl;
}
@@ -3051,6 +3297,7 @@ local_cnt(id)
if (lvtbl->tbl[cnt] == id) return cnt-1;
}
+
if (lvtbl->tbl == 0) {
lvtbl->tbl = ALLOC_N(ID, 2);
lvtbl->tbl[0] = 0;
@@ -3080,12 +3327,7 @@ static void
top_local_init()
{
local_push();
- if (the_scope->local_tbl) {
- lvtbl->cnt = the_scope->local_tbl[0];
- }
- else {
- lvtbl->cnt = 0;
- }
+ lvtbl->cnt = the_scope->local_tbl?the_scope->local_tbl[0]:0;
if (lvtbl->cnt > 0) {
lvtbl->tbl = ALLOC_N(ID, lvtbl->cnt+1);
MEMCPY(lvtbl->tbl, the_scope->local_tbl, ID, lvtbl->cnt+1);
@@ -3109,25 +3351,33 @@ top_local_setup()
i = lvtbl->tbl[0];
if (i < len) {
- if (the_scope->flag == SCOPE_ALLOCA) {
- VALUE *vars = the_scope->local_vars;
- the_scope->local_vars = ALLOC_N(VALUE, len);
- if (vars) {
- MEMCPY(the_scope->local_vars, vars, VALUE, i);
- memclear(the_scope->local_vars+i, len-i);
+ if (i == 0 || the_scope->flag == SCOPE_ALLOCA) {
+ VALUE *vars = ALLOC_N(VALUE, len+1);
+ if (the_scope->local_vars) {
+ *vars++ = the_scope->local_vars[-1];
+ MEMCPY(vars, the_scope->local_vars, VALUE, i);
+ memclear(vars+i, len-i);
}
else {
- memclear(the_scope->local_vars, len);
+ *vars++ = 0;
+ memclear(vars, len);
}
- the_scope->flag = SCOPE_MALLOC;
+ the_scope->local_vars = vars;
+ the_scope->flag |= SCOPE_MALLOC;
}
else {
- REALLOC_N(the_scope->local_vars, VALUE, len);
+ VALUE *vars = the_scope->local_vars-1;
+ REALLOC_N(vars, VALUE, len+1);
+ the_scope->local_vars = vars+1;
memclear(the_scope->local_vars+i, len-i);
- free(the_scope->local_tbl);
}
lvtbl->tbl[0] = len;
+ if (the_scope->local_tbl && the_scope->local_vars[-1] == 0) {
+ free(the_scope->local_tbl);
+ }
+ the_scope->local_vars[-1] = 0;
the_scope->local_tbl = lvtbl->tbl;
+ lvtbl->nofree = 1;
}
}
local_pop();
@@ -3157,8 +3407,6 @@ dyna_in_block()
static void
cref_pop()
{
- NODE *cref = cur_cref;
-
cur_cref = cur_cref->nd_next;
}
@@ -3199,10 +3447,10 @@ static struct op_tbl rb_op_tbl[] = {
'/', "/",
'%', "%",
POW, "**",
- UPLUS, "+(unary)",
- UMINUS, "-(unary)",
UPLUS, "+@",
UMINUS, "-@",
+ UPLUS, "+(unary)",
+ UMINUS, "-(unary)",
'|', "|",
'^', "^",
'&', "&",
@@ -3280,13 +3528,13 @@ rb_intern(name)
break;
}
}
- if (id == 0) Bug("Unknown operator `%s'", name);
+ if (id == 0) NameError("Unknown operator `%s'", name);
break;
}
last = strlen(name)-1;
if (name[last] == '=') {
- /* attribute asignment */
+ /* attribute assignment */
char *buf = ALLOCA_N(char,last+1);
strncpy(buf, name, last);
@@ -3362,24 +3610,20 @@ rb_id2name(id)
return ok.name;
}
-static int
-const_check(id, val, class)
+int
+rb_is_const_id(id)
ID id;
- VALUE val;
- struct RClass *class;
{
- if (is_const_id(id) && rb_const_defined(class, id)) {
- Warning("constant redefined for %s", rb_class2name(class));
- return ST_STOP;
- }
- return ST_CONTINUE;
+ if (is_const_id(id)) return TRUE;
+ return FALSE;
}
-void
-rb_const_check(class, module)
- struct RClass *class, *module;
+int
+rb_is_instance_id(id)
+ ID id;
{
- st_foreach(module->iv_tbl, const_check, class);
+ if (is_instance_id(id)) return TRUE;
+ return FALSE;
}
void