ATOKダイレクト数式計算プラグインのソースコード
それなりに使えるレベルになったのでアップしてみた。
セットアップツールで公開しようかと思ったのだけど、はてなってzipファイルはアップロードできないようなのでソースコードを公開。
calc.y
class Calcp prechigh nonassoc UMINUS right '^' left '*' '/' left '+' '-' right '=' preclow rule target: exp | /* none */ { result = 0 } exp: exp '+' exp { result += val[2] } | exp '-' exp { result -= val[2] } | exp '*' exp { result *= val[2] } | exp '/' exp { result /= val[2] } | exp '^' exp { result **= val[2] } | '(' exp ')' { result = val[1] } | '-' NUMBER =UMINUS { result = -val[1] } | NUMBER | exp '=' end
これはRaccでコンパイルしてcalc.rbファイルに。
calc_plugin.rb
$KCODE = "UTF-8" require 'jcode' require File.dirname(__FILE__) + '\calc.rb' ### 字句解析部 class Calcp def parse(str) @q = [] until str.empty? case str when /\A\s+/ when /\A(\d|\.)+/ @q.push [:NUMBER, $&.to_f] when /\A.|\n/o s = $& @q.push [s, s] end str = $' end @q.push [false, '$end'] do_parse end def next_token @q.shift end end module Atok_plugin def run_process( a_request_data ) result_data = Hash.new parser = Calcp.new result = 0 result_str = String.new begin result = parser.parse(toHankaku( a_request_data[ 'composition_string' ] )) rescue ParseError result_str = "Error!" end if result % 1 == 0 result = result.to_i end if result_str.empty? result_str = result.to_s end equal = "" if nil == a_request_data[ 'composition_string' ].rindex(/["=="]/) equal = "=" end candidate_array = Array.new candidate_array.push( { 'hyoki' => toZenkaku(result_str)} ) candidate_array.push( { 'hyoki' => "#{toZenkaku(a_request_data[ 'composition_string' ])}#{toZenkaku(equal)}#{toZenkaku(result_str)}" }) candidate_array.push( { 'hyoki' => toHankaku(result_str)} ) candidate_array.push( { 'hyoki' => "#{toHankaku(a_request_data[ 'composition_string' ])}#{equal}#{toHankaku(result_str)}" }) result_data[ 'candidate' ] = candidate_array result_data end end def toHankaku(str) zenkakuMap = Hash.new{ |hash, key| key} zenkakuMap.update({ "0"=>"0", "1"=>"1", "2"=>"2", "3"=>"3", "4"=>"4", "5"=>"5", "6"=>"6", "7"=>"7", "8"=>"8", "9"=>"9", "+"=>"+", "−"=>"-", "*"=>"*", "/"=>"/", "^"=>"^", "."=> ".", "("=> "(", ")"=> ")", " "=> " ", "="=>"="}) result = String.new str.each_char { |char| result.concat(zenkakuMap[char]) } result end def toZenkaku(str) hankakuMap = Hash.new{ |hash, key| key} hankakuMap.update({ "0"=>"0", "1"=>"1", "2"=>"2", "3"=>"3", "4"=>"4", "5"=>"5", "6"=>"6", "7"=>"7", "8"=>"8", "9"=>"9", "+"=>"+", "-"=>"−", "*"=>"*", "/"=>"/", "^"=>"^", "."=> ".", "("=> "(", ")"=> ")", " "=> " ", "="=>"="}) result = String.new str.each_char { |char| result.concat(hankakuMap[char]) } result end
こっちがプラグインとして登録しているファイル。
calc.rbのファイル名を変える場合は
require File.dirname(__FILE__) + '\calc.rb'
の行を適宜直す。
ATOKは通常の変換モードで数式を入力しようとすると全角になるので、全角の入力で使えるように考慮してみた。変換結果をF10で半角にできないっぽいので半角の候補も追加。これで一応使い物になるかなー。