require "curses"
def keisan(shiki, ichi=0, ans=0.0)
suuji,enzan = [], []
yuusen = {'+'=>1,'-'=>1,'*'=>2,'/'=>2 }
tekiyou = ->{
b, a, e, = suuji.pop, suuji.pop, enzan.pop
suuji << (e=='+' ? a+b : e=='-' ? a-b : e=='*' ? a*b : a/b)}
yomu_atai = lambda do
ichi += 1 while shiki[ichi]==' '
raise "式の途中で終わりました" unless shiki[ichi]
if shiki[ichi,3] && shiki[ichi,3].downcase=="ans"
next [ans, ichi+3]
end
if shiki[ichi]=='-'
ichi += 1
v, ichi = yomu_atai.call
next [-v, ichi]
end
if shiki[ichi]=='('
v, ichi2 = keisan(shiki, ichi+1, ans)
raise "閉じカッコ ) がありません" unless shiki[ichi2]==')'
next [v, ichi2+1]
end
hajime=ichi
ichi += 1 while shiki[ichi] && shiki[ichi]=~/[0-9.]/
raise "数値が見つかりません" if hajime==ichi
[shiki[hajime...ichi].to_f, ichi]
end
atai_hoshii=true
while ichi < shiki.length
ichi += 1 while shiki[ichi]==' '
break if ichi>=shiki.length || shiki[ichi]==')'
if atai_hoshii
v, ichi = yomu_atai.call
suuji << v
atai_hoshii=false
next
end
e=shiki[ichi]
raise "演算子が不正です" unless yuusen[e]
while enzan.any? && yuusen[enzan[-1]] && yuusen[enzan[-1]] >= yuusen[e]
tekiyou.call
end
enzan << e
ichi += 1
atai_hoshii=true
end
tekiyou.call while enzan.any?
[suuji[0], ichi]
end
include Curses
init_screen
cbreak
noecho
curs_set(0)
nyuryoku=""
messeji="Enter=計算 / BS=削除 / Ctrl+L=クリア / q=終了"
kekka, ans ="", 0.0
begin
loop do
clear
setpos(0,0)
addstr("curses電卓(+-*/() 小数)"[0,cols-1])
setpos(1,0)
addstr(messeji[0,cols-1])
setpos(2,0)
addstr(("> "+nyuryoku)[0,cols-1])
setpos(3,0)
addstr(("= "+kekka)[0,cols-1])
key=getch
case key
when 'q','Q' then break
when 10,13
begin
shiki = nyuryoku.strip
shiki = ans.to_s if shiki.empty?
shiki = ans.to_s + shiki if shiki.start_with?('+','*','/')
kotae, owari = keisan(shiki, 0, ans)
owari += 1 while shiki[owari]==' '
raise "式の後ろに余計な文字があります" if owari < shiki.length
ans = kotae
kekka, nyuryoku, messeji = kotae.to_s, "", "計算しました (ans=#{ans} )"
rescue => e
kekka, nyuryoku, messeji = "", "", "エラー: #{e.message}"
end
when 12
nyuryoku, kekka, messeji = "", "", "クリアしました"
when KEY_BACKSPACE,127,8
nyuryoku = nyuryoku[0...-1]
when Integer
nyuryoku << key.chr if key>=32 && key<127
when String
nyuryoku << key if key.ord>=32 && key.ord<127
end
end
ensure
close_screen
end