意味解析
最後に、意味解析を行うクラスを作ります。
class Calc def initialize @parser = Parser.new end def evalute src exp = @parser.parse(src) execute(exp) end def execute exp if exp.instance_of?(Array) case exp[0] when "+" execute(exp[1]) + execute(exp[2]) when "-" execute(exp[1]) - execute(exp[2]) when "*" execute(exp[1]) * execute(exp[2]) when "/" execute(exp[1]) / execute(exp[2]) end else exp end end end
Calc クラスが意味解析を行うクラスです。メソッドは3つあります。
コンストラクタではパーサを作成しています。
evalute メソッドはプログラムソースを評価します。まずパーサで構文木を作成します。次に execute メソッドに構文木を渡して計算を行い結果を返します。
evalute メソッドと excete メソッドが別れている理由は計算するときに再帰呼び出しを行うからです。 execute メソッドを見てください。配列でない場合はそのまま値を返しますが、配列だった場合は配列の最初(記号が入っている)で分岐してその葉となる1つめと2つめの要素はさらに execute メソッドを呼び出しています。この計算過程は以下のように進みます。
execute([*,[+,1,2],3]) execute([+,1,2]) * execute(3) (execute(1)+execute(2)) * execute(3) (1+execute(2)) * execute(3) (1+2) * execute(3) 3 * execute(3) 3 * 3 9
このようにして、意味解析を行うことができます。以上で今回のRubyによる計算機の作成はおしまいです。
次回はパーサをデータによって動的に変更できるようにしてみたいと思います。