From 897cf066952978ccbae1d57bbc14a03c7b98a1e1 Mon Sep 17 00:00:00 2001 From: Yukihiro Matsumoto Date: Wed, 1 Feb 1995 19:48:24 +0900 Subject: version 0.65 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://cache.ruby-lang.org/pub/ruby/1.0/ruby-0.65.tar.gz Wed Feb 1 19:48:24 1995 Yukihiro Matsumoto (matz@ix-02) * string.c(str_replace): 置き換える文字列の長さが等しい時メモリコ ピーをしない. * string.c(rindex): バグ修正. Mon Jan 30 11:23:05 1995 Yukihiro Matsumoto (matz@ix-02) * parse.y(value_expr): ifのチェックを追加. * gc.c(gc_mark): free cellの扱いにバグ. * parse.y: 文法の変更(よりシンプルに).例外を減らした. Thu Jan 26 00:52:55 1995 Yukihiro Matsumoto (matz@dyna) * parse.y: 引数として連想配列を置くことができるように.この場合, 連想配列リテラルが最終引数となる. * parse.y: 配列参照の`[]'内が空でもよいことにした. Tue Jan 24 14:45:15 1995 Yukihiro Matsumoto (matz@ix-02) * class.c(rb_include_module): `-v'を指定した時にはincludeしたモジュー ルとクラス定数が衝突していないかチェックする. Mon Jan 23 10:42:09 1995 Yukihiro Matsumoto (matz@ix-02) * parse.y(rb_class2name): メタクラスに関するbug fix. * dict.c: Dict[..]で辞書の生成が出来るように. * array.c: Array[..]で配列の生成が出来るように. * parse.y: 辞書の表現として{a,b,..}という形式も許すように. Fri Jan 20 10:28:38 1995 Yukihiro Matsumoto (matz@ix-02) * re.c(Regexp.quote): 正規表現をエスケープするメソッド. * 無駄なrb_intern()を減らした. * parse.y: `!', `!=', `!~'を特殊演算子にする.よってこれらは再定義 できなくなった. Wed Jan 18 13:20:41 1995 Yukihiro Matsumoto (matz@ix-02) * parse.y: 文法の整理(unless,untilをなくした). Tue Jan 17 11:11:27 1995 Yukihiro Matsumoto (matz@ix-02) * eval.c: defでメソッド再定義時にはスーパークラスのメソッドの可視 性を継承する.最初の定義の時は今までと同じデフォルト(トップレベ ルで関数的,クラス定義内で通常メソッド). * object.c(Class::new): オブジェクトの生成時に関数的メ ソッドinit_objectが必ず呼ばれるように変更. * eval.c: 未定義のメソッドに対してunknownメソッドが呼ばれるように なった.エラー表示が今までと同じになるようにenvを調節している. Fri Jan 13 14:40:30 1995 Yukihiro Matsumoto (matz@ix-02) * gc.c: gcを若干書き換えて整理した.が,あまり変化はなかったようだ. * parse.y(yylex): symbolを\symから:symに変更した. Thu Jan 12 01:39:28 1995 Yukihiro Matsumoto (matz@dyna) * eval.c: 新規関数 rb_eval_string(). * gc.c: gc_mark()を一部非再帰化. * variable.c(rb_ivar_{get,set}): インスタンス変数のアクセス周りで チェックが足りなかった. * variable.c: クラス定数とインスタンス変数でハッシュテーブルを共有 するようにした. * ruby.h: iv_tblをRBasicからRObjectとRClassへ移動した.これにより, ObjectとClass,Moduleしかインスタンス変数を持てなくなる.が,メモ リ効率は若干向上する. --- parse.y | 759 ++++++++++++++++++++++++++++++++-------------------------------- 1 file changed, 384 insertions(+), 375 deletions(-) (limited to 'parse.y') diff --git a/parse.y b/parse.y index c4148d88d3..7c84221c8c 100644 --- a/parse.y +++ b/parse.y @@ -3,7 +3,7 @@ parse.y - $Author: matz $ - $Date: 1995/01/10 10:42:45 $ + $Date: 1995/01/12 08:54:50 $ created at: Fri May 28 18:02:42 JST 1993 Copyright (C) 1994 Yukihiro Matsumoto @@ -50,7 +50,7 @@ static enum lex_state { static ID cur_class = Qnil, cur_mid = Qnil; static int in_module, in_single; -static void value_expr(); +static int value_expr(); static NODE *cond(); static NODE *cond2(); @@ -96,8 +96,6 @@ static void setup_top_local(); ELSE CASE WHEN - UNLESS - UNTIL WHILE FOR IN @@ -120,9 +118,7 @@ static void setup_top_local(); _FILE_ _LINE_ IF_MOD - UNLESS_MOD WHILE_MOD - UNTIL_MOD ALIAS %token IDENTIFIER GVAR IVAR CONSTANT @@ -131,14 +127,14 @@ static void setup_top_local(); %type singleton inc_list %type literal numeric -%type compstmts stmts stmt stmt0 expr expr0 var_ref +%type compexpr exprs expr arg primary var_ref %type if_tail opt_else case_body cases resque ensure -%type call_args call_args0 args args2 array +%type call_args call_args0 args args2 opt_args %type f_arglist f_args assoc_list assocs assoc %type mlhs mlhs_head mlhs_tail lhs iter_var opt_iter_var %type superclass variable symbol %type fname op rest_arg -%type f_arg +%type f_arg %token UPLUS /* unary+ */ %token UMINUS /* unary- */ %token POW /* ** */ @@ -156,11 +152,13 @@ static void setup_top_local(); %token OP_ASGN /* +=, -= etc. */ %token ASSOC /* => */ %token LPAREN LBRACK LBRACE +%token SYMBEG /* * precedence table */ +%left IF_MOD WHILE_MOD %left OR %left AND %left YIELD RETURN FAIL @@ -186,91 +184,74 @@ program : { lex_state = EXPR_BEG; init_top_local(); } - compstmts + compexpr { eval_tree = block_append(eval_tree, $2); setup_top_local(); } -compstmts : stmts opt_term +compexpr : exprs opt_term -stmts : /* none */ +exprs : /* none */ { $$ = Qnil; } - | stmt - | stmts term stmt + | expr + | exprs term expr { $$ = block_append($1, $3); } - | stmts error + | exprs error { lex_state = EXPR_BEG; } - stmt + expr { yyerrok; $$ = block_append($1, $4); } -stmt : CLASS IDENTIFIER superclass +expr : mlhs '=' args2 { - if (cur_class || cur_mid || in_single) - Error("nested class definition"); - cur_class = $2; - push_local(); + value_expr($3); + $1->nd_value = $3; + $$ = $1; } - compstmts - END + | assocs { - $$ = NEW_CLASS($2, $5, $3); - pop_local(); - cur_class = Qnil; + $$ = NEW_HASH($1); } - | MODULE IDENTIFIER + | RETURN args2 { - if (cur_class != Qnil) - Error("nested module definition"); - cur_class = $2; - in_module = 1; - push_local(); + value_expr($2); + if (!cur_mid && !in_single) + Error("return appeared outside of method"); + $$ = NEW_RET($2); } - compstmts - END + | FAIL args2 { - $$ = NEW_MODULE($2, $4); - pop_local(); - cur_class = Qnil; - in_module = 0; + value_expr($2); + $$ = NEW_FAIL($2); } - | DEF fname + | YIELD args2 { - if (cur_mid || in_single) - Error("nested method definition"); - cur_mid = $2; - push_local(); + value_expr($2); + $$ = NEW_YIELD($2); } - f_arglist - compstmts - END + | IDENTIFIER call_args0 { - $$ = NEW_DEFN($2, NEW_RFUNC($4, $5), cur_class?0:1); - pop_local(); - cur_mid = Qnil; + $$ = NEW_CALL(Qnil, $1, $2); } - | DEF singleton '.' fname + | primary '.' IDENTIFIER call_args0 { - value_expr($2); - in_single++; - push_local(); + value_expr($1); + $$ = NEW_CALL($1, $3, $4); } - f_arglist - compstmts - END + | SUPER call_args0 { - $$ = NEW_DEFS($2, $4, NEW_RFUNC($6, $7)); - pop_local(); - in_single--; + if (!cur_mid && !in_single) + Error("super called outside of method"); + $$ = NEW_SUPER($2); } | UNDEF fname { @@ -286,100 +267,31 @@ stmt : CLASS IDENTIFIER superclass Error("include appeared in method definition"); $$ = $2; } - | stmt0 IF_MOD stmt0 + | expr IF_MOD expr { $$ = NEW_IF(cond($3), $1, Qnil); } - | stmt0 UNLESS_MOD stmt0 - { - $$ = NEW_UNLESS(cond($3), $1, Qnil); - } - | stmt0 WHILE_MOD stmt0 + | expr WHILE_MOD expr { $$ = NEW_WHILE2(cond($3), $1); } - | stmt0 UNTIL_MOD stmt0 - { - $$ = NEW_UNTIL2(cond($3), $1); - } - | stmt AND stmt + | expr AND expr { $$ = NEW_AND(cond($1), cond($3)); } - | stmt OR stmt + | expr OR expr { $$ = NEW_OR(cond($1), cond($3)); } - | stmt0 - -stmt0 : mlhs '=' args2 - { - $1->nd_value = $3; - $$ = $1; - } - | REDO - { - $$ = NEW_REDO(); - } - | BREAK - { - $$ = NEW_BREAK(); - } - | CONTINUE - { - $$ = NEW_CONT(); - } - | RETRY - { - $$ = NEW_RETRY(); - } - | RETURN args2 - { - value_expr($2); - if (!cur_mid && !in_single) - Error("return appeared outside of method"); - $$ = NEW_RET($2); - } - | RETURN - { - if (!cur_mid && !in_single) - Error("return appeared outside of method"); - $$ = NEW_RET(Qnil); - } - | FAIL args2 - { - value_expr($2); - $$ = NEW_FAIL($2); - } - | YIELD args2 - { - value_expr($2); - $$ = NEW_YIELD($2); - } - | IDENTIFIER call_args0 - { - $$ = NEW_CALL(Qnil, $1, $2); - } - | expr0 '.' IDENTIFIER call_args0 - { - value_expr($1); - $$ = NEW_CALL($1, $3, $4); - } - | SUPER call_args0 - { - if (!cur_mid && !in_single) - Error("super called outside of method"); - $$ = NEW_SUPER($2); - } - | expr + | arg mlhs : mlhs_head { - $$ = NEW_MASGN(NEW_LIST($1),Qnil); + $$ = NEW_MASGN(NEW_LIST($1), Qnil); } | mlhs_head '*' lhs { - $$ = NEW_MASGN(NEW_LIST($1),$3); + $$ = NEW_MASGN(NEW_LIST($1), $3); } | mlhs_head mlhs_tail { @@ -390,18 +302,7 @@ mlhs : mlhs_head $$ = NEW_MASGN(list_concat(NEW_LIST($1),$2),$5); } -mlhs_head : variable comma - { - $$ = asignable($1, Qnil); - } - | expr0 '[' args rbracket comma - { - $$ = aryset($1, $3, Qnil); - } - | expr0 '.' IDENTIFIER comma - { - $$ = attrset($1, $3, Qnil); - } +mlhs_head : lhs comma mlhs_tail : lhs { @@ -416,24 +317,15 @@ lhs : variable { $$ = asignable($1, Qnil); } - | expr0 '[' args rbracket + | primary '[' opt_args rbracket { $$ = aryset($1, $3, Qnil); } - | expr0 '.' IDENTIFIER + | primary '.' IDENTIFIER { $$ = attrset($1, $3, Qnil); } -superclass : /* none */ - { - $$ = Qnil; - } - | ':' IDENTIFIER - { - $$ = $2; - } - inc_list : IDENTIFIER { $$ = NEW_INC($1); @@ -467,9 +359,7 @@ op : COLON2 { $$ = COLON2; } | '&' { $$ = '&'; } | CMP { $$ = CMP; } | EQ { $$ = EQ; } - | NEQ { $$ = NEQ; } | MATCH { $$ = MATCH; } - | NMATCH { $$ = NMATCH; } | '>' { $$ = '>'; } | GEQ { $$ = GEQ; } | '<' { $$ = '<'; } @@ -482,119 +372,26 @@ op : COLON2 { $$ = COLON2; } | '/' { $$ = '/'; } | '%' { $$ = '%'; } | POW { $$ = POW; } - | '!' { $$ = '!'; } | '~' { $$ = '~'; } | UPLUS { $$ = UMINUS; } | UMINUS { $$ = UPLUS; } | AREF { $$ = AREF; } | ASET { $$ = ASET; } -f_arglist : '(' f_args rparen - { - $$ = $2; - } - | term - { - $$ = NEW_ARGS(0, -1); - } - -f_args : /* no arg */ - { - $$ = NEW_ARGS(0, -1); - } - | f_arg - { - $$ = NEW_ARGS($1, -1); - } - | f_arg comma rest_arg - { - $$ = NEW_ARGS($1, $3); - } - | rest_arg - { - $$ = NEW_ARGS(Qnil, $1); - } - | f_arg error - { - lex_state = EXPR_BEG; - $$ = NEW_ARGS($1, -1); - } - | error - { - lex_state = EXPR_BEG; - $$ = NEW_ARGS(0, -1); - } - -f_arg : IDENTIFIER - { - if (!is_local_id($1)) - Error("formal argument must be local variable"); - local_cnt($1); - $$ = 1; - } - | f_arg comma IDENTIFIER - { - if (!is_local_id($3)) - Error("formal argument must be local variable"); - local_cnt($3); - $$ += 1; - } - -rest_arg : '*' IDENTIFIER - { - if (!is_local_id($2)) - Error("rest argument must be local variable"); - $$ = local_cnt($2); - } - -singleton : var_ref - { - if (nd_type($1) == NODE_SELF) { - $$ = NEW_SELF(); - } - else if (nd_type($1) == NODE_NIL) { - Error("Can't define single method for nil."); - $$ = Qnil; - } - else { - $$ = $1; - } - } - | LPAREN compstmts rparen - { - switch (nd_type($2)) { - case NODE_STR: - case NODE_STR2: - case NODE_XSTR: - case NODE_XSTR2: - case NODE_DREGX: - case NODE_DGLOB: - case NODE_LIT: - case NODE_ARRAY: - case NODE_ZARRAY: - Error("Can't define single method for literals."); - default: - break; - } - $$ = $2; - } - -expr : variable '=' expr +arg : variable '=' arg { value_expr($3); $$ = asignable($1, $3); } - | expr0 '[' args rbracket '=' expr + | primary '[' opt_args rbracket '=' arg { - value_expr($6); $$ = aryset($1, $3, $6); } - | expr0 '.' IDENTIFIER '=' expr + | primary '.' IDENTIFIER '=' arg { - value_expr($5); $$ = attrset($1, $3, $5); } - | variable OP_ASGN expr + | variable OP_ASGN arg { NODE *val; @@ -613,27 +410,31 @@ expr : variable '=' expr } $$ = asignable($1, call_op(val, $2, 1, $3)); } - | expr0 '[' args rbracket OP_ASGN expr + | primary '[' opt_args rbracket OP_ASGN arg { - $$ = NEW_OP_ASGN1($1,$5,list_concat(NEW_LIST($6),$3)); + NODE *args = NEW_LIST($6); + + if ($3) list_concat(args, $3); + $$ = NEW_OP_ASGN1($1, $5, args); } - | expr0 '.' IDENTIFIER OP_ASGN expr + | primary '.' IDENTIFIER OP_ASGN arg { $$ = NEW_OP_ASGN2($1, $4, $5); } - | expr DOT2 expr + | arg DOT2 arg { $$ = call_op($1, DOT2, 1, $3); } - | expr DOT3 expr + | arg DOT3 arg { $$ = NEW_DOT3(cond2($1), cond2($3)); } - | expr '+' expr + | arg '+' arg { $$ = Qnil; if ($1 && $3 - && (nd_type($3) == NODE_LIT || nd_type($3) == NODE_STR) + && (nd_type($3) == NODE_LIT + || nd_type($3) == NODE_STR) && nd_type($1) == NODE_CALL && $1->nd_mid == '+') { if ($1->nd_args->nd_head == Qnil) Bug("bad operand for `+'"); @@ -648,87 +449,87 @@ expr : variable '=' expr $$ = call_op($1, '+', 1, $3); } } - | expr '-' expr + | arg '-' arg { $$ = call_op($1, '-', 1, $3); } - | expr '*' expr + | arg '*' arg { $$ = call_op($1, '*', 1, $3); } - | expr '/' expr + | arg '/' arg { $$ = call_op($1, '/', 1, $3); } - | expr '%' expr + | arg '%' arg { $$ = call_op($1, '%', 1, $3); } - | expr POW expr + | arg POW arg { $$ = call_op($1, POW, 1, $3); } - | UPLUS expr + | UPLUS arg { $$ = call_op($2, UPLUS, 0); } - | UMINUS expr + | UMINUS arg { $$ = call_op($2, UMINUS, 0); } - | expr '|' expr + | arg '|' arg { $$ = call_op($1, '|', 1, $3); } - | expr '^' expr + | arg '^' arg { $$ = call_op($1, '^', 1, $3); } - | expr '&' expr + | arg '&' arg { $$ = call_op($1, '&', 1, $3); } - | expr CMP expr + | arg CMP arg { $$ = call_op($1, CMP, 1, $3); } - | expr '>' expr + | arg '>' arg { $$ = call_op($1, '>', 1, $3); } - | expr GEQ expr + | arg GEQ arg { $$ = call_op($1, GEQ, 1, $3); } - | expr '<' expr + | arg '<' arg { $$ = call_op($1, '<', 1, $3); } - | expr LEQ expr + | arg LEQ arg { $$ = call_op($1, LEQ, 1, $3); } - | expr EQ expr + | arg EQ arg { $$ = call_op($1, EQ, 1, $3); } - | expr NEQ expr + | arg NEQ arg { - $$ = call_op($1, NEQ, 1, $3); + $$ = NEW_NOT(call_op($1, EQ, 1, $3)); } - | expr MATCH expr + | arg MATCH arg { $$ = NEW_CALL($1, MATCH, NEW_LIST($3)); } - | expr NMATCH expr + | arg NMATCH arg { - $$ = NEW_CALL($1, NMATCH, NEW_LIST($3)); + $$ = NEW_NOT(NEW_CALL($1, MATCH, NEW_LIST($3))); } - | '!' expr + | '!' arg { - $$ = call_op($2, '!', 0); + $$ = NEW_NOT(cond($2)); } - | '~' expr + | '~' arg { if ($2 && (nd_type($2) == NODE_STR @@ -741,27 +542,27 @@ expr : variable '=' expr $$ = call_op($2, '~', 0); } } - | expr LSHFT expr + | arg LSHFT arg { $$ = call_op($1, LSHFT, 1, $3); } - | expr RSHFT expr + | arg RSHFT arg { $$ = call_op($1, RSHFT, 1, $3); } - | expr COLON2 expr + | arg COLON2 arg { $$ = call_op($1, COLON2, 1, $3); } - | expr ANDOP expr + | arg ANDOP arg { $$ = NEW_AND(cond($1), cond($3)); } - | expr OROP expr + | arg OROP arg { $$ = NEW_OR(cond($1), cond($3)); } - |expr0 + | primary { $$ = $1; } @@ -771,23 +572,37 @@ call_args : /* none */ $$ = Qnil; } | call_args0 - | '*' expr + | '*' arg { $$ = $2; } call_args0 : args - | args comma '*' expr + | assocs + { + $$ = NEW_LIST(NEW_HASH($1)); + } + | args comma assocs + { + $$ = list_append($1, NEW_HASH($3)); + } + | args comma '*' arg { $$ = call_op($1, '+', 1, $4); } -args : expr +opt_args : /* none */ + { + $$ = Qnil; + } + | args + +args : arg { value_expr($1); $$ = NEW_LIST($1); } - | args comma expr + | args comma arg { value_expr($3); $$ = list_append($1, $3); @@ -803,7 +618,7 @@ args2 : args } } -expr0 : literal +primary : literal { $$ = NEW_LIT($1); } @@ -820,10 +635,6 @@ expr0 : literal | DREGEXP | DGLOB | var_ref - | IDENTIFIER '(' call_args rparen - { - $$ = NEW_CALL(Qnil, $1, $3); - } | SUPER '(' call_args rparen { if (!cur_mid && !in_single) @@ -836,13 +647,12 @@ expr0 : literal Error("super called outside of method"); $$ = NEW_ZSUPER(); } - - | expr0 '[' args rbracket + | primary '[' opt_args rbracket { value_expr($1); $$ = NEW_CALL($1, AREF, $3); } - | LBRACK array rbracket + | LBRACK opt_args rbracket { if ($2 == Qnil) $$ = NEW_ZARRAY(); /* zero length array*/ @@ -854,8 +664,33 @@ expr0 : literal { $$ = NEW_HASH($2); } + | REDO + { + $$ = NEW_REDO(); + } + | BREAK + { + $$ = NEW_BREAK(); + } + | CONTINUE + { + $$ = NEW_CONT(); + } + | RETRY + { + $$ = NEW_RETRY(); + } + | RETURN + { + if (!cur_mid && !in_single) + Error("return appeared outside of method"); + $$ = NEW_RET(Qnil); + } | FAIL '(' args2 ')' { + if (nd_type($3) == NODE_ARRAY) { + Error("wrong number of argument to fail(0 or 1)"); + } value_expr($3); $$ = NEW_FAIL($3); } @@ -880,7 +715,7 @@ expr0 : literal { $$ = NEW_YIELD(Qnil); } - | expr0 '{' opt_iter_var '|' compstmts rbrace + | primary '{' opt_iter_var '|' compexpr rbrace { if (nd_type($1) == NODE_LVAR || nd_type($1) == NODE_MVAR) { @@ -888,52 +723,47 @@ expr0 : literal } $$ = NEW_ITER($3, $1, $5); } - | expr0 '.' IDENTIFIER '(' call_args rparen + | IDENTIFIER '(' call_args rparen + { + $$ = NEW_CALL(Qnil, $1, $3); + } + | primary '.' IDENTIFIER '(' call_args rparen { value_expr($1); $$ = NEW_CALL($1, $3, $5); } - | expr0 '.' IDENTIFIER + | primary '.' IDENTIFIER { value_expr($1); $$ = NEW_CALL($1, $3, Qnil); } - | IF stmt0 then - compstmts + | IF expr then + compexpr if_tail END { $$ = NEW_IF(cond($2), $4, $5); } - | UNLESS stmt0 then - compstmts opt_else END - { - $$ = NEW_UNLESS(cond($2), $4, $5); - } - | WHILE stmt0 term compstmts END + | WHILE expr term compexpr END { $$ = NEW_WHILE(cond($2), $4); } - | UNTIL stmt0 term compstmts END - { - $$ = NEW_UNTIL(cond($2), $4); - } - | CASE compstmts + | CASE compexpr case_body END { value_expr($2); $$ = NEW_CASE($2, $3); } - | FOR iter_var IN stmt0 term - compstmts + | FOR iter_var IN expr term + compexpr END { value_expr($4); $$ = NEW_FOR($2, $4, $6); } | PROTECT - compstmts + compexpr resque ensure END @@ -946,18 +776,77 @@ expr0 : literal $$ = NEW_PROT($2, $3, $4); } } - | LPAREN compstmts rparen + | LPAREN compexpr rparen { $$ = $2; } + | CLASS IDENTIFIER superclass + { + if (cur_class || cur_mid || in_single) + Error("nested class definition"); + cur_class = $2; + push_local(); + } + compexpr + END + { + $$ = NEW_CLASS($2, $5, $3); + pop_local(); + cur_class = Qnil; + } + | MODULE IDENTIFIER + { + if (cur_class != Qnil) + Error("nested module definition"); + cur_class = $2; + in_module = 1; + push_local(); + } + compexpr + END + { + $$ = NEW_MODULE($2, $4); + pop_local(); + cur_class = Qnil; + in_module = 0; + } + | DEF fname + { + if (cur_mid || in_single) + Error("nested method definition"); + cur_mid = $2; + push_local(); + } + f_arglist + compexpr + END + { + $$ = NEW_DEFN($2, NEW_RFUNC($4, $5), cur_class?0:1); + pop_local(); + cur_mid = Qnil; + } + | DEF singleton '.' fname + { + value_expr($2); + in_single++; + push_local(); + } + f_arglist + compexpr + END + { + $$ = NEW_DEFS($2, $4, NEW_RFUNC($6, $7)); + pop_local(); + in_single--; + } then : term | THEN | term THEN if_tail : opt_else - | ELSIF stmt0 then - compstmts + | ELSIF expr then + compexpr if_tail { $$ = NEW_IF(cond($2), $4, $5); @@ -967,7 +856,7 @@ opt_else : /* none */ { $$ = Qnil; } - | ELSE compstmts + | ELSE compexpr { $$ = $2; } @@ -982,7 +871,7 @@ opt_iter_var : /* none */ | iter_var case_body : WHEN args then - compstmts + compexpr cases { $$ = NEW_WHEN($2, $4, $5); @@ -990,7 +879,7 @@ case_body : WHEN args then cases : opt_else | WHEN args then - compstmts + compexpr cases { $$ = NEW_WHEN($2, $4, $5); @@ -1000,7 +889,7 @@ resque : /* none */ { $$ = Qnil; } - | RESQUE compstmts + | RESQUE compexpr { if ($2 == Qnil) $$ = (NODE*)1; @@ -1012,26 +901,19 @@ ensure : /* none */ { $$ = Qnil; } - | ENSURE compstmts + | ENSURE compexpr { $$ = $2; } -array : /* none */ - { - $$ = Qnil; - } - | args - literal : numeric - | '\\' symbol + | SYMBEG symbol { $$ = INT2FIX($2); } | REGEXP | GLOB - symbol : fname | IVAR | GVAR @@ -1058,11 +940,121 @@ var_ref : variable $$ = gettable($1); } +superclass : term + { + $$ = Qnil; + } + | colon + { + lex_state = EXPR_BEG; + } + IDENTIFIER + { + $$ = $3; + } + +f_arglist : '(' f_args rparen + { + $$ = $2; + } + | term + { + $$ = NEW_ARGS(0, -1); + } + +f_args : /* no arg */ + { + $$ = NEW_ARGS(0, -1); + } + | f_arg + { + $$ = NEW_ARGS($1, -1); + } + | f_arg comma rest_arg + { + $$ = NEW_ARGS($1, $3); + } + | rest_arg + { + $$ = NEW_ARGS(Qnil, $1); + } + | f_arg error + { + lex_state = EXPR_BEG; + $$ = NEW_ARGS($1, -1); + } + | error + { + lex_state = EXPR_BEG; + $$ = NEW_ARGS(0, -1); + } + +f_arg : IDENTIFIER + { + if (!is_local_id($1)) + Error("formal argument must be local variable"); + local_cnt($1); + $$ = 1; + } + | f_arg comma IDENTIFIER + { + if (!is_local_id($3)) + Error("formal argument must be local variable"); + local_cnt($3); + $$ += 1; + } + +rest_arg : '*' IDENTIFIER + { + if (!is_local_id($2)) + Error("rest argument must be local variable"); + $$ = local_cnt($2); + } + +singleton : var_ref + { + if (nd_type($1) == NODE_SELF) { + $$ = NEW_SELF(); + } + else if (nd_type($1) == NODE_NIL) { + Error("Can't define single method for nil."); + $$ = Qnil; + } + else { + $$ = $1; + } + } + | LPAREN compexpr rparen + { + switch (nd_type($2)) { + case NODE_STR: + case NODE_STR2: + case NODE_XSTR: + case NODE_XSTR2: + case NODE_DREGX: + case NODE_DGLOB: + case NODE_LIT: + case NODE_ARRAY: + case NODE_ZARRAY: + Error("Can't define single method for literals."); + default: + break; + } + $$ = $2; + } + assoc_list : /* none */ { $$ = Qnil; } | assocs + | args + { + if ($1->nd_alen%2 != 0) { + Error("odd number list for Dict"); + } + $$ = $1; + } assocs : assoc | assocs comma assoc @@ -1070,12 +1062,11 @@ assocs : assoc $$ = list_concat($1, $3); } -assoc : expr ASSOC expr +assoc : arg ASSOC arg { $$ = list_append(NEW_LIST($1), $3); } - opt_term : /* none */ | term @@ -1085,6 +1076,9 @@ term : sc sc : ';' { yyerrok; } nl : '\n' { yyerrok; } +colon : ':' + | SYMBEG + rparen : ')' { yyerrok; } rbracket : ']' { yyerrok; } rbrace : '}' { yyerrok; } @@ -1196,10 +1190,6 @@ parse_regx() else if (in_brack && c == 'b') { tokadd('\b'); } - else if (isdigit(c)) { - tokadd('\\'); - tokadd(c); - } else { pushback(); read_escape(LEAVE_BS); @@ -1348,8 +1338,6 @@ static struct kwtable { "super", SUPER, EXPR_END, "then", THEN, EXPR_BEG, "undef", UNDEF, EXPR_FNAME, - "unless", UNLESS, EXPR_BEG, - "until", UNTIL, EXPR_BEG, "when", WHEN, EXPR_BEG, "while", WHILE, EXPR_BEG, "yield", YIELD, EXPR_END, @@ -1406,13 +1394,6 @@ retry: return '*'; case '!': - if (lex_state == EXPR_FNAME) { - if ((c = nextc()) == '@') { - lex_state = EXPR_BEG; - return '!'; - } - pushback(); - } lex_state = EXPR_BEG; if ((c = nextc()) == '=') { return NEQ; @@ -1737,12 +1718,15 @@ retry: return c; case ':': - lex_state = EXPR_BEG; - if (nextc() == ':') { + c = nextc(); + if (c == ':') { + lex_state = EXPR_BEG; return COLON2; } pushback(); - return ':'; + if (isspace(c)) + return ':'; + return SYMBEG; case '/': if (lex_state == EXPR_BEG || lex_state == EXPR_MID) { @@ -1786,7 +1770,6 @@ retry: return c; case '[': - if (lex_state == EXPR_BEG || lex_state == EXPR_MID) c = LBRACK; else if (lex_state == EXPR_FNAME) { @@ -1811,8 +1794,10 @@ retry: case '\\': c = nextc(); - if (c == '\n') goto retry; /* skip \\n */ - lex_state = EXPR_FNAME; + if (c == '\n') { + sourceline++; + goto retry; /* skip \\n */ + } pushback(); return '\\'; @@ -1910,9 +1895,7 @@ retry: lex_state = mid->state; 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; - if (mid->id == UNTIL) return UNTIL_MOD; } return mid->id; } @@ -2444,6 +2427,7 @@ aryset(recv, idx, val) NODE *recv, *idx, *val; { value_expr(recv); + value_expr(val); return NEW_CALL(recv, ASET, list_append(idx, val)); } @@ -2453,18 +2437,19 @@ attrset(recv, id, val) ID id; { value_expr(recv); + value_expr(val); id &= ~ID_SCOPE_MASK; id |= ID_ATTRSET; - return NEW_CALL(recv, id, NEW_ARRAY(val)); + return NEW_CALL(recv, id, NEW_LIST(val)); } -static void +static int value_expr(node) NODE *node; { - if (node == Qnil) return; + if (node == Qnil) return TRUE; switch (nd_type(node)) { case NODE_RETURN: @@ -2472,25 +2457,29 @@ value_expr(node) case NODE_BREAK: case NODE_REDO: case NODE_RETRY: + case NODE_FAIL: case NODE_WHILE: case NODE_WHILE2: case NODE_INC: case NODE_CLASS: case NODE_MODULE: + case NODE_DEFN: + case NODE_DEFS: Error("void value expression"); + return FALSE; break; case NODE_BLOCK: while (node->nd_next) { node = node->nd_next; } - if (node) { - value_expr(node->nd_head); - } - break; + return value_expr(node->nd_head); + + case NODE_IF: + return value_expr(node->nd_body) && value_expr(node->nd_else); default: - break; + return TRUE; } } @@ -2635,8 +2624,8 @@ init_top_local() lvtbl->cnt = 0; } if (lvtbl->cnt > 0) { - lvtbl->tbl = ALLOC_N(ID, lvtbl->cnt); - MEMCPY(lvtbl->tbl, the_scope->local_tbl, VALUE, lvtbl->cnt); + lvtbl->tbl = ALLOC_N(ID, lvtbl->cnt+1); + MEMCPY(lvtbl->tbl, the_scope->local_tbl, ID, lvtbl->cnt); } else { lvtbl->tbl = Qnil; @@ -2892,7 +2881,7 @@ rb_class2name(class) Fail("0x%x is not a class/module", class); } - if (FL_TEST(class, FL_SINGLE)) { + while (FL_TEST(class, FL_SINGLE)) { class = (struct RClass*)class->super; } @@ -2906,3 +2895,23 @@ rb_class2name(class) } Bug("class 0x%x not named", class); } + +static int +const_check(id, val, class) + ID id; + VALUE val; + struct RClass *class; +{ + if (is_const_id(id) && rb_const_bound(class, id)) { + Warning("constant redefined for %s", rb_class2name(class)); + return ST_STOP; + } + return ST_CONTINUE; +} + +void +rb_const_check(class, module) + struct RClass *class, *module; +{ + st_foreach(module->iv_tbl, const_check, class); +} -- cgit v1.2.3