dentaku 0.1.0 → 0.1.1
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.
- data/README.md +3 -3
- data/Rakefile +3 -0
- data/lib/dentaku.rb +5 -1
- data/lib/dentaku/evaluator.rb +16 -1
- data/lib/dentaku/tokenizer.rb +7 -2
- data/lib/dentaku/version.rb +1 -1
- data/spec/calculator_spec.rb +6 -0
- data/spec/dentaku_spec.rb +2 -2
- data/spec/tokenizer_spec.rb +9 -0
- metadata +54 -33
data/README.md
CHANGED
@@ -36,10 +36,10 @@ evaluate expressions against those stored values:
|
|
36
36
|
|
37
37
|
For maximum CS geekery, `bind` is an alias of `store`.
|
38
38
|
|
39
|
-
If you're too lazy to be building calculator objects, there's a
|
40
|
-
|
39
|
+
If you're too lazy to be building calculator objects, there's a shortcut just
|
40
|
+
for you:
|
41
41
|
|
42
|
-
Dentaku
|
42
|
+
Dentaku('plums * 1.5', {:plums => 2})
|
43
43
|
=> 3.0
|
44
44
|
|
45
45
|
|
data/Rakefile
CHANGED
data/lib/dentaku.rb
CHANGED
@@ -2,7 +2,7 @@ require "dentaku/calculator"
|
|
2
2
|
require "dentaku/version"
|
3
3
|
|
4
4
|
module Dentaku
|
5
|
-
def self.
|
5
|
+
def self.evaluate(expression, data={})
|
6
6
|
calculator.evaluate(expression, data)
|
7
7
|
end
|
8
8
|
|
@@ -12,3 +12,7 @@ module Dentaku
|
|
12
12
|
@calculator ||= Dentaku::Calculator.new
|
13
13
|
end
|
14
14
|
end
|
15
|
+
|
16
|
+
def Dentaku(expression, data={})
|
17
|
+
Dentaku.evaluate(expression, data)
|
18
|
+
end
|
data/lib/dentaku/evaluator.rb
CHANGED
@@ -9,9 +9,11 @@ module Dentaku
|
|
9
9
|
T_COMPARATOR = TokenMatcher.new(:comparator)
|
10
10
|
T_OPEN = TokenMatcher.new(:grouping, :open)
|
11
11
|
T_CLOSE = TokenMatcher.new(:grouping, :close)
|
12
|
+
T_COMMA = TokenMatcher.new(:grouping, :comma)
|
12
13
|
T_NON_GROUP = TokenMatcher.new(:grouping).invert
|
13
14
|
T_LOGICAL = TokenMatcher.new(:logical)
|
14
15
|
T_COMBINATOR = TokenMatcher.new(:combinator)
|
16
|
+
T_IF = TokenMatcher.new(:function, :if)
|
15
17
|
|
16
18
|
P_GROUP = [T_OPEN, T_NON_GROUP, T_CLOSE]
|
17
19
|
P_MATH_ADD = [T_NUMERIC, T_ADDSUB, T_NUMERIC]
|
@@ -19,12 +21,15 @@ module Dentaku
|
|
19
21
|
P_COMPARISON = [T_NUMERIC, T_COMPARATOR, T_NUMERIC]
|
20
22
|
P_COMBINE = [T_LOGICAL, T_COMBINATOR, T_LOGICAL]
|
21
23
|
|
24
|
+
P_IF = [T_IF, T_OPEN, T_NON_GROUP, T_COMMA, T_NON_GROUP, T_COMMA, T_NON_GROUP, T_CLOSE]
|
25
|
+
|
22
26
|
RULES = [
|
23
27
|
[P_GROUP, :evaluate_group],
|
24
28
|
[P_MATH_MUL, :apply],
|
25
29
|
[P_MATH_ADD, :apply],
|
26
30
|
[P_COMPARISON, :apply],
|
27
|
-
[P_COMBINE, :apply]
|
31
|
+
[P_COMBINE, :apply],
|
32
|
+
[P_IF, :if],
|
28
33
|
]
|
29
34
|
|
30
35
|
def evaluate(tokens)
|
@@ -93,5 +98,15 @@ module Dentaku
|
|
93
98
|
raise "unknown comparator '#{ comparator }'"
|
94
99
|
end
|
95
100
|
end
|
101
|
+
|
102
|
+
def if(*args)
|
103
|
+
_, open, cond, _, true_value, _, false_value, close = args
|
104
|
+
|
105
|
+
if evaluate_token_stream([cond])
|
106
|
+
evaluate_token_stream([true_value])
|
107
|
+
else
|
108
|
+
evaluate_token_stream([false_value])
|
109
|
+
end
|
110
|
+
end
|
96
111
|
end
|
97
112
|
end
|
data/lib/dentaku/tokenizer.rb
CHANGED
@@ -15,8 +15,12 @@ module Dentaku
|
|
15
15
|
when '/' then :divide
|
16
16
|
end
|
17
17
|
end),
|
18
|
-
TokenScanner.new(:grouping, '\(|\)', lambda do |raw|
|
19
|
-
raw
|
18
|
+
TokenScanner.new(:grouping, '\(|\)|,', lambda do |raw|
|
19
|
+
case raw
|
20
|
+
when '(' then :open
|
21
|
+
when ')' then :close
|
22
|
+
when ',' then :comma
|
23
|
+
end
|
20
24
|
end),
|
21
25
|
TokenScanner.new(:comparator, '<=|>=|!=|<>|<|>|=', lambda do |raw|
|
22
26
|
case raw
|
@@ -30,6 +34,7 @@ module Dentaku
|
|
30
34
|
end
|
31
35
|
end),
|
32
36
|
TokenScanner.new(:combinator, '(and|or)\b', lambda {|raw| raw.strip.to_sym }),
|
37
|
+
TokenScanner.new(:function, '(if)\b', lambda {|raw| raw.strip.to_sym }),
|
33
38
|
TokenScanner.new(:identifier, '[A-Za-z_]+', lambda {|raw| raw.to_sym })
|
34
39
|
]
|
35
40
|
|
data/lib/dentaku/version.rb
CHANGED
data/spec/calculator_spec.rb
CHANGED
@@ -49,4 +49,10 @@ describe Dentaku::Calculator do
|
|
49
49
|
calculator.evaluate('foo * 2', :foo => 2).should eq(4)
|
50
50
|
calculator.evaluate('foo * 2', 'foo' => 4).should eq(8)
|
51
51
|
end
|
52
|
+
|
53
|
+
describe 'functions' do
|
54
|
+
it 'should include IF' do
|
55
|
+
calculator.evaluate('if (foo < 10, 10, 20)', :foo => 2).should eq(10)
|
56
|
+
end
|
57
|
+
end
|
52
58
|
end
|
data/spec/dentaku_spec.rb
CHANGED
@@ -2,10 +2,10 @@ require 'dentaku'
|
|
2
2
|
|
3
3
|
describe Dentaku do
|
4
4
|
it 'should evaulate an expression' do
|
5
|
-
Dentaku
|
5
|
+
Dentaku('5+3').should eql(8)
|
6
6
|
end
|
7
7
|
|
8
8
|
it 'should bind values to variables' do
|
9
|
-
Dentaku
|
9
|
+
Dentaku('oranges > 7', {:oranges => 10}).should be_true
|
10
10
|
end
|
11
11
|
end
|
data/spec/tokenizer_spec.rb
CHANGED
@@ -66,4 +66,13 @@ describe Dentaku::Tokenizer do
|
|
66
66
|
tokens.map(&:category).should eq([:identifier, :comparator, :numeric])
|
67
67
|
tokens.map(&:value).should eq([:andover, :lt, 10])
|
68
68
|
end
|
69
|
+
|
70
|
+
describe 'functions' do
|
71
|
+
it 'include IF' do
|
72
|
+
tokens = tokenizer.tokenize('if(x < 10, y, z)')
|
73
|
+
tokens.length.should eq(10)
|
74
|
+
tokens.map(&:category).should eq([:function, :grouping, :identifier, :comparator, :numeric, :grouping, :identifier, :grouping, :identifier, :grouping])
|
75
|
+
tokens.map(&:value).should eq([:if, :open, :x, :lt, 10, :comma, :y, :comma, :z, :close])
|
76
|
+
end
|
77
|
+
end
|
69
78
|
end
|
metadata
CHANGED
@@ -1,36 +1,47 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: dentaku
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 25
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 1
|
10
|
+
version: 0.1.1
|
6
11
|
platform: ruby
|
7
|
-
authors:
|
12
|
+
authors:
|
8
13
|
- Solomon White
|
9
14
|
autorequire:
|
10
15
|
bindir: bin
|
11
16
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
17
|
+
|
18
|
+
date: 2012-01-24 00:00:00 -07:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
15
22
|
name: rspec
|
16
|
-
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
17
25
|
none: false
|
18
|
-
requirements:
|
19
|
-
- -
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
22
33
|
type: :development
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
'
|
28
|
-
email:
|
34
|
+
version_requirements: *id001
|
35
|
+
description: " Dentaku is a parser and evaluator for mathematical formulas\n"
|
36
|
+
email:
|
29
37
|
- rubysolo@gmail.com
|
30
38
|
executables: []
|
39
|
+
|
31
40
|
extensions: []
|
41
|
+
|
32
42
|
extra_rdoc_files: []
|
33
|
-
|
43
|
+
|
44
|
+
files:
|
34
45
|
- .gitignore
|
35
46
|
- Gemfile
|
36
47
|
- README.md
|
@@ -51,31 +62,41 @@ files:
|
|
51
62
|
- spec/token_scanner_spec.rb
|
52
63
|
- spec/token_spec.rb
|
53
64
|
- spec/tokenizer_spec.rb
|
65
|
+
has_rdoc: true
|
54
66
|
homepage: http://github.com/rubysolo/dentaku
|
55
67
|
licenses: []
|
68
|
+
|
56
69
|
post_install_message:
|
57
70
|
rdoc_options: []
|
58
|
-
|
71
|
+
|
72
|
+
require_paths:
|
59
73
|
- lib
|
60
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
75
|
none: false
|
62
|
-
requirements:
|
63
|
-
- -
|
64
|
-
- !ruby/object:Gem::Version
|
65
|
-
|
66
|
-
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
hash: 3
|
80
|
+
segments:
|
81
|
+
- 0
|
82
|
+
version: "0"
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
84
|
none: false
|
68
|
-
requirements:
|
69
|
-
- -
|
70
|
-
- !ruby/object:Gem::Version
|
71
|
-
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
hash: 3
|
89
|
+
segments:
|
90
|
+
- 0
|
91
|
+
version: "0"
|
72
92
|
requirements: []
|
93
|
+
|
73
94
|
rubyforge_project: dentaku
|
74
|
-
rubygems_version: 1.
|
95
|
+
rubygems_version: 1.3.7
|
75
96
|
signing_key:
|
76
97
|
specification_version: 3
|
77
98
|
summary: A formula language parser and evaluator
|
78
|
-
test_files:
|
99
|
+
test_files:
|
79
100
|
- spec/calculator_spec.rb
|
80
101
|
- spec/dentaku_spec.rb
|
81
102
|
- spec/evaluator_spec.rb
|