rudelo 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/Gemfile +9 -0
- data/Guardfile +5 -0
- data/LICENSE.txt +22 -0
- data/README.md +60 -0
- data/Rakefile +1 -0
- data/SET_LOGIC_MATCHER.md +100 -0
- data/lib/rudelo/matchers/set_logic.rb +68 -0
- data/lib/rudelo/parsers/set_logic_parser.rb +88 -0
- data/lib/rudelo/parsers/set_logic_transform.rb +160 -0
- data/lib/rudelo/parsers/set_value_parser.rb +68 -0
- data/lib/rudelo/parsers/set_value_transform.rb +10 -0
- data/lib/rudelo/version.rb +3 -0
- data/lib/rudelo.rb +6 -0
- data/rudelo.gemspec +26 -0
- data/spec/matchers/set_logic_spec.rb +59 -0
- data/spec/parsers/set_logic_parser_spec.rb +147 -0
- data/spec/parsers/set_logic_transform_spec.rb +269 -0
- data/spec/parsers/set_value_parser_spec.rb +89 -0
- data/spec/parsers/set_value_transform_spec.rb +21 -0
- data/spec/spec_helper.rb +17 -0
- metadata +160 -0
@@ -0,0 +1,59 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
require 'rudelo'
|
4
|
+
require 'rufus-decision'
|
5
|
+
describe "Rudelo::Matchers::SetLogic" do
|
6
|
+
subject{Rudelo::Matchers::SetLogic.new}
|
7
|
+
|
8
|
+
it "matches multiple values against multiple cells correctly" do
|
9
|
+
cell1 = "$in same-as $(a b c)"
|
10
|
+
cell2 = "$in same-as $(k f r)"
|
11
|
+
expect(subject.matches?(cell1, 'a b c')).to be_true
|
12
|
+
expect(subject.matches?(cell2, 'a b c')).to be_false
|
13
|
+
expect(subject.matches?(cell1, 'k f r')).to be_false
|
14
|
+
expect(subject.matches?(cell2, 'k f r')).to be_true
|
15
|
+
expect(subject.matches?(cell1, 'a b c')).to be_true
|
16
|
+
expect(subject.matches?(cell2, 'a b c')).to be_false
|
17
|
+
end
|
18
|
+
|
19
|
+
context "rufus-decision" do
|
20
|
+
let(:table){
|
21
|
+
table = Rufus::Decision::Table.new(%{
|
22
|
+
in:group, out:situation
|
23
|
+
$(bob jeff mary alice ralph) & $in #= 2, company
|
24
|
+
$(bob jeff mary alice ralph) & $in same-as $in #= 3, crowd
|
25
|
+
$(bob jeff mary alice ralph) >= $in #> 3, exclusive-party
|
26
|
+
$(bob jeff mary alice ralph) & $in < $in #> 5, PARTY!
|
27
|
+
$(bob jeff mary alice ralph) & $in < $in #> 3, party
|
28
|
+
})
|
29
|
+
table.matchers.unshift Rudelo::Matchers::SetLogic.new
|
30
|
+
table
|
31
|
+
}
|
32
|
+
it "transforms values" do
|
33
|
+
expect(
|
34
|
+
table.transform({'group' => "bob alice"})
|
35
|
+
).to eq({'group' => "bob alice", 'situation' => "company"})
|
36
|
+
|
37
|
+
expect(
|
38
|
+
table.transform({'group' => "bob alice jeff"})
|
39
|
+
).to eq({'group' => "bob alice jeff", 'situation' => "crowd"})
|
40
|
+
|
41
|
+
expect(
|
42
|
+
table.transform({'group' => "bob alice jeff ralph"})
|
43
|
+
).to eq({'group' => "bob alice jeff ralph", 'situation' => "exclusive-party"})
|
44
|
+
|
45
|
+
expect(
|
46
|
+
table.transform({'group' => "bob alice jeff don"})
|
47
|
+
).to eq({'group' => "bob alice jeff don", 'situation' => "party"})
|
48
|
+
|
49
|
+
expect(
|
50
|
+
table.transform({'group' => "bob alice jeff mary ralph don"})
|
51
|
+
).to eq({'group' => "bob alice jeff mary ralph don", 'situation' => "PARTY!"})
|
52
|
+
|
53
|
+
expect(
|
54
|
+
table.transform({'group' => "bob alice jeff mary don bev"})
|
55
|
+
).to eq({'group' => "bob alice jeff mary don bev", 'situation' => "PARTY!"})
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
require 'pp'
|
3
|
+
|
4
|
+
require 'rudelo/parsers/set_logic_parser'
|
5
|
+
|
6
|
+
describe "Rudelo::Parsers::SetLogicParser" do
|
7
|
+
let(:parser) { Rudelo::Parsers::SetLogicParser.new }
|
8
|
+
|
9
|
+
context "cardinality_expression" do
|
10
|
+
let(:expr_parser){ parser.cardinality_expression }
|
11
|
+
|
12
|
+
it "parses cardinality (symbols)" do
|
13
|
+
expect(expr_parser).to parse('#= 5', trace: true).as({
|
14
|
+
:cardinality_expression=>{ :op=>'#=', :qty=>"5"}
|
15
|
+
})
|
16
|
+
expect(expr_parser).to parse('#> 5', trace: true)
|
17
|
+
expect(expr_parser).to parse('#< 4', trace: true)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "parses cardinality (words)" do
|
21
|
+
expect(expr_parser).to parse('cardinality-equals 5', trace: true).as({
|
22
|
+
:cardinality_expression=>{ :op=>'cardinality-equals', :qty=>"5"}
|
23
|
+
})
|
24
|
+
expect(expr_parser).to parse('cardinality-greater-than 5', trace: true)
|
25
|
+
expect(expr_parser).to parse('cardinality-less-than 4', trace: true)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context "set construction expression" do
|
30
|
+
let(:expr_parser){ parser.set_construction_expression }
|
31
|
+
|
32
|
+
it "parses set construction to an iterative operation list" do
|
33
|
+
|
34
|
+
expect(expr_parser).to parse('$(bob mary) union $(ralph jeff) & $in', trace: true).as({
|
35
|
+
:set_construction_expression=>{
|
36
|
+
:left=>{:element_list=>[{:element=>"bob"}, {:element=>"mary"}] },
|
37
|
+
:right=>[
|
38
|
+
{ set_op: {
|
39
|
+
left: {op: "union"},
|
40
|
+
right: {element_list:[
|
41
|
+
{:element=>"ralph"}, {:element=>"jeff"}
|
42
|
+
]}
|
43
|
+
}},
|
44
|
+
{ set_op: {
|
45
|
+
left: {op: "&"},
|
46
|
+
right: {:in_set=>"$in"}}}
|
47
|
+
]
|
48
|
+
}
|
49
|
+
})
|
50
|
+
end
|
51
|
+
it "parses set construction ops in symbol form" do
|
52
|
+
expect(expr_parser).to parse('$(bob mary) & $in', trace: true)
|
53
|
+
expect(expr_parser).to parse('$(bob mary) + $in', trace: true)
|
54
|
+
expect(expr_parser).to parse('$(bob mary)-$in', trace: true)
|
55
|
+
expect(expr_parser).to parse('$(bob mary) ^ $in', trace: true)
|
56
|
+
end
|
57
|
+
|
58
|
+
it "parses set construction ops in word form" do
|
59
|
+
expect(expr_parser).to parse('$in intersection $(bob mary)', trace: true)
|
60
|
+
expect(expr_parser).to parse('$in union $(bob mary)', trace: true)
|
61
|
+
expect(expr_parser).to parse('$in difference $(bob mary)', trace: true)
|
62
|
+
expect(expr_parser).to parse('$in exclusive $(bob mary)', trace: true)
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
context "set logic expression" do
|
68
|
+
let(:expr_parser){ parser.set_logic_expression }
|
69
|
+
|
70
|
+
it "parses set logic to a left-right tree" do
|
71
|
+
expect(expr_parser).to parse('$(bob mary) < $(ralph jeff bob mary)', trace: true).as({
|
72
|
+
:set_logic_expression=>{
|
73
|
+
:left=>{:element_list=>[
|
74
|
+
{:element=>"bob"}, {:element=>"mary"}] },
|
75
|
+
:op => "<",
|
76
|
+
:right=>{:element_list=>[
|
77
|
+
{:element=>"ralph"}, {:element=>"jeff"}, {:element=>"bob"}, {:element=>"mary"}]}
|
78
|
+
}
|
79
|
+
})
|
80
|
+
end
|
81
|
+
|
82
|
+
it "parses the left hand side as a set construction expression" do
|
83
|
+
expect(expr_parser).to parse('$(bob mary) union $in < $(ralph jeff bob mary)', trace: true).as({
|
84
|
+
:set_logic_expression=>{
|
85
|
+
:left=> {
|
86
|
+
:set_construction_expression=>{
|
87
|
+
:left=>{
|
88
|
+
:element_list=>[{:element=>"bob"}, {:element=>"mary"}]
|
89
|
+
},
|
90
|
+
:right=>[{set_op: { left: {:op=>"union"}, right: {:in_set=>"$in"}}}]
|
91
|
+
}
|
92
|
+
},
|
93
|
+
:op => "<",
|
94
|
+
:right=>{:element_list=>[
|
95
|
+
{:element=>"ralph"}, {:element=>"jeff"}, {:element=>"bob"}, {:element=>"mary"}]}
|
96
|
+
}
|
97
|
+
})
|
98
|
+
end
|
99
|
+
|
100
|
+
it "parses set logic ops in symbol form" do
|
101
|
+
expect(expr_parser).to parse('$(bob mary) < $in', trace: true)
|
102
|
+
expect(expr_parser).to parse('$(bob mary) <= $in', trace: true)
|
103
|
+
expect(expr_parser).to parse('$(bob mary)>$in', trace: true)
|
104
|
+
expect(expr_parser).to parse('$(bob mary) >= $in', trace: true)
|
105
|
+
end
|
106
|
+
|
107
|
+
it "parses set logic ops in word form" do
|
108
|
+
expect(expr_parser).to parse('$in superset $(bob mary)', trace: true)
|
109
|
+
expect(expr_parser).to parse('$in subset $(bob mary)', trace: true)
|
110
|
+
expect(expr_parser).to parse('$in proper-superset $(bob mary)', trace: true)
|
111
|
+
expect(expr_parser).to parse('$in proper-subset $(bob mary)', trace: true)
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
context "set logic expression" do
|
117
|
+
let(:expr_parser){ parser.match_expression }
|
118
|
+
it "parses a bare cardinality expression" do
|
119
|
+
expect(expr_parser).to parse('#= 5', trace: true).as({
|
120
|
+
match_expression: {
|
121
|
+
right: {
|
122
|
+
cardinality_expression: {op: "#=", qty: "5"}
|
123
|
+
}
|
124
|
+
}
|
125
|
+
})
|
126
|
+
end
|
127
|
+
|
128
|
+
it "parses an explicit set expression" do
|
129
|
+
expect(expr_parser).to parse('$(bob, jeff)', trace: true).as({
|
130
|
+
superset_match_expression: {
|
131
|
+
element_list: [{element: "bob"}, {element: "jeff"}]
|
132
|
+
}
|
133
|
+
})
|
134
|
+
end
|
135
|
+
|
136
|
+
it "parses a set construction expression with optional cardinality" do
|
137
|
+
expect(expr_parser).to parse('$(bob, jeff) + $in', trace: true)
|
138
|
+
expect(expr_parser).to parse('$(bob, jeff) + $in #> 3', trace: true)
|
139
|
+
end
|
140
|
+
|
141
|
+
it "parses a set logic expression with optional cardinality" do
|
142
|
+
expect(expr_parser).to parse('$(bob, jeff) <= $in', trace: true)
|
143
|
+
expect(expr_parser).to parse('$(bob, jeff) <= $in #> 3', trace: true)
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
end
|
@@ -0,0 +1,269 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
require 'rudelo/parsers/set_logic_parser'
|
4
|
+
require 'rudelo/parsers/set_logic_transform'
|
5
|
+
|
6
|
+
describe "Rudelo::Parsers::SetLogicTransform" do
|
7
|
+
let(:parser) { Rudelo::Parsers::SetLogicParser.new }
|
8
|
+
let(:in_set){ Set.new(%w{a b c}) }
|
9
|
+
let(:xform) { Rudelo::Parsers::SetLogicTransform.new(in_set) }
|
10
|
+
let(:empty_set) { Set.new }
|
11
|
+
|
12
|
+
context "ops" do
|
13
|
+
specify{expect(xform.apply(:op => "+")).to eq(:"+")}
|
14
|
+
specify{expect(xform.apply(:op => "#=")).to eq(:"==")}
|
15
|
+
specify{expect(xform.apply(:op => "cardinality-equals")).to eq(:"==")}
|
16
|
+
specify{expect(xform.apply(:op => "#>")).to eq(:>)}
|
17
|
+
specify{expect(xform.apply(:op => "cardinality-greater-than")).to eq(:>)}
|
18
|
+
specify{expect(xform.apply(:op => "proper-superset")).to eq(:proper_superset?)}
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
context "CardinalityExpr" do
|
23
|
+
subject{ Rudelo::Parsers::SetLogicTransform::CardinalityExpr }
|
24
|
+
let(:set){ Set.new(%w{a b c}) }
|
25
|
+
specify{ expect(subject.new(:>, 2).eval(set)).to be_true }
|
26
|
+
specify{ expect(subject.new(:<, 2).eval(set)).to be_false }
|
27
|
+
specify{ expect(subject.new(:==, 2).eval(set)).to be_false }
|
28
|
+
specify{ expect(subject.new(:==, 3).eval(set)).to be_true }
|
29
|
+
end
|
30
|
+
|
31
|
+
context "SetLogicExpr" do
|
32
|
+
subject{ Rudelo::Parsers::SetLogicTransform::SetLogicExpr }
|
33
|
+
let(:set1){ Set.new(%w{a b c}) }
|
34
|
+
let(:set2){ Set.new(%w{b c}) }
|
35
|
+
let(:set3){ Set.new(%w{b c d}) }
|
36
|
+
specify{ expect(
|
37
|
+
subject.new(set1, :proper_superset?, set2).eval
|
38
|
+
).to be_true }
|
39
|
+
specify{ expect(subject.new(set1, :proper_subset?, set2).eval).to be_false }
|
40
|
+
specify{ expect(subject.new(set3, :proper_subset?, set1).eval).to be_false }
|
41
|
+
specify{ expect(subject.new(set1, :==, set1).eval).to be_true }
|
42
|
+
end
|
43
|
+
|
44
|
+
context "SetOp" do
|
45
|
+
subject{ Rudelo::Parsers::SetLogicTransform::SetOp }
|
46
|
+
let(:set1){ Set.new(%w{a b c}) }
|
47
|
+
let(:set2){ Set.new(%w{b c}) }
|
48
|
+
let(:set3){ Set.new(%w{b c d}) }
|
49
|
+
let(:set4){ Set.new(%w{a b c d}) }
|
50
|
+
let(:set5){ Set.new(%w{a}) }
|
51
|
+
specify{ expect(
|
52
|
+
subject.new(:+, set1).eval(set3)
|
53
|
+
).to eq(set4) }
|
54
|
+
specify{ expect(
|
55
|
+
subject.new(:-, set3).eval(set4)
|
56
|
+
).to eq(set5) }
|
57
|
+
specify{ expect(
|
58
|
+
subject.new(:-, set4).eval(set3)
|
59
|
+
).to eq(empty_set) }
|
60
|
+
end
|
61
|
+
|
62
|
+
context "SetOp" do
|
63
|
+
subject{ Rudelo::Parsers::SetLogicTransform::EmptyExpr.new }
|
64
|
+
specify{ expect(subject.eval).to be_true }
|
65
|
+
specify{ expect(subject.eval(false)).to be_true }
|
66
|
+
end
|
67
|
+
|
68
|
+
context "Set#eval" do
|
69
|
+
let(:set1){ Set.new(%w{a b c}) }
|
70
|
+
specify{ expect(empty_set.eval).to eq(empty_set) }
|
71
|
+
specify{ expect(set1.eval).to eq(set1) }
|
72
|
+
end
|
73
|
+
|
74
|
+
context "MatchExpr" do
|
75
|
+
subject{ Rudelo::Parsers::SetLogicTransform::MatchExpr }
|
76
|
+
before do
|
77
|
+
@scon_full = mock('SetConstructionExpr')
|
78
|
+
@scon_full.stub(:eval).and_return(Set.new['a'])
|
79
|
+
@scon_empty = mock('SetConstructionExpr')
|
80
|
+
@scon_empty.stub(:eval).and_return(Set.new)
|
81
|
+
|
82
|
+
@slog_true = mock('SetLogicExpr')
|
83
|
+
@slog_true.stub(:eval).and_return(true)
|
84
|
+
@slog_true.stub(:set).and_return(Set.new['a'])
|
85
|
+
|
86
|
+
@slog_false = mock('SetLogicExpr')
|
87
|
+
@slog_false.stub(:eval).and_return(false)
|
88
|
+
@slog_false.stub(:set).and_return(Set.new)
|
89
|
+
|
90
|
+
@scar_one = CardinalityExpr.new(:==, 1)
|
91
|
+
@scar_two = CardinalityExpr.new(:==, 2)
|
92
|
+
end
|
93
|
+
|
94
|
+
context "when right is empty" do
|
95
|
+
context "when left is SetConstructionExpr" do
|
96
|
+
it "returns true if the result size is > 0"
|
97
|
+
it "returns false if the result size is < 1"
|
98
|
+
end
|
99
|
+
context "when left is SetLogicExpr" do
|
100
|
+
it "returns true if the result is true"
|
101
|
+
it "returns true if the result is false"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
context "when right is CardinalityExpr" do
|
105
|
+
context "when left is SetConstructionExpr" do
|
106
|
+
it "runs cardinality expression on left result"
|
107
|
+
end
|
108
|
+
context "when left is SetLogicExpr" do
|
109
|
+
it "runs cardinality expression on left set"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
context "match expressions" do
|
116
|
+
subject{ xform.apply(parser.parse(expr)) }
|
117
|
+
context "cardinality expressions alone" do
|
118
|
+
let(:set){ Set.new(%w{a b c}) }
|
119
|
+
let(:expr){ "#> 2" }
|
120
|
+
it "should transform cardinality_expressions as match_expression.right" do
|
121
|
+
expect(subject.right).to be_a_kind_of(
|
122
|
+
Rudelo::Parsers::SetLogicTransform::CardinalityExpr)
|
123
|
+
end
|
124
|
+
it "should set match_expression.left to in_set" do
|
125
|
+
expect(subject.left).to eq(in_set)
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should eval correctly" do
|
129
|
+
expect(subject.right.eval(set)
|
130
|
+
).to be_true
|
131
|
+
expect(subject.eval).to be_true
|
132
|
+
|
133
|
+
expect(
|
134
|
+
xform.apply(
|
135
|
+
parser.parse("#< 2")
|
136
|
+
).right.eval(set)
|
137
|
+
).to be_false
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
context "logic expression" do
|
142
|
+
context "alone" do
|
143
|
+
let(:expr){ "$(k z v) > $in" }
|
144
|
+
it "transforms logic expression as match_expression.left" do
|
145
|
+
expect(subject.left).to be_a_kind_of(
|
146
|
+
Rudelo::Parsers::SetLogicTransform::SetLogicExpr)
|
147
|
+
end
|
148
|
+
it "should set match_expression.right to nil" do
|
149
|
+
expect(subject.right).to be_a_kind_of(
|
150
|
+
Rudelo::Parsers::SetLogicTransform::EmptyExpr)
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
context "with cardinality" do
|
155
|
+
let(:expr){ "$(k z v) > $in #= 2" }
|
156
|
+
it "transforms logic expression as match_expression.left" do
|
157
|
+
expect(subject.left).to be_a_kind_of(
|
158
|
+
Rudelo::Parsers::SetLogicTransform::SetLogicExpr)
|
159
|
+
end
|
160
|
+
it "should set match_expression.right to nil" do
|
161
|
+
expect(subject.right).to be_a_kind_of(
|
162
|
+
Rudelo::Parsers::SetLogicTransform::CardinalityExpr)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
context "construction expression" do
|
168
|
+
context "alone" do
|
169
|
+
let(:expr){ "$(k z v) + $in" }
|
170
|
+
it "transforms construction expression as match_expression.left" do
|
171
|
+
expect(subject.left).to be_a_kind_of(
|
172
|
+
Rudelo::Parsers::SetLogicTransform::SetConstructionExpr)
|
173
|
+
end
|
174
|
+
it "should set match_expression.right to nil expr" do
|
175
|
+
expect(subject.right).to be_a_kind_of(
|
176
|
+
Rudelo::Parsers::SetLogicTransform::EmptyExpr)
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|
180
|
+
context "with cardinality" do
|
181
|
+
let(:expr){ "$(k z v) + $in #= 2" }
|
182
|
+
it "transforms construction expression as match_expression.left" do
|
183
|
+
expect(subject.left).to be_a_kind_of(
|
184
|
+
Rudelo::Parsers::SetLogicTransform::SetConstructionExpr)
|
185
|
+
end
|
186
|
+
it "should set match_expression.right to nil" do
|
187
|
+
expect(subject.right).to be_a_kind_of(
|
188
|
+
Rudelo::Parsers::SetLogicTransform::CardinalityExpr)
|
189
|
+
end
|
190
|
+
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def matching(expr, opts)
|
196
|
+
in_set = Set.new(opts[:in_set])
|
197
|
+
Rudelo::Parsers::SetLogicTransform.new(in_set).apply(
|
198
|
+
Rudelo::Parsers::SetLogicParser.new.parse(expr)
|
199
|
+
).eval
|
200
|
+
end
|
201
|
+
|
202
|
+
context "cardinality examples" do
|
203
|
+
specify{ expect(matching(
|
204
|
+
'#= 2', in_set: %w{a b})).to be_true }
|
205
|
+
specify{ expect(matching(
|
206
|
+
'#< 3', in_set: %w{a b})).to be_true }
|
207
|
+
specify{ expect(matching(
|
208
|
+
'#> 1', in_set: %w{a b})).to be_true }
|
209
|
+
specify{ expect(matching(
|
210
|
+
'#= 3', in_set: %w{a b})).to be_false }
|
211
|
+
specify{ expect(matching(
|
212
|
+
'#> 3', in_set: %w{a b})).to be_false }
|
213
|
+
specify{ expect(matching(
|
214
|
+
'#< 1', in_set: %w{a b})).to be_false }
|
215
|
+
end
|
216
|
+
|
217
|
+
context "construction examples" do
|
218
|
+
specify{ expect(matching(
|
219
|
+
'$(a b c) & $in #= 2', in_set: %w{a b d})).to be_true }
|
220
|
+
specify{ expect(matching(
|
221
|
+
'$(a b c) & $in', in_set: %w{a b d})).to be_true }
|
222
|
+
specify{ expect(matching(
|
223
|
+
'$(a b c) & $in', in_set: %w{d e f})).to be_false }
|
224
|
+
specify{ expect(matching(
|
225
|
+
'$(a b c) & $in #= 2', in_set: %w{a k d})).to be_false }
|
226
|
+
specify{ expect(matching(
|
227
|
+
'$(a b c) + $in + $(e) #= 5', in_set: %w{b c d})).to be_true }
|
228
|
+
end
|
229
|
+
|
230
|
+
context "explicit set examples" do
|
231
|
+
specify{ expect(matching(
|
232
|
+
'$(a b c)', in_set: %w{a b})).to be_true }
|
233
|
+
specify{ expect(matching(
|
234
|
+
'$(a b c)', in_set: %w{a k d})).to be_false }
|
235
|
+
end
|
236
|
+
|
237
|
+
context "logic examples" do
|
238
|
+
specify{ expect(matching(
|
239
|
+
'$(a b c) > $in', in_set: %w{a b})).to be_true }
|
240
|
+
specify{ expect(matching(
|
241
|
+
'$(a b c) > $in #=2', in_set: %w{a b})).to be_true }
|
242
|
+
specify{ expect(matching(
|
243
|
+
'$(a b c) > $in #=1', in_set: %w{a})).to be_true }
|
244
|
+
specify{ expect(matching(
|
245
|
+
'$(a b c) ^ $in < $(a d k f)', in_set: %w{b c d})).to be_true }
|
246
|
+
specify{ expect(matching(
|
247
|
+
'$(a b c) ^ $in < $(a e k f)', in_set: %w{b c d})).to be_false }
|
248
|
+
end
|
249
|
+
|
250
|
+
context "using transform with multiple in-set values" do
|
251
|
+
it "allows re-using a transform" do
|
252
|
+
abc = Set.new(%w{a b c})
|
253
|
+
efg = Set.new(%w{e f g})
|
254
|
+
expr = '$in same-as $(a b c)'
|
255
|
+
|
256
|
+
transform = Rudelo::Parsers::SetLogicTransform.new(abc)
|
257
|
+
ast = transform.apply(parser.parse(expr))
|
258
|
+
|
259
|
+
expect(ast.eval).to be_true
|
260
|
+
|
261
|
+
expect(ast.eval(efg)).to be_false
|
262
|
+
|
263
|
+
expect(ast.eval(abc)).to be_true
|
264
|
+
end
|
265
|
+
|
266
|
+
end
|
267
|
+
|
268
|
+
end
|
269
|
+
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
require 'rudelo/parsers/set_value_parser'
|
4
|
+
|
5
|
+
describe "Rudelo::Parsers::SetValueParser" do
|
6
|
+
let(:parser) { Rudelo::Parsers::SetValueParser.new }
|
7
|
+
context "set parsing" do
|
8
|
+
it "parses bare sets" do
|
9
|
+
expect(parser).to parse(%Q{bob, mary}, trace: true).as({
|
10
|
+
element_list: [
|
11
|
+
{element: "bob"},
|
12
|
+
{element: "mary"}
|
13
|
+
]
|
14
|
+
})
|
15
|
+
expect(parser).to parse(%Q{bob}, trace: true).as({
|
16
|
+
element_list:
|
17
|
+
{element: "bob"}
|
18
|
+
|
19
|
+
})
|
20
|
+
|
21
|
+
expect(parser).to parse(%Q{bob, mary, jeff}, trace: true).as({
|
22
|
+
element_list: [
|
23
|
+
{element: "bob"},
|
24
|
+
{element: "mary"},
|
25
|
+
{element: "jeff"}
|
26
|
+
]
|
27
|
+
})
|
28
|
+
|
29
|
+
expect(parser).to parse(%Q{bob mary}, trace: true).as({
|
30
|
+
element_list: [
|
31
|
+
{element: "bob"},
|
32
|
+
{element: "mary"}
|
33
|
+
]
|
34
|
+
})
|
35
|
+
|
36
|
+
expect(parser).to parse(%Q{bob mary, ralph}, trace: true).as({
|
37
|
+
element_list: [
|
38
|
+
{element: "bob"},
|
39
|
+
{element: "mary"},
|
40
|
+
{element: "ralph"}
|
41
|
+
]
|
42
|
+
})
|
43
|
+
|
44
|
+
expect(parser).to parse(%Q{"bob mary", ralph}, trace: true).as({
|
45
|
+
element_list: [
|
46
|
+
{element: "bob mary"},
|
47
|
+
{element: "ralph"}
|
48
|
+
]
|
49
|
+
})
|
50
|
+
|
51
|
+
expect(parser).to parse(%Q{"bob, mary", ralph}, trace: true).as({
|
52
|
+
element_list: [
|
53
|
+
{element: "bob, mary"},
|
54
|
+
{element: "ralph"}
|
55
|
+
]
|
56
|
+
})
|
57
|
+
end
|
58
|
+
|
59
|
+
it "parses explicit sets" do
|
60
|
+
expect(parser).to parse(%Q{$(bob, mary)}, trace: true).as({
|
61
|
+
element_list: [
|
62
|
+
{element: "bob"},
|
63
|
+
{element: "mary"}
|
64
|
+
]
|
65
|
+
})
|
66
|
+
expect(parser).to parse(%Q{$("bob", mary)}, trace: true).as({
|
67
|
+
element_list: [
|
68
|
+
{element: "bob"},
|
69
|
+
{element: "mary"}
|
70
|
+
]
|
71
|
+
})
|
72
|
+
expect(parser).to parse(%Q{$("bob)dad", mary)}, trace: true).as({
|
73
|
+
element_list: [
|
74
|
+
{element: "bob)dad"},
|
75
|
+
{element: "mary"}
|
76
|
+
]
|
77
|
+
})
|
78
|
+
expect(parser).to parse(%Q{$("bob", mary jeff)}, trace: true).as({
|
79
|
+
element_list: [
|
80
|
+
{element: "bob"},
|
81
|
+
{element: "mary"},
|
82
|
+
{element: "jeff"},
|
83
|
+
]
|
84
|
+
})
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
require 'rudelo/parsers/set_value_parser'
|
4
|
+
require 'rudelo/parsers/set_value_transform'
|
5
|
+
|
6
|
+
describe "Rudelo::Parsers::SetValueTransform" do
|
7
|
+
let(:parser) { Rudelo::Parsers::SetValueParser.new }
|
8
|
+
let(:xform) { Rudelo::Parsers::SetValueTransform.new }
|
9
|
+
|
10
|
+
it "transforms an element to a string" do
|
11
|
+
expect(xform.apply(:element => "bob")).to eq("bob")
|
12
|
+
end
|
13
|
+
|
14
|
+
it "transforms a set to a Set" do
|
15
|
+
expect(xform.apply({:element_list=>[{:element=>"bob"}, {:element=>"mary"}]})).to eq(Set['mary', 'bob'])
|
16
|
+
end
|
17
|
+
|
18
|
+
it "works on a single element" do
|
19
|
+
expect(xform.apply(parser.parse('bob'))).to eq(Set['bob'])
|
20
|
+
end
|
21
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
|
2
|
+
require 'rubygems'
|
3
|
+
require 'bundler/setup'
|
4
|
+
|
5
|
+
require 'rudelo'
|
6
|
+
|
7
|
+
RSpec.configure do |config|
|
8
|
+
config.expect_with :rspec do |c|
|
9
|
+
c.syntax = :expect
|
10
|
+
end
|
11
|
+
|
12
|
+
config.order = 'random'
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
require "parslet"
|
17
|
+
require "parslet/rig/rspec"
|