parsanol 1.3.99-arm-linux → 1.3.101-arm-linux

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '0449928649d5a003cea029230dccdb8d4a1cf5e15a3115d713396f256e5a4cbf'
4
- data.tar.gz: 6f78bd36cb506e26a808d16d0e82cab33d1d4af239ff2850247b9ff29925e51a
3
+ metadata.gz: 4fd1314a9ec192bbb07d077678f6b47ee816c6aceb22f5f8c6e37eedf5437703
4
+ data.tar.gz: 7a1bfe5c2d16e243ae40f5c3f711888937c8fb98c18d8e6d88ce180ee551e100
5
5
  SHA512:
6
- metadata.gz: dc51f046f4d0e11b562f8dc35d37eed3476cb6d6bc77f0692d5363b87a8707444f04f4416a1dfef85db1a6e3dbb551f3477145831e2daa1cf21159646c086ef6
7
- data.tar.gz: 02bcffde2c4565099de61ffc31de674f24c244bbb1ac2bb5820ae5c4636d780f775ce092f57c64c2d8a47706a275899e7ea4358ffe26a93ee6b204a7b9609859
6
+ metadata.gz: 2fbfffa60cb521128df34e153537b2a692c7cb93e513b56f8a2fc3d00d7655504c21f7e3c6b55465d2d4d3ade007fce8a01b798191d43dddfe2a668c13895081
7
+ data.tar.gz: 10b1b6cef6d8490591e061d303dc264acf836313b414aeb26f016afdb089c3d27b6286c08921acfc0317fade20e9d70f1af26346d765453ce30b53107c0f9c6d
@@ -1,4 +1,4 @@
1
1
  [diffend] Oversized file quarantined before diffing.
2
2
  name: data/lib/parsanol/3.2/parsanol_native.so
3
- size: 34547268 bytes
4
- sha256: 5ffe08395738b583a3472e832256ff294510921a25ff6e53dc90c951905191ec
3
+ size: 34471380 bytes
4
+ sha256: b173569fc4832c4463657ee385337964d42d85f0aa13847b0c1044d2fcc55f70
@@ -1,4 +1,4 @@
1
1
  [diffend] Oversized file quarantined before diffing.
2
2
  name: data/lib/parsanol/3.3/parsanol_native.so
3
- size: 34732408 bytes
4
- sha256: c187d2bd208b1d8aef9c66f4d3188496789e48b93dc6fb59c65cbbfcd300a6ca
3
+ size: 34656540 bytes
4
+ sha256: 960c9d040d78fc90dbf5aa42b9b4d4685db1962a9b4ec22f905820d87a48ac26
@@ -1,4 +1,4 @@
1
1
  [diffend] Oversized file quarantined before diffing.
2
2
  name: data/lib/parsanol/3.4/parsanol_native.so
3
- size: 34726616 bytes
4
- sha256: 14dcfeb7a0bad418583ac54f7430c5212c273c5df0a3e0ae3eaba8ed14156907
3
+ size: 34650712 bytes
4
+ sha256: 0fd3652b9a3da3d83cca520dcee15bf02d5497ad97e3c9a23529d5813e7ef51b
@@ -1,4 +1,4 @@
1
1
  [diffend] Oversized file quarantined before diffing.
2
2
  name: data/lib/parsanol/4.0/parsanol_native.so
3
- size: 34736332 bytes
4
- sha256: 8eb3b9649e9070ee5ec045863c45cdc50a4ae76faf0c0c45fa6f26f15e503db4
3
+ size: 34660448 bytes
4
+ sha256: 905510a7562305c41aa2e1bb9a1a081fe8ecc42c379f02d3481d9f713d71d193
@@ -236,9 +236,15 @@ module Parsanol
236
236
  end
237
237
 
238
238
  # Reports detailed error by reparsing with reporter.
239
+ #
240
+ # The default reporter is Deepest (parsanol-ruby#265): the native
241
+ # engine's failure diagnostics report the furthest failure, and a
242
+ # consumer's file:line:col degrades to "line 1 char 1" when the
243
+ # interpreter raises the outermost sequence instead. Explicit
244
+ # reporters (Tree for full cause trees) are honored unchanged.
239
245
  def report_detailed_error(input, consume_all, reporter, _initial_error)
240
246
  input.bytepos = 0
241
- error_reporter = reporter || Parsanol::ErrorReporter::Tree.new
247
+ error_reporter = reporter || Parsanol::ErrorReporter::Deepest.new
242
248
  success, cause = run_with_context(input, error_reporter, consume_all)
243
249
 
244
250
  # Second parse should also fail
@@ -211,6 +211,7 @@ module Parsanol
211
211
 
212
212
  # Check minimum bound
213
213
  if occurrence < @min
214
+ Recovery.stash_partial(source.bytepos, result[1, occurrence], @result_tag)
214
215
  source.bytepos = start_pos
215
216
  return context.err_at(self, source, min_error, start_pos,
216
217
  failure_children(last_failure))
@@ -218,6 +219,9 @@ module Parsanol
218
219
 
219
220
  # Check complete consumption
220
221
  if consume_all && source.chars_left.positive?
222
+ # R1.5: the partial run IS the best partial root — stash it
223
+ # before reporting the leftover-input failure.
224
+ Recovery.stash_partial(source.bytepos, result[1, occurrence], @result_tag)
221
225
  return context.err(self, source, @extra_error,
222
226
  failure_children(last_failure))
223
227
  end
@@ -98,12 +98,16 @@ module Parsanol
98
98
  # @return [Array<Integer, Parsanol::Cause>] [depth, deepest_leaf]
99
99
  #
100
100
  def find_deepest_leaf(node, rank = 0)
101
+ return [rank, node] if node.nil?
102
+
101
103
  best_node = node
102
104
  best_rank = rank
103
105
 
104
106
  kids = node.children
105
107
  if kids && !kids.empty?
106
108
  kids.each do |kid|
109
+ next if kid.nil?
110
+
107
111
  kid_rank, kid_node = find_deepest_leaf(kid, rank + 1)
108
112
 
109
113
  if kid_rank > best_rank
Binary file
@@ -282,8 +282,10 @@ module Parsanol
282
282
  if parsanol_grammar
283
283
  # No native diagnostics (e.g. incomplete-input errors): one
284
284
  # interpreter pass with the reporter attached — a success
285
- # recovers the tree, a failure raises the cause tree.
286
- reporter = Parsanol::ErrorReporter::Tree.new
285
+ # recovers the tree, a failure raises the cause tree. Deepest
286
+ # keeps the fallback's diagnostics at parity with the direct
287
+ # interpreter path (parsanol-ruby#265).
288
+ reporter = Parsanol::ErrorReporter::Deepest.new
287
289
  source = Parsanol::Source.new(input)
288
290
  success, value = grammar.run_with_context(source, reporter, true)
289
291
  return grammar.finalize_result(value) if success
@@ -217,14 +217,51 @@ module Parsanol
217
217
  shape = parse(entry_name, input, mode: mode)
218
218
  { "ok" => true, "shape" => shape }
219
219
  rescue Parsanol::ParseFailed => e
220
+ # The journaling re-parse fails at the same point with the
221
+ # interpreter's deepest cause — report ITS error, not the
222
+ # initial parse's (the native FFI's coarse failure position
223
+ # loses the deepest offset).
224
+ captures, reparse_error = recovery_journal(entry_name, input, mode)
220
225
  { "ok" => false,
221
- "error" => recovery_error(e),
222
- "captures" => recovery_journal(entry_name, input, mode) }
226
+ "error" => reparse_error || recovery_error(e),
227
+ "captures" => captures,
228
+ "partial" => recovery_partial(entry_name) }
229
+ end
230
+
231
+ # R1.5 (TODO.sota/1): the deepest repetition prefix the failed
232
+ # journaling pass matched, shaped like the root (the item array
233
+ # under the root rule's name). Nil when nothing matched.
234
+ def recovery_partial(entry_name)
235
+ stash = Parsanol::Recovery.take_partial
236
+ return nil if stash.nil?
237
+
238
+ _end_pos, items, _tag = stash
239
+ # The stash holds raw per-iteration results; the root atom's
240
+ # flatten (the same laws the success shape goes through) turns
241
+ # sequence-tagged iterations into their shaped values.
242
+ flattened = items.map { |item| root_atom(entry_name).flatten(item) }
243
+ root_name = entry(entry_name)["root"].to_sym
244
+ { root_name => flattened }
223
245
  end
224
246
 
225
247
  def recovery_error(err)
226
- pos = err.parse_failure_cause&.position
227
- { "offset" => pos, "message" => err.message }
248
+ cause = err.parse_failure_cause
249
+ # The raised cause can sit shallower than the real failure (a
250
+ # consume-all leftover reported at the partial run's end);
251
+ # recovery annotations carry the DEEPEST position in the cause
252
+ # tree — the same semantics as the rs engine's failure wire.
253
+ { "offset" => cause && deepest_position(cause),
254
+ "message" => err.message }
255
+ end
256
+
257
+ def deepest_position(cause)
258
+ max = cause.position
259
+ Array(cause.children).each do |child|
260
+ next if child.nil?
261
+
262
+ max = [max, deepest_position(child)].max
263
+ end
264
+ max
228
265
  end
229
266
 
230
267
  # Journaling re-parse — always on the Ruby engine (journaling
@@ -233,18 +270,21 @@ module Parsanol
233
270
  # by the differential specs, so the observed captures agree.
234
271
  def recovery_journal(entry_name, input, _mode)
235
272
  Parsanol::Recovery.start_journal
273
+ reparse_error = nil
236
274
  begin
237
275
  parse(entry_name, input, mode: :ruby)
238
- rescue Parsanol::ParseFailed
276
+ rescue Parsanol::ParseFailed => e
239
277
  # expected: the journaling pass fails at the same point
278
+ reparse_error = recovery_error(e)
240
279
  end
241
- Parsanol::Recovery.stop_journal.each_with_object({}) do |(name, value), out|
280
+ captures = Parsanol::Recovery.stop_journal.each_with_object({}) do |(name, value), out|
242
281
  # Both the initial attempt and the diagnostic re-parse journal
243
282
  # into the shared thread-local; identical observations dedupe.
244
283
  wire = value.is_a?(Slice) ? slice_wire(value) : value
245
284
  (out[name.to_s] ||= []) << wire
246
285
  out[name.to_s].uniq!
247
286
  end
287
+ [captures, reparse_error]
248
288
  end
249
289
 
250
290
  def slice_wire(slice)
@@ -11,6 +11,10 @@ module Parsanol
11
11
  def start_journal
12
12
  Thread.current[:parsanol_recovery_journal] = []
13
13
  Thread.current[:parsanol_recovery_journaling] = true
14
+ # R1.5 partial-tree collection rides the journaling (recovery)
15
+ # pass: success paths never touch the stash.
16
+ Thread.current[:parsanol_recovery_partial] = nil
17
+ Thread.current[:parsanol_recovery_collect_partial] = true
14
18
  end
15
19
 
16
20
  # Stops journaling and returns the journal: [name, value] pairs in
@@ -29,5 +33,25 @@ module Parsanol
29
33
  def journaling?
30
34
  Thread.current[:parsanol_recovery_journaling] == true
31
35
  end
36
+
37
+ # R1.5: the deepest repetition prefix matched before the failure.
38
+ # Repetition failure paths call stash_partial; the furthest-reaching
39
+ # prefix wins. [end_pos, items, tag]
40
+ def stash_partial(end_pos, items, tag)
41
+ return unless Thread.current[:parsanol_recovery_collect_partial]
42
+ return if items.empty? # nothing matched: no partial, like rs
43
+
44
+ current = Thread.current[:parsanol_recovery_partial]
45
+ return if current && current[0] >= end_pos
46
+
47
+ Thread.current[:parsanol_recovery_partial] = [end_pos, items.dup, tag]
48
+ end
49
+
50
+ def take_partial
51
+ value = Thread.current[:parsanol_recovery_partial]
52
+ Thread.current[:parsanol_recovery_partial] = nil
53
+ Thread.current[:parsanol_recovery_collect_partial] = nil
54
+ value
55
+ end
32
56
  end
33
57
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Parsanol
4
- VERSION = "1.3.99"
4
+ VERSION = "1.3.101"
5
5
  end
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.99
4
+ version: 1.3.101
5
5
  platform: arm-linux
6
6
  authors:
7
7
  - Ribose Inc.