lib/dentaku/calculator.rb in dentaku-1.0.0 vs lib/dentaku/calculator.rb in dentaku-1.1.0
- old
+ new
@@ -1,9 +1,9 @@
require 'dentaku/evaluator'
+require 'dentaku/expression'
require 'dentaku/rules'
require 'dentaku/token'
-require 'dentaku/tokenizer'
module Dentaku
class Calculator
attr_reader :result
@@ -20,23 +20,24 @@
fns.each { |fn| Rules.add_function(fn) }
self
end
def evaluate(expression, data={})
- @tokenizer ||= Tokenizer.new
- @tokens = @tokenizer.tokenize(expression)
+ evaluate!(expression, data)
+ rescue UnboundVariableError
+ yield expression if block_given?
+ end
+ def evaluate!(expression, data={})
store(data) do
+ expr = Expression.new(expression, @memory)
+ raise UnboundVariableError.new(expr.identifiers) if expr.unbound?
@evaluator ||= Evaluator.new
- @result = @evaluator.evaluate(replace_identifiers_with_values)
+ @result = @evaluator.evaluate(expr.tokens)
end
end
- def memory(key=nil)
- key ? @memory[key.to_sym] : @memory
- end
-
def store(key_or_hash, value=nil)
restore = @memory.dup
if value
@memory[key_or_hash.to_sym] = value
@@ -60,31 +61,8 @@
@memory = {}
end
def empty?
@memory.empty?
- end
-
- private
-
- def replace_identifiers_with_values
- @tokens.map do |token|
- if token.is?(:identifier)
- value = memory(token.value)
- type = type_for_value(value)
-
- Token.new(type, value)
- else
- token
- end
- end
- end
-
- def type_for_value(value)
- case value
- when String then :string
- when TrueClass, FalseClass then :logical
- else :numeric
- end
end
end
end