dentaku 3.5.7 → 4.0.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/.github/workflows/rspec.yml +2 -6
- data/.github/workflows/rubocop.yml +1 -1
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +91 -0
- data/Gemfile +14 -1
- data/README.md +87 -0
- data/dentaku.gemspec +14 -14
- data/lib/dentaku/ast/access.rb +18 -1
- data/lib/dentaku/ast/arithmetic.rb +5 -17
- data/lib/dentaku/ast/array.rb +6 -0
- data/lib/dentaku/ast/bitwise.rb +6 -4
- data/lib/dentaku/ast/case/case_conditional.rb +6 -0
- data/lib/dentaku/ast/case/case_else.rb +6 -0
- data/lib/dentaku/ast/case/case_switch_variable.rb +6 -0
- data/lib/dentaku/ast/case/case_then.rb +6 -0
- data/lib/dentaku/ast/case/case_when.rb +7 -0
- data/lib/dentaku/ast/case.rb +30 -3
- data/lib/dentaku/ast/combinators.rb +49 -4
- data/lib/dentaku/ast/comparators.rb +3 -7
- data/lib/dentaku/ast/function.rb +12 -13
- data/lib/dentaku/ast/function_registry.rb +11 -2
- data/lib/dentaku/ast/functions/abs.rb +1 -1
- data/lib/dentaku/ast/functions/and.rb +4 -4
- data/lib/dentaku/ast/functions/avg.rb +3 -3
- data/lib/dentaku/ast/functions/duration.rb +1 -1
- data/lib/dentaku/ast/functions/if.rb +9 -1
- data/lib/dentaku/ast/functions/intercept.rb +4 -4
- data/lib/dentaku/ast/functions/max.rb +1 -1
- data/lib/dentaku/ast/functions/min.rb +1 -1
- data/lib/dentaku/ast/functions/mul.rb +3 -3
- data/lib/dentaku/ast/functions/or.rb +4 -4
- data/lib/dentaku/ast/functions/pluck.rb +1 -1
- data/lib/dentaku/ast/functions/round.rb +1 -1
- data/lib/dentaku/ast/functions/rounddown.rb +2 -2
- data/lib/dentaku/ast/functions/roundup.rb +2 -2
- data/lib/dentaku/ast/functions/ruby_math.rb +5 -2
- data/lib/dentaku/ast/functions/string_functions.rb +5 -5
- data/lib/dentaku/ast/functions/sum.rb +3 -3
- data/lib/dentaku/ast/functions/xor.rb +4 -4
- data/lib/dentaku/ast/grouping.rb +6 -0
- data/lib/dentaku/ast/negation.rb +5 -0
- data/lib/dentaku/ast/node.rb +25 -0
- data/lib/dentaku/ast/operation.rb +7 -0
- data/lib/dentaku/bulk_expression_solver.rb +22 -16
- data/lib/dentaku/calculator.rb +45 -17
- data/lib/dentaku/date_arithmetic.rb +2 -2
- data/lib/dentaku/dependency_resolver.rb +12 -5
- data/lib/dentaku/exceptions.rb +105 -13
- data/lib/dentaku/numeric_parser.rb +68 -0
- data/lib/dentaku/parser.rb +24 -48
- data/lib/dentaku/print_visitor.rb +1 -0
- data/lib/dentaku/token_matcher.rb +31 -37
- data/lib/dentaku/token_matchers.rb +3 -3
- data/lib/dentaku/token_scanner.rb +3 -4
- data/lib/dentaku/tokenizer.rb +2 -16
- data/lib/dentaku/version.rb +1 -1
- data/spec/ast/case_spec.rb +7 -0
- data/spec/ast/function_spec.rb +11 -25
- data/spec/bulk_expression_solver_spec.rb +48 -3
- data/spec/calculator_spec.rb +77 -0
- data/spec/dependency_resolver_spec.rb +14 -0
- data/spec/exceptions_spec.rb +87 -0
- data/spec/gemspec_spec.rb +10 -0
- data/spec/identifiers_spec.rb +66 -0
- data/spec/numeric_parser_spec.rb +66 -0
- data/spec/parser_spec.rb +35 -0
- data/spec/print_visitor_spec.rb +5 -0
- data/spec/tokenizer_spec.rb +6 -0
- data/spec/volatile_functions_spec.rb +121 -0
- metadata +27 -150
- data/.travis.yml +0 -10
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'dentaku'
|
|
3
|
+
require 'dentaku/calculator'
|
|
4
|
+
|
|
5
|
+
describe Dentaku::Calculator do
|
|
6
|
+
describe 'volatile functions' do
|
|
7
|
+
let(:calculator) { described_class.new }
|
|
8
|
+
let(:call_count) { { count: 0 } }
|
|
9
|
+
|
|
10
|
+
def register_counter(volatile:)
|
|
11
|
+
counter = call_count
|
|
12
|
+
calculator.add_function(:vol, :numeric, ->(x) { counter[:count] += 1; x }, volatile: volatile)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
describe 'registration' do
|
|
16
|
+
it 'marks generated function classes volatile' do
|
|
17
|
+
registry = Dentaku::AST::FunctionRegistry.new
|
|
18
|
+
registry.register(:vol, :numeric, ->(x) { x }, volatile: true)
|
|
19
|
+
expect(registry.get(:vol).volatile?).to be true
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'defaults to non-volatile' do
|
|
23
|
+
registry = Dentaku::AST::FunctionRegistry.new
|
|
24
|
+
registry.register(:plain, :numeric, ->(x) { x })
|
|
25
|
+
expect(registry.get(:plain).volatile?).to be_falsy
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'reports built-in function classes as non-volatile' do
|
|
29
|
+
expect(Dentaku::AST::If.volatile?).to be false
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it 'accepts a fifth tuple element in add_functions' do
|
|
33
|
+
calculator.add_functions([
|
|
34
|
+
[:vol5, :numeric, ->(x) { x }, nil, true],
|
|
35
|
+
[:plain5, :numeric, ->(x) { x }],
|
|
36
|
+
])
|
|
37
|
+
expect(calculator.dependencies('IF(vol5(1) > 0, a, b)')).to eq(%w(a b))
|
|
38
|
+
expect(calculator.dependencies('IF(plain5(1) > 0, a, b)')).to eq(['a'])
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
describe 'dependency resolution' do
|
|
43
|
+
it 'does not evaluate a volatile IF predicate and returns both branches' do
|
|
44
|
+
register_counter(volatile: true)
|
|
45
|
+
expect(calculator.dependencies('IF(vol(1) > 0, a, b)')).to eq(%w(a b))
|
|
46
|
+
expect(call_count[:count]).to eq(0)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it 'still prunes when the predicate uses a pure custom function' do
|
|
50
|
+
register_counter(volatile: false)
|
|
51
|
+
expect(calculator.dependencies('IF(vol(1) > 0, a, b)')).to eq(['a'])
|
|
52
|
+
expect(call_count[:count]).to eq(1)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it 'treats volatility as recursive through the guard subtree' do
|
|
56
|
+
register_counter(volatile: true)
|
|
57
|
+
expect(calculator.dependencies('IF(1 + vol(1) > 2, a, b)')).to eq(%w(a b))
|
|
58
|
+
expect(call_count[:count]).to eq(0)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it 'does not prune CASE with a volatile switch' do
|
|
62
|
+
register_counter(volatile: true)
|
|
63
|
+
deps = calculator.dependencies('CASE vol(1) WHEN 1 THEN a ELSE b END')
|
|
64
|
+
expect(deps).to eq(%w(a b))
|
|
65
|
+
expect(call_count[:count]).to eq(0)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it 'does not prune CASE with a volatile when-clause' do
|
|
69
|
+
register_counter(volatile: true)
|
|
70
|
+
deps = calculator.dependencies('CASE 1 WHEN vol(1) THEN a ELSE b END')
|
|
71
|
+
expect(deps).to eq(%w(a b))
|
|
72
|
+
expect(call_count[:count]).to eq(0)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it 'does not treat a volatile AND operand as decisive' do
|
|
76
|
+
register_counter(volatile: true)
|
|
77
|
+
expect(calculator.dependencies('vol(0) > 1 AND x')).to eq(['x'])
|
|
78
|
+
expect(call_count[:count]).to eq(0)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it 'still prunes AND on a pure decisive operand without running the volatile side' do
|
|
82
|
+
register_counter(volatile: true)
|
|
83
|
+
expect(calculator.dependencies('1 > 2 AND vol(1) > 0')).to eq([])
|
|
84
|
+
expect(call_count[:count]).to eq(0)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
describe 'evaluation' do
|
|
89
|
+
it 'evaluates a volatile predicate exactly once per evaluate!' do
|
|
90
|
+
register_counter(volatile: true)
|
|
91
|
+
expect(calculator.evaluate!('IF(vol(2) > 1, a, b)', a: 1, b: 2)).to eq(1)
|
|
92
|
+
expect(call_count[:count]).to eq(1)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it 'requires variables from both branches when the predicate is volatile' do
|
|
96
|
+
register_counter(volatile: true)
|
|
97
|
+
expect {
|
|
98
|
+
calculator.evaluate!('IF(vol(2) > 1, a, b)', a: 1)
|
|
99
|
+
}.to raise_error(Dentaku::UnboundVariableError) { |error|
|
|
100
|
+
expect(error.unbound_variables).to eq(['b'])
|
|
101
|
+
}
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it 'does not change runtime short-circuit behavior for direct AST evaluation' do
|
|
105
|
+
register_counter(volatile: true)
|
|
106
|
+
node = calculator.ast('IF(vol(2) > 1, a, b)')
|
|
107
|
+
expect(node.value('a' => 1)).to eq(1)
|
|
108
|
+
expect(call_count[:count]).to eq(1)
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
describe 'solve' do
|
|
113
|
+
it 'resolves expressions with volatile guards when all branch inputs are provided' do
|
|
114
|
+
register_counter(volatile: true)
|
|
115
|
+
calculator.store(a: 1, b: 2)
|
|
116
|
+
result = calculator.solve!(c: 'IF(vol(2) > 1, a, b)', d: 'c + 1')
|
|
117
|
+
expect(result[:d]).to eq(2)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dentaku
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 4.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Solomon White
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: bigdecimal
|
|
@@ -15,126 +15,42 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - ">="
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: '
|
|
18
|
+
version: '3.1'
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - ">="
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: '
|
|
25
|
+
version: '3.1'
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: concurrent-ruby
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
29
29
|
requirements:
|
|
30
|
-
- - "
|
|
30
|
+
- - "~>"
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: '
|
|
32
|
+
version: '1.1'
|
|
33
33
|
type: :runtime
|
|
34
34
|
prerelease: false
|
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
36
|
requirements:
|
|
37
|
-
- - "
|
|
38
|
-
- !ruby/object:Gem::Version
|
|
39
|
-
version: '0'
|
|
40
|
-
- !ruby/object:Gem::Dependency
|
|
41
|
-
name: pry
|
|
42
|
-
requirement: !ruby/object:Gem::Requirement
|
|
43
|
-
requirements:
|
|
44
|
-
- - ">="
|
|
45
|
-
- !ruby/object:Gem::Version
|
|
46
|
-
version: '0'
|
|
47
|
-
type: :development
|
|
48
|
-
prerelease: false
|
|
49
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
-
requirements:
|
|
51
|
-
- - ">="
|
|
52
|
-
- !ruby/object:Gem::Version
|
|
53
|
-
version: '0'
|
|
54
|
-
- !ruby/object:Gem::Dependency
|
|
55
|
-
name: pry-byebug
|
|
56
|
-
requirement: !ruby/object:Gem::Requirement
|
|
57
|
-
requirements:
|
|
58
|
-
- - ">="
|
|
59
|
-
- !ruby/object:Gem::Version
|
|
60
|
-
version: '0'
|
|
61
|
-
type: :development
|
|
62
|
-
prerelease: false
|
|
63
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
-
requirements:
|
|
65
|
-
- - ">="
|
|
66
|
-
- !ruby/object:Gem::Version
|
|
67
|
-
version: '0'
|
|
68
|
-
- !ruby/object:Gem::Dependency
|
|
69
|
-
name: pry-stack_explorer
|
|
70
|
-
requirement: !ruby/object:Gem::Requirement
|
|
71
|
-
requirements:
|
|
72
|
-
- - ">="
|
|
73
|
-
- !ruby/object:Gem::Version
|
|
74
|
-
version: '0'
|
|
75
|
-
type: :development
|
|
76
|
-
prerelease: false
|
|
77
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
-
requirements:
|
|
79
|
-
- - ">="
|
|
80
|
-
- !ruby/object:Gem::Version
|
|
81
|
-
version: '0'
|
|
82
|
-
- !ruby/object:Gem::Dependency
|
|
83
|
-
name: rake
|
|
84
|
-
requirement: !ruby/object:Gem::Requirement
|
|
85
|
-
requirements:
|
|
86
|
-
- - ">="
|
|
87
|
-
- !ruby/object:Gem::Version
|
|
88
|
-
version: '0'
|
|
89
|
-
type: :development
|
|
90
|
-
prerelease: false
|
|
91
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
92
|
-
requirements:
|
|
93
|
-
- - ">="
|
|
94
|
-
- !ruby/object:Gem::Version
|
|
95
|
-
version: '0'
|
|
96
|
-
- !ruby/object:Gem::Dependency
|
|
97
|
-
name: rspec
|
|
98
|
-
requirement: !ruby/object:Gem::Requirement
|
|
99
|
-
requirements:
|
|
100
|
-
- - ">="
|
|
101
|
-
- !ruby/object:Gem::Version
|
|
102
|
-
version: '0'
|
|
103
|
-
type: :development
|
|
104
|
-
prerelease: false
|
|
105
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
106
|
-
requirements:
|
|
107
|
-
- - ">="
|
|
108
|
-
- !ruby/object:Gem::Version
|
|
109
|
-
version: '0'
|
|
110
|
-
- !ruby/object:Gem::Dependency
|
|
111
|
-
name: rubocop
|
|
112
|
-
requirement: !ruby/object:Gem::Requirement
|
|
113
|
-
requirements:
|
|
114
|
-
- - ">="
|
|
115
|
-
- !ruby/object:Gem::Version
|
|
116
|
-
version: '0'
|
|
117
|
-
type: :development
|
|
118
|
-
prerelease: false
|
|
119
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
120
|
-
requirements:
|
|
121
|
-
- - ">="
|
|
37
|
+
- - "~>"
|
|
122
38
|
- !ruby/object:Gem::Version
|
|
123
|
-
version: '
|
|
39
|
+
version: '1.1'
|
|
124
40
|
- !ruby/object:Gem::Dependency
|
|
125
|
-
name:
|
|
41
|
+
name: tsort
|
|
126
42
|
requirement: !ruby/object:Gem::Requirement
|
|
127
43
|
requirements:
|
|
128
44
|
- - ">="
|
|
129
45
|
- !ruby/object:Gem::Version
|
|
130
|
-
version:
|
|
131
|
-
type: :
|
|
46
|
+
version: 0.1.1
|
|
47
|
+
type: :runtime
|
|
132
48
|
prerelease: false
|
|
133
49
|
version_requirements: !ruby/object:Gem::Requirement
|
|
134
50
|
requirements:
|
|
135
51
|
- - ">="
|
|
136
52
|
- !ruby/object:Gem::Version
|
|
137
|
-
version:
|
|
53
|
+
version: 0.1.1
|
|
138
54
|
description: " Dentaku is a parser and evaluator for mathematical formulas\n"
|
|
139
55
|
email:
|
|
140
56
|
- rubysolo@gmail.com
|
|
@@ -147,7 +63,6 @@ files:
|
|
|
147
63
|
- ".gitignore"
|
|
148
64
|
- ".pryrc"
|
|
149
65
|
- ".rubocop.yml"
|
|
150
|
-
- ".travis.yml"
|
|
151
66
|
- CHANGELOG.md
|
|
152
67
|
- Gemfile
|
|
153
68
|
- LICENSE
|
|
@@ -214,6 +129,7 @@ files:
|
|
|
214
129
|
- lib/dentaku/dependency_resolver.rb
|
|
215
130
|
- lib/dentaku/exceptions.rb
|
|
216
131
|
- lib/dentaku/flat_hash.rb
|
|
132
|
+
- lib/dentaku/numeric_parser.rb
|
|
217
133
|
- lib/dentaku/parser.rb
|
|
218
134
|
- lib/dentaku/print_visitor.rb
|
|
219
135
|
- lib/dentaku/string_casing.rb
|
|
@@ -263,6 +179,9 @@ files:
|
|
|
263
179
|
- spec/dependency_resolver_spec.rb
|
|
264
180
|
- spec/exceptions_spec.rb
|
|
265
181
|
- spec/external_function_spec.rb
|
|
182
|
+
- spec/gemspec_spec.rb
|
|
183
|
+
- spec/identifiers_spec.rb
|
|
184
|
+
- spec/numeric_parser_spec.rb
|
|
266
185
|
- spec/parser_spec.rb
|
|
267
186
|
- spec/print_visitor_spec.rb
|
|
268
187
|
- spec/spec_helper.rb
|
|
@@ -272,10 +191,16 @@ files:
|
|
|
272
191
|
- spec/tokenizer_spec.rb
|
|
273
192
|
- spec/visitor/infix_spec.rb
|
|
274
193
|
- spec/visitor_spec.rb
|
|
275
|
-
|
|
194
|
+
- spec/volatile_functions_spec.rb
|
|
195
|
+
homepage: https://github.com/rubysolo/dentaku
|
|
276
196
|
licenses:
|
|
277
197
|
- MIT
|
|
278
|
-
metadata:
|
|
198
|
+
metadata:
|
|
199
|
+
homepage_uri: https://github.com/rubysolo/dentaku
|
|
200
|
+
source_code_uri: https://github.com/rubysolo/dentaku
|
|
201
|
+
changelog_uri: https://github.com/rubysolo/dentaku/blob/main/CHANGELOG.md
|
|
202
|
+
bug_tracker_uri: https://github.com/rubysolo/dentaku/issues
|
|
203
|
+
rubygems_mfa_required: 'true'
|
|
279
204
|
rdoc_options: []
|
|
280
205
|
require_paths:
|
|
281
206
|
- lib
|
|
@@ -283,62 +208,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
283
208
|
requirements:
|
|
284
209
|
- - ">="
|
|
285
210
|
- !ruby/object:Gem::Version
|
|
286
|
-
version: '
|
|
211
|
+
version: '3.2'
|
|
287
212
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
288
213
|
requirements:
|
|
289
214
|
- - ">="
|
|
290
215
|
- !ruby/object:Gem::Version
|
|
291
216
|
version: '0'
|
|
292
217
|
requirements: []
|
|
293
|
-
rubygems_version: 3.6.
|
|
218
|
+
rubygems_version: 3.6.9
|
|
294
219
|
specification_version: 4
|
|
295
220
|
summary: A formula language parser and evaluator
|
|
296
|
-
test_files:
|
|
297
|
-
- spec/ast/abs_spec.rb
|
|
298
|
-
- spec/ast/addition_spec.rb
|
|
299
|
-
- spec/ast/all_spec.rb
|
|
300
|
-
- spec/ast/and_function_spec.rb
|
|
301
|
-
- spec/ast/and_spec.rb
|
|
302
|
-
- spec/ast/any_spec.rb
|
|
303
|
-
- spec/ast/arithmetic_spec.rb
|
|
304
|
-
- spec/ast/avg_spec.rb
|
|
305
|
-
- spec/ast/case_spec.rb
|
|
306
|
-
- spec/ast/comparator_spec.rb
|
|
307
|
-
- spec/ast/count_spec.rb
|
|
308
|
-
- spec/ast/division_spec.rb
|
|
309
|
-
- spec/ast/filter_spec.rb
|
|
310
|
-
- spec/ast/function_spec.rb
|
|
311
|
-
- spec/ast/intercept_spec.rb
|
|
312
|
-
- spec/ast/map_spec.rb
|
|
313
|
-
- spec/ast/max_spec.rb
|
|
314
|
-
- spec/ast/min_spec.rb
|
|
315
|
-
- spec/ast/mul_spec.rb
|
|
316
|
-
- spec/ast/negation_spec.rb
|
|
317
|
-
- spec/ast/node_spec.rb
|
|
318
|
-
- spec/ast/numeric_spec.rb
|
|
319
|
-
- spec/ast/or_spec.rb
|
|
320
|
-
- spec/ast/pluck_spec.rb
|
|
321
|
-
- spec/ast/reduce_spec.rb
|
|
322
|
-
- spec/ast/round_spec.rb
|
|
323
|
-
- spec/ast/rounddown_spec.rb
|
|
324
|
-
- spec/ast/roundup_spec.rb
|
|
325
|
-
- spec/ast/string_functions_spec.rb
|
|
326
|
-
- spec/ast/sum_spec.rb
|
|
327
|
-
- spec/ast/switch_spec.rb
|
|
328
|
-
- spec/ast/xor_spec.rb
|
|
329
|
-
- spec/benchmark.rb
|
|
330
|
-
- spec/bulk_expression_solver_spec.rb
|
|
331
|
-
- spec/calculator_spec.rb
|
|
332
|
-
- spec/dentaku_spec.rb
|
|
333
|
-
- spec/dependency_resolver_spec.rb
|
|
334
|
-
- spec/exceptions_spec.rb
|
|
335
|
-
- spec/external_function_spec.rb
|
|
336
|
-
- spec/parser_spec.rb
|
|
337
|
-
- spec/print_visitor_spec.rb
|
|
338
|
-
- spec/spec_helper.rb
|
|
339
|
-
- spec/token_matcher_spec.rb
|
|
340
|
-
- spec/token_scanner_spec.rb
|
|
341
|
-
- spec/token_spec.rb
|
|
342
|
-
- spec/tokenizer_spec.rb
|
|
343
|
-
- spec/visitor/infix_spec.rb
|
|
344
|
-
- spec/visitor_spec.rb
|
|
221
|
+
test_files: []
|