dentaku 1.2.1 → 1.2.2

Sign up to get free protection for your applications and to get access to all the features.
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