えぐち@エスアンドイー です。

>>> 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 <eguchi / shizuokanet.ne.jp> writes:
...
えぐち> matz> これってのは `<&>'って演算子なんですか? なんか難しいですね.
えぐち> 
えぐち> 我ながらセンスないです ^^;;;
えぐち> 単項前置の演算子記号と当たらない様にすると、
えぐち> これぐらいしか、思いつきません。
えぐち> 
えぐち> 動作を突差に連想できない演算子は
えぐち> 使われないだろうから、この提案は引っ込めます ^^;;;

引っ込めたのを、すぐ持ち出すのもあれですが、、
ほぼ発音と一致する記号の組で、演算子を構成できる事に気づきました。

  NOR:	式1 !| 式2
  NAND:	式1 !& 式2
  XOR:	式1 ^| 式2
  XAND:	式1 ^& 式2

考えた範囲では、ほかの前置(中置)演算子とは、衝突しません。
ただ ! が識別子の最終文字の !(bang) と衝突するので、

  true!| false

は

  undefined local variable or method `true!' for #<Object:0xa2f44> (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;