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