以前,Rubyで6÷2(1+2)を書いたのですが,そのスクリプトで使用しているsyntax.rbは現在,ダウンロードできなくなっていたため,コードを新たに作りました.
Raccを使用しています.必要ならgem install raccとしたのち,実行すると,次のようになります.
$ ruby calc1.rb 1+2×3=7 3×(8+5×(6−2))÷2=42 6÷2(1+2)=1 6÷2×(1+2)=9
「6÷2(1+2)」と「6÷2×(1+2)」の評価結果が違うことも,確認できます.
以下,Rubyスクリプトの詳細を書きます.実行すると,カレントディレクトリにcalc.yとcalc.rbを作ります.calc.yは,次のページの内容をベースとしています.
違いもあります.演算子を「+−×÷」に変更し,「2(1+2)」を正しい式(連接による積)として認識するよう,CONCATというラベルで,定義を挿入しています*1.優先順位は,乗算・除算記号よりも上位としました.
さて,冒頭のTogetterまとめで,「1か9かどうかというのは実のところルール次第」とコメントしたので,「6÷2(1+2)=9」となるよう,ルールを変えてみましょう.
構文規則は変更せず,優先順位を「left '×' '÷' CONCAT」として乗除と同じにしました.
出力は…
$ ruby calc2.rb 1+2×3=7 3×(8+5×(6−2))÷2=42 2(1+2)−2=4 2(1+2)÷2=3 6÷2(1+2)=1 6÷2×(1+2)=9
残念ながら「6÷2(1+2)=1」と出まして,9ではありません.この対策について,今のところアイデアなしの状況です.
なお「2(1+2)−2=4」「2(1+2)÷2=3」は,動作確認用に追加したものです.これらは(「2(1+2)」を構文的に正しいという前提のもと)正しい評価結果です.優先順位の指定について,Rubyスクリプトを
prechigh left '×' '÷' left CONCAT left '+' '−' preclow
と書き換えてから,実行しなおすと,「2(1+2)÷2=2」になります.これは「(1+2)÷2=3÷2=1」と評価しており*2,期待した動作です.さらに
prechigh left '×' '÷' left '+' '−' left CONCAT preclow
としてみると,「2(1+2)−2=2」と変わります.「(1+2)−2=1」が優先されています.
なのですが,上のように修正しても,「6÷2(1+2)=1」は変更ありません.
うーん,本日はここまでです.
*1:raccコマンド実行中に「10 shift/reduce conflicts」と出ます.ruby -d calc1.rbと実行しても,表示されるようにしています.
*2:「整数÷整数」は整数です.3÷2を有理数で表現することも可能で,http://d.hatena.ne.jp/takehikom/20110524/1306182300 で試みています.