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 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 module-method
40
- shortcut just for you:
39
+ If you're too lazy to be building calculator objects, there's a shortcut just
40
+ for you:
41
41
 
42
- Dentaku['plums * 1.5', {:plums => 2}]
42
+ Dentaku('plums * 1.5', {:plums => 2})
43
43
  => 3.0
44
44
 
45
45
 
data/Rakefile CHANGED
@@ -8,3 +8,6 @@ task :spec do
8
8
  t.pattern = 'spec/*_spec.rb'
9
9
  end
10
10
  end
11
+
12
+ desc "Default: run specs."
13
+ task :default => :spec
@@ -2,7 +2,7 @@ require "dentaku/calculator"
2
2
  require "dentaku/version"
3
3
 
4
4
  module Dentaku
5
- def self.[](expression, data={})
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
@@ -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
@@ -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 == '(' ? :open : :close
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
 
@@ -1,3 +1,3 @@
1
1
  module Dentaku
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
@@ -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
@@ -2,10 +2,10 @@ require 'dentaku'
2
2
 
3
3
  describe Dentaku do
4
4
  it 'should evaulate an expression' do
5
- Dentaku['5+3'].should eql(8)
5
+ Dentaku('5+3').should eql(8)
6
6
  end
7
7
 
8
8
  it 'should bind values to variables' do
9
- Dentaku['oranges > 7', {:oranges => 10}].should be_true
9
+ Dentaku('oranges > 7', {:oranges => 10}).should be_true
10
10
  end
11
11
  end
@@ -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
- version: 0.1.0
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
- date: 2012-01-20 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
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
- requirement: &70125220014660 !ruby/object:Gem::Requirement
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
17
25
  none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
21
- version: '0'
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
22
33
  type: :development
23
- prerelease: false
24
- version_requirements: *70125220014660
25
- description: ! ' Dentaku is a parser and evaluator for mathematical formulas
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
- files:
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
- require_paths:
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
- version: '0'
66
- required_rubygems_version: !ruby/object:Gem::Requirement
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
- version: '0'
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.8.10
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