ruby-listから移動しました。

Yukihiro Matsumotoさんの
<983338515.494474.5211.nullmailer / ev.netlab.zetabits.com>から
> 最終判断はもちろん私がするんですが、ちょうと今日が〆切だった
> りするんで、yaccファイルとたわむれている心の余裕がなかったん
> ですね。文法的に(conflictせずに)実現できるかどうかもわかりま
> せんでしたし。
> 
> でも、小迫さんの方法ではちょっとつらそうですね。singletonと
> 同じようなやり方をして、生成側で NODE_CONST であるかどうかを
> 判定するとかが良いのでしょうか?

前のは、かなりつらい方法でした。
勉強になります。
以下の例も扱うには、全体を式にしてから扱うしか、
解決方法がなさそうですね。

class (1 < 2).type < Object
  p self
end


時間に余裕がある方は、お試しください。

--- parse.y	Mon Feb 26 14:29:00 2001
+++ /home/kosako/ruby/parse.y	Wed Feb 28 15:00:58 2001
@@ -206,7 +206,7 @@
 %type <node> if_tail opt_else case_body cases rescue exc_list exc_var ensure
 %type <node> args ret_args when_args call_args paren_args opt_paren_args
 %type <node> command_args aref_args opt_block_arg block_arg var_ref
-%type <node> mrhs mrhs_basic superclass block_call block_command
+%type <node> mrhs mrhs_basic block_call block_command
 %type <node> f_arglist f_args f_optarg f_opt f_block_arg opt_f_block_arg
 %type <node> assoc_list assocs assoc undef_list backref
 %type <node> block_var opt_block_var brace_block do_block lhs none
@@ -1253,7 +1253,7 @@
 			$$ = NEW_FOR($2, $5, $8);
 		        fixpos($$, $2);
 		    }
-		| kCLASS cname superclass
+		| kCLASS expr term
 		    {
 			if (in_def || in_single)
 			    yyerror("class definition in method body");
@@ -1265,7 +1265,19 @@
 		  compstmt
 		  kEND
 		    {
-		        $$ = NEW_CLASS($2, $5, $3);
+			if (nd_type($2) == NODE_CALL && $2->nd_mid == '<') {
+			  if (nd_type($2->nd_args) == NODE_ARRAY &&
+			      ((NODE* )$2->nd_args)->nd_alen == 1) {
+			    $$ = NEW_CLASS($2->nd_recv, $5,
+					   ((NODE* )$2->nd_args)->nd_head);
+			  }
+			  else {
+			    yyerror("Invalid superclass syntax");
+			  }
+			}
+			else {
+			  $$ = NEW_CLASS($2, $5, 0);
+			}
 		        nd_set_line($$, $<num>4);
 		        local_pop();
 			cref_pop();
@@ -1634,20 +1646,6 @@
 backref		: tNTH_REF
 		| tBACK_REF
 
-superclass	: term
-		    {
-			$$ = 0;
-		    }
-		| '<'
-		    {
-			lex_state = EXPR_BEG;
-		    }
-		  expr term
-		    {
-			$$ = $3;
-		    }
-		| error term {yyerrok; $$ = 0;}
-
 f_arglist	: '(' f_args opt_nl ')'
 		    {
 			$$ = $2;
@@ -3373,7 +3371,8 @@
 	if (cond_nest > 0) {
 	    cond_stack = (cond_stack<<1)|0;
 	}
-	if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
+	if (lex_state == EXPR_BEG || lex_state == EXPR_MID ||
+	    lex_state == EXPR_CLASS) {
 	    c = tLPAREN;
 	}
 	else if (lex_state == EXPR_ARG && space_seen) {


--- eval.c	Tue Feb 27 16:52:11 2001
+++ /home/kosako/ruby/eval.c	Wed Feb 28 15:06:36 2001
@@ -3046,10 +3046,12 @@
       case NODE_CLASS:
 	{
 	    VALUE super, klass, tmp;
+	    ID cname;
 
 	    if (NIL_P(ruby_class)) {
 		rb_raise(rb_eTypeError, "no outer class/module");
 	    }
+
 	    if (node->nd_super) {
 		super = superclass(self, node->nd_super);
 	    }
@@ -3057,13 +3059,24 @@
 		super = 0;
 	    }
 
-	    klass = 0;
-	    if ((ruby_class == rb_cObject) && rb_autoload_defined(node->nd_cname)) {
-		rb_autoload_load(node->nd_cname);
+	    if (nd_type(node->nd_cname) == NODE_CONST) {
+		cname = ((NODE* )node->nd_cname)->nd_vid;
+		klass = 0;
+		if ((ruby_class == rb_cObject) && rb_autoload_defined(cname)) {
+		  rb_autoload_load(cname);
+		}
+		if (rb_const_defined_at(ruby_class, cname)) {
+		  klass = rb_const_get(ruby_class, cname);
+		}
 	    }
-	    if (rb_const_defined_at(ruby_class, node->nd_cname)) {
-		klass = rb_const_get(ruby_class, node->nd_cname);
+	    else {
+		cname = 0;
+		klass = rb_eval(self, (NODE* )node->nd_cname);
+		if (! klass || TYPE(klass) != T_CLASS) {
+		  rb_raise(rb_eTypeError, "class name value is not a class object");
+		}
 	    }
+
 	    if (klass) {
 		if (TYPE(klass) != T_CLASS) {
 		    rb_raise(rb_eTypeError, "%s is not a class",
@@ -3090,9 +3103,14 @@
 	    else {
 	      override_class:
 		if (!super) super = rb_cObject;
-		klass = rb_define_class_id(node->nd_cname, super);
-		rb_const_set(ruby_class, node->nd_cname, klass);
-		rb_set_class_path(klass,ruby_class,rb_id2name(node->nd_cname));
+		if (cname) {
+		    klass = rb_define_class_id(cname, super);
+		    rb_const_set(ruby_class, cname, klass);
+		    rb_set_class_path(klass,ruby_class,rb_id2name(cname));
+		}
+		else {
+		    klass = rb_define_class("(anonymous)", super);
+		}
 	    }
 	    if (ruby_wrapper) {
 		rb_extend_object(klass, ruby_wrapper);

----
小迫@ソフネック   渋谷区恵比寿1-15-1