parsanol 1.3.87 → 1.3.88

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: a0b4e99564a7a93dc454c5e004acb05f2fb6884dc993a75c3eb30565c0360687
4
- data.tar.gz: 64ce48196a227e8c4f73dbc1d16a5415a278ef8a7730aaa7c8e85b45b28e75b3
3
+ metadata.gz: c24632a252a0d882d2491b361a569d8e96132f5c25942660db5c531313ebe913
4
+ data.tar.gz: 6349b99005ed86363fc2a13943a2c4e5dd4ce3958a364d12cb82ceea4c660d64
5
5
  SHA512:
6
- metadata.gz: 2fde0240109a63a418d2851ca9578293934c784a0e14c74ecf74032dab99c361c729fdb468c4a4c8fdbc39e0f836a00a04202ccc7cfc96485230adfe636c7772
7
- data.tar.gz: 516e9a87cc5577b0f00d1f994783cb0da6132105052f466f3ed4afb45b41445d29234d96443c15e39b1557d14c93395457c10d9bc5b4a2d7d30ef8393dcc4ae1
6
+ metadata.gz: 81eca9be5955bc6e28413a88622392ad25c969307a9ee3d2d29255c4c59ad543f560c06c94cbcb34044b143365ad87622115a2786b4d8e7a5dd609cb91b5d4b6
7
+ data.tar.gz: 943d81f3c10eb2e2e662ca1312d41c25f5b0cff23e455f5aec1d605d0be868dd0e682104980f4b46333d5e262399814d9cf2a9fa8626a578297a045218fff52e
data/Cargo.lock CHANGED
@@ -307,9 +307,9 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
307
307
 
308
308
  [[package]]
309
309
  name = "parsanol"
310
- version = "0.18.0"
310
+ version = "0.18.2"
311
311
  source = "registry+https://github.com/rust-lang/crates.io-index"
312
- checksum = "dc899494d6b94ea8df14279b7dcbac89d59ba4d1be52f7b8ffe840674c6c8e3c"
312
+ checksum = "b059d18a92c61ba7c7c6241bb446196729dadf618e6e34c0b79935f0292d7a27"
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.0"
329
+ version = "0.18.2"
330
330
  source = "registry+https://github.com/rust-lang/crates.io-index"
331
- checksum = "b437046956f356eee0eb9b407ff1f1f6286af1f70f1af1d305c54a64c65b64e2"
331
+ checksum = "4b9a6de83c376137ccce01cb8890427a8879b34b6ac4832cc0413c5624923001"
332
332
  dependencies = [
333
333
  "proc-macro2",
334
334
  "quote",
@@ -263,10 +263,10 @@ module Parsanol
263
263
  [false, @reporter.err(*)]
264
264
  end
265
265
 
266
- # Records one captured trivia unit (kind, text) for attachment to
267
- # the next successful Named capture.
268
- def push_captured_trivia(kind, text)
269
- @pending_trivia << { kind: kind, text: text }
266
+ # Records one captured trivia unit (kind, text, input offset)
267
+ # for attachment to the next successful Named capture.
268
+ def push_captured_trivia(kind, text, pos)
269
+ @pending_trivia << { kind: kind, text: text, pos: pos }
270
270
  nil
271
271
  end
272
272
 
@@ -41,7 +41,7 @@ module Parsanol
41
41
 
42
42
  comments = context.take_pending_trivia
43
43
  result = wrap_result(value)
44
- result = attach_comments(result, comments) unless comments.empty?
44
+ result = attach_comments(result, comments, source) unless comments.empty?
45
45
  ok(result)
46
46
  end
47
47
 
@@ -50,9 +50,13 @@ module Parsanol
50
50
  # parsanol-ruby#152: trivia captured ahead of this capture rides
51
51
  # with it under `comments:`. The attachment only fires when the
52
52
  # grammar declared capture AND trivia actually preceded — key
53
- # absence everywhere else keeps v1 trees byte-identical.
54
- def attach_comments(result, comments)
55
- list = comments.map { |unit| { unit[:kind] => unit[:text] } }
53
+ # absence everywhere else keeps v1 trees byte-identical. Units
54
+ # carry their input offset so the value is a positioned Slice,
55
+ # like every other capture value (native parity, ruby#180).
56
+ def attach_comments(result, comments, source)
57
+ list = comments.map do |unit|
58
+ { unit[:kind] => Slice.new(unit[:pos], unit[:text], source.input) }
59
+ end
56
60
  if result.is_a?(Hash)
57
61
  result.merge(comments: list)
58
62
  else
@@ -61,13 +61,17 @@ module Parsanol
61
61
  def record(source, context, start_pos, end_pos)
62
62
  text = source.input[start_pos...end_pos]
63
63
  # A trivia unit may lead with whitespace before the comment
64
- # shape; markers test the comment head.
64
+ # shape; markers test the comment head. The recorded offset
65
+ # must agree with the recorded content as a slice of the
66
+ # input: trimmed marker text starts after the unit's leading
67
+ # whitespace, not at the wrapper (native parity, ruby#180).
65
68
  stripped = text.lstrip
66
69
  marker, label = @capturers&.find { |m, _label| stripped.start_with?(m) }
67
70
  if marker
68
- context.push_captured_trivia(label, stripped.strip)
71
+ context.push_captured_trivia(label, stripped.strip,
72
+ start_pos + (text.length - stripped.length))
69
73
  elsif @whitespace_kind
70
- context.push_captured_trivia(@whitespace_kind, text)
74
+ context.push_captured_trivia(@whitespace_kind, text, start_pos)
71
75
  end
72
76
  end
73
77
  end
@@ -310,9 +310,16 @@ module Parsanol
310
310
  transformed
311
311
  elsif is_repetition
312
312
  if transformed.is_a?(Array)
313
- if transformed.all? do |item|
314
- item.is_a?(Hash) && item.key?(sym_key)
315
- end
313
+ if transformed.all?(Hash)
314
+ # Hash items carry their own capture
315
+ # names (parslet semantics) — the
316
+ # single-key path
317
+ # (transform_repetition_value) already
318
+ # keeps them; this multi-key path (a
319
+ # Named with a trivia attachment, or
320
+ # merged siblings) must agree — only
321
+ # unnamed items take the parent name
322
+ # per item.
316
323
  transformed
317
324
  else
318
325
  transformed.map { |item| { sym_key => item } }
@@ -296,29 +296,49 @@ module Parsanol
296
296
  if peek&.type == :punct && peek.value == "*"
297
297
  advance
298
298
  max = peek&.type == :num ? advance.value.to_i : nil
299
- node = Node.new(:rep, parse_postfixed, min, max)
299
+ node = Node.new(:rep, parse_rep_body, min, max)
300
300
  else
301
- node = Node.new(:rep, parse_postfixed, min, min)
301
+ node = Node.new(:rep, parse_rep_body, min, min)
302
302
  end
303
- return node
303
+ return capture_postfix(node)
304
304
  elsif token.type == :punct && token.value == "*"
305
305
  advance
306
306
  max = peek&.type == :num ? advance.value.to_i : nil
307
- return Node.new(:rep, parse_postfixed, 0, max)
307
+ return capture_postfix(Node.new(:rep, parse_rep_body, 0, max))
308
308
  end
309
309
  parse_postfixed
310
310
  end
311
311
 
312
- def parse_postfixed
312
+ # A repetition's body must not claim the `as` that follows the
313
+ # repetition's own closing paren (parsanol-ruby#197): the body
314
+ # parser is postfix-blind, and the postfix wraps the REPETITION —
315
+ # `*( X ) as name` captures the whole repeated run, matching the
316
+ # Ruby DSL's `.repeat.as(:name)`. An `as` inside the body's own
317
+ # parens still binds the body — write `*( ( X ) as name )` for
318
+ # that (naming each iteration's X).
319
+ def parse_rep_body
313
320
  sign = nil
314
321
  if peek&.type == :punct && %w[! &].include?(peek.value)
315
322
  sign = advance.value == "&"
316
323
  end
317
324
  node = parse_primary
325
+ sign.nil? ? node : Node.new(:pred, sign, node)
326
+ end
327
+
328
+ def capture_postfix(node)
318
329
  if peek&.type == :ident && peek.value == "as"
319
330
  advance
320
331
  node = Node.new(:cap, ident.value, node)
321
332
  end
333
+ node
334
+ end
335
+
336
+ def parse_postfixed
337
+ sign = nil
338
+ if peek&.type == :punct && %w[! &].include?(peek.value)
339
+ sign = advance.value == "&"
340
+ end
341
+ node = capture_postfix(parse_primary)
322
342
  sign.nil? ? node : Node.new(:pred, sign, node)
323
343
  end
324
344
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Parsanol
4
- VERSION = "1.3.87"
4
+ VERSION = "1.3.88"
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.87
4
+ version: 1.3.88
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.