From: EGUCHI Osamu Date: 1999-02-17T13:07:07+09:00 Subject: [ruby-dev:5187] [REQ][PATCH] (Re: Re: [REQ] nand/nor/xor ) えぐち@エスアンドイー です。 >>> On Wed, 17 Feb 1999 01:50:51 +0900, えぐち said: えぐち> えぐち@エスアンドイー です。 えぐち> えぐち> >>> On Wed, 17 Feb 1999 00:24:08 +0900, matz@netlab.co.jp (Yukihiro Matsumoto) said: えぐち> えぐち> matz> まつもと ゆきひろです えぐち> matz> えぐち> matz> In message "[ruby-dev:5073] Re: [REQ] nand/nor/xor (Re: Re: parse error "and")" えぐち> matz> on 99/02/13, EGUCHI Osamu writes: ... えぐち> matz> これってのは `<&>'って演算子なんですか? なんか難しいですね. えぐち> えぐち> 我ながらセンスないです ^^;;; えぐち> 単項前置の演算子記号と当たらない様にすると、 えぐち> これぐらいしか、思いつきません。 えぐち> えぐち> 動作を突差に連想できない演算子は えぐち> 使われないだろうから、この提案は引っ込めます ^^;;; 引っ込めたのを、すぐ持ち出すのもあれですが、、 ほぼ発音と一致する記号の組で、演算子を構成できる事に気づきました。 NOR: 式1 !| 式2 NAND: 式1 !& 式2 XOR: 式1 ^| 式2 XAND: 式1 ^& 式2 考えた範囲では、ほかの前置(中置)演算子とは、衝突しません。 ただ ! が識別子の最終文字の !(bang) と衝突するので、 true!| false は undefined local variable or method `true!' for # (NameError) となります。 しかし、 true!= false も parse error なので、よしとしました(をぃをぃ) おおまかなせつめい。 <真理値表(を作るプログラム)> === for op in ['!|', '!&', '^|', '^&' ] puts op for left in [false, true] for right in [false, true] expr = "%5s %s %5s " % [left, op, right] puts expr + ' => ' + (eval expr).inspect end end end === <真理値表(を作るプログラムの実行結果)> % ./ruby opr.rb !| false !| false => true false !| true => false true !| false => false true !| true => false !& false !& false => true false !& true => true true !& false => true true !& true => false ^| false ^| false => false false ^| true => true true ^| false => true true ^| true => false ^& false ^& false => true false ^& true => false true ^& false => false true ^& true => true と言う動作をします。 優先度は %nonassoc tDOT2 tDOT3 +%left tNOROP %left tOROP +%left tXOROP +%left tXANDOP +%left tNANDOP %left tANDOP %nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH としました。 def finite?(n) inf(n) !| nan?(n) # not inf(n) || nan?(n) end の様につかいます。 いかがでしょうか? # 変数 !|= 式 #と言うも考えましたが、さすがに醜悪なのでやめました ^^;;;; えぐち --- ../ruby-1.3.1-990215/parse.y Fri Feb 12 20:17:05 1999 +++ parse.y Wed Feb 17 12:36:39 1999 @@ -189,6 +189,8 @@ %token tGEQ /* >= */ %token tLEQ /* <= */ %token tANDOP tOROP /* && and || */ +%token tNANDOP tNOROP /* !& and !| */ +%token tXANDOP tXOROP /* ^& and ^| */ %token tMATCH tNMATCH /* =~ and !~ */ %token tDOT2 tDOT3 /* .. and ... */ %token tAREF tASET /* [] and []= */ @@ -215,7 +217,11 @@ %right '=' tOP_ASGN %right '?' ':' %nonassoc tDOT2 tDOT3 +%left tNOROP %left tOROP +%left tXOROP +%left tXANDOP +%left tNANDOP %left tANDOP %nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH %left '>' tGEQ '<' tLEQ @@ -768,6 +774,26 @@ { $$ = logop(NODE_OR, $1, $3); } + | arg tNOROP arg + { + $$ = NEW_NOT(logop(NODE_OR, $1, $3)); + } + | arg tNANDOP arg + { + $$ = NEW_NOT(logop(NODE_AND, $1, $3)); + } + | arg tXOROP arg + { + value_expr($1); + value_expr($3); + $$ = NEW_NOT(call_op(cond($1), tEQ, 1, cond($3))); + } + | arg tXANDOP arg + { + value_expr($1); + value_expr($3); + $$ = call_op(cond($1), tEQ, 1, cond($3)); + } | kDEFINED opt_nl {in_defined = 1;} arg { in_defined = 0; @@ -2527,6 +2553,12 @@ if (c == '~') { return tNMATCH; } + if (c == '&') { + return tNANDOP; + } + if (c == '|') { + return tNOROP; + } pushback(c); return '!'; @@ -2953,9 +2985,15 @@ case '^': lex_state = EXPR_BEG; - if (nextc() == '=') { + if ((c = nextc()) == '=') { yylval.id = '^'; return tOP_ASGN; + } + if (c == '&') { + return tXANDOP; + } + if (c == '|') { + return tXOROP; } pushback(c); return c;