predicator 1.2.1 → 2.0.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.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +42 -0
  3. data/{LICENSE.txt → LICENSE} +1 -1
  4. data/README.md +322 -46
  5. data/lib/predicator/ast.rb +74 -187
  6. data/lib/predicator/boundary.rb +237 -0
  7. data/lib/predicator/civil.rb +112 -0
  8. data/lib/predicator/duration_text.rb +92 -0
  9. data/lib/predicator/emitter/chains.rb +62 -0
  10. data/lib/predicator/emitter/statements.rb +86 -0
  11. data/lib/predicator/emitter.rb +187 -0
  12. data/lib/predicator/errors.rb +140 -0
  13. data/lib/predicator/evaluator/access.rb +108 -0
  14. data/lib/predicator/evaluator/arithmetic.rb +132 -0
  15. data/lib/predicator/evaluator/calls.rb +129 -0
  16. data/lib/predicator/evaluator/casts.rb +158 -0
  17. data/lib/predicator/evaluator/chronology.rb +88 -0
  18. data/lib/predicator/evaluator/compare.rb +158 -0
  19. data/lib/predicator/evaluator/json_functions.rb +167 -0
  20. data/lib/predicator/evaluator/json_scan.rb +303 -0
  21. data/lib/predicator/evaluator/library.rb +127 -0
  22. data/lib/predicator/evaluator/math_functions.rb +72 -0
  23. data/lib/predicator/evaluator/order.rb +120 -0
  24. data/lib/predicator/evaluator/rich_types.rb +146 -0
  25. data/lib/predicator/evaluator/statements.rb +151 -0
  26. data/lib/predicator/evaluator.rb +391 -117
  27. data/lib/predicator/float_text.rb +94 -0
  28. data/lib/predicator/iso_text.rb +99 -0
  29. data/lib/predicator/lexer/literals.rb +115 -0
  30. data/lib/predicator/lexer/numbers.rb +91 -0
  31. data/lib/predicator/lexer.rb +194 -0
  32. data/lib/predicator/parser/durations.rb +108 -0
  33. data/lib/predicator/parser/operators.rb +86 -0
  34. data/lib/predicator/parser/postfix.rb +57 -0
  35. data/lib/predicator/parser/primaries.rb +122 -0
  36. data/lib/predicator/parser/statements.rb +114 -0
  37. data/lib/predicator/parser/token_text.rb +52 -0
  38. data/lib/predicator/parser.rb +217 -438
  39. data/lib/predicator/result.rb +46 -0
  40. data/lib/predicator/tagged/reader.rb +139 -0
  41. data/lib/predicator/tagged/writer.rb +106 -0
  42. data/lib/predicator/tagged.rb +134 -0
  43. data/lib/predicator/values.rb +147 -0
  44. data/lib/predicator/version.rb +4 -1
  45. data/lib/predicator.rb +384 -14
  46. metadata +53 -147
  47. data/.gitignore +0 -11
  48. data/.rubocop.yml +0 -46
  49. data/.travis.yml +0 -5
  50. data/CODE_OF_CONDUCT.md +0 -49
  51. data/Gemfile +0 -4
  52. data/HISTORY.md +0 -51
  53. data/Rakefile +0 -24
  54. data/lib/predicator/context.rb +0 -18
  55. data/lib/predicator/lexer.rex +0 -69
  56. data/lib/predicator/lexer.rex.rb +0 -187
  57. data/lib/predicator/parser.y +0 -120
  58. data/lib/predicator/visitors/dot.rb +0 -113
  59. data/lib/predicator/visitors/each.rb +0 -16
  60. data/lib/predicator/visitors/instructions.rb +0 -183
  61. data/lib/predicator/visitors/string.rb +0 -76
  62. data/lib/predicator/visitors/visitor.rb +0 -100
  63. data/lib/predicator/visitors.rb +0 -5
  64. data/predicator.gemspec +0 -34
@@ -1,16 +0,0 @@
1
- module Predicator
2
- module Visitors
3
- class Each < Visitor
4
- attr_reader :block
5
-
6
- def initialize block
7
- @block = block
8
- end
9
-
10
- def visit node
11
- super
12
- block.call node
13
- end
14
- end
15
- end
16
- end
@@ -1,183 +0,0 @@
1
- module Predicator
2
- module Visitors
3
- class Instructions < Visitor
4
- attr_reader :instructions
5
-
6
- def initialize instructions=[]
7
- @instructions = instructions
8
- @label_locations = {}
9
- end
10
-
11
- def accept ast
12
- super
13
- update_jumps
14
- remove_labels
15
- @instructions
16
- end
17
-
18
- private
19
-
20
- def visit_AND node
21
- visit node.left
22
- @instructions.push jump_instruction("false", node)
23
- visit node.right
24
- @instructions.push label_instruction(node)
25
- end
26
-
27
- def visit_OR node
28
- visit node.left
29
- @instructions.push jump_instruction("true", node)
30
- visit node.right
31
- @instructions.push label_instruction(node)
32
- end
33
-
34
- def visit_NOT node
35
- super
36
- @instructions.push ["not"]
37
- end
38
-
39
- def visit_EQ node
40
- visit node.left
41
- add_typecast_to_instructions node
42
- visit node.right
43
- @instructions.push ["compare", "EQ"]
44
- end
45
-
46
- def visit_GT node
47
- visit node.left
48
- add_typecast_to_instructions node
49
- visit node.right
50
- @instructions.push ["compare", "GT"]
51
- end
52
-
53
- def visit_LT node
54
- visit node.left
55
- add_typecast_to_instructions node
56
- visit node.right
57
- @instructions.push ["compare", "LT"]
58
- end
59
-
60
- def visit_BETWEEN node
61
- visit node.left
62
- add_typecast_to_instructions node
63
- visit node.middle
64
- visit node.right
65
- @instructions.push ["compare", "BETWEEN"]
66
- end
67
-
68
- def visit_IN node
69
- visit node.left
70
- add_typecast_to_instructions node
71
- visit node.right
72
- @instructions.push ["compare", "IN"]
73
- end
74
-
75
- def visit_NOTIN node
76
- visit node.left
77
- add_typecast_to_instructions node
78
- visit node.right
79
- @instructions.push ["compare", "NOTIN"]
80
- end
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
-
96
- def visit_ARRAY node
97
- contents = node.left.map{ |item| item.left }
98
- @instructions.push ["array", contents]
99
- end
100
-
101
- def visit_VARIABLE node
102
- @instructions.push ["load", node.symbol]
103
- end
104
-
105
- def visit_BOOL node
106
- super
107
- @instructions.push ["to_bool"]
108
- end
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
-
140
- def terminal node
141
- @instructions.push ["lit", node.symbol]
142
- end
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
-
153
- def jump_instruction condition, node
154
- ["j#{condition}", node.object_id.to_s]
155
- end
156
-
157
- def label_instruction node
158
- label = node.object_id.to_s
159
- @label_locations[label] = @instructions.size
160
- ["label", label]
161
- end
162
-
163
- def update_jumps
164
- @instructions.each_with_index do |inst, idx|
165
- next unless inst.first =~ /^j/
166
- label = inst.pop
167
- offset = calculate_offset idx, @label_locations[label]
168
- inst.push offset
169
- end
170
- end
171
-
172
- def calculate_offset from_idx, to_idx
173
- offset = to_idx - from_idx
174
- num_labels = @instructions[from_idx...to_idx].count{ |i| i.first == "label" }
175
- offset - num_labels
176
- end
177
-
178
- def remove_labels
179
- @instructions.delete_if{ |inst| inst.first == "label" }
180
- end
181
- end
182
- end
183
- end
@@ -1,76 +0,0 @@
1
- module Predicator
2
- module Visitors
3
- class String < Visitor
4
- private
5
-
6
- def terminal node
7
- node.left.to_s
8
- end
9
-
10
- def visit_STRING node
11
- "'#{node.left}'"
12
- end
13
-
14
- def visit_ARRAY node
15
- contents = node.left.map{ |item| visit item }.join(", ")
16
- "[#{contents}]"
17
- end
18
-
19
- def visit_NOT node
20
- "!#{visit node.left}"
21
- end
22
-
23
- def visit_GROUP node
24
- "(#{visit node.left})"
25
- end
26
-
27
- def visit_EQ node
28
- [visit(node.left), " = ", visit(node.right)].join
29
- end
30
-
31
- def visit_GT node
32
- [visit(node.left), " > ", visit(node.right)].join
33
- end
34
-
35
- def visit_LT node
36
- [visit(node.left), " < ", visit(node.right)].join
37
- end
38
-
39
- def visit_AND node
40
- [visit(node.left), " and ", visit(node.right)].join
41
- end
42
-
43
- def visit_OR node
44
- [visit(node.left), " or ", visit(node.right)].join
45
- end
46
-
47
- def visit_BETWEEN node
48
- [visit(node.left), " between ", visit(node.middle), " and ", visit(node.right)].join
49
- end
50
-
51
- def visit_IN node
52
- [visit(node.left), " in ", visit(node.right)].join
53
- end
54
-
55
- def visit_NOTIN node
56
- [visit(node.left), " not in ", visit(node.right)].join
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
74
- end
75
- end
76
- end
@@ -1,100 +0,0 @@
1
- module Predicator
2
- module Visitors
3
- class Visitor
4
- DISPATCH_CACHE = Hash.new { |h,k|
5
- h[k] = "visit_#{k}"
6
- }
7
-
8
- def accept node
9
- visit node
10
- end
11
-
12
- private
13
-
14
- def visit node
15
- send DISPATCH_CACHE[node.type], node
16
- end
17
-
18
- def visit_children node
19
- node.children.each {|child| visit child}
20
- end
21
-
22
- def terminal node; end
23
-
24
- def visit_ARRAY node
25
- node.left.each{ |item| visit item }
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
98
- end
99
- end
100
- end
@@ -1,5 +0,0 @@
1
- require "predicator/visitors/visitor"
2
- require "predicator/visitors/each"
3
- require "predicator/visitors/dot"
4
- require "predicator/visitors/string"
5
- require "predicator/visitors/instructions"
data/predicator.gemspec DELETED
@@ -1,34 +0,0 @@
1
- # coding: utf-8
2
- lib = File.expand_path "../lib", __FILE__
3
- $LOAD_PATH.unshift lib unless $LOAD_PATH.include? lib
4
- require "predicator/version"
5
-
6
- Gem::Specification.new do |spec|
7
- spec.name = "predicator"
8
- spec.version = Predicator::VERSION
9
- spec.authors = ["JohnnyT"]
10
- spec.email = ["ubergeek3141@gmail.com"]
11
-
12
- spec.summary = %q{A secure, non-evaling condition (boolean predicate) engine for end users}
13
- spec.homepage = "https://github.com/riddler/predicator/tree/master/impl/rb"
14
- spec.license = "MIT"
15
-
16
- spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(bin|test|spec|features)/}) }
17
- spec.bindir = "exe"
18
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename f }
19
- spec.require_paths = ["lib"]
20
-
21
- spec.metadata["allowed_push_host"] = "https://rubygems.org"
22
- spec.metadata["changelog_uri"] = "https://github.com/riddler/predicator/blob/master/impl/rb/HISTORY.md"
23
- spec.metadata["source_code_uri"] = "https://github.com/riddler/predicator/tree/master/impl/rb"
24
- spec.metadata["bug_tracker_uri"] = "https://github.com/riddler/predicator/issues"
25
-
26
- spec.add_development_dependency "bundler"
27
- spec.add_development_dependency "coveralls"
28
- spec.add_development_dependency "minitest", "= 5.4.2"
29
- spec.add_development_dependency "minitest-focus"
30
- spec.add_development_dependency "oedipus_lex"
31
- spec.add_development_dependency "pry-nav"
32
- spec.add_development_dependency "racc"
33
- spec.add_development_dependency "rake"
34
- end