dentaku 1.2.1 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c588f75b508adbbda4b56b6b3286144aff133c01
4
+ data.tar.gz: b444936b8e75de4aa64af4a39b0d2e9d667b85f3
5
+ SHA512:
6
+ metadata.gz: 33f894376d9098500762e3a5aab7e6be70ce95a3da9fb0c7dd09186bbb30db0471b8bcc750dd906bb3dfdc585f37f5bfe59002dbe4f93a4a65f5784b7e9b2d02
7
+ data.tar.gz: 0fbf3567fd3b9b5e8e5db7df0647ddc687842f9e6b2bdce9e685d1c2a45fdfa2b1ad9ca80c7c5a1ac4fc2e5a910faf167205520d7f52a40ae1ea4de7c573c32e
data/README.md CHANGED
@@ -255,6 +255,7 @@ contributors:
255
255
  * [jasonhutchens](https://github.com/jasonhutchens)
256
256
  * [jmangs](https://github.com/jmangs)
257
257
  * [mvbrocato](https://github.com/mvbrocato)
258
+ * [schneidmaster](https://github.com/schneidmaster)
258
259
  * [thbar](https://github.com/thbar) / [BoxCar](https://www.boxcar.io)
259
260
 
260
261
 
@@ -39,20 +39,24 @@ module Dentaku
39
39
  end
40
40
 
41
41
  def solve!(expression_hash)
42
+ expressions = Hash[expression_hash.map { |k,v| [k.to_s, v] }]
43
+
42
44
  # expression_hash: { variable_name: "string expression" }
43
45
  # TSort thru the expressions' dependencies, then evaluate all
44
- expression_dependencies = Hash[expression_hash.map do |var, expr|
46
+ expression_dependencies = Hash[expressions.map do |var, expr|
45
47
  [var, dependencies(expr)]
46
48
  end]
49
+
47
50
  variables_in_resolve_order = DependencyResolver::find_resolve_order(
48
51
  expression_dependencies)
49
52
 
50
- results = {}
51
- variables_in_resolve_order.each do |var_name|
52
- results[var_name] = evaluate!(expression_hash[var_name], results)
53
+ results = variables_in_resolve_order.each_with_object({}) do |var_name, r|
54
+ r[var_name] = evaluate!(expressions[var_name], r)
53
55
  end
54
56
 
55
- results
57
+ expression_hash.each_with_object({}) do |(k, _), r|
58
+ r[k] = results[k.to_s]
59
+ end
56
60
  end
57
61
 
58
62
  def dependencies(expression)
@@ -62,12 +66,12 @@ module Dentaku
62
66
  def store(key_or_hash, value=nil)
63
67
  restore = @memory.dup
64
68
 
65
- if !value.nil?
66
- @memory[key_or_hash.to_sym] = value
67
- else
68
- key_or_hash.each do |key, value|
69
- @memory[key.to_sym] = value
69
+ if value.nil?
70
+ key_or_hash.each do |key, val|
71
+ @memory[key.downcase.to_s] = val
70
72
  end
73
+ else
74
+ @memory[key_or_hash.to_s] = value
71
75
  end
72
76
 
73
77
  if block_given?
@@ -9,8 +9,8 @@ module Dentaku
9
9
  end
10
10
 
11
11
  def initialize(vars_to_dependencies_hash)
12
- # ensure variables are symbols
13
- @vars_to_deps = Hash[vars_to_dependencies_hash.map { |k, v| [k.to_sym, v]}]
12
+ # ensure variables are strings
13
+ @vars_to_deps = Hash[vars_to_dependencies_hash.map { |k, v| [k.to_s, v]}]
14
14
  end
15
15
 
16
16
  def tsort_each_node(&block)
@@ -18,7 +18,7 @@ module Dentaku
18
18
  end
19
19
 
20
20
  def tsort_each_child(node, &block)
21
- @vars_to_deps[node.to_sym].each(&block)
21
+ @vars_to_deps[node.to_s].each(&block)
22
22
  end
23
23
  end
24
24
  end
@@ -47,10 +47,12 @@ module Dentaku
47
47
  pattern.each do |matcher|
48
48
  _matched, match = matcher.match(token_stream, position + matches.length)
49
49
  matched &&= _matched
50
+ break unless matched
50
51
  matches += match
51
52
  end
52
53
 
53
54
  return position, matches if matched
55
+ return if pattern.first.caret?
54
56
  position += 1
55
57
  end
56
58
 
@@ -2,13 +2,14 @@ require 'dentaku/tokenizer'
2
2
 
3
3
  module Dentaku
4
4
  class Expression
5
- attr_reader :tokens
5
+ attr_reader :tokens, :variables
6
6
 
7
7
  def initialize(string, variables={})
8
8
  @raw = string
9
9
  @tokenizer ||= Tokenizer.new
10
10
  @tokens = @tokenizer.tokenize(@raw)
11
- replace_identifiers_with_values(variables)
11
+ @variables = Hash[variables.map { |k,v| [k.to_s, v] }]
12
+ replace_identifiers_with_values
12
13
  end
13
14
 
14
15
  def identifiers
@@ -21,18 +22,18 @@ module Dentaku
21
22
 
22
23
  private
23
24
 
24
- def replace_identifiers_with_values(variables)
25
+ def replace_identifiers_with_values
25
26
  @tokens.map! do |token|
26
27
  if token.is?(:identifier)
27
- replace_identifier_with_value(token, variables)
28
+ replace_identifier_with_value(token)
28
29
  else
29
30
  token
30
31
  end
31
32
  end
32
33
  end
33
34
 
34
- def replace_identifier_with_value(token, variables)
35
- key = token.value.to_sym
35
+ def replace_identifier_with_value(token)
36
+ key = token.value.to_s
36
37
 
37
38
  if variables.key? key
38
39
  value = variables[key]
@@ -1,7 +1,7 @@
1
1
  class ExternalFunction < Struct.new(:name, :type, :signature, :body)
2
2
  def initialize(*)
3
3
  super
4
- self.name = self.name.to_sym
4
+ self.name = self.name.to_s
5
5
  end
6
6
 
7
7
  def tokens
data/lib/dentaku/rules.rb CHANGED
@@ -13,6 +13,7 @@ module Dentaku
13
13
  [ p(:not), :not ],
14
14
 
15
15
  [ p(:group), :evaluate_group ],
16
+ [ p(:start_neg), :negate ],
16
17
  [ p(:math_pow), :apply ],
17
18
  [ p(:math_mod), :apply ],
18
19
  [ p(:math_mul), :apply ],
@@ -66,7 +67,8 @@ module Dentaku
66
67
  :numeric, :string, :addsub, :subtract, :muldiv, :pow, :mod,
67
68
  :comparator, :comp_gt, :comp_lt, :fopen, :open, :close, :comma,
68
69
  :non_close_plus, :non_group, :non_group_star, :arguments,
69
- :logical, :combinator, :if, :round, :roundup, :rounddown, :not
70
+ :logical, :combinator, :if, :round, :roundup, :rounddown, :not,
71
+ :anchored_minus
70
72
  ].each_with_object({}) do |name, matchers|
71
73
  matchers[name] = TokenMatcher.send(name)
72
74
  end
@@ -80,6 +82,7 @@ module Dentaku
80
82
  math_pow: pattern(:numeric, :pow, :numeric),
81
83
  math_mod: pattern(:numeric, :mod, :numeric),
82
84
  negation: pattern(:subtract, :numeric),
85
+ start_neg: pattern(:anchored_minus, :numeric),
83
86
  percentage: pattern(:numeric, :mod),
84
87
  range_asc: pattern(:numeric, :comp_lt, :numeric, :comp_lt, :numeric),
85
88
  range_desc: pattern(:numeric, :comp_gt, :numeric, :comp_gt, :numeric),
@@ -44,6 +44,15 @@ module Dentaku
44
44
  [matched, matched_tokens]
45
45
  end
46
46
 
47
+ def caret
48
+ @caret = true
49
+ self
50
+ end
51
+
52
+ def caret?
53
+ @caret
54
+ end
55
+
47
56
  def star
48
57
  @min = 0
49
58
  @max = Float::INFINITY
@@ -93,6 +102,7 @@ module Dentaku
93
102
 
94
103
  def self.addsub; new(:operator, [:add, :subtract]); end
95
104
  def self.subtract; new(:operator, :subtract); end
105
+ def self.anchored_minus; new(:operator, :subtract).caret; end
96
106
  def self.muldiv; new(:operator, [:multiply, :divide]); end
97
107
  def self.pow; new(:operator, :pow); end
98
108
  def self.mod; new(:operator, :mod); end
@@ -81,7 +81,7 @@ module Dentaku
81
81
  end
82
82
 
83
83
  def identifier
84
- new(:identifier, '\w+\b', lambda { |raw| raw.strip.downcase.to_sym })
84
+ new(:identifier, '\w+\b', lambda { |raw| raw.strip.downcase.to_s })
85
85
  end
86
86
  end
87
87
  end
@@ -10,7 +10,7 @@ module Dentaku
10
10
  def tokenize(string)
11
11
  @nesting = 0
12
12
  @tokens = []
13
- input = string.dup
13
+ input = string.to_s.dup
14
14
 
15
15
  until input.empty?
16
16
  raise "parse error at: '#{ input }'" unless TokenScanner.scanners.any? do |scanner|
@@ -1,3 +1,3 @@
1
1
  module Dentaku
2
- VERSION = "1.2.1"
2
+ VERSION = "1.2.2"
3
3
  end
@@ -6,6 +6,22 @@ describe Dentaku::Calculator do
6
6
 
7
7
  it 'evaluates an expression' do
8
8
  expect(calculator.evaluate('7+3')).to eq(10)
9
+ expect(calculator.evaluate('2 -1')).to eq(1)
10
+ expect(calculator.evaluate('-1 + 2')).to eq(1)
11
+ expect(calculator.evaluate('1 - 2')).to eq(-1)
12
+ expect(calculator.evaluate('1 - - 2')).to eq(3)
13
+ expect(calculator.evaluate('-1 - - 2')).to eq(1)
14
+ expect(calculator.evaluate('1 - - - 2')).to eq(-1)
15
+ expect(calculator.evaluate('(-1 + 2)')).to eq(1)
16
+ expect(calculator.evaluate('-(1 + 2)')).to eq(-3)
17
+ expect(calculator.evaluate('2 ^ - 1')).to eq(0.5)
18
+ expect(calculator.evaluate('2 ^ -(3 - 2)')).to eq(0.5)
19
+ expect(calculator.evaluate('(2 + 3) - 1')).to eq(4)
20
+ expect(calculator.evaluate('(-2 + 3) - 1')).to eq(0)
21
+ expect(calculator.evaluate('(-2 - 3) - 1')).to eq(-6)
22
+ expect(calculator.evaluate('1 + -2 ^ 2')).to eq(-3)
23
+ expect(calculator.evaluate('3 + -num', :num => 2)).to eq(1)
24
+ expect(calculator.evaluate('-num + 3', :num => 2)).to eq(1)
9
25
  end
10
26
 
11
27
  describe 'memory' do
@@ -32,10 +48,10 @@ describe Dentaku::Calculator do
32
48
 
33
49
  describe 'dependencies' do
34
50
  it "finds dependencies in a generic statement" do
35
- expect(calculator.dependencies("bob + dole / 3")).to eq([:bob, :dole])
51
+ expect(calculator.dependencies("bob + dole / 3")).to eq(['bob', 'dole'])
36
52
  end
37
53
  it "doesn't consider variables in memory as dependencies" do
38
- expect(with_memory.dependencies("apples + oranges")).to eq([:oranges])
54
+ expect(with_memory.dependencies("apples + oranges")).to eq(['oranges'])
39
55
  end
40
56
  end
41
57
 
@@ -48,6 +64,14 @@ describe Dentaku::Calculator do
48
64
  )).to eq(pear: 1, weekly_apple_budget: 21, weekly_fruit_budget: 25)
49
65
  end
50
66
 
67
+ it "preserves hash keys" do
68
+ expect(calculator.solve!(
69
+ 'meaning_of_life' => 'age + kids',
70
+ 'age' => 40,
71
+ 'kids' => 2
72
+ )).to eq('age' => 40, 'kids' => 2, 'meaning_of_life' => 42)
73
+ end
74
+
51
75
  it "lets you know about a cycle if one occurs" do
52
76
  expect do
53
77
  calculator.solve!(health: "happiness", happiness: "health")
@@ -64,7 +88,7 @@ describe Dentaku::Calculator do
64
88
  unbound = 'foo * 1.5'
65
89
  expect { calculator.evaluate!(unbound) }.to raise_error(Dentaku::UnboundVariableError)
66
90
  expect { calculator.evaluate!(unbound) }.to raise_error do |error|
67
- expect(error.unbound_variables).to eq [:foo]
91
+ expect(error.unbound_variables).to eq ['foo']
68
92
  end
69
93
  expect(calculator.evaluate(unbound)).to be_nil
70
94
  expect(calculator.evaluate(unbound) { :bar }).to eq :bar
@@ -112,7 +136,6 @@ describe Dentaku::Calculator do
112
136
  expect(calculator.evaluate('some_boolean OR 7 > 5', :some_boolean => true)).to be_truthy
113
137
  expect(calculator.evaluate('some_boolean OR 7 < 5', :some_boolean => true)).to be_truthy
114
138
  expect(calculator.evaluate('some_boolean OR 7 < 5', :some_boolean => false)).to be_falsey
115
-
116
139
  end
117
140
 
118
141
  describe 'functions' do
@@ -138,5 +161,12 @@ describe Dentaku::Calculator do
138
161
  expect(calculator.evaluate('NOT(some_boolean) AND 7 > 5', :some_boolean => true)).to be_falsey
139
162
  expect(calculator.evaluate('NOT(some_boolean) OR 7 < 5', :some_boolean => false)).to be_truthy
140
163
  end
164
+
165
+ it 'evaluates functions with negative numbers' do
166
+ expect(calculator.evaluate('if (-1 < 5, -1, 5)')).to eq(-1)
167
+ expect(calculator.evaluate('if (-1 = -1, -1, 5)')).to eq(-1)
168
+ expect(calculator.evaluate('round(-1.23, 1)')).to eq(BigDecimal.new('-1.2'))
169
+ expect(calculator.evaluate('NOT(some_boolean) AND -1 > 3', :some_boolean => true)).to be_falsey
170
+ end
141
171
  end
142
172
  end
data/spec/dentaku_spec.rb CHANGED
@@ -12,4 +12,11 @@ describe Dentaku do
12
12
  it 'evaulates a nested function' do
13
13
  expect(Dentaku('roundup(roundup(3 * cherries) + raspberries)', cherries: 1.5, raspberries: 0.9)).to eql(6)
14
14
  end
15
+
16
+ it 'treats variables as case-insensitive' do
17
+ expect(Dentaku('40 + N', 'n' => 2)).to eql(42)
18
+ expect(Dentaku('40 + N', 'N' => 2)).to eql(42)
19
+ expect(Dentaku('40 + n', 'N' => 2)).to eql(42)
20
+ expect(Dentaku('40 + n', 'n' => 2)).to eql(42)
21
+ end
15
22
  end
@@ -44,6 +44,8 @@ describe Dentaku::Evaluator do
44
44
  it 'supports unary minus' do
45
45
  expect(evaluator.evaluate(token_stream(:subtract, 1))).to eq(-1)
46
46
  expect(evaluator.evaluate(token_stream(1, :subtract, :subtract, 1))).to eq(2)
47
+ expect(evaluator.evaluate(token_stream(1, :subtract, :subtract, :subtract, 1))).to eq(0)
48
+ expect(evaluator.evaluate(token_stream(:subtract, 1, :add, 1))).to eq(0)
47
49
  end
48
50
 
49
51
  it 'supports unary percentage' do
@@ -77,6 +79,23 @@ describe Dentaku::Evaluator do
77
79
  expect(position).to eq 0
78
80
  expect(tokens.length).to eq 8
79
81
  end
82
+
83
+ describe 'with start-anchored token' do
84
+ let(:number) { [Dentaku::TokenMatcher.new(:numeric).caret] }
85
+ let(:string) { [Dentaku::TokenMatcher.new(:string).caret] }
86
+ let(:stream) { token_stream(1, 'foo') }
87
+
88
+ it 'matches anchored to the beginning of the token stream' do
89
+ position, tokens = evaluator.find_rule_match(number, stream)
90
+ expect(position).to eq 0
91
+ expect(tokens.length).to eq 1
92
+ end
93
+
94
+ it 'does not match later in the stream' do
95
+ position, _tokens = evaluator.find_rule_match(string, stream)
96
+ expect(position).to be_nil
97
+ end
98
+ end
80
99
  end
81
100
 
82
101
  describe 'functions' do
@@ -16,19 +16,19 @@ describe Dentaku::Tokenizer do
16
16
  it 'tokenizes comparison with =' do
17
17
  tokens = tokenizer.tokenize('number = 5')
18
18
  expect(tokens.map(&:category)).to eq([:identifier, :comparator, :numeric])
19
- expect(tokens.map(&:value)).to eq([:number, :eq, 5])
19
+ expect(tokens.map(&:value)).to eq(['number', :eq, 5])
20
20
  end
21
21
 
22
22
  it 'tokenizes comparison with =' do
23
23
  tokens = tokenizer.tokenize('number = 5')
24
24
  expect(tokens.map(&:category)).to eq([:identifier, :comparator, :numeric])
25
- expect(tokens.map(&:value)).to eq([:number, :eq, 5])
25
+ expect(tokens.map(&:value)).to eq(['number', :eq, 5])
26
26
  end
27
27
 
28
28
  it 'tokenizes comparison with alternate ==' do
29
29
  tokens = tokenizer.tokenize('number == 5')
30
30
  expect(tokens.map(&:category)).to eq([:identifier, :comparator, :numeric])
31
- expect(tokens.map(&:value)).to eq([:number, :eq, 5])
31
+ expect(tokens.map(&:value)).to eq(['number', :eq, 5])
32
32
  end
33
33
 
34
34
  it 'ignores whitespace' do
@@ -52,37 +52,55 @@ describe Dentaku::Tokenizer do
52
52
  it 'accepts arbitrary identifiers' do
53
53
  tokens = tokenizer.tokenize('monkeys > 1500')
54
54
  expect(tokens.map(&:category)).to eq([:identifier, :comparator, :numeric])
55
- expect(tokens.map(&:value)).to eq([:monkeys, :gt, 1500])
55
+ expect(tokens.map(&:value)).to eq(['monkeys', :gt, 1500])
56
56
  end
57
57
 
58
58
  it 'recognizes double-quoted strings' do
59
59
  tokens = tokenizer.tokenize('animal = "giraffe"')
60
60
  expect(tokens.map(&:category)).to eq([:identifier, :comparator, :string])
61
- expect(tokens.map(&:value)).to eq([:animal, :eq, 'giraffe'])
61
+ expect(tokens.map(&:value)).to eq(['animal', :eq, 'giraffe'])
62
62
  end
63
63
 
64
64
  it 'recognizes single-quoted strings' do
65
65
  tokens = tokenizer.tokenize("animal = 'giraffe'")
66
66
  expect(tokens.map(&:category)).to eq([:identifier, :comparator, :string])
67
- expect(tokens.map(&:value)).to eq([:animal, :eq, 'giraffe'])
67
+ expect(tokens.map(&:value)).to eq(['animal', :eq, 'giraffe'])
68
+ end
69
+
70
+ it 'recognizes binary minus operator' do
71
+ tokens = tokenizer.tokenize('2 - 3')
72
+ expect(tokens.map(&:category)).to eq([:numeric, :operator, :numeric])
73
+ expect(tokens.map(&:value)).to eq([2, :subtract, 3])
74
+ end
75
+
76
+ it 'recognizes unary minus operator' do
77
+ tokens = tokenizer.tokenize('-2 + 3')
78
+ expect(tokens.map(&:category)).to eq([:operator, :numeric, :operator, :numeric])
79
+ expect(tokens.map(&:value)).to eq([:subtract, 2, :add, 3])
80
+ end
81
+
82
+ it 'recognizes unary minus operator' do
83
+ tokens = tokenizer.tokenize('2 - -3')
84
+ expect(tokens.map(&:category)).to eq([:numeric, :operator, :operator, :numeric])
85
+ expect(tokens.map(&:value)).to eq([2, :subtract, :subtract, 3])
68
86
  end
69
87
 
70
88
  it 'matches "<=" before "<"' do
71
89
  tokens = tokenizer.tokenize('perimeter <= 7500')
72
90
  expect(tokens.map(&:category)).to eq([:identifier, :comparator, :numeric])
73
- expect(tokens.map(&:value)).to eq([:perimeter, :le, 7500])
91
+ expect(tokens.map(&:value)).to eq(['perimeter', :le, 7500])
74
92
  end
75
93
 
76
94
  it 'matches "and" for logical expressions' do
77
95
  tokens = tokenizer.tokenize('octopi <= 7500 AND sharks > 1500')
78
96
  expect(tokens.map(&:category)).to eq([:identifier, :comparator, :numeric, :combinator, :identifier, :comparator, :numeric])
79
- expect(tokens.map(&:value)).to eq([:octopi, :le, 7500, :and, :sharks, :gt, 1500])
97
+ expect(tokens.map(&:value)).to eq(['octopi', :le, 7500, :and, 'sharks', :gt, 1500])
80
98
  end
81
99
 
82
100
  it 'matches "or" for logical expressions' do
83
101
  tokens = tokenizer.tokenize('size < 3 or admin = 1')
84
102
  expect(tokens.map(&:category)).to eq([:identifier, :comparator, :numeric, :combinator, :identifier, :comparator, :numeric])
85
- expect(tokens.map(&:value)).to eq([:size, :lt, 3, :or, :admin, :eq, 1])
103
+ expect(tokens.map(&:value)).to eq(['size', :lt, 3, :or, 'admin', :eq, 1])
86
104
  end
87
105
 
88
106
  it 'detects unbalanced parentheses' do
@@ -94,7 +112,7 @@ describe Dentaku::Tokenizer do
94
112
  tokens = tokenizer.tokenize('andover < 10')
95
113
  expect(tokens.length).to eq(3)
96
114
  expect(tokens.map(&:category)).to eq([:identifier, :comparator, :numeric])
97
- expect(tokens.map(&:value)).to eq([:andover, :lt, 10])
115
+ expect(tokens.map(&:value)).to eq(['andover', :lt, 10])
98
116
  end
99
117
 
100
118
  describe 'functions' do
@@ -102,7 +120,7 @@ describe Dentaku::Tokenizer do
102
120
  tokens = tokenizer.tokenize('if(x < 10, y, z)')
103
121
  expect(tokens.length).to eq(10)
104
122
  expect(tokens.map(&:category)).to eq([:function, :grouping, :identifier, :comparator, :numeric, :grouping, :identifier, :grouping, :identifier, :grouping])
105
- expect(tokens.map(&:value)).to eq([:if, :fopen, :x, :lt, 10, :comma, :y, :comma, :z, :close])
123
+ expect(tokens.map(&:value)).to eq([:if, :fopen, 'x', :lt, 10, :comma, 'y', :comma, 'z', :close])
106
124
  end
107
125
 
108
126
  it 'include ROUND/UP/DOWN' do
metadata CHANGED
@@ -1,59 +1,53 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dentaku
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
5
- prerelease:
4
+ version: 1.2.2
6
5
  platform: ruby
7
6
  authors:
8
7
  - Solomon White
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2014-10-22 00:00:00.000000000 Z
11
+ date: 2014-12-19 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: rake
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - ">="
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0'
22
20
  type: :development
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - ">="
28
25
  - !ruby/object:Gem::Version
29
26
  version: '0'
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: rspec
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - ">="
36
32
  - !ruby/object:Gem::Version
37
33
  version: '0'
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ! '>='
38
+ - - ">="
44
39
  - !ruby/object:Gem::Version
45
40
  version: '0'
46
- description: ! ' Dentaku is a parser and evaluator for mathematical formulas
47
-
48
- '
41
+ description: |2
42
+ Dentaku is a parser and evaluator for mathematical formulas
49
43
  email:
50
44
  - rubysolo@gmail.com
51
45
  executables: []
52
46
  extensions: []
53
47
  extra_rdoc_files: []
54
48
  files:
55
- - .gitignore
56
- - .travis.yml
49
+ - ".gitignore"
50
+ - ".travis.yml"
57
51
  - Gemfile
58
52
  - README.md
59
53
  - Rakefile
@@ -86,33 +80,26 @@ files:
86
80
  homepage: http://github.com/rubysolo/dentaku
87
81
  licenses:
88
82
  - MIT
83
+ metadata: {}
89
84
  post_install_message:
90
85
  rdoc_options: []
91
86
  require_paths:
92
87
  - lib
93
88
  required_ruby_version: !ruby/object:Gem::Requirement
94
- none: false
95
89
  requirements:
96
- - - ! '>='
90
+ - - ">="
97
91
  - !ruby/object:Gem::Version
98
92
  version: '0'
99
- segments:
100
- - 0
101
- hash: -1375666282720046081
102
93
  required_rubygems_version: !ruby/object:Gem::Requirement
103
- none: false
104
94
  requirements:
105
- - - ! '>='
95
+ - - ">="
106
96
  - !ruby/object:Gem::Version
107
97
  version: '0'
108
- segments:
109
- - 0
110
- hash: -1375666282720046081
111
98
  requirements: []
112
99
  rubyforge_project: dentaku
113
- rubygems_version: 1.8.23.2
100
+ rubygems_version: 2.2.2
114
101
  signing_key:
115
- specification_version: 3
102
+ specification_version: 4
116
103
  summary: A formula language parser and evaluator
117
104
  test_files:
118
105
  - spec/binary_operation_spec.rb