msfl_visitors 0.0.4 → 0.1.0.dev

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bfe406385ca7f2a298e5734eab80bb39919117d0
4
- data.tar.gz: a64c2b8e45a0a324aee12760b845bcdb2c75f3ab
3
+ metadata.gz: 7c087841af641cd54315d9e01ede56327e432e50
4
+ data.tar.gz: 62b019613fe964774360e3cfde4ce61603c20686
5
5
  SHA512:
6
- metadata.gz: 091cd53361857fec191d593e95c8ba099306409d277c40add3362cbacebf6f0a4d68bd5e6ab2550b3f239948b5008717da1366ab6334036b4ac18a1b80500431
7
- data.tar.gz: 59430f4f34128a5c388a057d5820c8dce8bf0f052d7c671921e63a1b1e3a69a8dcebf07ff7564721189616c2f4a99582a4232fa82892c4c16758ae91e90e5edb
6
+ metadata.gz: b0deb50dbdb4057b19c49daa95d151bfff4a8885451d5ad588b8b704247e0e5ccded964ad7d5e1cd9336a7d0d5c836d77b8cd464b8c98d7a5b8e039c15a5dd61
7
+ data.tar.gz: a79e6d2c395b9e1b573e5a6207504fb59fcffbdf491e2b0081aba6d70d75f492a1e01314f9f0473983407a28e99aef1e7c436d418fb93eca2f9e9fdd575dd2d5
@@ -3,13 +3,18 @@ module MSFLVisitors
3
3
 
4
4
  attr_accessor :root
5
5
 
6
- def initialize(msfl)
7
- self.root = MSFLVisitors::Parsers::MSFLParser.new.parse msfl
6
+ def initialize(obj, parser = MSFLVisitors::Parsers::MSFLParser.new)
7
+ self.root = parser.parse obj
8
8
  end
9
9
 
10
10
  # Use this method to walk the AST with a particular visitor
11
11
  def accept(visitor)
12
12
  root.accept visitor
13
13
  end
14
+
15
+ def ==(other)
16
+ self.class == other.class &&
17
+ root == other.root
18
+ end
14
19
  end
15
20
  end
@@ -1,12 +1,23 @@
1
- require_relative 'binary'
1
+ require_relative 'iterator'
2
2
  module MSFLVisitors
3
3
  module Nodes
4
- class And < Binary
4
+ class And < Iterator
5
5
 
6
6
  def accept(visitor)
7
- MSFLVisitors::Nodes::Grouping::Grouping.new(left).accept visitor
8
- visitor.visit self
9
- MSFLVisitors::Nodes::Grouping::Grouping.new(right).accept visitor
7
+ nodes = Array.new
8
+ if items.count > 1
9
+ items.each do |item|
10
+ nodes << MSFLVisitors::Nodes::Grouping::Grouping.new(item)
11
+ nodes << BinaryAnd.new
12
+ end
13
+ nodes.pop
14
+ elsif items.count == 1
15
+ nodes << items.first
16
+ end
17
+
18
+ nodes.each do |node|
19
+ node.accept visitor
20
+ end
10
21
  end
11
22
  end
12
23
  end
@@ -0,0 +1,7 @@
1
+ require_relative 'constant_value'
2
+ module MSFLVisitors
3
+ module Nodes
4
+ class BinaryAnd < ConstantValue
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ require_relative 'binary'
2
+ module MSFLVisitors
3
+ module Nodes
4
+ class Containment < Binary
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ require_relative 'value'
2
+ module MSFLVisitors
3
+ module Nodes
4
+ class Field < Value
5
+ end
6
+ end
7
+ end
@@ -1,23 +1,7 @@
1
- require_relative 'base'
1
+ require_relative 'set/set'
2
2
  module MSFLVisitors
3
3
  module Nodes
4
- class Filter < Base
5
-
6
- attr_accessor :contents
7
-
8
- def accept(visitor)
9
- contents.accept visitor
10
- end
11
-
12
- # @param nodes [Array<MSFL::Nodes::Base>] the nodes that the filter surrounds
13
- def initialize(nodes)
14
- self.contents = nodes
15
- end
16
-
17
- def ==(other)
18
- self.class == other.class &&
19
- contents == other.contents
20
- end
4
+ class Filter < Set::Set
21
5
  end
22
6
  end
23
7
  end
@@ -0,0 +1,18 @@
1
+ require_relative 'base'
2
+ module MSFLVisitors
3
+ module Nodes
4
+ class Iterator < Base
5
+
6
+ attr_accessor :items
7
+
8
+ def initialize(nodes)
9
+ self.items = nodes
10
+ end
11
+
12
+ def ==(other)
13
+ self.class == other.class &&
14
+ items == other.items
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,9 @@
1
+ require_relative '../constant_value'
2
+ module MSFLVisitors
3
+ module Nodes
4
+ module Set
5
+ class Close < ConstantValue
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ require_relative '../constant_value'
2
+ module MSFLVisitors
3
+ module Nodes
4
+ module Set
5
+ class Delimiter < ConstantValue
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ require_relative '../constant_value'
2
+ module MSFLVisitors
3
+ module Nodes
4
+ module Set
5
+ class Open < ConstantValue
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,39 @@
1
+ require_relative '../base'
2
+ module MSFLVisitors
3
+ module Nodes
4
+ module Set
5
+ class Set < Base
6
+
7
+ attr_accessor :contents
8
+
9
+ def accept(visitor)
10
+ nodes = Array.new
11
+ nodes << Open.new
12
+ if contents.count > 0
13
+ contents.each do |item|
14
+ nodes << item
15
+ nodes << Delimiter.new
16
+ end
17
+ # Remove the last (and therefore extra) delimiter
18
+ nodes.pop
19
+ end
20
+ nodes << Close.new
21
+
22
+ nodes.each do |node|
23
+ node.accept visitor
24
+ end
25
+ end
26
+
27
+ # @param nodes [Array<MSFL::Nodes::Base>] the nodes that the filter surrounds
28
+ def initialize(nodes)
29
+ self.contents = Array(nodes)
30
+ end
31
+
32
+ def ==(other)
33
+ self.class == other.class &&
34
+ contents == other.contents
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -2,13 +2,17 @@
2
2
  require_relative 'nodes/and'
3
3
  require_relative 'nodes/base'
4
4
  require_relative 'nodes/binary'
5
+ require_relative 'nodes/binary_and'
5
6
  require_relative 'nodes/boolean'
6
7
  require_relative 'nodes/comparison'
7
8
  require_relative 'nodes/constant_value'
9
+ require_relative 'nodes/containment'
8
10
  require_relative 'nodes/date'
9
11
  require_relative 'nodes/date_time'
10
12
  require_relative 'nodes/equal'
13
+ require_relative 'nodes/field'
11
14
  require_relative 'nodes/filter'
15
+ require_relative 'nodes/iterator'
12
16
  require_relative 'nodes/greater_than'
13
17
  require_relative 'nodes/greater_than_equal'
14
18
  require_relative 'nodes/grouping/close'
@@ -18,6 +22,10 @@ require_relative 'nodes/less_than'
18
22
  require_relative 'nodes/less_than_equal'
19
23
  require_relative 'nodes/number'
20
24
  require_relative 'nodes/range_value'
25
+ require_relative 'nodes/set/close'
26
+ require_relative 'nodes/set/delimiter'
27
+ require_relative 'nodes/set/set'
28
+ require_relative 'nodes/set/open'
21
29
  require_relative 'nodes/time'
22
30
  require_relative 'nodes/value'
23
31
  require_relative 'nodes/word'
@@ -4,8 +4,13 @@ module MSFLVisitors
4
4
  class MSFLParser
5
5
  include MSFL::Validators::Definitions::HashKey
6
6
 
7
+ OPERATORS_TO_NODE_CLASS = {
8
+ gt: Nodes::GreaterThan,
9
+ gte: Nodes::GreaterThanEqual,
10
+ in: Nodes::Containment,
11
+ }
12
+
7
13
  def parse(obj, lhs = false)
8
- # send("parse_#{obj.class.to_s.gsub('::', '_')}", obj, lhs)
9
14
  case obj
10
15
 
11
16
  when Float, Fixnum
@@ -35,11 +40,21 @@ module MSFLVisitors
35
40
  obj.each do |k, v|
36
41
  nodes << hash_dispatch(k, v, lhs)
37
42
  end
38
- MSFLVisitors::Nodes::Filter.new nodes
43
+ # If there's exactly one node in nodes and it's a filter node we don't want to wrap it in yet
44
+ # another filter node, so we just return the filter node
45
+ if nodes.count == 1 && nodes.first.is_a?(MSFLVisitors::Nodes::Filter)
46
+ nodes.first
47
+ else
48
+ MSFLVisitors::Nodes::Filter.new nodes
49
+ end
39
50
  end
40
51
 
41
52
  def parse_Set(obj, lhs = false)
42
-
53
+ nodes = MSFL::Types::Set.new([])
54
+ obj.each do |item|
55
+ nodes << parse(item)
56
+ end
57
+ MSFLVisitors::Nodes::Set::Set.new nodes
43
58
  end
44
59
 
45
60
  def hash_dispatch(key, value, lhs = false)
@@ -47,7 +62,7 @@ module MSFLVisitors
47
62
  # Detect the node type, forward the lhs if it was passed in (essentially when the operator is a binary op)
48
63
  args = [lhs, parse(value)] if lhs
49
64
  args ||= [parse(value)]
50
- Object.const_get("MSFLVisitors::Nodes::#{key.to_s.capitalize}").new(*args)
65
+ OPERATORS_TO_NODE_CLASS[key].new(*args)
51
66
  else
52
67
  # the key is a field
53
68
  # there are three possible scenarios when they key is a field
@@ -61,7 +76,7 @@ module MSFLVisitors
61
76
  # { model: { in: ["Corolla", "Civic", "Mustang"] } }
62
77
  #
63
78
  # 2 & 3 are just hashes and can be parsed using the same method
64
- lhs = MSFLVisitors::Nodes::Word.new key
79
+ lhs = MSFLVisitors::Nodes::Field.new key
65
80
 
66
81
  # the node type generated by parsing value can use the lhs node when appropriate and otherwise ignore it
67
82
  # although I can't think of a situation when it would ignore it.
@@ -3,7 +3,6 @@ module MSFLVisitors
3
3
  module Chewy
4
4
  class TermFilter
5
5
  BINARY_OPERATORS = {
6
- Nodes::And => ' & ',
7
6
  Nodes::GreaterThan => ' > ',
8
7
  Nodes::LessThan => ' < ',
9
8
  Nodes::GreaterThanEqual => ' >= ',
@@ -14,24 +13,39 @@ module MSFLVisitors
14
13
  def render(node)
15
14
  case node
16
15
 
17
- when Nodes::Comparison, Nodes::And
16
+ when Nodes::Comparison
18
17
  BINARY_OPERATORS[node.class]
19
18
 
19
+ when Nodes::BinaryAnd
20
+ ' & '
21
+
20
22
  when Nodes::Date, Nodes::Time
21
23
  node.value.iso8601
22
24
 
23
25
  when Nodes::Boolean, Nodes::Number
24
26
  node.value
25
27
 
26
- when Nodes::Word
28
+ when Nodes::Field
27
29
  node.value.to_s
28
30
 
31
+ when Nodes::Word
32
+ %("#{node.value.to_s}")
33
+
29
34
  when Nodes::Grouping::Close
30
35
  ' )'
31
36
 
32
37
  when Nodes::Grouping::Open
33
38
  '( '
34
39
 
40
+ when Nodes::Set::Close
41
+ ' ]'
42
+
43
+ when Nodes::Set::Delimiter
44
+ ', '
45
+
46
+ when Nodes::Set::Open
47
+ '[ '
48
+
35
49
  else
36
50
  fail ArgumentError.new("Unrecognized node type: #{node.class}")
37
51
  end
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'msfl_visitors'
3
- s.version = '0.0.4'
4
- s.date = '2015-05-01'
3
+ s.version = '0.1.0.dev'
4
+ s.date = '2015-05-06'
5
5
  s.summary = "Convert MSFL to other forms"
6
6
  s.description = "Visitor pattern approach to converting MSFL to other forms."
7
7
  s.authors = ["Courtland Caldwell"]
data/spec/ast_spec.rb ADDED
@@ -0,0 +1,78 @@
1
+ require 'spec_helper'
2
+
3
+ describe MSFLVisitors::AST do
4
+
5
+ let(:msfl) { { make: "Honda" } }
6
+
7
+ describe "#initialize" do
8
+
9
+ let(:parser) do
10
+ p = double('Fake Parser')
11
+ expect(p).to receive(:parse).with(msfl).once
12
+ p
13
+ end
14
+
15
+ subject { described_class.new msfl, parser }
16
+
17
+ it "eagerly parses the first argument" do
18
+ subject
19
+ end
20
+
21
+ context "when a parser is specified" do
22
+
23
+ it "uses the specified parser" do
24
+ subject
25
+ end
26
+ end
27
+ end
28
+
29
+ describe "#accept" do
30
+
31
+ let(:parser) { double('Fake Parser', parse: root) }
32
+
33
+ let(:root) do
34
+ r = double('Fake Root Node')
35
+ expect(r).to receive(:accept).with(visitor).once
36
+ r
37
+ end
38
+
39
+ let(:visitor) { double('Fake Visitor') }
40
+
41
+ subject { described_class.new(msfl, parser).accept visitor }
42
+
43
+ it "delegates to the root node" do
44
+ subject
45
+ end
46
+ end
47
+
48
+ describe "#==" do
49
+
50
+ subject { left == right }
51
+
52
+ let(:left) { described_class.new(msfl) }
53
+
54
+ let(:right) { described_class.new(msfl) }
55
+
56
+ context "when the two ASTs are the same class" do
57
+
58
+ context "when the two ASTs have equal root nodes" do
59
+
60
+ it { is_expected.to be true }
61
+ end
62
+
63
+ context "when the two ASTs do not have equal root nodes" do
64
+
65
+ let(:right) { described_class.new({ value: 1000 }) }
66
+
67
+ it { is_expected.to be false }
68
+ end
69
+ end
70
+
71
+ context "when the two ASTs are not the same class" do
72
+
73
+ let(:right) { double('Fake AST') }
74
+
75
+ it { is_expected.to be false }
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ describe MSFLVisitors::Nodes::Iterator do
4
+
5
+ describe "#==" do
6
+
7
+ let(:one) { MSFLVisitors::Nodes::Number.new(1) }
8
+
9
+ let(:two) { MSFLVisitors::Nodes::Number.new(2) }
10
+
11
+ let(:left) { MSFLVisitors::Nodes::Iterator.new [one, two] }
12
+
13
+ let(:right) { MSFLVisitors::Nodes::Iterator.new [one, two] }
14
+
15
+ subject { left == right }
16
+
17
+ context "when lhs and rhs are the same class" do
18
+
19
+ context "when lhs#items is equal to rhs#items" do
20
+
21
+ it { is_expected.to be true }
22
+ end
23
+
24
+ context "when lhs#items is not equal to rhs#items" do
25
+
26
+ let(:right) { MSFLVisitors::Nodes::Iterator.new [one] }
27
+
28
+ it { is_expected.to be false }
29
+ end
30
+ end
31
+
32
+ context "when lhs is a different class than rhs" do
33
+
34
+ let(:right) { Object.new }
35
+
36
+ it { is_expected.to be false }
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,70 @@
1
+ # This is a working file until I split these up
2
+ require 'spec_helper'
3
+
4
+ describe MSFLVisitors::Parsers::MSFLParser do
5
+
6
+ let(:expected_node) { ->(comp_node) { MSFLVisitors::Nodes::Filter.new [ comp_node ] } }
7
+
8
+ let(:left) { MSFLVisitors::Nodes::Field.new :value }
9
+
10
+ let(:right) { MSFLVisitors::Nodes::Number.new 1000 }
11
+
12
+ describe "parsing a trivial filter" do
13
+
14
+ subject { described_class.new.parse msfl }
15
+
16
+ let(:msfl) { { value: 1000 } }
17
+
18
+ it "is the expected node" do
19
+ expect(subject).to eq expected_node.call(MSFLVisitors::Nodes::Equal.new(left, right))
20
+ end
21
+ end
22
+
23
+ describe "#parse" do
24
+
25
+ context "when parsing a filter" do
26
+
27
+ subject { -> (filter) { described_class.new.parse filter } }
28
+
29
+ let(:implicit_equality_filter) { { value: 1000 } }
30
+
31
+ let(:explicit_gte_filter) { { value: { gte: 1000 } } }
32
+
33
+ let(:containment_filter) { { value: { in: containment_values } } }
34
+
35
+ let(:containment_values) { MSFL::Types::Set.new [50, 250, 20000] }
36
+
37
+ it "handles implicit equality comparisons" do
38
+ expect(subject.call(implicit_equality_filter)).to eq expected_node.call(MSFLVisitors::Nodes::Equal.new(left, right))
39
+ end
40
+
41
+ it "handles explicit comparisons" do
42
+ comparison_node = MSFLVisitors::Nodes::GreaterThanEqual.new left, right
43
+ expect(subject.call(explicit_gte_filter)).to eq expected_node.call(comparison_node)
44
+ end
45
+
46
+ # { value: { in: [50, 250, 20000] } }
47
+ #
48
+ # => Nodes::Containment.new(Nodes::Field.new(:value),
49
+ # Nodes::Set::Set.new([
50
+ # Nodes::Number.new(50),
51
+ # Nodes::Number.new(250),
52
+ # Nodes::Number.new(20000)]))
53
+ it "handles containments" do
54
+ contained_nodes = containment_values.map { |value| MSFLVisitors::Nodes::Number.new(value) }
55
+ set_node = MSFLVisitors::Nodes::Set::Set.new(contained_nodes)
56
+ containment_node = MSFLVisitors::Nodes::Containment.new left, set_node
57
+ expect(subject.call(containment_filter)).to eq expected_node.call(containment_node)
58
+ end
59
+
60
+ context "when the filter contains an unsupported type" do
61
+
62
+ let(:bad_filter) { { foo: Object.new } }
63
+
64
+ it "raises an ArgumentError" do
65
+ expect { subject.call(bad_filter) }.to raise_error ArgumentError
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe MSFLVisitors::Renderers::Chewy::TermFilter do
4
+
5
+ let(:node) { fail ArgumentError, "You must define the node variable in each scope." }
6
+
7
+ let(:collector) { String.new }
8
+
9
+ let(:renderer) { MSFLVisitors::Renderers::Chewy::TermFilter.new }
10
+
11
+ describe "#render" do
12
+
13
+ let(:node) { double('Unsupported Type') }
14
+
15
+ subject { renderer.render node }
16
+
17
+ context "when attempting to render an unsupported type" do
18
+
19
+ it "raises an ArgumentError" do
20
+ expect { subject }.to raise_error ArgumentError
21
+ end
22
+ end
23
+ end
24
+ end
@@ -10,20 +10,37 @@ describe MSFLVisitors::Visitor do
10
10
 
11
11
  let(:visitor) { described_class.new collector, renderer }
12
12
 
13
- let(:left) { MSFLVisitors::Nodes::Word.new "lhs" }
13
+ let(:left) { MSFLVisitors::Nodes::Field.new "lhs" }
14
14
 
15
15
  let(:right) { MSFLVisitors::Nodes::Word.new "rhs" }
16
16
 
17
- subject(:result) { node.accept visitor }
17
+ subject(:result) { collector }
18
+
19
+ before(:each) { node.accept visitor }
18
20
 
19
21
  context "when visiting" do
20
22
 
23
+ describe "a Set node" do
24
+
25
+ let(:node) { MSFLVisitors::Nodes::Set::Set.new values }
26
+
27
+ let(:values) { MSFL::Types::Set.new([item_one, item_two]) }
28
+
29
+ let(:item_one) { MSFLVisitors::Nodes::Word.new "item_one" }
30
+
31
+ let(:item_two) { MSFLVisitors::Nodes::Word.new "item_two" }
32
+
33
+ it "results in: '[ \"item_one\", \"item_two\" ]'" do
34
+ expect(result).to eq "[ \"item_one\", \"item_two\" ]"
35
+ end
36
+ end
37
+
21
38
  describe "an Equal node" do
22
39
 
23
40
  let(:node) { MSFLVisitors::Nodes::Equal.new left, right }
24
41
 
25
42
  it "results in: 'left == right'" do
26
- expect(result).to eq "lhs == rhs"
43
+ expect(result).to eq "lhs == \"rhs\""
27
44
  end
28
45
  end
29
46
 
@@ -32,7 +49,7 @@ describe MSFLVisitors::Visitor do
32
49
  let(:node) { MSFLVisitors::Nodes::GreaterThan.new left, right }
33
50
 
34
51
  it "returns: 'left > right'" do
35
- expect(result).to eq "lhs > rhs"
52
+ expect(result).to eq "lhs > \"rhs\""
36
53
  end
37
54
  end
38
55
 
@@ -41,7 +58,7 @@ describe MSFLVisitors::Visitor do
41
58
  let(:node) { MSFLVisitors::Nodes::GreaterThanEqual.new left, right }
42
59
 
43
60
  it "returns: 'left >= right'" do
44
- expect(result).to eq "lhs >= rhs"
61
+ expect(result).to eq "lhs >= \"rhs\""
45
62
  end
46
63
  end
47
64
 
@@ -50,7 +67,7 @@ describe MSFLVisitors::Visitor do
50
67
  let(:node) { MSFLVisitors::Nodes::LessThan.new left, right }
51
68
 
52
69
  it "returns: 'left < right'" do
53
- expect(result).to eq "lhs < rhs"
70
+ expect(result).to eq 'lhs < "rhs"'
54
71
  end
55
72
  end
56
73
 
@@ -59,16 +76,63 @@ describe MSFLVisitors::Visitor do
59
76
  let(:node) { MSFLVisitors::Nodes::LessThanEqual.new left, right }
60
77
 
61
78
  it "returns: 'left <= right'" do
62
- expect(result).to eq "lhs <= rhs"
79
+ expect(result).to eq 'lhs <= "rhs"'
63
80
  end
64
81
  end
65
82
 
66
83
  describe "an And node" do
67
84
 
68
- let(:node) { MSFLVisitors::Nodes::And.new left, right }
85
+ let(:first_field) { MSFLVisitors::Nodes::Field.new "first_field" }
86
+
87
+ let(:first_value) { MSFLVisitors::Nodes::Word.new "first_word" }
88
+
89
+ let(:first) { MSFLVisitors::Nodes::Equal.new(first_field, first_value) }
90
+
91
+ let(:second_field) { MSFLVisitors::Nodes::Field.new "second_field" }
92
+
93
+ let(:second_value) { MSFLVisitors::Nodes::Word.new "second_word" }
94
+
95
+ let(:second) { MSFLVisitors::Nodes::Equal.new(second_field, second_value) }
96
+
97
+ let(:third_field) { MSFLVisitors::Nodes::Field.new "third_field" }
98
+
99
+ let(:third_value) { MSFLVisitors::Nodes::Word.new "third_word" }
100
+
101
+ let(:third) { MSFLVisitors::Nodes::Equal.new(third_field, third_value) }
69
102
 
70
- it "returns: '( left ) & ( right )'" do
71
- expect(result).to eq "( lhs ) & ( rhs )"
103
+ context "when the And node has zero items" do
104
+ let(:node) { MSFLVisitors::Nodes::And.new([]) }
105
+
106
+ it "is empty" do
107
+ expect(result).to be_empty
108
+ end
109
+ end
110
+
111
+ context "when the node has one item" do
112
+
113
+ let(:node) { MSFLVisitors::Nodes::And.new([first])}
114
+
115
+ it "returns: the item without adding parentheses" do
116
+ expect(result).to eq 'first_field == "first_word"'
117
+ end
118
+ end
119
+
120
+ context "when the node has two items" do
121
+
122
+ let(:node) { MSFLVisitors::Nodes::And.new([first, second]) }
123
+
124
+ it "returns: '( first_field == \"first_word\" ) & ( second_field == \"second_word\" )'" do
125
+ expect(result).to eq '( first_field == "first_word" ) & ( second_field == "second_word" )'
126
+ end
127
+ end
128
+
129
+ context "when the node has three items" do
130
+
131
+ let(:node) { MSFLVisitors::Nodes::And.new([first, second, third]) }
132
+
133
+ it "returns: '( first_field == \"first_word\" ) & ( second_field == \"second_word\" ) & ( third_field == \"third_word\" )'" do
134
+ expect(result).to eq '( first_field == "first_word" ) & ( second_field == "second_word" ) & ( third_field == "third_word" )'
135
+ end
72
136
  end
73
137
  end
74
138
 
@@ -106,8 +170,8 @@ describe MSFLVisitors::Visitor do
106
170
 
107
171
  let(:node) { MSFLVisitors::Nodes::Word.new word }
108
172
 
109
- it "is a literal string" do
110
- expect(result).to eq word
173
+ it "is a double quoted literal string" do
174
+ expect(result).to eq "\"#{word}\""
111
175
  end
112
176
  end
113
177
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: msfl_visitors
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.1.0.dev
5
5
  platform: ruby
6
6
  authors:
7
7
  - Courtland Caldwell
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-01 00:00:00.000000000 Z
11
+ date: 2015-05-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: msfl
@@ -119,22 +119,30 @@ files:
119
119
  - lib/msfl_visitors/nodes/and.rb
120
120
  - lib/msfl_visitors/nodes/base.rb
121
121
  - lib/msfl_visitors/nodes/binary.rb
122
+ - lib/msfl_visitors/nodes/binary_and.rb
122
123
  - lib/msfl_visitors/nodes/boolean.rb
123
124
  - lib/msfl_visitors/nodes/comparison.rb
124
125
  - lib/msfl_visitors/nodes/constant_value.rb
126
+ - lib/msfl_visitors/nodes/containment.rb
125
127
  - lib/msfl_visitors/nodes/date.rb
126
128
  - lib/msfl_visitors/nodes/date_time.rb
127
129
  - lib/msfl_visitors/nodes/equal.rb
130
+ - lib/msfl_visitors/nodes/field.rb
128
131
  - lib/msfl_visitors/nodes/filter.rb
129
132
  - lib/msfl_visitors/nodes/greater_than.rb
130
133
  - lib/msfl_visitors/nodes/greater_than_equal.rb
131
134
  - lib/msfl_visitors/nodes/grouping/close.rb
132
135
  - lib/msfl_visitors/nodes/grouping/grouping.rb
133
136
  - lib/msfl_visitors/nodes/grouping/open.rb
137
+ - lib/msfl_visitors/nodes/iterator.rb
134
138
  - lib/msfl_visitors/nodes/less_than.rb
135
139
  - lib/msfl_visitors/nodes/less_than_equal.rb
136
140
  - lib/msfl_visitors/nodes/number.rb
137
141
  - lib/msfl_visitors/nodes/range_value.rb
142
+ - lib/msfl_visitors/nodes/set/close.rb
143
+ - lib/msfl_visitors/nodes/set/delimiter.rb
144
+ - lib/msfl_visitors/nodes/set/open.rb
145
+ - lib/msfl_visitors/nodes/set/set.rb
138
146
  - lib/msfl_visitors/nodes/time.rb
139
147
  - lib/msfl_visitors/nodes/value.rb
140
148
  - lib/msfl_visitors/nodes/word.rb
@@ -143,7 +151,10 @@ files:
143
151
  - lib/msfl_visitors/visitor.rb
144
152
  - msfl_visitors.gemspec
145
153
  - simplecov_custom_profiles.rb
146
- - spec/parsers/parse_msfl_spec.rb
154
+ - spec/ast_spec.rb
155
+ - spec/nodes/iterator_spec.rb
156
+ - spec/parsers/msfl_parser_spec.rb
157
+ - spec/renderers/chewy/term_filter_spec.rb
147
158
  - spec/spec_helper.rb
148
159
  - spec/visitors/chewy_term_filter_spec.rb
149
160
  homepage: https://github.com/Referly/msfl_visitors
@@ -161,9 +172,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
161
172
  version: '0'
162
173
  required_rubygems_version: !ruby/object:Gem::Requirement
163
174
  requirements:
164
- - - ">="
175
+ - - ">"
165
176
  - !ruby/object:Gem::Version
166
- version: '0'
177
+ version: 1.3.1
167
178
  requirements: []
168
179
  rubyforge_project:
169
180
  rubygems_version: 2.2.2
@@ -171,7 +182,10 @@ signing_key:
171
182
  specification_version: 4
172
183
  summary: Convert MSFL to other forms
173
184
  test_files:
174
- - spec/parsers/parse_msfl_spec.rb
185
+ - spec/ast_spec.rb
186
+ - spec/nodes/iterator_spec.rb
187
+ - spec/parsers/msfl_parser_spec.rb
188
+ - spec/renderers/chewy/term_filter_spec.rb
175
189
  - spec/spec_helper.rb
176
190
  - spec/visitors/chewy_term_filter_spec.rb
177
191
  has_rdoc:
@@ -1,22 +0,0 @@
1
- # This is a working file until I split these up
2
- require 'spec_helper'
3
-
4
- describe MSFLVisitors::Parsers::MSFLParser do
5
-
6
- describe "parsing a trivial filter" do
7
-
8
- subject { described_class.new.parse msfl }
9
-
10
- let(:msfl) { { make: "Ferrari" } }
11
-
12
- let(:expected) { MSFLVisitors::Nodes::Filter.new [ MSFLVisitors::Nodes::Equal.new(left, right) ] }
13
-
14
- let(:left) { MSFLVisitors::Nodes::Word.new :make }
15
-
16
- let(:right) { MSFLVisitors::Nodes::Word.new "Ferrari" }
17
-
18
- it "is the expected AST" do
19
- expect(subject).to eq expected
20
- end
21
- end
22
- end