parsanol 1.3.113 → 1.3.114

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: d9a04b4f0add7d25933bf9ddd041f28cf067e9b2750abb6595915d63cdd4cd3a
4
- data.tar.gz: 69767361cdcb52ddeb7e0dbd4b05498e72fffe4d64639c4c5d00aad723f7c659
3
+ metadata.gz: c113bca1ed586242d379c7be03cda7897c6cbb2862d2305f9257cd7670b5e62b
4
+ data.tar.gz: 4aa6a7a5e0d7f8d7c8ab5424b89d02d6835beee3f12e8cfacefe07e07d3344b4
5
5
  SHA512:
6
- metadata.gz: 8407c77dbca38833e2e2ddf189d601be84ed14f07bbe5e972feb76ce016df3f88c7725951ed20ba74b5403ad83dae25fef8d3f1259c6312e6e4158e709c037ba
7
- data.tar.gz: 9fe4fd4df2ba548a686226ee50c80c60945dfad0e3719d7b1593fe9678a5a2f464df833940cb87201e86b98243c025d94ab42664b914f29ea3ca2649773c6aff
6
+ metadata.gz: 3259ed625a354e9d36ec43c2737f8d7c0c91e783ca6f573317f0a61a6f0268073f426cc3866721262cca167fd6ee0d7a112751741720dadf1ac9a858a3acb79d
7
+ data.tar.gz: 51fe65b35a4cef0f660148e90331cb0bae788710c35214baa2d0139a9e516faa0c43e75004bbd23d0874e68fdddf01fb5c437135399f2c1e2198b8742f8310f5
data/Cargo.lock CHANGED
@@ -307,9 +307,9 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
307
307
 
308
308
  [[package]]
309
309
  name = "parsanol"
310
- version = "0.19.7"
310
+ version = "0.19.8"
311
311
  source = "registry+https://github.com/rust-lang/crates.io-index"
312
- checksum = "5233088cf0cde65b9a6e5e41d558b689becc722ccf156946c8f118049f2d3f5c"
312
+ checksum = "86357f129e791c3b7b79a0a8a2b10c7ad00a2e0f8452224bc1cd15b81a7d5c31"
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.19.7"
329
+ version = "0.19.8"
330
330
  source = "registry+https://github.com/rust-lang/crates.io-index"
331
- checksum = "c84688541fbbd11509183b9c53debd924bcdbfae8cf8aca053414ea11a7aa7e9"
331
+ checksum = "45bbd7570b3fe0a704e1db635f2f54b792d34646576794244646e88f4575c06d"
332
332
  dependencies = [
333
333
  "proc-macro2",
334
334
  "quote",
@@ -233,12 +233,24 @@ module Parsanol
233
233
  # compile time — the tree shape consumers read, opt-in via
234
234
  # `mode` in the grammar header. Engines see ordinary
235
235
  # Named atoms; identity rides the differential corpus.
236
- def apply_modern_captures(atom)
236
+ def apply_modern_captures(atom, rule_name)
237
237
  return atom if @document.edition == "v1"
238
+ # A glue rule's own body compiles unwrapped (parsanol-ruby#364):
239
+ # the declaration means the tree never sees this subtree named,
240
+ # inside or out.
241
+ return atom if glue_rule?(rule_name)
238
242
 
239
243
  wrap_uncaptured(atom)
240
244
  end
241
245
 
246
+ # The `glue` declaration's verdict (parsanol-ruby#364): references
247
+ # to declared glue rules never wrap — the trivia exemption's
248
+ # "glue never becomes a capture", author-declared for rules that
249
+ # eat more than whitespace.
250
+ def glue_rule?(name)
251
+ @document.glue_rules.include?(name.to_s)
252
+ end
253
+
242
254
  def wrap_uncaptured(atom)
243
255
  case atom
244
256
  when Atoms::Named
@@ -254,10 +266,11 @@ module Parsanol
254
266
  # capture-producing refs both stay unwrapped; the bodies
255
267
  # agree by design.
256
268
  if trivia_only?(atom.rule_name.to_s, { atom.rule_name.to_s => true }) ||
269
+ glue_rule?(atom.rule_name.to_s) ||
257
270
  produces_capture?(atom.parslet)
258
271
  atom
259
272
  else
260
- Atoms::Named.new(atom, atom.rule_name.to_s)
273
+ Atoms::Named.new(atom, atom.rule_name.to_sym)
261
274
  end
262
275
  # rubocop:enable Lint/DuplicateBranch
263
276
  when Atoms::Sequence, Atoms::Alternative
@@ -440,9 +453,10 @@ module Parsanol
440
453
  case atom
441
454
  when Atoms::Named then nil
442
455
  when Atoms::Entity
443
- # Mirror wrap_uncaptured's verdicts: trivia glue and
444
- # capture-producing refs both stay bare.
456
+ # Mirror wrap_uncaptured's verdicts: trivia glue, declared
457
+ # glue, and capture-producing refs all stay bare.
445
458
  unless trivia_only?(atom.rule_name.to_s, { atom.rule_name.to_s => true }) ||
459
+ glue_rule?(atom.rule_name.to_s) ||
446
460
  produces_capture?(atom.parslet)
447
461
  lines << "rule #{site}: reference to #{atom.rule_name} produces no capture -- " \
448
462
  "modern mode would name it #{atom.rule_name}"
@@ -482,7 +496,7 @@ module Parsanol
482
496
  # atom_for; a mutual-reference grammar must hit the cache,
483
497
  # not rebuild), then the cache takes the wrapped tree.
484
498
  @atom_cache[name] = atom
485
- atom = apply_modern_captures(atom)
499
+ atom = apply_modern_captures(atom, name)
486
500
  @atom_cache[name] = atom
487
501
  atom
488
502
  end
@@ -18,7 +18,7 @@ module Parsanol
18
18
  Test = Struct.new(:entry, :kind, :input, :expect)
19
19
 
20
20
  attr_accessor :grammar_name, :version, :edition, :source, :uses, :skip_declaration, :skip_source,
21
- :atomic_rules, :skip_capture_key, :brace_rules
21
+ :atomic_rules, :skip_capture_key, :brace_rules, :glue_rules
22
22
  # R2 declared resync: rule name -> skip pattern (the span matched
23
23
  # at a recovery point is consumed as annotated error text).
24
24
  attr_reader :resyncs
@@ -60,6 +60,10 @@ module Parsanol
60
60
  # contiguously).
61
61
  @atomic_rules = []
62
62
  @brace_rules = []
63
+ # Rules declared `glue <name> ...` (parsanol-ruby#364): the
64
+ # edition-2 wrap never names them — references stay bare and
65
+ # the rule's own body compiles unwrapped.
66
+ @glue_rules = []
63
67
  @authored_rules = nil
64
68
  # R2 declared resync: rule -> skip pattern. Recovery consumes
65
69
  # each pattern match at a failure point as annotated error text
@@ -338,6 +338,24 @@ module Parsanol
338
338
  skip_newlines
339
339
  next
340
340
  end
341
+ # `glue <rule> [<rule>...]` (parsanol-ruby#364): names rules
342
+ # whose references edition 2 never wraps — glue the tree must
343
+ # not see. Same-line names accumulate; the declaration may
344
+ # appear any number of times.
345
+ if peek&.type == :ident && peek.value == "glue"
346
+ advance
347
+ names = []
348
+ while peek&.type == :ident
349
+ names << ident.value
350
+ end
351
+ if names.empty?
352
+ raise ParseError, "glue must name at least one rule"
353
+ end
354
+
355
+ document.glue_rules.concat(names)
356
+ skip_newlines
357
+ next
358
+ end
341
359
  # `atomic <rule> = ...` suppresses skip-trivia injection inside
342
360
  # the rule body: token-shaped rules match their input
343
361
  # contiguously instead of spanning trivia between iterations.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Parsanol
4
- VERSION = "1.3.113"
4
+ VERSION = "1.3.114"
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.113
4
+ version: 1.3.114
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.