From: nobu.nakada@... Date: 2002-06-15T16:06:34+09:00 Subject: [ruby-dev:17446] ternary operator and char literal (Re: parse error with `true || break ? 0 : 1' (PR#261)) なかだです。 話が長くなりそうなので、devに振ります。 At Fri, 14 Jun 2002 14:39:22 +0900 (JST), akr@m17n.org wrote: > % ruby -ve 'true || break ? 0 : 1' > ruby 1.7.2 (2002-06-12) [i386-freebsd4.2] > -e:1: syntax error > true || break ? 0 : 1 > ^ > -e:1: warning: useless use of a literal in void context > > というように true || break ? 0 : 1 が parse error になります。 > > 演算子の優先順位の点からいえば、?: よりも || のほうが優先されるため、 > これが不正である理由はないように思います。 > > これが syntax error になるのは仕様しょうか。 At Sat, 15 Jun 2002 03:40:00 +0900 (JST), akr@m17n.org wrote: > In article <20020614173449.202F913FA@helium.ruby-lang.org>, > nobu.nokada@softhome.net writes: > > > これは、三項演算子ではなくてbreakの引数のリテラル`? 'と解釈され > > ています。その後に0が連続しているのでsyntax errorになります。 > > void contextのwarningは最後の1に対するものです。 > > はい。問題はなぜ ? がリテラルになっちゃうかという話なわけです。 > > むろん、直接的には break の後が EXPR_MID なので中置演算子は認識されな > いからです。 > > そもそも EXPR_MID とは何かというのがよくわかっていないんですが、たぶん、 > 中置演算子が意味のない文脈を表現しているのだと思います。break の場合に > ついていえば、中置演算子の左辺が break だと、左辺の評価中に制御が外に > 出てしまい、中置演算子の機能が動作しないからでしょう。 > > このような観点から見ると、問題は中置演算子の左辺自体ではなく、左辺の右 > 端のトークンだけに依存して EXPR_MID であることがが決定されるということ > にあります。まぁ、これは通常は問題ないわけですが、挙げた例のように問題 > が出ることもあります。 左辺の右端だけで決定されているというよりも、右辺をどこで終了さ せるかが問題なのでは。 > とすれば、「正しい」修正は右端のトークンだけではなく、左辺を検査するこ > とです。しかし、これは非常に困難です。なぜかというとこの処理の時点では > 左辺はまだ認識されていないためです。左辺が認識されるのはこの時点で読も > うとしているトークンが先読みとしてパーザに渡された後なわけで、そのトー > クンの読み方を制御するために左辺を調べようというのは因果律に反します。 > > # まぁ、不可能とはいいませんが。backtrack するとか。 Rubyの文法を人間が期待するように完全に解釈しようとすると、 backtrackしかないような気はします。 > というようにまじめにやると厄介な話なので、仕様ないしは既知のバグという > あたりかなぁ、とか思っています。 > > もちろん、なにかトリックを見つけて近似するというのはありかも知れません > が、それで嬉しい人はまずいないんじゃないですかね。 どちらかというと、?のリテラルで空白を禁止したほうが直観的なよう な気がします。必要なら`?\ 'とできますし。 それと、こういうのも一見して分かりにくいと思うので、二文字以上 の単語の先頭の?はリテラルとみなさないほうが良いのでは。 p ?aif true #=> 97 ついでに、ソースと別ディレクトリでコンパイルしていると、 keywordsを変更しても$(srcdir)/lex.cが読み込まれてしまって、変更 が反映されません。 Index: parse.y =================================================================== RCS file: /cvs/ruby/src/ruby/parse.y,v retrieving revision 1.184 diff -u -2 -p -r1.184 parse.y --- parse.y 2002/06/14 06:27:18 1.184 +++ parse.y 2002/06/15 06:54:40 @@ -3032,5 +3032,5 @@ here_document(term, indent) } -#include "lex.c" +#include static void @@ -3266,8 +3266,8 @@ yylex() c = nextc(); if (c == -1) { - rb_compile_error("incomplete character syntax"); - return 0; + return '?'; } - if (IS_ARG() && ISSPACE(c)){ + if ((lex_state != EXPR_BEG && ISSPACE(c)) || ismbchar(c) || + (ISALNUM(c) || c == '_') && (lex_p >= lex_pend || is_identchar(*lex_p))){ pushback(c); lex_state = EXPR_BEG; -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦