ibex-runtime 0.2.0 → 0.4.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/README.md +100 -272
- data/lib/ibex/runtime/cst/green/node.rb +1 -1
- data/lib/ibex/runtime/cst/green/token.rb +1 -1
- data/lib/ibex/runtime/cst/green/trivia.rb +1 -1
- data/lib/ibex/runtime/cst/incremental/blender.rb +1 -1
- data/lib/ibex/runtime/cst/incremental/lexed_syntax.rb +2 -2
- data/lib/ibex/runtime/cst/incremental/parse_memo.rb +2 -2
- data/lib/ibex/runtime/cst/incremental/relexer.rb +3 -0
- data/lib/ibex/runtime/cst/incremental/session.rb +26 -2
- data/lib/ibex/runtime/cst/parse_result.rb +7 -7
- data/lib/ibex/runtime/cst/serialize.rb +6 -3
- data/lib/ibex/runtime/cst/syntax_node.rb +4 -4
- data/lib/ibex/runtime/cst/syntax_token.rb +5 -5
- data/lib/ibex/runtime/cst/typed_node.rb +1 -1
- data/lib/ibex/runtime/cst/validator.rb +40 -30
- data/lib/ibex/runtime/embedded_source.rb +98 -0
- data/lib/ibex/runtime/event.rb +7 -4
- data/lib/ibex/runtime/event_jsonl_tracer.rb +1 -1
- data/lib/ibex/runtime/event_sanitizer.rb +32 -26
- data/lib/ibex/runtime/generated_lexer.rb +23 -16
- data/lib/ibex/runtime/lexer_input.rb +1 -1
- data/lib/ibex/runtime/location_span.rb +15 -15
- data/lib/ibex/runtime/observation.rb +1 -1
- data/lib/ibex/runtime/parser.rb +309 -191
- data/lib/ibex/runtime/parser_sync_recovery.rb +19 -15
- data/lib/ibex/runtime/repair.rb +36 -5
- data/lib/ibex/runtime/repair_priority_queue.rb +10 -6
- data/lib/ibex/runtime/repair_search.rb +92 -29
- data/lib/ibex/runtime/syntax_repair.rb +490 -0
- data/lib/ibex/runtime/syntax_session.rb +416 -0
- data/lib/ibex/runtime/table_format.rb +1 -1
- data/lib/ibex/runtime/version.rb +1 -1
- data/lib/ibex/runtime.rb +2 -1
- data/lib/ibex/tables/compact.rb +16 -12
- data/lib/ibex/tables/compact_actions.rb +45 -33
- data/lib/ibex/tables/compact_productions.rb +18 -15
- data/sig/ibex/runtime/cst/green/node.rbs +2 -2
- data/sig/ibex/runtime/cst/green/token.rbs +2 -2
- data/sig/ibex/runtime/cst/green/trivia.rbs +2 -2
- data/sig/ibex/runtime/cst/incremental/blender.rbs +2 -2
- data/sig/ibex/runtime/cst/incremental/lexed_syntax.rbs +3 -3
- data/sig/ibex/runtime/cst/incremental/parse_memo.rbs +4 -4
- data/sig/ibex/runtime/cst/incremental/session.rbs +8 -2
- data/sig/ibex/runtime/cst/parse_result.rbs +9 -9
- data/sig/ibex/runtime/cst/serialize.rbs +8 -6
- data/sig/ibex/runtime/cst/syntax_node.rbs +6 -6
- data/sig/ibex/runtime/cst/syntax_token.rbs +10 -10
- data/sig/ibex/runtime/cst/typed_node.rbs +2 -2
- data/sig/ibex/runtime/cst/validator.rbs +46 -42
- data/sig/ibex/runtime/embedded_source.rbs +21 -0
- data/sig/ibex/runtime/event.rbs +7 -5
- data/sig/ibex/runtime/event_jsonl_tracer.rbs +1 -1
- data/sig/ibex/runtime/event_sanitizer.rbs +50 -44
- data/sig/ibex/runtime/generated_lexer.rbs +31 -24
- data/sig/ibex/runtime/lexer_input.rbs +2 -2
- data/sig/ibex/runtime/location_span.rbs +28 -28
- data/sig/ibex/runtime/observation.rbs +2 -2
- data/sig/ibex/runtime/parser.rbs +266 -252
- data/sig/ibex/runtime/parser_sync_recovery.rbs +15 -15
- data/sig/ibex/runtime/repair.rbs +28 -8
- data/sig/ibex/runtime/repair_priority_queue.rbs +9 -7
- data/sig/ibex/runtime/repair_search.rbs +38 -19
- data/sig/ibex/runtime/syntax_repair.rbs +177 -0
- data/sig/ibex/runtime/syntax_session.rbs +186 -0
- data/sig/ibex/tables/compact.rbs +12 -12
- data/sig/ibex/tables/compact_actions.rbs +10 -17
- data/sig/ibex/tables/compact_productions.rbs +19 -19
- metadata +12 -6
- data/lib/ibex/runtime/jsonl_tracer.rb +0 -75
- data/sig/ibex/runtime/jsonl_tracer.rbs +0 -42
|
@@ -6,6 +6,10 @@ module Ibex
|
|
|
6
6
|
# Converts application-owned values into bounded, data-only event summaries.
|
|
7
7
|
# rubocop:disable Metrics/ModuleLength
|
|
8
8
|
module EventSanitizer
|
|
9
|
+
# @rbs!
|
|
10
|
+
# type json_value = String | Integer | Float | bool | nil | Array[json_value] | Hash[String, json_value]
|
|
11
|
+
# type sanitized_value = untyped
|
|
12
|
+
|
|
9
13
|
MAX_DEPTH = 3 #: Integer
|
|
10
14
|
MAX_COLLECTION_ENTRIES = 16 #: Integer
|
|
11
15
|
MAX_STRING_BYTES = 256 #: Integer
|
|
@@ -17,9 +21,9 @@ module Ibex
|
|
|
17
21
|
# Copy a runtime payload into deeply frozen JSON data. Unknown objects are
|
|
18
22
|
# summarized instead of being retained, so callers cannot smuggle mutable
|
|
19
23
|
# application identities into an Event.
|
|
20
|
-
# @rbs (Hash[
|
|
24
|
+
# @rbs (Hash[sanitized_value, sanitized_value] input) -> Hash[String, json_value]
|
|
21
25
|
def data(input)
|
|
22
|
-
result = {}
|
|
26
|
+
result = {} # @type var result: Hash[String, json_value]
|
|
23
27
|
consumed = 0
|
|
24
28
|
core_call(Hash, :each_pair, input) do |key, raw|
|
|
25
29
|
break if consumed == MAX_COLLECTION_ENTRIES
|
|
@@ -32,14 +36,14 @@ module Ibex
|
|
|
32
36
|
{ "unavailable" => "event_data" }.freeze
|
|
33
37
|
end
|
|
34
38
|
|
|
35
|
-
# @rbs (
|
|
39
|
+
# @rbs (sanitized_value input) -> json_value
|
|
36
40
|
def value(input)
|
|
37
41
|
summarize(input, depth: 0, seen: {})
|
|
38
42
|
rescue StandardError
|
|
39
43
|
unavailable("sanitization")
|
|
40
44
|
end
|
|
41
45
|
|
|
42
|
-
# @rbs (
|
|
46
|
+
# @rbs (sanitized_value location) -> Hash[String, json_value]?
|
|
43
47
|
def location(location)
|
|
44
48
|
return nil unless location
|
|
45
49
|
|
|
@@ -55,7 +59,7 @@ module Ibex
|
|
|
55
59
|
unavailable("location")
|
|
56
60
|
end
|
|
57
61
|
|
|
58
|
-
# @rbs (
|
|
62
|
+
# @rbs (sanitized_value input) -> String
|
|
59
63
|
def string(input)
|
|
60
64
|
return "<unavailable>" unless core_type?(input, String)
|
|
61
65
|
|
|
@@ -78,7 +82,7 @@ module Ibex
|
|
|
78
82
|
"<unavailable>"
|
|
79
83
|
end
|
|
80
84
|
|
|
81
|
-
# @rbs (
|
|
85
|
+
# @rbs (sanitized_value input) -> String
|
|
82
86
|
def class_name(input)
|
|
83
87
|
klass = core_call(Object, :class, input)
|
|
84
88
|
name = core_call(Module, :name, klass)
|
|
@@ -89,7 +93,7 @@ module Ibex
|
|
|
89
93
|
|
|
90
94
|
private
|
|
91
95
|
|
|
92
|
-
# @rbs (
|
|
96
|
+
# @rbs (sanitized_value input, depth: Integer, seen: Hash[Integer, bool]) -> json_value
|
|
93
97
|
def summarize(input, depth:, seen:)
|
|
94
98
|
return input if primitive?(input)
|
|
95
99
|
return bounded_integer(input) if core_type?(input, Integer)
|
|
@@ -102,7 +106,7 @@ module Ibex
|
|
|
102
106
|
{ "type" => "object", "class" => class_name(input) }.freeze
|
|
103
107
|
end
|
|
104
108
|
|
|
105
|
-
# @rbs (
|
|
109
|
+
# @rbs (sanitized_value input, depth: Integer, seen: Hash[Integer, bool]) -> json_value
|
|
106
110
|
def json_data(input, depth:, seen:)
|
|
107
111
|
return unavailable("depth") if depth >= DATA_MAX_DEPTH
|
|
108
112
|
return input if primitive?(input)
|
|
@@ -116,7 +120,7 @@ module Ibex
|
|
|
116
120
|
{ "type" => "object", "class" => class_name(input) }.freeze
|
|
117
121
|
end
|
|
118
122
|
|
|
119
|
-
# @rbs (Array[
|
|
123
|
+
# @rbs (Array[sanitized_value] input, depth: Integer, seen: Hash[Integer, bool]) -> json_value
|
|
120
124
|
def summarize_array(input, depth:, seen:)
|
|
121
125
|
return unavailable("depth") if depth >= MAX_DEPTH
|
|
122
126
|
|
|
@@ -125,7 +129,7 @@ module Ibex
|
|
|
125
129
|
end
|
|
126
130
|
end
|
|
127
131
|
|
|
128
|
-
# @rbs (Hash[
|
|
132
|
+
# @rbs (Hash[sanitized_value, sanitized_value] input, depth: Integer, seen: Hash[Integer, bool]) -> json_value
|
|
129
133
|
def summarize_hash(input, depth:, seen:)
|
|
130
134
|
return unavailable("depth") if depth >= MAX_DEPTH
|
|
131
135
|
|
|
@@ -133,7 +137,7 @@ module Ibex
|
|
|
133
137
|
return { "cycle" => true }.freeze if seen[identity]
|
|
134
138
|
|
|
135
139
|
nested = seen.merge(identity => true)
|
|
136
|
-
entries = []
|
|
140
|
+
entries = [] # @type var entries: Array[Array[json_value]]
|
|
137
141
|
length = core_call(Hash, :length, input)
|
|
138
142
|
core_call(Hash, :each_pair, input) do |key, child|
|
|
139
143
|
break if entries.length == MAX_COLLECTION_ENTRIES
|
|
@@ -148,20 +152,20 @@ module Ibex
|
|
|
148
152
|
summary.freeze
|
|
149
153
|
end
|
|
150
154
|
|
|
151
|
-
# @rbs (Array[
|
|
155
|
+
# @rbs (Array[sanitized_value] input, depth: Integer, seen: Hash[Integer, bool]) -> json_value
|
|
152
156
|
def json_array(input, depth:, seen:)
|
|
153
157
|
copy_array(input, seen: seen) do |child, nested|
|
|
154
158
|
json_data(child, depth: depth + 1, seen: nested)
|
|
155
159
|
end
|
|
156
160
|
end
|
|
157
161
|
|
|
158
|
-
# @rbs (Hash[
|
|
162
|
+
# @rbs (Hash[sanitized_value, sanitized_value] input, depth: Integer, seen: Hash[Integer, bool]) -> json_value
|
|
159
163
|
def json_hash(input, depth:, seen:)
|
|
160
164
|
identity = object_identity(input)
|
|
161
165
|
return { "cycle" => true }.freeze if seen[identity]
|
|
162
166
|
|
|
163
167
|
nested = seen.merge(identity => true)
|
|
164
|
-
result = {}
|
|
168
|
+
result = {} # @type var result: Hash[String, json_value]
|
|
165
169
|
length = core_call(Hash, :length, input)
|
|
166
170
|
consumed = 0
|
|
167
171
|
core_call(Hash, :each_pair, input) do |key, child|
|
|
@@ -174,8 +178,8 @@ module Ibex
|
|
|
174
178
|
result.freeze
|
|
175
179
|
end
|
|
176
180
|
|
|
177
|
-
# @rbs (Array[
|
|
178
|
-
# { (
|
|
181
|
+
# @rbs (Array[sanitized_value] input, seen: Hash[Integer, bool])
|
|
182
|
+
# { (sanitized_value, Hash[Integer, bool]) -> json_value } -> json_value
|
|
179
183
|
def copy_array(input, seen:)
|
|
180
184
|
identity = object_identity(input)
|
|
181
185
|
return { "cycle" => true }.freeze if seen[identity]
|
|
@@ -191,14 +195,14 @@ module Ibex
|
|
|
191
195
|
result.freeze
|
|
192
196
|
end
|
|
193
197
|
|
|
194
|
-
# @rbs (
|
|
198
|
+
# @rbs (sanitized_value input) -> bool
|
|
195
199
|
def primitive?(input)
|
|
196
200
|
core_type?(input, NilClass) ||
|
|
197
201
|
core_type?(input, TrueClass) ||
|
|
198
202
|
core_type?(input, FalseClass)
|
|
199
203
|
end
|
|
200
204
|
|
|
201
|
-
# @rbs (Integer input) ->
|
|
205
|
+
# @rbs (Integer input) -> json_value
|
|
202
206
|
def bounded_integer(input)
|
|
203
207
|
bits = core_call(Integer, :bit_length, input)
|
|
204
208
|
return input if bits <= MAX_INTEGER_BITS
|
|
@@ -210,17 +214,17 @@ module Ibex
|
|
|
210
214
|
}.freeze
|
|
211
215
|
end
|
|
212
216
|
|
|
213
|
-
# @rbs (Float input) ->
|
|
217
|
+
# @rbs (Float input) -> json_value
|
|
214
218
|
def finite_float(input)
|
|
215
219
|
core_call(Float, :finite?, input) ? input : string(core_call(Float, :to_s, input))
|
|
216
220
|
end
|
|
217
221
|
|
|
218
|
-
# @rbs (
|
|
222
|
+
# @rbs (sanitized_value input, Module type) -> bool
|
|
219
223
|
def core_type?(input, type)
|
|
220
224
|
core_call(Module, :===, type, input)
|
|
221
225
|
end
|
|
222
226
|
|
|
223
|
-
# @rbs (
|
|
227
|
+
# @rbs (sanitized_value key) -> String
|
|
224
228
|
def data_key(key)
|
|
225
229
|
return string(key) if core_type?(key, String)
|
|
226
230
|
return string(core_call(Symbol, :name, key)) if core_type?(key, Symbol)
|
|
@@ -237,12 +241,12 @@ module Ibex
|
|
|
237
241
|
"#{prefix}\u2026".freeze
|
|
238
242
|
end
|
|
239
243
|
|
|
240
|
-
# @rbs (
|
|
244
|
+
# @rbs (sanitized_value input) -> Integer
|
|
241
245
|
def object_identity(input)
|
|
242
246
|
core_call(BasicObject, :__id__, input)
|
|
243
247
|
end
|
|
244
248
|
|
|
245
|
-
# @rbs (
|
|
249
|
+
# @rbs (sanitized_value location, Symbol field) -> sanitized_value
|
|
246
250
|
def location_field(location, field)
|
|
247
251
|
if core_type?(location, Hash)
|
|
248
252
|
return core_call(Hash, :fetch, location, field) do
|
|
@@ -256,13 +260,15 @@ module Ibex
|
|
|
256
260
|
nil
|
|
257
261
|
end
|
|
258
262
|
|
|
259
|
-
# @rbs (String reason) -> Hash[String,
|
|
263
|
+
# @rbs (String reason) -> Hash[String, json_value]
|
|
260
264
|
def unavailable(reason)
|
|
261
265
|
{ "unavailable" => reason.freeze }.freeze
|
|
262
266
|
end
|
|
263
267
|
|
|
264
|
-
#
|
|
265
|
-
#
|
|
268
|
+
# Reflection deliberately erases the receiver's method signature; callers validate
|
|
269
|
+
# returned values at each sanitization boundary.
|
|
270
|
+
# @rbs (Module owner, Symbol method_name, sanitized_value receiver, *sanitized_value, **sanitized_value)
|
|
271
|
+
# ?{ (*sanitized_value) -> sanitized_value } -> sanitized_value
|
|
266
272
|
def core_call(owner, method_name, receiver, ...)
|
|
267
273
|
owner.instance_method(method_name).bind(receiver).call(...)
|
|
268
274
|
end
|
|
@@ -21,7 +21,7 @@ module Ibex
|
|
|
21
21
|
# @rbs @lexer_byte_column: Integer
|
|
22
22
|
# @rbs @lexer_byte_offset: Integer
|
|
23
23
|
# @rbs @lexer_lexeme: String?
|
|
24
|
-
# @rbs @lexer_emission: Object | Array[
|
|
24
|
+
# @rbs @lexer_emission: Object | Array[Object?]
|
|
25
25
|
# @rbs @lexer_skip_requested: bool
|
|
26
26
|
# @rbs @lexer_pending_green_trivia: Array[CST::GreenTrivia]
|
|
27
27
|
# @rbs @lexer_cst_trivia_policy: Symbol
|
|
@@ -47,8 +47,11 @@ module Ibex
|
|
|
47
47
|
self
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
-
# Lex and parse one String, IO, or Fiber source.
|
|
51
|
-
#
|
|
50
|
+
# Lex and semantically parse one String, IO, or Fiber source.
|
|
51
|
+
# Parser and generated lexer actions execute. Loading the generated file
|
|
52
|
+
# may also execute user sections; this trusted application path is not a
|
|
53
|
+
# sandbox.
|
|
54
|
+
# @rbs (String | IO | Fiber source, ?file: String) -> Object?
|
|
52
55
|
def parse(source, file: "(input)")
|
|
53
56
|
lex(source, file: file)
|
|
54
57
|
parser = self #: Parser
|
|
@@ -61,6 +64,8 @@ module Ibex
|
|
|
61
64
|
end
|
|
62
65
|
|
|
63
66
|
# Parse one generated-lexer source and return its semantic and syntax results.
|
|
67
|
+
# Parser and generated lexer actions execute. This trusted application
|
|
68
|
+
# path is not a sandbox.
|
|
64
69
|
# @rbs (String | IO | Fiber source, ?file: String) -> CST::ParseResult
|
|
65
70
|
def parse_with_syntax(source, file: "(input)")
|
|
66
71
|
lex(source, file: file)
|
|
@@ -76,7 +81,9 @@ module Ibex
|
|
|
76
81
|
end
|
|
77
82
|
|
|
78
83
|
# Parse without executing parser production actions.
|
|
79
|
-
#
|
|
84
|
+
# Generated lexer actions still run because they define tokenization and
|
|
85
|
+
# lexer state. Loading user sections and running lexer actions are trusted
|
|
86
|
+
# application boundaries, so this method is not a no-user-code sandbox.
|
|
80
87
|
# @rbs (String source, ?file: String) -> CST::SyntaxResult
|
|
81
88
|
def parse_syntax(source, file: "(input)")
|
|
82
89
|
parse_syntax_with_cache(CST::SourceText.new(source, file: file), CST::NodeCache.new)
|
|
@@ -98,7 +105,7 @@ module Ibex
|
|
|
98
105
|
end
|
|
99
106
|
|
|
100
107
|
# Pull one token using longest match and declaration-order tie breaking.
|
|
101
|
-
# @rbs () -> [
|
|
108
|
+
# @rbs () -> [Object?, Object?, Hash[Symbol, Object?]]
|
|
102
109
|
def next_token
|
|
103
110
|
input = @lexer_input
|
|
104
111
|
raise ParseError, "(lexer):1:1: call parse or lex before next_token" unless input
|
|
@@ -148,7 +155,7 @@ module Ibex
|
|
|
148
155
|
# @rbs (CST::SourceText source_text, CST::NodeCache cache) -> CST::LexedSyntax
|
|
149
156
|
def scan_syntax_with_cache(source_text, cache)
|
|
150
157
|
lex(source_text.text, file: source_text.file || "(input)")
|
|
151
|
-
raw_tokens = [] #: Array[Array[
|
|
158
|
+
raw_tokens = [] #: Array[Array[Object?]]
|
|
152
159
|
green_tokens = [] #: Array[CST::GreenToken]
|
|
153
160
|
states = [] #: Array[Symbol]
|
|
154
161
|
loop do
|
|
@@ -159,7 +166,7 @@ module Ibex
|
|
|
159
166
|
raw_tokens << [external, value, location]
|
|
160
167
|
green_tokens << green
|
|
161
168
|
state = location[:ibex_lexer_start_state] if location.is_a?(Hash)
|
|
162
|
-
states << (state ? state.to_sym : :INITIAL)
|
|
169
|
+
states << (state ? state.to_s.to_sym : :INITIAL)
|
|
163
170
|
break if token_id == Parser::EOF_TOKEN
|
|
164
171
|
end
|
|
165
172
|
offsets = [] #: Array[Integer]
|
|
@@ -172,7 +179,7 @@ module Ibex
|
|
|
172
179
|
CST::LexedSyntax.new(raw_tokens: raw_tokens, memo: memo)
|
|
173
180
|
end
|
|
174
181
|
|
|
175
|
-
# @rbs (Integer token_id,
|
|
182
|
+
# @rbs (Integer token_id, Object? value, Object? location, CST::NodeCache cache) -> CST::GreenToken
|
|
176
183
|
def scanned_green_token(token_id, value, location, cache)
|
|
177
184
|
leading = scanned_green_trivia(location, :leading_trivia)
|
|
178
185
|
text = if location.is_a?(Hash) && location[:ibex_cst_text].is_a?(String)
|
|
@@ -186,7 +193,7 @@ module Ibex
|
|
|
186
193
|
cache.intern_token_fields(kind: token_id, text: text, leading: leading)
|
|
187
194
|
end
|
|
188
195
|
|
|
189
|
-
# @rbs (Array[CST::GreenToken] tokens,
|
|
196
|
+
# @rbs (Array[CST::GreenToken] tokens, Object? location, CST::NodeCache cache) -> void
|
|
190
197
|
def replace_previous_scanned_trailing(tokens, location, cache)
|
|
191
198
|
trailing = scanned_green_trivia(location, :cst_previous_trailing)
|
|
192
199
|
previous = tokens.last
|
|
@@ -202,7 +209,7 @@ module Ibex
|
|
|
202
209
|
)
|
|
203
210
|
end
|
|
204
211
|
|
|
205
|
-
# @rbs (
|
|
212
|
+
# @rbs (Object? location, Symbol key) -> Array[CST::GreenTrivia]
|
|
206
213
|
def scanned_green_trivia(location, key)
|
|
207
214
|
return [] unless location.is_a?(Hash)
|
|
208
215
|
|
|
@@ -275,8 +282,8 @@ module Ibex
|
|
|
275
282
|
}
|
|
276
283
|
end
|
|
277
284
|
|
|
278
|
-
# @rbs (Hash[Symbol, untyped] rule, String lexeme, Hash[Symbol,
|
|
279
|
-
# [
|
|
285
|
+
# @rbs (Hash[Symbol, untyped] rule, String lexeme, Hash[Symbol, Object?] location) ->
|
|
286
|
+
# [Object?, Object?, Hash[Symbol, Object?]]?
|
|
280
287
|
def apply_lexer_rule(rule, lexeme, location)
|
|
281
288
|
@lexer_lexeme = lexeme
|
|
282
289
|
@lexer_emission = NO_EMISSION
|
|
@@ -310,7 +317,7 @@ module Ibex
|
|
|
310
317
|
end
|
|
311
318
|
|
|
312
319
|
# Emit a token from a lexer action.
|
|
313
|
-
# @rbs (
|
|
320
|
+
# @rbs (Object? token, ?Object? value) -> Object?
|
|
314
321
|
def emit(token, value = NO_EMISSION)
|
|
315
322
|
actual = value.equal?(NO_EMISSION) ? @lexer_lexeme : value
|
|
316
323
|
@lexer_emission = [token, actual]
|
|
@@ -330,7 +337,7 @@ module Ibex
|
|
|
330
337
|
@lexer_lexeme
|
|
331
338
|
end
|
|
332
339
|
|
|
333
|
-
# @rbs (String text, Hash[Symbol,
|
|
340
|
+
# @rbs (String text, Hash[Symbol, Object?] location) -> void
|
|
334
341
|
def retain_cst_trivia(text, _location)
|
|
335
342
|
return if cst_trivia_policy == :drop
|
|
336
343
|
|
|
@@ -344,7 +351,7 @@ module Ibex
|
|
|
344
351
|
@lexer_pending_green_trivia << value
|
|
345
352
|
end
|
|
346
353
|
|
|
347
|
-
# @rbs (Hash[Symbol,
|
|
354
|
+
# @rbs (Hash[Symbol, Object?] location) -> Hash[Symbol, Object?]
|
|
348
355
|
def attach_cst_trivia(location)
|
|
349
356
|
policy = cst_trivia_policy
|
|
350
357
|
trivia = @lexer_pending_green_trivia
|
|
@@ -481,7 +488,7 @@ module Ibex
|
|
|
481
488
|
}
|
|
482
489
|
end
|
|
483
490
|
|
|
484
|
-
# @rbs () -> Hash[Symbol,
|
|
491
|
+
# @rbs () -> Hash[Symbol, Object?]
|
|
485
492
|
def lexer_zero_width_location
|
|
486
493
|
position = lexer_position
|
|
487
494
|
{
|
|
@@ -9,10 +9,10 @@ module Ibex
|
|
|
9
9
|
# supplied by the lexer. A reduction wraps the outer boundaries in this
|
|
10
10
|
# immutable value so actions can distinguish synthesized spans.
|
|
11
11
|
class LocationSpan
|
|
12
|
-
attr_reader :start #:
|
|
13
|
-
attr_reader :finish #:
|
|
12
|
+
attr_reader :start #: Object?
|
|
13
|
+
attr_reader :finish #: Object?
|
|
14
14
|
|
|
15
|
-
# @rbs (start:
|
|
15
|
+
# @rbs (start: Object?, finish: Object?, ?empty: bool) -> void
|
|
16
16
|
def initialize(start:, finish:, empty: false)
|
|
17
17
|
@start = start
|
|
18
18
|
@finish = finish
|
|
@@ -23,7 +23,7 @@ module Ibex
|
|
|
23
23
|
# Build a span for an LR reduction. Nonempty reductions cover the first
|
|
24
24
|
# through last located RHS entry. Empty reductions are zero-width at the
|
|
25
25
|
# current lookahead location.
|
|
26
|
-
# @rbs (Array[
|
|
26
|
+
# @rbs (Array[Object?] locations, lookahead: Object?) -> LocationSpan?
|
|
27
27
|
def self.for_reduction(locations, lookahead:)
|
|
28
28
|
if locations.empty?
|
|
29
29
|
return unless lookahead
|
|
@@ -44,40 +44,40 @@ module Ibex
|
|
|
44
44
|
@empty
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
-
# @rbs () ->
|
|
47
|
+
# @rbs () -> Object?
|
|
48
48
|
def file = location_value(@start, :file)
|
|
49
49
|
|
|
50
|
-
# @rbs () ->
|
|
50
|
+
# @rbs () -> Object?
|
|
51
51
|
def line = location_value(@start, :line)
|
|
52
52
|
|
|
53
|
-
# @rbs () ->
|
|
53
|
+
# @rbs () -> Object?
|
|
54
54
|
def column = location_value(@start, :column)
|
|
55
55
|
|
|
56
|
-
# @rbs () ->
|
|
56
|
+
# @rbs () -> Object?
|
|
57
57
|
def source_line = location_value(@start, :source_line)
|
|
58
58
|
|
|
59
|
-
# @rbs () ->
|
|
59
|
+
# @rbs () -> Object?
|
|
60
60
|
def end_file
|
|
61
61
|
return file if empty?
|
|
62
62
|
|
|
63
63
|
location_value(@finish, :end_file) || location_value(@finish, :file)
|
|
64
64
|
end
|
|
65
65
|
|
|
66
|
-
# @rbs () ->
|
|
66
|
+
# @rbs () -> Object?
|
|
67
67
|
def end_line
|
|
68
68
|
return line if empty?
|
|
69
69
|
|
|
70
70
|
location_value(@finish, :end_line) || location_value(@finish, :line)
|
|
71
71
|
end
|
|
72
72
|
|
|
73
|
-
# @rbs () ->
|
|
73
|
+
# @rbs () -> Object?
|
|
74
74
|
def end_column
|
|
75
75
|
return column if empty?
|
|
76
76
|
|
|
77
77
|
location_value(@finish, :end_column) || location_value(@finish, :column)
|
|
78
78
|
end
|
|
79
79
|
|
|
80
|
-
# @rbs () -> Hash[Symbol,
|
|
80
|
+
# @rbs () -> Hash[Symbol, Object?]
|
|
81
81
|
def to_h
|
|
82
82
|
{
|
|
83
83
|
file: file, line: line, column: column,
|
|
@@ -89,12 +89,12 @@ module Ibex
|
|
|
89
89
|
class << self
|
|
90
90
|
private
|
|
91
91
|
|
|
92
|
-
# @rbs (
|
|
92
|
+
# @rbs (Object? location) -> Object?
|
|
93
93
|
def boundary_start(location)
|
|
94
94
|
location.is_a?(LocationSpan) ? location.start : location
|
|
95
95
|
end
|
|
96
96
|
|
|
97
|
-
# @rbs (
|
|
97
|
+
# @rbs (Object? location) -> Object?
|
|
98
98
|
def boundary_finish(location)
|
|
99
99
|
location.is_a?(LocationSpan) ? location.finish : location
|
|
100
100
|
end
|
|
@@ -102,7 +102,7 @@ module Ibex
|
|
|
102
102
|
|
|
103
103
|
private
|
|
104
104
|
|
|
105
|
-
# @rbs (
|
|
105
|
+
# @rbs (Object? location, Symbol key) -> Object?
|
|
106
106
|
def location_value(location, key)
|
|
107
107
|
return location.public_send(key) if location.respond_to?(key)
|
|
108
108
|
return location[key] || location[key.to_s] if location.is_a?(Hash)
|
|
@@ -57,7 +57,7 @@ module Ibex
|
|
|
57
57
|
|
|
58
58
|
private
|
|
59
59
|
|
|
60
|
-
# @rbs (Symbol type, Hash[
|
|
60
|
+
# @rbs (Symbol type, Hash[Object?, Object?] data, ?observers: Array[Proc]?) -> void
|
|
61
61
|
def emit_runtime_event(type, data, observers: runtime_observer_snapshot)
|
|
62
62
|
return unless observers
|
|
63
63
|
|