From ece02a3a800ec2820c56e29d8596a524ecf0f5e5 Mon Sep 17 00:00:00 2001 From: Michael MacDonald Date: Mon, 11 Feb 2019 15:44:58 +1100 Subject: [PATCH 1/2] Add decimal component --- README.md | 7 ++++++- lib/boolean_dsl/evaluator.rb | 4 ++++ lib/boolean_dsl/parser.rb | 6 +++++- spec/evaluator/evaluate_spec.rb | 8 ++++++++ spec/parser_spec.rb | 12 +++++++++--- 5 files changed, 32 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 6b77a8c..a00d911 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,11 @@ Our DSL consists of these components: 'alpha' 'What is your name?' +* **decimal**, a sequence of [0-9]\*.[0-9]\*. Examples: + + 0.123 + 45.78 + * **integer**, a sequence of 0-9. Examples: 0 @@ -66,7 +71,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..4a98939 100644 --- a/lib/boolean_dsl/parser.rb +++ b/lib/boolean_dsl/parser.rb @@ -4,6 +4,10 @@ class BooleanDsl::Parser < Parslet::Parser rule(:space?) { space.maybe } # Literals + rule(:decimal) do + (match('[0-9]').repeat(1) >> str(".") >> match('[0-9]').repeat(1)).as(:decimal) >> space? + end + rule(:integer) { match('[0-9]').repeat(1).as(:integer) >> space? } rule(:string_content) { (str("'").absent? >> any).repeat } @@ -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..30199ec 100644 --- a/spec/evaluator/evaluate_spec.rb +++ b/spec/evaluator/evaluate_spec.rb @@ -14,6 +14,14 @@ )).to be_truthy end + specify do + expect(evaluator.evaluate( + left: { decimal: '1.1' }, + comparison_operator: '>', + right: { decimal: '1.0' }, + )).to be_truthy + end + specify do expect(evaluator.evaluate( left: { integer: '1' }, diff --git a/spec/parser_spec.rb b/spec/parser_spec.rb index 6e33a20..978d803 100644 --- a/spec/parser_spec.rb +++ b/spec/parser_spec.rb @@ -11,6 +11,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") } + end + context 'string literals' do specify { expect(parser.parse_with_debug("''")).to eq(string: []) } #TODO: https://github.com/kschiess/parslet/pull/98 specify { expect(parser.parse_with_debug("' '")).to eq(string: ' ') } @@ -128,10 +134,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 From 697dc11e6b03c96c6c237b3c2a2a99fd0232f5f0 Mon Sep 17 00:00:00 2001 From: Michael MacDonald Date: Mon, 11 Feb 2019 16:35:46 +1100 Subject: [PATCH 2/2] Allow for negative (and explicit positive) integers and decimals --- README.md | 7 ++++--- lib/boolean_dsl/parser.rb | 4 ++-- spec/evaluator/evaluate_spec.rb | 10 +++++----- spec/parser_spec.rb | 4 ++++ 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index a00d911..7975c37 100644 --- a/README.md +++ b/README.md @@ -49,14 +49,15 @@ Our DSL consists of these components: 'alpha' 'What is your name?' -* **decimal**, a sequence of [0-9]\*.[0-9]\*. Examples: +* **decimal**, a sequence of [+-]?[0-9]\*.[0-9]\*. Examples: 0.123 - 45.78 + -45.78 -* **integer**, a sequence of 0-9. Examples: +* **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, diff --git a/lib/boolean_dsl/parser.rb b/lib/boolean_dsl/parser.rb index 4a98939..c88128e 100644 --- a/lib/boolean_dsl/parser.rb +++ b/lib/boolean_dsl/parser.rb @@ -5,10 +5,10 @@ class BooleanDsl::Parser < Parslet::Parser # Literals rule(:decimal) do - (match('[0-9]').repeat(1) >> str(".") >> match('[0-9]').repeat(1)).as(:decimal) >> space? + (match('[+-]').maybe >> match('[0-9]').repeat(1) >> str(".") >> match('[0-9]').repeat(1)).as(:decimal) >> space? end - rule(:integer) { match('[0-9]').repeat(1).as(:integer) >> space? } + 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? } diff --git a/spec/evaluator/evaluate_spec.rb b/spec/evaluator/evaluate_spec.rb index 30199ec..bb22e21 100644 --- a/spec/evaluator/evaluate_spec.rb +++ b/spec/evaluator/evaluate_spec.rb @@ -8,7 +8,7 @@ specify do expect(evaluator.evaluate( - left: { integer: '1' }, + left: { integer: '+1' }, comparison_operator: '==', right: { integer: '1' }, )).to be_truthy @@ -16,9 +16,9 @@ specify do expect(evaluator.evaluate( - left: { decimal: '1.1' }, - comparison_operator: '>', - right: { decimal: '1.0' }, + left: { decimal: '-2.1' }, + comparison_operator: '<', + right: { decimal: '+1.2' }, )).to be_truthy end @@ -51,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 978d803..8120b00 100644 --- a/spec/parser_spec.rb +++ b/spec/parser_spec.rb @@ -9,12 +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