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 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