predicator 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|