parsanol 1.3.73-aarch64-linux → 1.3.75-aarch64-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: d44785098f80ef9ed51a27badccb31294e3866fffe8e889ab97c67f6db8a5588
4
- data.tar.gz: d69ac94f5284eab7b6e6c40bfd993b62f1bab34b92e3a08532d3d1bbe8fe5686
3
+ metadata.gz: edf4ccd4b8c5c7c3378523a7fa43ef2e32e11155781bff7f873e3a49b9481a30
4
+ data.tar.gz: 9b7d86faa94485390a0c6180e3dadf4543f069ef9d354f1ccf787144139cf86b
5
5
  SHA512:
6
- metadata.gz: 4c8efa1d096a9d0320ec7326d8d498a1cfa96202d23faf4b8b1f808c38e87ef63c33d706a43b2e2b65c639edaa4f1ea1f5f6c229dcdb3ec6b5dd7771d87f81de
7
- data.tar.gz: f8d6456b7db1a205397117360c39335c6d9cc565cc7ebacb32ef79811f453a1061f77b8ff2abf683232c0ffbc5527572c3aa1596d951ea1f2b7dbe19557b59cd
6
+ metadata.gz: 6f89babe098c185419c7e1b77663fd86a6266d2d83189a4e5f4daf6aa41bcd9574e1bed3771a13ab184f5ad5704bc6ecdf9e381ca246758a23e9024eb974583b
7
+ data.tar.gz: 169f755acd8786706b437a4a35cdb1f6f476b54c128a95e360335fbbe839a100018610e056ea62081c6c2c2b757e3da6f17ef5e452f250689c83178baa008bef
@@ -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: 39109176 bytes
4
- sha256: b3467d47089b0c1b52ea453bd75478547a0bfeeaf8a7623ee66660190afcf6c9
3
+ size: 39704456 bytes
4
+ sha256: a135d135a732e11cb68dee4882527851eb8e9346da5629c9bb7df615d2a308ab
@@ -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: 39344224 bytes
4
- sha256: afe35b8257f519860d7baf36decde544b3ad56680ea70cbbb3d9253dab9b817c
3
+ size: 39939488 bytes
4
+ sha256: dfea98feff95223ada71bd842967d8595be2dc075293d923fe8e7a1a99ad811d
@@ -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: 39344064 bytes
4
- sha256: c831fc32e5395b1eeeb08b6a7896ef18e19a3669eef191e26049886f260d1829
3
+ size: 39943512 bytes
4
+ sha256: 9d5e917560b5711e58d35ed13e67ae493331f944fcee76a67cefe4ec26f10833
@@ -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: 39354120 bytes
4
- sha256: decd9a091dc652a9d564723516770ccb1520577cc243e41b3d7a8a5812c2b13a
3
+ size: 39953568 bytes
4
+ sha256: bbc70e64cef9b49c0cd0eccae472398682d171aa4472bce16eda8b5fac3b2e46
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Parsanol
4
+ module Atoms
5
+ # Matches empty and yields a constant value (coradoc-markdown
6
+ # Output parity, rs#137 follow-up): the native wire carries the
7
+ # value as wire data, so constant-yielding grammar shapes parse
8
+ # on both engines with identical trees.
9
+ class Constant < Base
10
+ attr_reader :value
11
+
12
+ def initialize(value)
13
+ super()
14
+ @value = value
15
+ end
16
+
17
+ def try(_source, _context, _consume_all)
18
+ [true, @value]
19
+ end
20
+
21
+ def to_s_inner(_prec)
22
+ "constant(#{@value.inspect})"
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Parsanol
4
+ module Atoms
5
+ # Inspects the byte window behind the current position: the
6
+ # previous +count+ bytes must equal +pattern+ (positive) or
7
+ # differ (negative). Consumes nothing, yields nil — the
8
+ # precedes?/does_not_precede? guard shape (coradoc-markdown
9
+ # parity, rs#137 follow-up).
10
+ class Lookbehind < Base
11
+ attr_reader :count, :pattern, :positive
12
+
13
+ def initialize(count, pattern, positive: true)
14
+ super()
15
+ @count = count
16
+ @pattern = pattern
17
+ @positive = positive
18
+ end
19
+
20
+ def try(source, _context, _consume_all)
21
+ start = source.bytepos
22
+ behind = start >= @count ? source.input.byteslice(start - @count, @count) : nil
23
+ matched = !behind.nil? && behind == @pattern.b
24
+ [matched == @positive, nil]
25
+ end
26
+
27
+ def to_s_inner(_prec)
28
+ "lookbehind(#{@count}, #{@pattern.inspect}, #{@positive ? '+' : '-'})"
29
+ end
30
+ end
31
+ end
32
+ end
@@ -29,6 +29,8 @@ module Parsanol
29
29
  # compiler derives markers from each capturer rule's first Str
30
30
  # atom, e.g. "//" => :line_comment); units not matching any
31
31
  # marker are whitespace-shaped and stay unrecorded.
32
+ attr_reader :capturers
33
+
32
34
  def initialize(atom, capturers)
33
35
  super(atom)
34
36
  @capturers = capturers
@@ -30,6 +30,8 @@ module Parsanol
30
30
  require "parsanol/atoms/trivia"
31
31
  require "parsanol/atoms/named"
32
32
  require "parsanol/atoms/lookahead"
33
+ require "parsanol/atoms/constant"
34
+ require "parsanol/atoms/lookbehind"
33
35
  require "parsanol/atoms/cut"
34
36
  require "parsanol/atoms/alternative"
35
37
  require "parsanol/atoms/sequence"
@@ -1,4 +1,4 @@
1
1
  [diffend] Oversized file quarantined before diffing.
2
2
  name: data/lib/parsanol/native/libparsanol.so
3
- size: 34952888 bytes
4
- sha256: fa8b3f171de5974c942b0d7ae3900c818e42919e7ad54873a21d30b5e2413b66
3
+ size: 35562848 bytes
4
+ sha256: 355e4493e98b097ba22cc503ad409039bb5611d18e616cf0ceff7cb1f364eb64
@@ -191,6 +191,13 @@ module Parsanol
191
191
  when ::Parsanol::Atoms::Lookahead
192
192
  [:lookahead, atom.positive,
193
193
  atom_structure(atom.bound_parslet, visited)]
194
+ when ::Parsanol::Atoms::Constant
195
+ # The value differentiates otherwise-identical constant
196
+ # atoms — without it every Constant hashes alike and the
197
+ # grammar cache serves the first wire forever.
198
+ [:constant, atom.value.inspect]
199
+ when ::Parsanol::Atoms::Lookbehind
200
+ [:lookbehind, atom.count, atom.pattern, atom.positive]
194
201
  else
195
202
  [:unknown, atom.class.name]
196
203
  end
@@ -18,6 +18,10 @@ module Parsanol
18
18
  def initialize
19
19
  @atoms = []
20
20
  @atom_cache = {} # object_id => atom_id for deduplication
21
+ # Strong retention: cache keys are object_ids; without holding the
22
+ # atoms, the GC can free one and a later allocation reuses its id,
23
+ # aliasing to a stale wire atom (the #138 recycled-id class).
24
+ @retained_atoms = []
21
25
  end
22
26
 
23
27
  # Main serialization method
@@ -78,6 +82,15 @@ module Parsanol
78
82
  serialize_custom_ref(atom)
79
83
  when Parsanol::Atoms::Dynamic
80
84
  serialize_dynamic(atom)
85
+ when Parsanol::Atoms::TriviaCapture
86
+ # parsanol-ruby#152: the capture wrapper carries
87
+ # its marker table so the native engine records
88
+ # comment-shaped units into the pending channel
89
+ # and attaches them to the next Named capture
90
+ # under `comments:`. A distinct variant keeps the
91
+ # declared gate: engines predating it reject
92
+ # capture-carrying artifacts loudly.
93
+ serialize_trivia_capture(atom)
81
94
  when Parsanol::Atoms::Trivia
82
95
  # Wire-distinct from Ignore (rs#172): the Rust
83
96
  # engine suppresses trivia-position diagnostics by
@@ -85,6 +98,20 @@ module Parsanol
85
98
  # reject skip-carrying artifacts loudly (unknown
86
99
  # variant), which is the declared gate.
87
100
  serialize_trivia(atom)
101
+ when Parsanol::Atoms::Constant
102
+ # rs#137 follow-up: coradoc-markdown's Output
103
+ # atoms — empty match yielding a wire constant.
104
+ { "Constant" => { "value" => serialize_constant_value(atom.value) } }
105
+ when Parsanol::Atoms::Lookbehind
106
+ # rs#137 follow-up: the precedes?/does_not_precede?
107
+ # guards — inspect the bytes behind the position.
108
+ {
109
+ "Lookbehind" => {
110
+ "count" => atom.count,
111
+ "pattern" => atom.pattern,
112
+ "positive" => atom.positive,
113
+ },
114
+ }
88
115
  when Parsanol::Atoms::Ignored
89
116
  serialize_ignored(atom)
90
117
  else
@@ -95,6 +122,7 @@ module Parsanol
95
122
  # Now reserve an atom_id and cache
96
123
  atom_id = @atoms.size
97
124
  @atom_cache[cache_key] = atom_id
125
+ @retained_atoms << atom
98
126
  @atoms << serialized
99
127
 
100
128
  atom_id
@@ -170,6 +198,7 @@ module Parsanol
170
198
  # This prevents infinite recursion when a rule references itself
171
199
  atom_id = @atoms.size
172
200
  @atom_cache[cache_key] = atom_id
201
+ @retained_atoms << atom
173
202
 
174
203
  # Add a placeholder that will be replaced
175
204
  @atoms << nil
@@ -283,6 +312,32 @@ module Parsanol
283
312
  "parse this grammar with mode: :ruby"
284
313
  end
285
314
 
315
+ def serialize_constant_value(value)
316
+ case value
317
+ when nil then "Nil" # unit variant serializes as the bare tag
318
+ when true, false then { "Bool" => value }
319
+ when Integer then { "Int" => value }
320
+ when String then { "Str" => value }
321
+ when Array then { "Array" => value.map { |v| serialize_constant_value(v) } }
322
+ when Hash
323
+ { "Hash" => value.map { |k, v| [k.to_s, serialize_constant_value(v)] } }
324
+ else
325
+ raise UnsupportedGrammar,
326
+ "constant atoms carry nil/bool/int/string/array/hash values " \
327
+ "(got #{value.class}); restructure the grammar for native parsing"
328
+ end
329
+ end
330
+
331
+ def serialize_trivia_capture(atom)
332
+ inner_id = serialize_atom(atom.wrapped_atom)
333
+ {
334
+ "TriviaCapture" => {
335
+ "atom" => inner_id,
336
+ "rules" => atom.capturers.map { |marker, label| [marker, label.to_s] },
337
+ },
338
+ }
339
+ end
340
+
286
341
  def serialize_trivia(atom)
287
342
  inner_id = serialize_atom(atom.wrapped_atom)
288
343
  {
@@ -298,9 +298,17 @@ module Parsanol
298
298
  is_repetition = value.is_a?(Array) && !value.empty? &&
299
299
  value.first.equal?(REPETITION_SYM)
300
300
 
301
+ # parsanol-ruby#152: `comments` lists are host-constructed
302
+ # trivia attachments, not parser repetitions — their unit
303
+ # hashes carry the trivia kind key, never the attachment
304
+ # key, so the re-keying below must not wrap them.
305
+ is_trivia_attachment = is_repetition && sym_key == :comments
306
+
301
307
  transformed = transform(value, named: true)
302
308
 
303
- result[sym_key] = if is_repetition
309
+ result[sym_key] = if is_trivia_attachment
310
+ transformed
311
+ elsif is_repetition
304
312
  if transformed.is_a?(Array)
305
313
  if transformed.all? do |item|
306
314
  item.is_a?(Hash) && item.key?(sym_key)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Parsanol
4
- VERSION = "1.3.73"
4
+ VERSION = "1.3.75"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: parsanol
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.73
4
+ version: 1.3.75
5
5
  platform: aarch64-linux
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-10-06 00:00:00.000000000 Z
11
+ date: 2026-10-07 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A small Ruby library for constructing parsers in the PEG (Parsing Expression
14
14
  Grammar) fashion. Parsanol provides Parslet-compatible API with additional features
@@ -37,6 +37,7 @@ files:
37
37
  - lib/parsanol/atoms/base.rb
38
38
  - lib/parsanol/atoms/can_flatten.rb
39
39
  - lib/parsanol/atoms/capture.rb
40
+ - lib/parsanol/atoms/constant.rb
40
41
  - lib/parsanol/atoms/context.rb
41
42
  - lib/parsanol/atoms/context_optimized.rb
42
43
  - lib/parsanol/atoms/custom.rb
@@ -47,6 +48,7 @@ files:
47
48
  - lib/parsanol/atoms/ignored.rb
48
49
  - lib/parsanol/atoms/infix.rb
49
50
  - lib/parsanol/atoms/lookahead.rb
51
+ - lib/parsanol/atoms/lookbehind.rb
50
52
  - lib/parsanol/atoms/named.rb
51
53
  - lib/parsanol/atoms/re.rb
52
54
  - lib/parsanol/atoms/repetition.rb