predicator 1.1.0 → 1.2.0
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 +4 -4
- data/.rubocop.yml +46 -0
- data/HISTORY.md +8 -0
- data/README.md +30 -8
- data/lib/predicator/ast.rb +71 -19
- data/lib/predicator/evaluator.rb +55 -14
- data/lib/predicator/lexer.rex +18 -0
- data/lib/predicator/lexer.rex.rb +27 -0
- data/lib/predicator/parser.rb +233 -97
- data/lib/predicator/parser.y +54 -17
- data/lib/predicator/version.rb +1 -1
- data/lib/predicator/visitors/dot.rb +21 -8
- data/lib/predicator/visitors/instructions.rb +72 -6
- data/lib/predicator/visitors/string.rb +16 -0
- data/lib/predicator/visitors/visitor.rb +71 -19
- data/predicator.gemspec +1 -0
- metadata +18 -3
data/lib/predicator/version.rb
CHANGED
@@ -23,20 +23,13 @@ digraph parse_tree {
|
|
23
23
|
|
24
24
|
private
|
25
25
|
|
26
|
-
def
|
26
|
+
def visit_children node
|
27
27
|
node.children.each do |c|
|
28
28
|
@edges << "#{node.object_id} -> #{c.object_id};"
|
29
29
|
end
|
30
30
|
super
|
31
31
|
end
|
32
32
|
|
33
|
-
alias_method :ternary, :binary
|
34
|
-
|
35
|
-
def unary node
|
36
|
-
@edges << "#{node.object_id} -> #{node.left.object_id};"
|
37
|
-
super
|
38
|
-
end
|
39
|
-
|
40
33
|
def visit_EQ node
|
41
34
|
@nodes << "#{node.object_id} [label=\"=\"];"
|
42
35
|
super
|
@@ -77,6 +70,26 @@ digraph parse_tree {
|
|
77
70
|
super
|
78
71
|
end
|
79
72
|
|
73
|
+
def visit_DATEAGO node
|
74
|
+
@nodes << "#{node.object_id} [label=\"ago\"];"
|
75
|
+
super
|
76
|
+
end
|
77
|
+
|
78
|
+
def visit_DATEFROMNOW node
|
79
|
+
@nodes << "#{node.object_id} [label=\"from now\"];"
|
80
|
+
super
|
81
|
+
end
|
82
|
+
|
83
|
+
def visit_STRSTARTSWITH node
|
84
|
+
@nodes << "#{node.object_id} [label=\"starts with\"];"
|
85
|
+
super
|
86
|
+
end
|
87
|
+
|
88
|
+
def visit_STRENDSWITH node
|
89
|
+
@nodes << "#{node.object_id} [label=\"ends with\"];"
|
90
|
+
super
|
91
|
+
end
|
92
|
+
|
80
93
|
def visit_STRING node
|
81
94
|
value = node.left
|
82
95
|
@nodes << "#{node.object_id} [label=\"'#{value}'\"];"
|
@@ -37,35 +37,62 @@ module Predicator
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def visit_EQ node
|
40
|
-
|
40
|
+
visit node.left
|
41
|
+
add_typecast_to_instructions node
|
42
|
+
visit node.right
|
41
43
|
@instructions.push ["compare", "EQ"]
|
42
44
|
end
|
43
45
|
|
44
46
|
def visit_GT node
|
45
|
-
|
47
|
+
visit node.left
|
48
|
+
add_typecast_to_instructions node
|
49
|
+
visit node.right
|
46
50
|
@instructions.push ["compare", "GT"]
|
47
51
|
end
|
48
52
|
|
49
53
|
def visit_LT node
|
50
|
-
|
54
|
+
visit node.left
|
55
|
+
add_typecast_to_instructions node
|
56
|
+
visit node.right
|
51
57
|
@instructions.push ["compare", "LT"]
|
52
58
|
end
|
53
59
|
|
54
60
|
def visit_BETWEEN node
|
55
|
-
|
61
|
+
visit node.left
|
62
|
+
add_typecast_to_instructions node
|
63
|
+
visit node.middle
|
64
|
+
visit node.right
|
56
65
|
@instructions.push ["compare", "BETWEEN"]
|
57
66
|
end
|
58
67
|
|
59
68
|
def visit_IN node
|
60
|
-
|
69
|
+
visit node.left
|
70
|
+
add_typecast_to_instructions node
|
71
|
+
visit node.right
|
61
72
|
@instructions.push ["compare", "IN"]
|
62
73
|
end
|
63
74
|
|
64
75
|
def visit_NOTIN node
|
65
|
-
|
76
|
+
visit node.left
|
77
|
+
add_typecast_to_instructions node
|
78
|
+
visit node.right
|
66
79
|
@instructions.push ["compare", "NOTIN"]
|
67
80
|
end
|
68
81
|
|
82
|
+
def visit_STRSTARTSWITH node
|
83
|
+
visit node.left
|
84
|
+
add_typecast_to_instructions node
|
85
|
+
visit node.right
|
86
|
+
@instructions.push ["compare", "STARTSWITH"]
|
87
|
+
end
|
88
|
+
|
89
|
+
def visit_STRENDSWITH node
|
90
|
+
visit node.left
|
91
|
+
add_typecast_to_instructions node
|
92
|
+
visit node.right
|
93
|
+
@instructions.push ["compare", "ENDSWITH"]
|
94
|
+
end
|
95
|
+
|
69
96
|
def visit_ARRAY node
|
70
97
|
contents = node.left.map{ |item| item.left }
|
71
98
|
@instructions.push ["array", contents]
|
@@ -80,10 +107,49 @@ module Predicator
|
|
80
107
|
@instructions.push ["to_bool"]
|
81
108
|
end
|
82
109
|
|
110
|
+
def visit_DATE node
|
111
|
+
@instructions.push ["lit", node.symbol]
|
112
|
+
@instructions.push ["to_date"]
|
113
|
+
end
|
114
|
+
|
115
|
+
def visit_DATEAGO node
|
116
|
+
visit node.left
|
117
|
+
@instructions.push ["date_ago"]
|
118
|
+
end
|
119
|
+
|
120
|
+
def visit_DATEFROMNOW node
|
121
|
+
visit node.left
|
122
|
+
@instructions.push ["date_from_now"]
|
123
|
+
end
|
124
|
+
|
125
|
+
def visit_DURATION node
|
126
|
+
as_seconds = node.symbol.to_i * 24 * 60 * 60
|
127
|
+
@instructions.push ["lit", as_seconds]
|
128
|
+
end
|
129
|
+
|
130
|
+
def visit_BLANK node
|
131
|
+
visit node.left
|
132
|
+
@instructions.push ["blank"]
|
133
|
+
end
|
134
|
+
|
135
|
+
def visit_PRESENT node
|
136
|
+
visit node.left
|
137
|
+
@instructions.push ["present"]
|
138
|
+
end
|
139
|
+
|
83
140
|
def terminal node
|
84
141
|
@instructions.push ["lit", node.symbol]
|
85
142
|
end
|
86
143
|
|
144
|
+
def add_typecast_to_instructions node
|
145
|
+
type = case node.right.type.to_s
|
146
|
+
when /INT/ then "to_int"
|
147
|
+
when /STR/ then "to_str"
|
148
|
+
when /DATE/ then "to_date"
|
149
|
+
end
|
150
|
+
@instructions.push [type]
|
151
|
+
end
|
152
|
+
|
87
153
|
def jump_instruction condition, node
|
88
154
|
["j#{condition}", node.object_id.to_s]
|
89
155
|
end
|
@@ -55,6 +55,22 @@ module Predicator
|
|
55
55
|
def visit_NOTIN node
|
56
56
|
[visit(node.left), " not in ", visit(node.right)].join
|
57
57
|
end
|
58
|
+
|
59
|
+
def visit_STRSTARTSWITH node
|
60
|
+
[visit(node.left), " starts with ", visit(node.right)].join
|
61
|
+
end
|
62
|
+
|
63
|
+
def visit_STRENDSWITH node
|
64
|
+
[visit(node.left), " ends with ", visit(node.right)].join
|
65
|
+
end
|
66
|
+
|
67
|
+
def visit_DATEAGO node
|
68
|
+
visit(node.left) + " ago"
|
69
|
+
end
|
70
|
+
|
71
|
+
def visit_DATEFROMNOW node
|
72
|
+
visit(node.left) + " from now"
|
73
|
+
end
|
58
74
|
end
|
59
75
|
end
|
60
76
|
end
|
@@ -19,30 +19,82 @@ module Predicator
|
|
19
19
|
node.children.each {|child| visit child}
|
20
20
|
end
|
21
21
|
|
22
|
-
def visit_NOT node; visit_children node; end
|
23
|
-
def visit_GROUP node; visit_children node; end
|
24
|
-
def visit_BOOL node; visit_children node; end
|
25
|
-
|
26
|
-
def visit_EQ node; visit_children node; end
|
27
|
-
def visit_GT node; visit_children node; end
|
28
|
-
def visit_LT node; visit_children node; end
|
29
|
-
def visit_AND node; visit_children node; end
|
30
|
-
def visit_OR node; visit_children node; end
|
31
|
-
def visit_IN node; visit_children node; end
|
32
|
-
def visit_NOTIN node; visit_children node; end
|
33
|
-
|
34
|
-
def visit_BETWEEN node; visit_children node; end
|
35
|
-
|
36
22
|
def terminal node; end
|
37
|
-
def visit_TRUE node; terminal node; end
|
38
|
-
def visit_FALSE node; terminal node; end
|
39
|
-
def visit_INTEGER node; terminal node; end
|
40
|
-
def visit_STRING node; terminal node; end
|
41
|
-
def visit_VARIABLE node; terminal node; end
|
42
23
|
|
43
24
|
def visit_ARRAY node
|
44
25
|
node.left.each{ |item| visit item }
|
45
26
|
end
|
27
|
+
|
28
|
+
visit_children_methods = %w(
|
29
|
+
visit_EQ visit_GT visit_LT
|
30
|
+
visit_NOT visit_GROUP visit_BOOL
|
31
|
+
visit_IN visit_NOTIN visit_BETWEEN
|
32
|
+
visit_DATEAGO visit_DATEFROMNOW
|
33
|
+
visit_AND visit_OR
|
34
|
+
visit_STRSTARTSWITH visit_STRENDSWITH
|
35
|
+
)
|
36
|
+
visit_children_methods.each do |method_name|
|
37
|
+
define_method method_name do |node|
|
38
|
+
visit_children node
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
%w( visit_INTEQ visit_STREQ visit_DATEQ ).each do |method_name|
|
43
|
+
define_method method_name do |node|
|
44
|
+
visit_EQ node
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
%w( visit_INTGT visit_STRGT visit_DATGT ).each do |method_name|
|
49
|
+
define_method method_name do |node|
|
50
|
+
visit_GT node
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
%w( visit_INTLT visit_STRLT visit_DATLT ).each do |method_name|
|
55
|
+
define_method method_name do |node|
|
56
|
+
visit_LT node
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
%w( visit_INTIN visit_STRIN ).each do |method_name|
|
61
|
+
define_method method_name do |node|
|
62
|
+
visit_IN node
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
%w( visit_INTNOTIN visit_STRNOTIN ).each do |method_name|
|
67
|
+
define_method method_name do |node|
|
68
|
+
visit_NOTIN node
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
%w( visit_INTBETWEEN visit_DATBETWEEN ).each do |method_name|
|
73
|
+
define_method method_name do |node|
|
74
|
+
visit_BETWEEN node
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
terminal_methods = %w(
|
79
|
+
visit_TRUE visit_FALSE
|
80
|
+
visit_DATE visit_DURATION
|
81
|
+
visit_INTEGER visit_STRING visit_VARIABLE
|
82
|
+
visit_BLANK visit_PRESENT
|
83
|
+
)
|
84
|
+
terminal_methods.each do |method_name|
|
85
|
+
define_method method_name do |node|
|
86
|
+
terminal node
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
array_methods = %w(
|
91
|
+
visit_INTARRAY visit_STRARRAY
|
92
|
+
)
|
93
|
+
array_methods.each do |method_name|
|
94
|
+
define_method method_name do |node|
|
95
|
+
visit_ARRAY node
|
96
|
+
end
|
97
|
+
end
|
46
98
|
end
|
47
99
|
end
|
48
100
|
end
|
data/predicator.gemspec
CHANGED
@@ -21,6 +21,7 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.add_development_dependency "bundler"
|
22
22
|
spec.add_development_dependency "coveralls"
|
23
23
|
spec.add_development_dependency "minitest", "= 5.4.2"
|
24
|
+
spec.add_development_dependency "minitest-focus"
|
24
25
|
spec.add_development_dependency "oedipus_lex"
|
25
26
|
spec.add_development_dependency "pry-nav"
|
26
27
|
spec.add_development_dependency "racc"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: predicator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- JohnnyT
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-09-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - '='
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: 5.4.2
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: minitest-focus
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: oedipus_lex
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -116,6 +130,7 @@ extensions: []
|
|
116
130
|
extra_rdoc_files: []
|
117
131
|
files:
|
118
132
|
- ".gitignore"
|
133
|
+
- ".rubocop.yml"
|
119
134
|
- ".travis.yml"
|
120
135
|
- CODE_OF_CONDUCT.md
|
121
136
|
- Gemfile
|
@@ -159,7 +174,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
159
174
|
version: '0'
|
160
175
|
requirements: []
|
161
176
|
rubyforge_project:
|
162
|
-
rubygems_version: 2.
|
177
|
+
rubygems_version: 2.6.8
|
163
178
|
signing_key:
|
164
179
|
specification_version: 4
|
165
180
|
summary: Predicate Engine
|