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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +42 -0
- data/{LICENSE.txt → LICENSE} +1 -1
- data/README.md +322 -46
- data/lib/predicator/ast.rb +74 -187
- data/lib/predicator/boundary.rb +237 -0
- data/lib/predicator/civil.rb +112 -0
- data/lib/predicator/duration_text.rb +92 -0
- data/lib/predicator/emitter/chains.rb +62 -0
- data/lib/predicator/emitter/statements.rb +86 -0
- data/lib/predicator/emitter.rb +187 -0
- data/lib/predicator/errors.rb +140 -0
- data/lib/predicator/evaluator/access.rb +108 -0
- data/lib/predicator/evaluator/arithmetic.rb +132 -0
- data/lib/predicator/evaluator/calls.rb +129 -0
- data/lib/predicator/evaluator/casts.rb +158 -0
- data/lib/predicator/evaluator/chronology.rb +88 -0
- data/lib/predicator/evaluator/compare.rb +158 -0
- data/lib/predicator/evaluator/json_functions.rb +167 -0
- data/lib/predicator/evaluator/json_scan.rb +303 -0
- data/lib/predicator/evaluator/library.rb +127 -0
- data/lib/predicator/evaluator/math_functions.rb +72 -0
- data/lib/predicator/evaluator/order.rb +120 -0
- data/lib/predicator/evaluator/rich_types.rb +146 -0
- data/lib/predicator/evaluator/statements.rb +151 -0
- data/lib/predicator/evaluator.rb +391 -117
- data/lib/predicator/float_text.rb +94 -0
- data/lib/predicator/iso_text.rb +99 -0
- data/lib/predicator/lexer/literals.rb +115 -0
- data/lib/predicator/lexer/numbers.rb +91 -0
- data/lib/predicator/lexer.rb +194 -0
- data/lib/predicator/parser/durations.rb +108 -0
- data/lib/predicator/parser/operators.rb +86 -0
- data/lib/predicator/parser/postfix.rb +57 -0
- data/lib/predicator/parser/primaries.rb +122 -0
- data/lib/predicator/parser/statements.rb +114 -0
- data/lib/predicator/parser/token_text.rb +52 -0
- data/lib/predicator/parser.rb +217 -438
- data/lib/predicator/result.rb +46 -0
- data/lib/predicator/tagged/reader.rb +139 -0
- data/lib/predicator/tagged/writer.rb +106 -0
- data/lib/predicator/tagged.rb +134 -0
- data/lib/predicator/values.rb +147 -0
- data/lib/predicator/version.rb +4 -1
- data/lib/predicator.rb +384 -14
- metadata +53 -147
- data/.gitignore +0 -11
- data/.rubocop.yml +0 -46
- data/.travis.yml +0 -5
- data/CODE_OF_CONDUCT.md +0 -49
- data/Gemfile +0 -4
- data/HISTORY.md +0 -51
- data/Rakefile +0 -24
- data/lib/predicator/context.rb +0 -18
- data/lib/predicator/lexer.rex +0 -69
- data/lib/predicator/lexer.rex.rb +0 -187
- data/lib/predicator/parser.y +0 -120
- data/lib/predicator/visitors/dot.rb +0 -113
- data/lib/predicator/visitors/each.rb +0 -16
- data/lib/predicator/visitors/instructions.rb +0 -183
- data/lib/predicator/visitors/string.rb +0 -76
- data/lib/predicator/visitors/visitor.rb +0 -100
- data/lib/predicator/visitors.rb +0 -5
- data/predicator.gemspec +0 -34
data/lib/predicator/parser.rb
CHANGED
|
@@ -1,442 +1,221 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "values"
|
|
4
|
+
require_relative "errors"
|
|
5
|
+
require_relative "float_text"
|
|
6
|
+
require_relative "duration_text"
|
|
7
|
+
require_relative "lexer"
|
|
8
|
+
require_relative "ast"
|
|
9
|
+
require_relative "parser/token_text"
|
|
10
|
+
require_relative "parser/operators"
|
|
11
|
+
require_relative "parser/postfix"
|
|
12
|
+
require_relative "parser/primaries"
|
|
13
|
+
require_relative "parser/durations"
|
|
14
|
+
require_relative "parser/statements"
|
|
6
15
|
|
|
7
|
-
require 'racc/parser.rb'
|
|
8
|
-
|
|
9
|
-
require "predicator/lexer.rex"
|
|
10
|
-
require "predicator/visitors"
|
|
11
|
-
require "predicator/ast"
|
|
12
16
|
module Predicator
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
17
|
+
# The compiler's second stage: the token stream the {Lexer} answers in,
|
|
18
|
+
# the reference's syntax tree ({Ast}) out, or the one refusal that stopped
|
|
19
|
+
# it. It is a recursive descent over the reference's grammar, with its
|
|
20
|
+
# precedence, lowest first:
|
|
21
|
+
#
|
|
22
|
+
# program -> statement ( ";" statement )* ";"?
|
|
23
|
+
# statement -> if | while | location "=" expression | expression
|
|
24
|
+
# expression -> logical_or
|
|
25
|
+
# logical_or -> logical_and ( ( "OR" | "||" ) logical_and )*
|
|
26
|
+
# logical_and -> logical_not ( ( "AND" | "&&" ) logical_not )*
|
|
27
|
+
# logical_not -> ( "NOT" | "!" ) logical_not | comparison
|
|
28
|
+
# comparison -> addition ( comparison_op | "in" | "contains" ) addition )?
|
|
29
|
+
# addition -> multiplication ( ( "+" | "-" ) multiplication )*
|
|
30
|
+
# multiplication -> unary ( ( "*" | "/" | "%" ) unary )*
|
|
31
|
+
# unary -> ( "-" | "!" ) unary | postfix
|
|
32
|
+
# postfix -> primary ( "[" expression "]" | "." name | "::" type )*
|
|
33
|
+
#
|
|
34
|
+
# The binary operators associate to the left; a comparison takes one
|
|
35
|
+
# operator at most, so a second is a token after a finished expression.
|
|
36
|
+
# A statement ending in a closing brace needs no separator before the
|
|
37
|
+
# next; a program holds one statement at least.
|
|
38
|
+
#
|
|
39
|
+
# A refusal is a {Lexer::Refusal}: a {Predicator::ParseError} carrying the
|
|
40
|
+
# reference's message, the position and span of the token it names, and a
|
|
41
|
+
# reason, which is this package's token for the refusal. Nothing raises.
|
|
42
|
+
#
|
|
43
|
+
# One refusal is not the reference's, which follows a source as deep as it
|
|
44
|
+
# nests: a source that nests more than {DEPTH_LIMIT} levels is refused
|
|
45
|
+
# with the reason `nesting_depth_exceeded`, at the token the descent
|
|
46
|
+
# stopped on, rather than left to exhaust the stack. A level is counted
|
|
47
|
+
# each time the descent re-enters the whole expression (inside a
|
|
48
|
+
# parenthesis, a list, an object, an index, a call's arguments, a
|
|
49
|
+
# statement's condition or value), for each prefix operator, a relative
|
|
50
|
+
# date's operand, a block's statements, an `else if` and a statement's
|
|
51
|
+
# assignment probe; a chain of left-associative operators or of postfix
|
|
52
|
+
# steps is read in a loop and costs none. Where the stack a parse runs on
|
|
53
|
+
# is too small to reach the limit, as a Fiber's default stack is, the
|
|
54
|
+
# source is refused under the same reason at the token the stack ran out
|
|
55
|
+
# on, with a message saying so, rather than raising.
|
|
56
|
+
#
|
|
57
|
+
# The module holds no state; each call parses with its own {Descent}. It
|
|
58
|
+
# is private to the package.
|
|
59
|
+
module Parser
|
|
60
|
+
# How many levels a source may nest, the whole expression counting as
|
|
61
|
+
# the first. A source at exactly this depth parses. It is above the 300
|
|
62
|
+
# parentheses the reference's compile transcript compiles, and below
|
|
63
|
+
# the depth the costliest nesting reaches on a thread's default stack.
|
|
64
|
+
DEPTH_LIMIT = 400
|
|
65
|
+
|
|
66
|
+
# The seven scalar type names a cast may name, in the reference's order.
|
|
67
|
+
CAST_TYPE_NAMES = %w[integer float string boolean date datetime duration].freeze
|
|
68
|
+
|
|
69
|
+
# The tag a refusal is thrown with, to the catch around a parse or a
|
|
70
|
+
# probe.
|
|
71
|
+
REFUSED = :refused
|
|
72
|
+
|
|
73
|
+
# Parses one expression.
|
|
74
|
+
#
|
|
75
|
+
# @param tokens [Array<Lexer::Token>] a stream the lexer answered, which
|
|
76
|
+
# ends in its `:eof` token
|
|
77
|
+
# @return [Object, Lexer::Refusal] the expression's {Ast} node, or the
|
|
78
|
+
# refusal
|
|
79
|
+
def self.parse(tokens) = Descent.new(tokens).whole_expression
|
|
80
|
+
|
|
81
|
+
# Parses a program: one or more statements.
|
|
82
|
+
#
|
|
83
|
+
# @param tokens [Array<Lexer::Token>] a stream the lexer answered, which
|
|
84
|
+
# ends in its `:eof` token
|
|
85
|
+
# @return [Ast::Program, Lexer::Refusal] the program, or the refusal
|
|
86
|
+
def self.parse_program(tokens) = Descent.new(tokens).whole_program
|
|
87
|
+
|
|
88
|
+
# One parse of one token stream: the tokens, the cursor and how many
|
|
89
|
+
# productions are open. A refusal is thrown to the catch around the
|
|
90
|
+
# whole parse (or around the assignment probe that discards it) and is
|
|
91
|
+
# never seen outside this class.
|
|
92
|
+
class Descent
|
|
93
|
+
include TokenText
|
|
94
|
+
include Operators
|
|
95
|
+
include Postfix
|
|
96
|
+
include Primaries
|
|
97
|
+
include Durations
|
|
98
|
+
include Statements
|
|
99
|
+
|
|
100
|
+
def initialize(tokens)
|
|
101
|
+
@tokens = tokens
|
|
102
|
+
@index = 0
|
|
103
|
+
@depth = 0
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# @return [Object, Lexer::Refusal]
|
|
107
|
+
def whole_expression
|
|
108
|
+
guarded do
|
|
109
|
+
node = expression
|
|
110
|
+
trailing = peek
|
|
111
|
+
refuse("trailing_token", "Unexpected token #{describe(trailing)} after expression", trailing) unless at?(:eof)
|
|
112
|
+
node
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# @return [Ast::Program, Lexer::Refusal]
|
|
117
|
+
def whole_program
|
|
118
|
+
guarded do
|
|
119
|
+
start = start_of(peek)
|
|
120
|
+
statements = statement_sequence(:eof)
|
|
121
|
+
after_statement(peek) unless at?(:eof)
|
|
122
|
+
Ast::Program.new(statements:, position: start,
|
|
123
|
+
span: between(statements.first.span.start, statements.last.span.end))
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
private
|
|
128
|
+
|
|
129
|
+
# The parse in the block, or the refusal it threw; a stack exhausted
|
|
130
|
+
# short of the depth limit is refused where it ran out.
|
|
131
|
+
def guarded(&)
|
|
132
|
+
catch(REFUSED, &)
|
|
133
|
+
rescue SystemStackError
|
|
134
|
+
catch(REFUSED) do
|
|
135
|
+
refuse("nesting_depth_exceeded", "Expression nests deeper than the stack this parse runs on can follow, " \
|
|
136
|
+
"short of the depth limit of #{DEPTH_LIMIT} levels", peek)
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def peek = @tokens[@index]
|
|
141
|
+
|
|
142
|
+
def previous = @tokens[@index - 1]
|
|
143
|
+
|
|
144
|
+
def at?(type) = peek.type == type
|
|
145
|
+
|
|
146
|
+
def advance
|
|
147
|
+
token = peek
|
|
148
|
+
@index += 1
|
|
149
|
+
token
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# The token, consumed, when it is of the type given; the refusal
|
|
153
|
+
# naming it otherwise.
|
|
154
|
+
def expect(type, reason, message)
|
|
155
|
+
refuse(reason, "#{message} #{describe(peek)}", peek) unless at?(type)
|
|
156
|
+
advance
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Reads one production one level deeper, or refuses at the token the
|
|
160
|
+
# descent stopped on when the source is already at the limit.
|
|
161
|
+
def descend
|
|
162
|
+
enter
|
|
163
|
+
yield
|
|
164
|
+
ensure
|
|
165
|
+
@depth -= 1
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# The whole expression, one level deeper. It is the production read most
|
|
169
|
+
# often, so it counts its own level rather than through a block.
|
|
170
|
+
def expression
|
|
171
|
+
enter
|
|
172
|
+
logical_or
|
|
173
|
+
ensure
|
|
174
|
+
@depth -= 1
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# Counts one more open production; the ensure of whoever called it counts
|
|
178
|
+
# it back, the refusal included.
|
|
179
|
+
def enter
|
|
180
|
+
@depth += 1
|
|
181
|
+
return if @depth <= DEPTH_LIMIT
|
|
182
|
+
|
|
183
|
+
refuse("nesting_depth_exceeded", "Expression nests past the depth limit of #{DEPTH_LIMIT} levels, " \
|
|
184
|
+
"the whole expression counting as the first", peek)
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# Throws the refusal: its position is its span's start.
|
|
188
|
+
def refuse(reason, message, token, span = span_of(token))
|
|
189
|
+
error = ParseError.new(reason:, message:, position: span.start)
|
|
190
|
+
throw REFUSED, Lexer::Refusal.new(error:, span:)
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def start_of(token) = Position.new(line: token.line, column: token.column)
|
|
194
|
+
|
|
195
|
+
# One past the token's last character; a string token, which may hold
|
|
196
|
+
# a line feed, carries its own.
|
|
197
|
+
def end_of(token) = token.end_position || Position.new(line: token.line, column: token.column + token.length)
|
|
198
|
+
|
|
199
|
+
def span_of(token) = Lexer::Span.new(start: start_of(token), end: end_of(token))
|
|
200
|
+
|
|
201
|
+
# A node's own token, as its position and its span.
|
|
202
|
+
def leaf(token) = { position: start_of(token), span: span_of(token) }
|
|
203
|
+
|
|
204
|
+
# From an opening token to past its closing one.
|
|
205
|
+
def delimited(open, close) = { position: start_of(open), span: between(start_of(open), end_of(close)) }
|
|
206
|
+
|
|
207
|
+
# From a node's start to past a token.
|
|
208
|
+
def reaching(node, token) = between(node.span.start, end_of(token))
|
|
209
|
+
|
|
210
|
+
# From a prefix token to its operand's end.
|
|
211
|
+
def prefixed(token, operand) = { position: start_of(token), span: between(start_of(token), operand.span.end) }
|
|
212
|
+
|
|
213
|
+
# An infix node: at its operator, over its operands.
|
|
214
|
+
def infix(token, left, right) = { position: start_of(token), span: between(left.span.start, right.span.end) }
|
|
215
|
+
|
|
216
|
+
def between(start, finish) = Lexer::Span.new(start:, end: finish)
|
|
33
217
|
end
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
racc_action_table = [
|
|
38
|
-
6, 7, 10, 6, 7, 10, 9, 15, 31, 9,
|
|
39
|
-
6, 7, 10, 6, 7, 10, 9, 16, 17, 9,
|
|
40
|
-
16, 17, 14, 16, 17, 14, 52, 6, 7, 10,
|
|
41
|
-
25, 28, 14, 9, 53, 14, 20, 21, 22, 23,
|
|
42
|
-
24, 18, 19, 37, 57, 38, 39, 41, 38, 14,
|
|
43
|
-
26, 27, 16, 17, 37, 38, 56, 39, 41, 37,
|
|
44
|
-
38, 60, 39, 41, 37, 38, 70, 39, 41, 72,
|
|
45
|
-
71, 16, 17, 73, 58, 59, 37, 38, 39, 41,
|
|
46
|
-
61, 52, 37, 37, 38 ]
|
|
47
|
-
|
|
48
|
-
racc_action_check = [
|
|
49
|
-
0, 0, 0, 9, 9, 9, 0, 1, 15, 9,
|
|
50
|
-
10, 10, 10, 16, 16, 16, 10, 29, 29, 16,
|
|
51
|
-
1, 1, 0, 32, 32, 9, 24, 17, 17, 17,
|
|
52
|
-
8, 8, 10, 17, 25, 16, 8, 8, 8, 8,
|
|
53
|
-
8, 8, 8, 23, 30, 26, 23, 23, 27, 17,
|
|
54
|
-
8, 8, 30, 30, 20, 20, 28, 20, 20, 21,
|
|
55
|
-
21, 48, 21, 21, 22, 22, 62, 22, 22, 64,
|
|
56
|
-
62, 33, 33, 64, 40, 40, 52, 52, 61, 61,
|
|
57
|
-
49, 53, 60, 71, 73 ]
|
|
58
|
-
|
|
59
|
-
racc_action_pointer = [
|
|
60
|
-
-2, 7, nil, nil, nil, nil, nil, nil, 21, 1,
|
|
61
|
-
8, nil, nil, nil, nil, 8, 11, 25, nil, nil,
|
|
62
|
-
32, 37, 42, 21, 20, 15, 22, 25, 32, 4,
|
|
63
|
-
39, nil, 10, 58, nil, nil, nil, nil, nil, nil,
|
|
64
|
-
47, nil, nil, nil, nil, nil, nil, nil, 48, 67,
|
|
65
|
-
nil, nil, 54, 75, nil, nil, nil, nil, nil, nil,
|
|
66
|
-
60, 53, 59, nil, 62, nil, nil, nil, nil, nil,
|
|
67
|
-
nil, 61, nil, 61, nil, nil ]
|
|
68
|
-
|
|
69
|
-
racc_action_default = [
|
|
70
|
-
-48, -48, -1, -2, -3, -4, -5, -6, -7, -48,
|
|
71
|
-
-48, -14, -15, -16, -46, -48, -48, -48, -11, -12,
|
|
72
|
-
-48, -48, -48, -48, -48, -48, -48, -48, -48, -8,
|
|
73
|
-
-48, 76, -9, -10, -17, -23, -30, -40, -41, -42,
|
|
74
|
-
-48, -45, -18, -24, -31, -19, -25, -32, -48, -48,
|
|
75
|
-
-21, -26, -48, -48, -28, -29, -47, -13, -43, -44,
|
|
76
|
-
-48, -48, -48, -35, -48, -38, -22, -27, -20, -33,
|
|
77
|
-
-34, -48, -37, -48, -36, -39 ]
|
|
78
|
-
|
|
79
|
-
racc_goto_table = [
|
|
80
|
-
35, 43, 46, 62, 50, 51, 54, 55, 34, 42,
|
|
81
|
-
45, 48, 1, 36, 44, 47, 49, 64, nil, nil,
|
|
82
|
-
nil, 29, 30, nil, nil, nil, nil, nil, 32, 33,
|
|
83
|
-
nil, nil, 65, 66, 67, nil, nil, nil, nil, nil,
|
|
84
|
-
63, nil, nil, nil, nil, nil, nil, nil, 68, nil,
|
|
85
|
-
nil, nil, nil, 75, 69, nil, nil, nil, nil, 74 ]
|
|
86
|
-
|
|
87
|
-
racc_goto_check = [
|
|
88
|
-
12, 12, 12, 15, 11, 13, 12, 12, 10, 10,
|
|
89
|
-
10, 10, 1, 14, 14, 14, 14, 16, nil, nil,
|
|
90
|
-
nil, 1, 1, nil, nil, nil, nil, nil, 1, 1,
|
|
91
|
-
nil, nil, 12, 11, 13, nil, nil, nil, nil, nil,
|
|
92
|
-
10, nil, nil, nil, nil, nil, nil, nil, 10, nil,
|
|
93
|
-
nil, nil, nil, 12, 14, nil, nil, nil, nil, 10 ]
|
|
94
|
-
|
|
95
|
-
racc_goto_pointer = [
|
|
96
|
-
nil, 12, nil, nil, nil, nil, nil, nil, nil, nil,
|
|
97
|
-
-12, -20, -20, -19, -7, -49, -35, nil ]
|
|
98
|
-
|
|
99
|
-
racc_goto_default = [
|
|
100
|
-
nil, nil, 2, 3, 4, 5, 8, 11, 12, 13,
|
|
101
|
-
nil, nil, nil, nil, nil, nil, nil, 40 ]
|
|
102
|
-
|
|
103
|
-
racc_reduce_table = [
|
|
104
|
-
0, 0, :racc_error,
|
|
105
|
-
1, 32, :_reduce_none,
|
|
106
|
-
1, 32, :_reduce_none,
|
|
107
|
-
1, 32, :_reduce_none,
|
|
108
|
-
1, 32, :_reduce_none,
|
|
109
|
-
1, 33, :_reduce_5,
|
|
110
|
-
1, 33, :_reduce_6,
|
|
111
|
-
1, 33, :_reduce_7,
|
|
112
|
-
2, 34, :_reduce_8,
|
|
113
|
-
3, 34, :_reduce_9,
|
|
114
|
-
3, 34, :_reduce_10,
|
|
115
|
-
2, 34, :_reduce_11,
|
|
116
|
-
2, 34, :_reduce_12,
|
|
117
|
-
3, 35, :_reduce_13,
|
|
118
|
-
1, 36, :_reduce_none,
|
|
119
|
-
1, 36, :_reduce_none,
|
|
120
|
-
1, 36, :_reduce_none,
|
|
121
|
-
3, 38, :_reduce_17,
|
|
122
|
-
3, 38, :_reduce_18,
|
|
123
|
-
3, 38, :_reduce_19,
|
|
124
|
-
5, 38, :_reduce_20,
|
|
125
|
-
3, 38, :_reduce_21,
|
|
126
|
-
4, 38, :_reduce_22,
|
|
127
|
-
3, 39, :_reduce_23,
|
|
128
|
-
3, 39, :_reduce_24,
|
|
129
|
-
3, 39, :_reduce_25,
|
|
130
|
-
3, 39, :_reduce_26,
|
|
131
|
-
4, 39, :_reduce_27,
|
|
132
|
-
3, 39, :_reduce_28,
|
|
133
|
-
3, 39, :_reduce_29,
|
|
134
|
-
3, 40, :_reduce_30,
|
|
135
|
-
3, 40, :_reduce_31,
|
|
136
|
-
3, 40, :_reduce_32,
|
|
137
|
-
5, 40, :_reduce_33,
|
|
138
|
-
3, 42, :_reduce_34,
|
|
139
|
-
1, 46, :_reduce_none,
|
|
140
|
-
3, 46, :_reduce_36,
|
|
141
|
-
3, 44, :_reduce_37,
|
|
142
|
-
1, 47, :_reduce_none,
|
|
143
|
-
3, 47, :_reduce_39,
|
|
144
|
-
1, 41, :_reduce_40,
|
|
145
|
-
1, 43, :_reduce_41,
|
|
146
|
-
1, 45, :_reduce_42,
|
|
147
|
-
2, 45, :_reduce_43,
|
|
148
|
-
2, 45, :_reduce_44,
|
|
149
|
-
1, 48, :_reduce_45,
|
|
150
|
-
1, 37, :_reduce_46,
|
|
151
|
-
3, 37, :_reduce_47 ]
|
|
152
|
-
|
|
153
|
-
racc_reduce_n = 48
|
|
154
|
-
|
|
155
|
-
racc_shift_n = 76
|
|
156
|
-
|
|
157
|
-
racc_token_table = {
|
|
158
|
-
false => 0,
|
|
159
|
-
:error => 1,
|
|
160
|
-
:TRUE => 2,
|
|
161
|
-
:FALSE => 3,
|
|
162
|
-
:LPAREN => 4,
|
|
163
|
-
:RPAREN => 5,
|
|
164
|
-
:LBRACKET => 6,
|
|
165
|
-
:RBRACKET => 7,
|
|
166
|
-
:BANG => 8,
|
|
167
|
-
:NOT => 9,
|
|
168
|
-
:DOT => 10,
|
|
169
|
-
:COMMA => 11,
|
|
170
|
-
:AT => 12,
|
|
171
|
-
:AND => 13,
|
|
172
|
-
:OR => 14,
|
|
173
|
-
:EQ => 15,
|
|
174
|
-
:GT => 16,
|
|
175
|
-
:LT => 17,
|
|
176
|
-
:BETWEEN => 18,
|
|
177
|
-
:IN => 19,
|
|
178
|
-
:PRESENT => 20,
|
|
179
|
-
:BLANK => 21,
|
|
180
|
-
:INTEGER => 22,
|
|
181
|
-
:STRING => 23,
|
|
182
|
-
:IDENTIFIER => 24,
|
|
183
|
-
:DATE => 25,
|
|
184
|
-
:DURATION => 26,
|
|
185
|
-
:AGO => 27,
|
|
186
|
-
:FROMNOW => 28,
|
|
187
|
-
:STARTSWITH => 29,
|
|
188
|
-
:ENDSWITH => 30 }
|
|
189
|
-
|
|
190
|
-
racc_nt_base = 31
|
|
191
|
-
|
|
192
|
-
racc_use_result_var = false
|
|
193
|
-
|
|
194
|
-
Racc_arg = [
|
|
195
|
-
racc_action_table,
|
|
196
|
-
racc_action_check,
|
|
197
|
-
racc_action_default,
|
|
198
|
-
racc_action_pointer,
|
|
199
|
-
racc_goto_table,
|
|
200
|
-
racc_goto_check,
|
|
201
|
-
racc_goto_default,
|
|
202
|
-
racc_goto_pointer,
|
|
203
|
-
racc_nt_base,
|
|
204
|
-
racc_reduce_table,
|
|
205
|
-
racc_token_table,
|
|
206
|
-
racc_shift_n,
|
|
207
|
-
racc_reduce_n,
|
|
208
|
-
racc_use_result_var ]
|
|
209
|
-
|
|
210
|
-
Racc_token_to_s_table = [
|
|
211
|
-
"$end",
|
|
212
|
-
"error",
|
|
213
|
-
"TRUE",
|
|
214
|
-
"FALSE",
|
|
215
|
-
"LPAREN",
|
|
216
|
-
"RPAREN",
|
|
217
|
-
"LBRACKET",
|
|
218
|
-
"RBRACKET",
|
|
219
|
-
"BANG",
|
|
220
|
-
"NOT",
|
|
221
|
-
"DOT",
|
|
222
|
-
"COMMA",
|
|
223
|
-
"AT",
|
|
224
|
-
"AND",
|
|
225
|
-
"OR",
|
|
226
|
-
"EQ",
|
|
227
|
-
"GT",
|
|
228
|
-
"LT",
|
|
229
|
-
"BETWEEN",
|
|
230
|
-
"IN",
|
|
231
|
-
"PRESENT",
|
|
232
|
-
"BLANK",
|
|
233
|
-
"INTEGER",
|
|
234
|
-
"STRING",
|
|
235
|
-
"IDENTIFIER",
|
|
236
|
-
"DATE",
|
|
237
|
-
"DURATION",
|
|
238
|
-
"AGO",
|
|
239
|
-
"FROMNOW",
|
|
240
|
-
"STARTSWITH",
|
|
241
|
-
"ENDSWITH",
|
|
242
|
-
"$start",
|
|
243
|
-
"predicate",
|
|
244
|
-
"boolean_predicate",
|
|
245
|
-
"logical_predicate",
|
|
246
|
-
"group_predicate",
|
|
247
|
-
"comparison_predicate",
|
|
248
|
-
"variable",
|
|
249
|
-
"integer_comparison_predicate",
|
|
250
|
-
"string_comparison_predicate",
|
|
251
|
-
"date_comparison_predicate",
|
|
252
|
-
"integer",
|
|
253
|
-
"integer_array",
|
|
254
|
-
"string",
|
|
255
|
-
"string_array",
|
|
256
|
-
"date",
|
|
257
|
-
"integer_array_contents",
|
|
258
|
-
"string_array_contents",
|
|
259
|
-
"duration" ]
|
|
260
|
-
|
|
261
|
-
Racc_debug_parser = false
|
|
262
|
-
|
|
263
|
-
##### State transition tables end #####
|
|
264
|
-
|
|
265
|
-
# reduce 0 omitted
|
|
266
|
-
|
|
267
|
-
# reduce 1 omitted
|
|
268
|
-
|
|
269
|
-
# reduce 2 omitted
|
|
270
|
-
|
|
271
|
-
# reduce 3 omitted
|
|
272
|
-
|
|
273
|
-
# reduce 4 omitted
|
|
274
|
-
|
|
275
|
-
def _reduce_5(val, _values)
|
|
276
|
-
AST::True.new true
|
|
277
|
-
end
|
|
278
|
-
|
|
279
|
-
def _reduce_6(val, _values)
|
|
280
|
-
AST::False.new false
|
|
281
|
-
end
|
|
282
|
-
|
|
283
|
-
def _reduce_7(val, _values)
|
|
284
|
-
AST::BooleanVariable.new val.first
|
|
285
|
-
end
|
|
286
|
-
|
|
287
|
-
def _reduce_8(val, _values)
|
|
288
|
-
AST::Not.new val.last
|
|
289
|
-
end
|
|
290
|
-
|
|
291
|
-
def _reduce_9(val, _values)
|
|
292
|
-
AST::And.new val.first, val.last
|
|
293
|
-
end
|
|
294
|
-
|
|
295
|
-
def _reduce_10(val, _values)
|
|
296
|
-
AST::Or.new val.first, val.last
|
|
297
|
-
end
|
|
298
|
-
|
|
299
|
-
def _reduce_11(val, _values)
|
|
300
|
-
AST::Present.new val.first
|
|
301
|
-
end
|
|
302
|
-
|
|
303
|
-
def _reduce_12(val, _values)
|
|
304
|
-
AST::Blank.new val.first
|
|
305
|
-
end
|
|
306
|
-
|
|
307
|
-
def _reduce_13(val, _values)
|
|
308
|
-
AST::Group.new val[1]
|
|
309
|
-
end
|
|
310
|
-
|
|
311
|
-
# reduce 14 omitted
|
|
312
|
-
|
|
313
|
-
# reduce 15 omitted
|
|
314
|
-
|
|
315
|
-
# reduce 16 omitted
|
|
316
|
-
|
|
317
|
-
def _reduce_17(val, _values)
|
|
318
|
-
AST::IntegerEqual.new val.first, val.last
|
|
319
|
-
end
|
|
320
|
-
|
|
321
|
-
def _reduce_18(val, _values)
|
|
322
|
-
AST::IntegerGreaterThan.new val.first, val.last
|
|
323
|
-
end
|
|
324
|
-
|
|
325
|
-
def _reduce_19(val, _values)
|
|
326
|
-
AST::IntegerLessThan.new val.first, val.last
|
|
218
|
+
private_constant :Descent
|
|
219
|
+
end
|
|
220
|
+
private_constant :Parser
|
|
327
221
|
end
|
|
328
|
-
|
|
329
|
-
def _reduce_20(val, _values)
|
|
330
|
-
AST::IntegerBetween.new val.first, val[2], val.last
|
|
331
|
-
end
|
|
332
|
-
|
|
333
|
-
def _reduce_21(val, _values)
|
|
334
|
-
AST::IntegerIn.new val.first, val.last
|
|
335
|
-
end
|
|
336
|
-
|
|
337
|
-
def _reduce_22(val, _values)
|
|
338
|
-
AST::IntegerNotIn.new val.first, val.last
|
|
339
|
-
end
|
|
340
|
-
|
|
341
|
-
def _reduce_23(val, _values)
|
|
342
|
-
AST::StringEqual.new val.first, val.last
|
|
343
|
-
end
|
|
344
|
-
|
|
345
|
-
def _reduce_24(val, _values)
|
|
346
|
-
AST::StringGreaterThan.new val.first, val.last
|
|
347
|
-
end
|
|
348
|
-
|
|
349
|
-
def _reduce_25(val, _values)
|
|
350
|
-
AST::StringLessThan.new val.first, val.last
|
|
351
|
-
end
|
|
352
|
-
|
|
353
|
-
def _reduce_26(val, _values)
|
|
354
|
-
AST::StringIn.new val.first, val.last
|
|
355
|
-
end
|
|
356
|
-
|
|
357
|
-
def _reduce_27(val, _values)
|
|
358
|
-
AST::StringNotIn.new val.first, val.last
|
|
359
|
-
end
|
|
360
|
-
|
|
361
|
-
def _reduce_28(val, _values)
|
|
362
|
-
AST::StringStartsWith.new val.first, val.last
|
|
363
|
-
end
|
|
364
|
-
|
|
365
|
-
def _reduce_29(val, _values)
|
|
366
|
-
AST::StringEndsWith.new val.first, val.last
|
|
367
|
-
end
|
|
368
|
-
|
|
369
|
-
def _reduce_30(val, _values)
|
|
370
|
-
AST::DateEqual.new val.first, val.last
|
|
371
|
-
end
|
|
372
|
-
|
|
373
|
-
def _reduce_31(val, _values)
|
|
374
|
-
AST::DateGreaterThan.new val.first, val.last
|
|
375
|
-
end
|
|
376
|
-
|
|
377
|
-
def _reduce_32(val, _values)
|
|
378
|
-
AST::DateLessThan.new val.first, val.last
|
|
379
|
-
end
|
|
380
|
-
|
|
381
|
-
def _reduce_33(val, _values)
|
|
382
|
-
AST::DateBetween.new val.first, val[2], val.last
|
|
383
|
-
end
|
|
384
|
-
|
|
385
|
-
def _reduce_34(val, _values)
|
|
386
|
-
AST::IntegerArray.new val[1]
|
|
387
|
-
end
|
|
388
|
-
|
|
389
|
-
# reduce 35 omitted
|
|
390
|
-
|
|
391
|
-
def _reduce_36(val, _values)
|
|
392
|
-
[val.first, val.last].flatten
|
|
393
|
-
end
|
|
394
|
-
|
|
395
|
-
def _reduce_37(val, _values)
|
|
396
|
-
AST::StringArray.new val[1]
|
|
397
|
-
end
|
|
398
|
-
|
|
399
|
-
# reduce 38 omitted
|
|
400
|
-
|
|
401
|
-
def _reduce_39(val, _values)
|
|
402
|
-
[val.first, val.last].flatten
|
|
403
|
-
end
|
|
404
|
-
|
|
405
|
-
def _reduce_40(val, _values)
|
|
406
|
-
AST::Integer.new val.first.to_i
|
|
407
|
-
end
|
|
408
|
-
|
|
409
|
-
def _reduce_41(val, _values)
|
|
410
|
-
AST::String.new val.first
|
|
411
|
-
end
|
|
412
|
-
|
|
413
|
-
def _reduce_42(val, _values)
|
|
414
|
-
AST::Date.new val.first
|
|
415
|
-
end
|
|
416
|
-
|
|
417
|
-
def _reduce_43(val, _values)
|
|
418
|
-
AST::DateAgo.new val.first
|
|
419
|
-
end
|
|
420
|
-
|
|
421
|
-
def _reduce_44(val, _values)
|
|
422
|
-
AST::DateFromNow.new val.first
|
|
423
|
-
end
|
|
424
|
-
|
|
425
|
-
def _reduce_45(val, _values)
|
|
426
|
-
AST::Duration.new val.first
|
|
427
|
-
end
|
|
428
|
-
|
|
429
|
-
def _reduce_46(val, _values)
|
|
430
|
-
AST::Variable.new val.first
|
|
431
|
-
end
|
|
432
|
-
|
|
433
|
-
def _reduce_47(val, _values)
|
|
434
|
-
AST::Variable.new [val.first, val.last].flatten.join(".")
|
|
435
|
-
end
|
|
436
|
-
|
|
437
|
-
def _reduce_none(val, _values)
|
|
438
|
-
val[0]
|
|
439
|
-
end
|
|
440
|
-
|
|
441
|
-
end # class Parser
|
|
442
|
-
end # module Predicator
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Predicator
|
|
4
|
+
# What a call answers: a value, or an error value saying why there is none.
|
|
5
|
+
# Results are values, never raised; each entry point's raising variant
|
|
6
|
+
# raises {Predicator::Error} carrying the same error instead.
|
|
7
|
+
#
|
|
8
|
+
# A successful result's value may itself be nil (predicator's null), so
|
|
9
|
+
# {#ok?} is read from the error, not from the value.
|
|
10
|
+
#
|
|
11
|
+
# @!attribute [r] value
|
|
12
|
+
# @return [Object] the answer; nil when the result failed
|
|
13
|
+
# @!attribute [r] error
|
|
14
|
+
# @return [Object, nil] the error value; nil when the result succeeded
|
|
15
|
+
Result = Data.define(:value, :error) do
|
|
16
|
+
# @raise [ArgumentError] when it carries both a value and an error
|
|
17
|
+
def initialize(value:, error:)
|
|
18
|
+
raise ArgumentError, "a result carries a value or an error, not both" unless value.nil? || error.nil?
|
|
19
|
+
|
|
20
|
+
super
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# @return [Boolean] whether the call succeeded
|
|
24
|
+
def ok? = error.nil?
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# The two ways the package builds a {Result}. Private to the package: a
|
|
28
|
+
# host reads results and does not need to make them (Result.new and
|
|
29
|
+
# Result[] stay public, as Data defines them).
|
|
30
|
+
module Results
|
|
31
|
+
module_function
|
|
32
|
+
|
|
33
|
+
# A successful result.
|
|
34
|
+
def ok(value) = Result.new(value:, error: nil)
|
|
35
|
+
|
|
36
|
+
# A failed result.
|
|
37
|
+
#
|
|
38
|
+
# @raise [ArgumentError] when error is nil
|
|
39
|
+
def failure(error)
|
|
40
|
+
raise ArgumentError, "a failed result carries an error" if error.nil?
|
|
41
|
+
|
|
42
|
+
Result.new(value: nil, error:)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
private_constant :Results
|
|
46
|
+
end
|