Skip to content

Commit

Permalink
Add the concept of NULL
Browse files Browse the repository at this point in the history
Allow NULL to be referenced in formulas, and for passed-in variables to
have the value of 'null', which is evaluated as nil.
  • Loading branch information
tristil committed Feb 16, 2016
1 parent 0ce7c4a commit b14ded5
Show file tree
Hide file tree
Showing 8 changed files with 32 additions and 2 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ BUILT-IN OPERATORS AND FUNCTIONS

Math: `+ - * / %`

Logic: `< > <= >= <> != = AND OR`
Logic: `< > <= >= <> != = AND OR NULL`

Functions: `IF NOT MIN MAX ROUND ROUNDDOWN ROUNDUP`

Expand Down
2 changes: 2 additions & 0 deletions lib/dentaku/ast/identifier.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ def initialize(token)
def value(context={})
v = context[identifier]
case v
when :null
nil
when Node
v.value(context)
when NilClass
Expand Down
4 changes: 4 additions & 0 deletions lib/dentaku/calculator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ def store(key_or_hash, value=nil)
memory[key_or_hash.to_s.downcase] = value
end

memory.each do |key, value|
memory[key] = :null if value == 'null'
end

if block_given?
begin
result = yield
Expand Down
3 changes: 3 additions & 0 deletions lib/dentaku/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ def parse
operations.push op_class
end

when :null
output.push AST::Nil.new

when :function
arities.push 0
operations.push function(token)
Expand Down
5 changes: 5 additions & 0 deletions lib/dentaku/token_scanner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ def scan(string, last_token=nil)
class << self
def available_scanners
[
:null,
:whitespace,
:numeric,
:double_quoted_string,
Expand Down Expand Up @@ -68,6 +69,10 @@ def whitespace
new(:whitespace, '\s+')
end

def null
new(:null, 'null\b')
end

def numeric
new(:numeric, '(\d+(\.\d+)?|\.\d+)\b', lambda { |raw| raw =~ /\./ ? BigDecimal.new(raw) : raw.to_i })
end
Expand Down
10 changes: 10 additions & 0 deletions spec/calculator_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,16 @@
end
end

describe 'explicit NULL' do
it 'can be used in IF statements' do
expect(calculator.evaluate('IF(null, 1, 2)')).to eq(2)
end

it 'can be used in IF statements when passed in' do
expect(calculator.evaluate('IF(foo, 1, 2)', foo: 'null')).to eq(2)
end
end

describe 'case statements' do
it 'handles complex then statements' do
formula = <<-FORMULA
Expand Down
6 changes: 6 additions & 0 deletions spec/parser_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,10 @@
described_class.new([five, times, minus]).parse
}.to raise_error(Dentaku::ParseError)
end

it "evaluates explicit 'NULL' as a Nil" do
null = Dentaku::Token.new(:null, nil)
node = described_class.new([null]).parse
expect(node.value).to eq(nil)
end
end
2 changes: 1 addition & 1 deletion spec/token_scanner_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
end

it 'returns a list of all configured scanners' do
expect(described_class.scanners.length).to eq 13
expect(described_class.scanners.length).to eq 14
end

it 'allows customizing available scanners' do
Expand Down

0 comments on commit b14ded5

Please sign in to comment.