diff --git a/README.md b/README.md index 6b77a8c..7975c37 100644 --- a/README.md +++ b/README.md @@ -49,9 +49,15 @@ Our DSL consists of these components: 'alpha' 'What is your name?' -* **integer**, a sequence of 0-9. Examples: +* **decimal**, a sequence of [+-]?[0-9]\*.[0-9]\*. Examples: + + 0.123 + -45.78 + +* **integer**, a sequence of [+-]?[0-9]\*. Examples: 0 + -654 458457474 * **attribute** reference, a sequence of [A-z\_][A-z0-9\_]\*[?]. When an attribute reference is evaluated, @@ -66,7 +72,7 @@ Our DSL consists of these components: !Apple_Tree !what_i5_YOUR_name? -* **element** is one of a **string**, **integer**, or **attribute**. +* **element** is one of a **string**, **decimal**, **integer**, or **attribute**. * **comparison** consists of an **element**, followed by one of ==, !=, <, >, <=, >=, (the operator) followed by another **element**. When a comparison is evaluated, the 2 elements are compared using the operater diff --git a/lib/boolean_dsl/evaluator.rb b/lib/boolean_dsl/evaluator.rb index f1b893b..cba4c2f 100644 --- a/lib/boolean_dsl/evaluator.rb +++ b/lib/boolean_dsl/evaluator.rb @@ -1,3 +1,5 @@ +require 'bigdecimal' + class BooleanDsl::Evaluator attr_reader :parser, :expression, :context @@ -30,6 +32,8 @@ def evaluate(tree) !evaluate(tree[:negation]) elsif tree.key?(:string) tree[:string] + elsif tree.key?(:decimal) + BigDecimal(tree[:decimal]) elsif tree.key?(:integer) Integer(tree[:integer], 10) end diff --git a/lib/boolean_dsl/parser.rb b/lib/boolean_dsl/parser.rb index deecb95..c88128e 100644 --- a/lib/boolean_dsl/parser.rb +++ b/lib/boolean_dsl/parser.rb @@ -4,7 +4,11 @@ class BooleanDsl::Parser < Parslet::Parser rule(:space?) { space.maybe } # Literals - rule(:integer) { match('[0-9]').repeat(1).as(:integer) >> space? } + rule(:decimal) do + (match('[+-]').maybe >> match('[0-9]').repeat(1) >> str(".") >> match('[0-9]').repeat(1)).as(:decimal) >> space? + end + + rule(:integer) { (match('[+-]').maybe >> match('[0-9]').repeat(1)).as(:integer) >> space? } rule(:string_content) { (str("'").absent? >> any).repeat } rule(:string) { str("'") >> string_content.as(:string) >> str("'") >> space? } @@ -17,7 +21,7 @@ class BooleanDsl::Parser < Parslet::Parser rule(:negation) { str('!') >> attribute.as(:negation) } # Elements - rule(:element) { negation | integer | string | attribute } + rule(:element) { negation | decimal | integer | string | attribute } # Booleans are rules that will evaluate to a true or false result rule(:boolean) { value_comparison | negation | attribute } diff --git a/spec/evaluator/evaluate_spec.rb b/spec/evaluator/evaluate_spec.rb index 38f298e..bb22e21 100644 --- a/spec/evaluator/evaluate_spec.rb +++ b/spec/evaluator/evaluate_spec.rb @@ -8,12 +8,20 @@ specify do expect(evaluator.evaluate( - left: { integer: '1' }, + left: { integer: '+1' }, comparison_operator: '==', right: { integer: '1' }, )).to be_truthy end + specify do + expect(evaluator.evaluate( + left: { decimal: '-2.1' }, + comparison_operator: '<', + right: { decimal: '+1.2' }, + )).to be_truthy + end + specify do expect(evaluator.evaluate( left: { integer: '1' }, @@ -43,7 +51,7 @@ left: { left: { integer: '1' }, comparison_operator: '==', - right: { integer: '7' }, + right: { integer: '-1' }, }, boolean_operator: 'and', right: { diff --git a/spec/parser_spec.rb b/spec/parser_spec.rb index 6e33a20..8120b00 100644 --- a/spec/parser_spec.rb +++ b/spec/parser_spec.rb @@ -9,6 +9,16 @@ specify { expect(parser.parse_with_debug('12')).to eq(integer: "12") } specify { expect(parser.parse_with_debug('0 ')).to eq(integer: "0") } specify { expect(parser.parse_with_debug('12 ')).to eq(integer: "12") } + specify { expect(parser.parse_with_debug('-12')).to eq(integer: "-12") } + specify { expect(parser.parse_with_debug('+12')).to eq(integer: "+12") } + end + + context 'decimal literals' do + specify { expect(parser.parse_with_debug('0.00')).to eq(decimal: "0.00") } + specify { expect(parser.parse_with_debug('1.23')).to eq(decimal: "1.23") } + specify { expect(parser.parse_with_debug('1.23 ')).to eq(decimal: "1.23") } + specify { expect(parser.parse_with_debug('-1.23')).to eq(decimal: "-1.23") } + specify { expect(parser.parse_with_debug('+1.23')).to eq(decimal: "+1.23") } end context 'string literals' do @@ -128,10 +138,10 @@ end specify do - expect(parser.parse_with_debug('16 < 9565 ')).to eq( - left: { integer: "16" }, + expect(parser.parse_with_debug('16.5 < 9565.8 ')).to eq( + left: { decimal: "16.5" }, comparison_operator: "<", - right: { integer: "9565" } + right: { decimal: "9565.8" } ) end