dentaku 3.0.0 → 3.1.0
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 +4 -4
- data/.rubocop.yml +119 -0
- data/.travis.yml +8 -9
- data/CHANGELOG.md +9 -0
- data/Gemfile +0 -5
- data/LICENSE +21 -0
- data/README.md +44 -3
- data/Rakefile +4 -1
- data/dentaku.gemspec +8 -4
- data/lib/dentaku.rb +15 -2
- data/lib/dentaku/ast.rb +1 -0
- data/lib/dentaku/ast/access.rb +2 -2
- data/lib/dentaku/ast/arithmetic.rb +7 -7
- data/lib/dentaku/ast/bitwise.rb +2 -2
- data/lib/dentaku/ast/case.rb +5 -5
- data/lib/dentaku/ast/case/case_conditional.rb +1 -1
- data/lib/dentaku/ast/case/case_else.rb +2 -2
- data/lib/dentaku/ast/case/case_switch_variable.rb +2 -2
- data/lib/dentaku/ast/case/case_then.rb +2 -2
- data/lib/dentaku/ast/case/case_when.rb +2 -2
- data/lib/dentaku/ast/combinators.rb +10 -2
- data/lib/dentaku/ast/comparators.rb +34 -6
- data/lib/dentaku/ast/function.rb +1 -1
- data/lib/dentaku/ast/function_registry.rb +1 -1
- data/lib/dentaku/ast/functions/if.rb +6 -2
- data/lib/dentaku/ast/functions/max.rb +1 -1
- data/lib/dentaku/ast/functions/min.rb +1 -1
- data/lib/dentaku/ast/functions/ruby_math.rb +1 -1
- data/lib/dentaku/ast/functions/string_functions.rb +8 -8
- data/lib/dentaku/ast/functions/sum.rb +12 -0
- data/lib/dentaku/ast/grouping.rb +2 -2
- data/lib/dentaku/ast/identifier.rb +8 -5
- data/lib/dentaku/ast/negation.rb +2 -2
- data/lib/dentaku/ast/node.rb +1 -1
- data/lib/dentaku/ast/operation.rb +1 -1
- data/lib/dentaku/bulk_expression_solver.rb +39 -20
- data/lib/dentaku/calculator.rb +38 -28
- data/lib/dentaku/dependency_resolver.rb +1 -1
- data/lib/dentaku/flat_hash.rb +31 -0
- data/lib/dentaku/parser.rb +7 -6
- data/lib/dentaku/string_casing.rb +7 -0
- data/lib/dentaku/token.rb +1 -1
- data/lib/dentaku/token_matcher.rb +4 -4
- data/lib/dentaku/token_scanner.rb +18 -7
- data/lib/dentaku/tokenizer.rb +26 -2
- data/lib/dentaku/version.rb +1 -1
- data/spec/ast/arithmetic_spec.rb +2 -2
- data/spec/ast/comparator_spec.rb +57 -0
- data/spec/ast/function_spec.rb +1 -1
- data/spec/ast/max_spec.rb +5 -0
- data/spec/ast/min_spec.rb +5 -0
- data/spec/ast/sum_spec.rb +38 -0
- data/spec/benchmark.rb +2 -2
- data/spec/bulk_expression_solver_spec.rb +89 -1
- data/spec/calculator_spec.rb +40 -7
- data/spec/dentaku_spec.rb +11 -0
- data/spec/external_function_spec.rb +7 -7
- data/spec/parser_spec.rb +11 -11
- data/spec/spec_helper.rb +21 -3
- data/spec/token_matcher_spec.rb +0 -1
- data/spec/token_spec.rb +6 -0
- data/spec/tokenizer_spec.rb +37 -0
- metadata +70 -5
data/spec/parser_spec.rb
CHANGED
@@ -110,7 +110,7 @@ describe Dentaku::Parser do
|
|
110
110
|
one = token(1)
|
111
111
|
rbracket = token(:rbracket)
|
112
112
|
|
113
|
-
node
|
113
|
+
node = described_class.new([a, lbracket, one, rbracket]).parse
|
114
114
|
expect { node.value }.to raise_error(Dentaku::UnboundVariableError)
|
115
115
|
expect(node.value(a: [1, 2, 3])).to eq 2
|
116
116
|
end
|
@@ -120,24 +120,24 @@ describe Dentaku::Parser do
|
|
120
120
|
d_and = Dentaku::Token.new(:combinator, :and)
|
121
121
|
d_false = Dentaku::Token.new(:logical, false)
|
122
122
|
|
123
|
-
node
|
123
|
+
node = described_class.new([d_true, d_and, d_false]).parse
|
124
124
|
expect(node.value).to eq false
|
125
125
|
end
|
126
126
|
|
127
127
|
it 'evaluates a case statement' do
|
128
|
-
case_start
|
129
|
-
x
|
128
|
+
case_start = Dentaku::Token.new(:case, :open)
|
129
|
+
x = Dentaku::Token.new(:identifier, :x)
|
130
130
|
case_when1 = Dentaku::Token.new(:case, :when)
|
131
|
-
one
|
131
|
+
one = Dentaku::Token.new(:numeric, 1)
|
132
132
|
case_then1 = Dentaku::Token.new(:case, :then)
|
133
|
-
two
|
133
|
+
two = Dentaku::Token.new(:numeric, 2)
|
134
134
|
case_when2 = Dentaku::Token.new(:case, :when)
|
135
|
-
three
|
135
|
+
three = Dentaku::Token.new(:numeric, 3)
|
136
136
|
case_then2 = Dentaku::Token.new(:case, :then)
|
137
|
-
four
|
138
|
-
case_close
|
137
|
+
four = Dentaku::Token.new(:numeric, 4)
|
138
|
+
case_close = Dentaku::Token.new(:case, :close)
|
139
139
|
|
140
|
-
node
|
140
|
+
node = described_class.new(
|
141
141
|
[case_start,
|
142
142
|
x,
|
143
143
|
case_when1,
|
@@ -182,7 +182,7 @@ describe Dentaku::Parser do
|
|
182
182
|
end
|
183
183
|
|
184
184
|
it "evaluates explicit 'NULL' as a Nil" do
|
185
|
-
null
|
185
|
+
null = Dentaku::Token.new(:null, nil)
|
186
186
|
node = described_class.new([null]).parse
|
187
187
|
expect(node.value).to eq(nil)
|
188
188
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,8 +1,26 @@
|
|
1
1
|
require 'pry'
|
2
|
-
require '
|
2
|
+
require 'simplecov'
|
3
|
+
require 'codecov'
|
3
4
|
|
4
|
-
|
5
|
-
|
5
|
+
SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new([
|
6
|
+
SimpleCov::Formatter::HTMLFormatter,
|
7
|
+
SimpleCov::Formatter::Codecov,
|
8
|
+
])
|
9
|
+
|
10
|
+
SimpleCov.minimum_coverage 90
|
11
|
+
SimpleCov.minimum_coverage_by_file 80
|
12
|
+
|
13
|
+
SimpleCov.start do
|
14
|
+
add_filter "spec/"
|
15
|
+
end
|
16
|
+
|
17
|
+
RSpec.configure do |c|
|
18
|
+
c.before(:all) {
|
19
|
+
# add example for alias because we can set aliases just once
|
20
|
+
# before `calculator` method called
|
21
|
+
Dentaku.aliases = { roundup: ['roundupup'] }
|
22
|
+
}
|
23
|
+
end
|
6
24
|
|
7
25
|
# automatically create a token stream from bare values
|
8
26
|
def token_stream(*args)
|
data/spec/token_matcher_spec.rb
CHANGED
data/spec/token_spec.rb
CHANGED
@@ -7,4 +7,10 @@ describe Dentaku::Token do
|
|
7
7
|
expect(token.value).to eq(5)
|
8
8
|
expect(token.is?(:numeric)).to be_truthy
|
9
9
|
end
|
10
|
+
|
11
|
+
it 'compares category and value to determine equality' do
|
12
|
+
t1 = Dentaku::Token.new(:numeric, 5)
|
13
|
+
t2 = Dentaku::Token.new(:numeric, 5)
|
14
|
+
expect(t1 == t2).to be_truthy
|
15
|
+
end
|
10
16
|
end
|
data/spec/tokenizer_spec.rb
CHANGED
@@ -276,4 +276,41 @@ describe Dentaku::Tokenizer do
|
|
276
276
|
expect(tokens.map(&:value)).to eq([:exp!, :open, 5, :multiply, 3, :close])
|
277
277
|
end
|
278
278
|
end
|
279
|
+
|
280
|
+
describe 'aliases' do
|
281
|
+
let(:aliases) {
|
282
|
+
{
|
283
|
+
round: ['rrrrround!', 'redond'],
|
284
|
+
roundup: ['округлвверх'],
|
285
|
+
rounddown: ['округлвниз'],
|
286
|
+
if: ['если', 'cuando', '如果'],
|
287
|
+
max: ['макс', 'maximo'],
|
288
|
+
min: ['мин', 'minimo']
|
289
|
+
}
|
290
|
+
}
|
291
|
+
|
292
|
+
it 'replaced with function name' do
|
293
|
+
input = 'rrrrround!(8.2) + minimo(4,6,2)'
|
294
|
+
tokenizer.tokenize(input, aliases: aliases)
|
295
|
+
expect(tokenizer.replace_aliases(input)).to eq 'round(8.2) + min(4,6,2)'
|
296
|
+
end
|
297
|
+
|
298
|
+
it 'case insensitive' do
|
299
|
+
input = 'MinImO(4,6,2)'
|
300
|
+
tokenizer.tokenize(input, aliases: aliases)
|
301
|
+
expect(tokenizer.replace_aliases(input)).to eq 'min(4,6,2)'
|
302
|
+
end
|
303
|
+
|
304
|
+
it 'replace only whole aliases without word parts' do
|
305
|
+
input = 'maximo(2,minimoooo())' # `minimoooo` doesn't match `minimo`
|
306
|
+
tokenizer.tokenize(input, aliases: aliases)
|
307
|
+
expect(tokenizer.replace_aliases(input)).to eq 'max(2,minimoooo())'
|
308
|
+
end
|
309
|
+
|
310
|
+
it 'work with non-latin symbols' do
|
311
|
+
input = '如果(1,2,3)'
|
312
|
+
tokenizer.tokenize(input, aliases: aliases)
|
313
|
+
expect(tokenizer.replace_aliases(input)).to eq 'if(1,2,3)'
|
314
|
+
end
|
315
|
+
end
|
279
316
|
end
|
metadata
CHANGED
@@ -1,15 +1,71 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dentaku
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Solomon White
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-01-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: codecov
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pry
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: pry-byebug
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry-stack_explorer
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
13
69
|
- !ruby/object:Gem::Dependency
|
14
70
|
name: rake
|
15
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -39,7 +95,7 @@ dependencies:
|
|
39
95
|
- !ruby/object:Gem::Version
|
40
96
|
version: '0'
|
41
97
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
98
|
+
name: rubocop
|
43
99
|
requirement: !ruby/object:Gem::Requirement
|
44
100
|
requirements:
|
45
101
|
- - ">="
|
@@ -53,7 +109,7 @@ dependencies:
|
|
53
109
|
- !ruby/object:Gem::Version
|
54
110
|
version: '0'
|
55
111
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
112
|
+
name: simplecov
|
57
113
|
requirement: !ruby/object:Gem::Requirement
|
58
114
|
requirements:
|
59
115
|
- - ">="
|
@@ -75,9 +131,11 @@ extra_rdoc_files: []
|
|
75
131
|
files:
|
76
132
|
- ".gitignore"
|
77
133
|
- ".pryrc"
|
134
|
+
- ".rubocop.yml"
|
78
135
|
- ".travis.yml"
|
79
136
|
- CHANGELOG.md
|
80
137
|
- Gemfile
|
138
|
+
- LICENSE
|
81
139
|
- README.md
|
82
140
|
- Rakefile
|
83
141
|
- dentaku.gemspec
|
@@ -108,6 +166,7 @@ files:
|
|
108
166
|
- lib/dentaku/ast/functions/roundup.rb
|
109
167
|
- lib/dentaku/ast/functions/ruby_math.rb
|
110
168
|
- lib/dentaku/ast/functions/string_functions.rb
|
169
|
+
- lib/dentaku/ast/functions/sum.rb
|
111
170
|
- lib/dentaku/ast/functions/switch.rb
|
112
171
|
- lib/dentaku/ast/grouping.rb
|
113
172
|
- lib/dentaku/ast/identifier.rb
|
@@ -123,7 +182,9 @@ files:
|
|
123
182
|
- lib/dentaku/calculator.rb
|
124
183
|
- lib/dentaku/dependency_resolver.rb
|
125
184
|
- lib/dentaku/exceptions.rb
|
185
|
+
- lib/dentaku/flat_hash.rb
|
126
186
|
- lib/dentaku/parser.rb
|
187
|
+
- lib/dentaku/string_casing.rb
|
127
188
|
- lib/dentaku/token.rb
|
128
189
|
- lib/dentaku/token_matcher.rb
|
129
190
|
- lib/dentaku/token_matchers.rb
|
@@ -135,6 +196,7 @@ files:
|
|
135
196
|
- spec/ast/and_spec.rb
|
136
197
|
- spec/ast/arithmetic_spec.rb
|
137
198
|
- spec/ast/case_spec.rb
|
199
|
+
- spec/ast/comparator_spec.rb
|
138
200
|
- spec/ast/division_spec.rb
|
139
201
|
- spec/ast/function_spec.rb
|
140
202
|
- spec/ast/max_spec.rb
|
@@ -146,6 +208,7 @@ files:
|
|
146
208
|
- spec/ast/rounddown_spec.rb
|
147
209
|
- spec/ast/roundup_spec.rb
|
148
210
|
- spec/ast/string_functions_spec.rb
|
211
|
+
- spec/ast/sum_spec.rb
|
149
212
|
- spec/ast/switch_spec.rb
|
150
213
|
- spec/benchmark.rb
|
151
214
|
- spec/bulk_expression_solver_spec.rb
|
@@ -179,7 +242,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
179
242
|
version: '0'
|
180
243
|
requirements: []
|
181
244
|
rubyforge_project: dentaku
|
182
|
-
rubygems_version: 2.
|
245
|
+
rubygems_version: 2.5.2.1
|
183
246
|
signing_key:
|
184
247
|
specification_version: 4
|
185
248
|
summary: A formula language parser and evaluator
|
@@ -189,6 +252,7 @@ test_files:
|
|
189
252
|
- spec/ast/and_spec.rb
|
190
253
|
- spec/ast/arithmetic_spec.rb
|
191
254
|
- spec/ast/case_spec.rb
|
255
|
+
- spec/ast/comparator_spec.rb
|
192
256
|
- spec/ast/division_spec.rb
|
193
257
|
- spec/ast/function_spec.rb
|
194
258
|
- spec/ast/max_spec.rb
|
@@ -200,6 +264,7 @@ test_files:
|
|
200
264
|
- spec/ast/rounddown_spec.rb
|
201
265
|
- spec/ast/roundup_spec.rb
|
202
266
|
- spec/ast/string_functions_spec.rb
|
267
|
+
- spec/ast/sum_spec.rb
|
203
268
|
- spec/ast/switch_spec.rb
|
204
269
|
- spec/benchmark.rb
|
205
270
|
- spec/bulk_expression_solver_spec.rb
|