parsanol 1.3.95 → 1.3.96
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/Cargo.lock +4 -4
- data/lib/parsanol/atoms/context.rb +8 -0
- data/lib/parsanol/atoms/named.rb +2 -0
- data/lib/parsanol/native.rb +14 -0
- data/lib/parsanol/parg/artifact.rb +47 -0
- data/lib/parsanol/recovery.rb +33 -0
- data/lib/parsanol/version.rb +1 -1
- data/lib/parsanol.rb +1 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz: '
|
|
3
|
+
metadata.gz: 3361d31dc03ae64b82fbc5ac5429f28984b387f47b6de6f4dc782a192d75a396
|
|
4
|
+
data.tar.gz: '08c24046572b0bff4f377dfd959503d2fd86aa31c442af01e5c354f0a08e6af6'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 87807af6107e2df8acd840da4a815a7e432fb84cdd7f5dce3b6c737122179fe2d808d9cd259829f40b41945e9f20e85d76a99f92b04d4d31e6dc9e497518af44
|
|
7
|
+
data.tar.gz: 0a0250d855f6330a8bd0f559d8a02419f448e0f402801aa9eba97272d0e683f02a8f3557f35ad4b4b6b10ca59f11035542fb55f545048eb7af0d4030c4dd81bc
|
data/Cargo.lock
CHANGED
|
@@ -307,9 +307,9 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
|
|
307
307
|
|
|
308
308
|
[[package]]
|
|
309
309
|
name = "parsanol"
|
|
310
|
-
version = "0.18.
|
|
310
|
+
version = "0.18.9"
|
|
311
311
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
312
|
-
checksum = "
|
|
312
|
+
checksum = "456a6ee7850bd50d2254b3232d537af2de447ea354a40a06a33904da899cd57b"
|
|
313
313
|
dependencies = [
|
|
314
314
|
"ahash",
|
|
315
315
|
"getrandom 0.3.4",
|
|
@@ -326,9 +326,9 @@ dependencies = [
|
|
|
326
326
|
|
|
327
327
|
[[package]]
|
|
328
328
|
name = "parsanol-derive"
|
|
329
|
-
version = "0.18.
|
|
329
|
+
version = "0.18.9"
|
|
330
330
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
331
|
-
checksum = "
|
|
331
|
+
checksum = "280663d376aefe51ad6850535618f67fbb281d48f6ac024fad560ee39029ace1"
|
|
332
332
|
dependencies = [
|
|
333
333
|
"proc-macro2",
|
|
334
334
|
"quote",
|
|
@@ -72,6 +72,10 @@ module Parsanol
|
|
|
72
72
|
# and the NEXT successful Named capture attaches (and drains)
|
|
73
73
|
# them under `comments:`.
|
|
74
74
|
@pending_trivia = []
|
|
75
|
+
|
|
76
|
+
# Recovery journal (TODO.sota/1): non-nil only in recovery
|
|
77
|
+
# re-parses; Named captures append to the shared array.
|
|
78
|
+
@recovery_journal = Parsanol::Recovery.journal if Parsanol::Recovery.journaling?
|
|
75
79
|
@evict_threshold = 200
|
|
76
80
|
@evict_counter = 0
|
|
77
81
|
@evict_interval = 100
|
|
@@ -327,6 +331,10 @@ module Parsanol
|
|
|
327
331
|
# @return [Parsanol::Scope] capture variable bindings
|
|
328
332
|
attr_reader :captures
|
|
329
333
|
|
|
334
|
+
# Recovery journal (TODO.sota/1): a shared array when this
|
|
335
|
+
# context was created inside a recovery re-parse; nil otherwise.
|
|
336
|
+
attr_accessor :recovery_journal
|
|
337
|
+
|
|
330
338
|
# @return [Parsanol::Pools::ArrayPool] array object pool
|
|
331
339
|
attr_reader :array_pool
|
|
332
340
|
|
data/lib/parsanol/atoms/named.rb
CHANGED
|
@@ -42,6 +42,8 @@ module Parsanol
|
|
|
42
42
|
comments = context.take_pending_trivia
|
|
43
43
|
result = wrap_result(value)
|
|
44
44
|
result = attach_comments(result, comments, source) unless comments.empty?
|
|
45
|
+
# Recovery journal (TODO.sota/1): nil on every normal parse.
|
|
46
|
+
context.recovery_journal << [@name, result] if context.recovery_journal
|
|
45
47
|
ok(result)
|
|
46
48
|
end
|
|
47
49
|
|
data/lib/parsanol/native.rb
CHANGED
|
@@ -382,6 +382,20 @@ module Parsanol
|
|
|
382
382
|
:unavailable
|
|
383
383
|
end
|
|
384
384
|
end
|
|
385
|
+
name_cache_version if @native_state == :loaded
|
|
386
|
+
@native_state
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
private
|
|
390
|
+
|
|
391
|
+
# Compiled VM programs are cached on disk across processes; naming
|
|
392
|
+
# this gem release in the cache key means a new release never runs
|
|
393
|
+
# a program an older one compiled. Extensions built before the
|
|
394
|
+
# engine grew the hook simply skip it.
|
|
395
|
+
def name_cache_version
|
|
396
|
+
return unless respond_to?(:_set_cache_version)
|
|
397
|
+
|
|
398
|
+
_set_cache_version("parsanol-ruby #{Parsanol::VERSION}")
|
|
385
399
|
end
|
|
386
400
|
end
|
|
387
401
|
end
|
|
@@ -197,6 +197,53 @@ module Parsanol
|
|
|
197
197
|
end
|
|
198
198
|
end
|
|
199
199
|
|
|
200
|
+
# Best-effort recovery (TODO.sota/1, R1): on success returns
|
|
201
|
+
# {"ok": true, "shape": tree}; on ParseFailed returns
|
|
202
|
+
# {"ok": false, "error": {"offset", "message"}, "captures":
|
|
203
|
+
# {name => [values...]}} — the captures observed before the
|
|
204
|
+
# failure, from a journaling re-parse on the Ruby engine (tree
|
|
205
|
+
# parity with the native engine is enforced by the differential
|
|
206
|
+
# specs). The journal is best-effort: it may include captures
|
|
207
|
+
# from branches that later failed.
|
|
208
|
+
def parse_recovering(entry_name, input, mode: :native)
|
|
209
|
+
shape = parse(entry_name, input, mode: mode)
|
|
210
|
+
{ "ok" => true, "shape" => shape }
|
|
211
|
+
rescue Parsanol::ParseFailed => e
|
|
212
|
+
{ "ok" => false,
|
|
213
|
+
"error" => recovery_error(e),
|
|
214
|
+
"captures" => recovery_journal(entry_name, input, mode) }
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def recovery_error(err)
|
|
218
|
+
pos = err.parse_failure_cause&.position
|
|
219
|
+
{ "offset" => pos, "message" => err.message }
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
# Journaling re-parse — always on the Ruby engine (journaling
|
|
223
|
+
# rides the interpreter's diagnostic reparse; the native engine
|
|
224
|
+
# has no journal). Tree parity with the native engine is enforced
|
|
225
|
+
# by the differential specs, so the observed captures agree.
|
|
226
|
+
def recovery_journal(entry_name, input, _mode)
|
|
227
|
+
Parsanol::Recovery.start_journal
|
|
228
|
+
begin
|
|
229
|
+
parse(entry_name, input, mode: :ruby)
|
|
230
|
+
rescue Parsanol::ParseFailed
|
|
231
|
+
# expected: the journaling pass fails at the same point
|
|
232
|
+
end
|
|
233
|
+
Parsanol::Recovery.stop_journal.each_with_object({}) do |(name, value), out|
|
|
234
|
+
# Both the initial attempt and the diagnostic re-parse journal
|
|
235
|
+
# into the shared thread-local; identical observations dedupe.
|
|
236
|
+
wire = value.is_a?(Slice) ? slice_wire(value) : value
|
|
237
|
+
(out[name.to_s] ||= []) << wire
|
|
238
|
+
out[name.to_s].uniq!
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def slice_wire(slice)
|
|
243
|
+
{ "value" => slice.to_s, "offset" => slice.offset,
|
|
244
|
+
"length" => slice.content.length }
|
|
245
|
+
end
|
|
246
|
+
|
|
200
247
|
def test_to_hash(test)
|
|
201
248
|
{
|
|
202
249
|
"entry" => test.entry,
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Parsanol
|
|
4
|
+
# Recovery journaling (TODO.sota/1): when enabled for the current
|
|
5
|
+
# thread, every Named capture appends to a shared journal for the
|
|
6
|
+
# duration of the recovery re-parse. Success paths never enable it —
|
|
7
|
+
# normal parses see only a nil-context check.
|
|
8
|
+
module Recovery
|
|
9
|
+
module_function
|
|
10
|
+
|
|
11
|
+
def start_journal
|
|
12
|
+
Thread.current[:parsanol_recovery_journal] = []
|
|
13
|
+
Thread.current[:parsanol_recovery_journaling] = true
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Stops journaling and returns the journal: [name, value] pairs in
|
|
17
|
+
# capture order, including captures from branches that later failed
|
|
18
|
+
# (best-effort superset — same semantics as the rs recovery
|
|
19
|
+
# journal).
|
|
20
|
+
def stop_journal
|
|
21
|
+
Thread.current[:parsanol_recovery_journaling] = false
|
|
22
|
+
journal
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def journal
|
|
26
|
+
Thread.current[:parsanol_recovery_journal] || []
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def journaling?
|
|
30
|
+
Thread.current[:parsanol_recovery_journaling] == true
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
data/lib/parsanol/version.rb
CHANGED
data/lib/parsanol.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: parsanol
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.3.
|
|
4
|
+
version: 1.3.96
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
@@ -150,6 +150,7 @@ files:
|
|
|
150
150
|
- lib/parsanol/pools/position_pool.rb
|
|
151
151
|
- lib/parsanol/pools/slice_pool.rb
|
|
152
152
|
- lib/parsanol/position.rb
|
|
153
|
+
- lib/parsanol/recovery.rb
|
|
153
154
|
- lib/parsanol/resettable.rb
|
|
154
155
|
- lib/parsanol/result.rb
|
|
155
156
|
- lib/parsanol/result_builder.rb
|