parsanol 1.3.127-arm-linux → 1.3.129-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: 5101db070cd884f1f589f7c8b8d338a50231abc1a10095fede11993d1d5c4cc3
4
- data.tar.gz: 22226c62d53e1a291f0ee0ca0d4499b56d6fc82848171c85bb7d947e69e1ada7
3
+ metadata.gz: cc5b22c92ad2b6c2155b050c0a904e293758b6ba6a50a4be0ca5f3676f957a2a
4
+ data.tar.gz: f600012d26f0a706a1818980a3f98148c05c8b918ab9457e205cda11abbd39ce
5
5
  SHA512:
6
- metadata.gz: 131b1ee7c45c3d7103150a4fc99e22f3e3fefcb63672fa3a38151d36a16fb57f7ec7af617b17a7f5089471b8fbc24d39c1a70f9ed3846e727159aa598e413f02
7
- data.tar.gz: 8ea0a3732614b334bc6729d4c1c6bb84c66fdb46ca01b020a8d73db7c8b55b989851ae0e17ce15b1cba50314365d93dbf4553178ddd7f0abb10971036b780c3b
6
+ metadata.gz: 65cd647e2615a8c71cf6cdad62af2cf68180057a48376ec922210823177bec264f354f8a2e71f3bbb850fc9be72819b0c509f9e86d0463f15dd7e3a880adca0d
7
+ data.tar.gz: 1f7a4dd5fec3525487cc74396da93cd146c32a8ab3cc5878fe4ce6a155bead0722489397adff87e4c3dd2747460e2ac99717bb788ce67a33c4e8c17e71905452
@@ -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: 39740032 bytes
4
- sha256: c8d53988b1b0272b424a9e999eb14410a7d8633b97a12fc7a290fbe49e8b3182
3
+ size: 39723288 bytes
4
+ sha256: 10f38f0f0c6e8836e1a8066a52c3cd24f470b8e8a825ac8b4d5efd77c68f20b4
@@ -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: 39925276 bytes
4
- sha256: 9583103439fe4fd1c54990622ca380e01cb864dc11d4946fccd72823f344d7b0
3
+ size: 39908464 bytes
4
+ sha256: 92b5490941807ecb46f0756350eaa5dbab93733780db0df1bc1e490abb8d2a8e
@@ -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: 39919376 bytes
4
- sha256: 840045138064b78a947c1e1675c57921c963a7df7cd055407572969d99a28518
3
+ size: 39902616 bytes
4
+ sha256: a31eb03b3424856d166daa9eaa8b0783fb78d9940cb69b330b13e48e55ec4b9b
@@ -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: 39929132 bytes
4
- sha256: 7c81415e962f42359724f8b8abd2d7f884f2a783faacb3857c61966e085530d3
3
+ size: 39912372 bytes
4
+ sha256: 8d6c76e8ca867a59018580ec7ed779798b449b53187e4fcb4e04fb44b3ef56fb
@@ -253,6 +253,14 @@ module Parsanol
253
253
  # consumer's file:line:col degrades to "line 1 char 1" when the
254
254
  # interpreter raises the outermost sequence instead. Explicit
255
255
  # reporters (Tree for full cause trees) are honored unchanged.
256
+ #
257
+ # A CUSTOM reporter's #err/#err_at return value is
258
+ # "implementation-specific" (ErrorReporter::Base) — it observes
259
+ # the failure events but is not obliged to hand back a Cause. The
260
+ # raise-able cause is then derived by re-parsing with the #265
261
+ # default, so the raised ParseFailed still carries the
262
+ # deepest-failure diagnostics (the interpreter tier crashed with
263
+ # NoMethodError on the reporter's raw return value before).
256
264
  def report_detailed_error(input, consume_all, reporter, _initial_error, compatibility: :strict)
257
265
  input.bytepos = 0
258
266
  error_reporter = reporter ||
@@ -263,6 +271,13 @@ module Parsanol
263
271
  # Second parse should also fail
264
272
  raise "Invariant violation: parse succeeded during error reporting" if success
265
273
 
274
+ unless cause.is_a?(Parsanol::Cause)
275
+ input.bytepos = 0
276
+ success, cause = run_with_context(input, Parsanol::ErrorReporter::Deepest.new,
277
+ consume_all, **context_options)
278
+ raise "Invariant violation: parse succeeded during error reporting" if success
279
+ end
280
+
266
281
  cause.raise
267
282
  end
268
283
  end
@@ -1,4 +1,4 @@
1
1
  [diffend] Oversized file quarantined before diffing.
2
2
  name: data/lib/parsanol/native/libparsanol.so
3
- size: 36061184 bytes
4
- sha256: 9236ba74fe40e51df4ac355f6b1c5d8ac61ba516a58351d77dfda024c2ac62b8
3
+ size: 36061744 bytes
4
+ sha256: b1b4d96b84b9e088162cd1600e3cd355c65465c0d9d02194d26bd9c76561155c
@@ -26,15 +26,14 @@ module Parsanol
26
26
 
27
27
  SUPPORTED_SHAPE = "parsanol-tree/v2"
28
28
 
29
- # The editions this runtime parses (ruby#357's consolidation):
30
- # 1 = the legacy shapes; 2 = named trees + explicit spans.
31
- SUPPORTED_EDITIONS = [1, 2].freeze
29
+ # Edition 2 (named trees + explicit spans) is the only edition —
30
+ # edition-1 artifacts are rejected with the fix named.
31
+ SUPPORTED_EDITIONS = [2].freeze
32
32
 
33
33
  # The header and envelope spellings that have shipped: the quoted
34
- # v-forms stay loadable so artifacts baked before the numeric
34
+ # v-form stays loadable so artifacts baked before the numeric
35
35
  # surface remain readable.
36
36
  EDITION_ALIASES = {
37
- 1 => 1, "1" => 1, "v1" => 1, "classic" => 1,
38
37
  2 => 2, "2" => 2, "v2" => 2
39
38
  }.freeze
40
39
 
@@ -50,14 +49,13 @@ module Parsanol
50
49
  bindings = envelope["bindings"]
51
50
  validate_bindings!(bindings) unless bindings.nil?
52
51
  @envelope = envelope
53
- # The declared edition must be one this runtime understands
54
- # (ruby#357's consolidation: one axis, `edition`). Absent field
55
- # = the pre-1.3.109 artifacts, whose trees are edition 1.
56
- edition = EDITION_ALIASES[envelope.fetch("edition", 1)]
52
+ # The declared edition must be one this runtime understands.
53
+ # Absent field = a pre-1.3.109 edition-1 artifact — rejected.
54
+ edition = EDITION_ALIASES[envelope.fetch("edition", 2)]
57
55
  unless SUPPORTED_EDITIONS.include?(edition)
58
56
  raise ArtifactError,
59
- "artifact declares edition #{envelope['edition'].inspect}; this " \
60
- "runtime supports #{SUPPORTED_EDITIONS.map(&:inspect).join(', ')}"
57
+ "artifact declares edition #{envelope['edition'].inspect}; edition 1 " \
58
+ "was removed — recompile the grammar with edition \"v2\""
61
59
  end
62
60
  @path = path
63
61
  @tables_dir = tables_dir
@@ -71,11 +69,10 @@ module Parsanol
71
69
 
72
70
  def version = envelope["version"]
73
71
 
74
- # The edition the artifact's trees carry: 1 = the legacy shapes,
75
- # 2 = fully named trees. Legacy artifacts that spell the field
76
- # "v2" (or omit it) normalize here.
72
+ # The edition the artifact's trees carry (always 2). Legacy
73
+ # artifacts that spell the field "v2" normalize here.
77
74
  def edition
78
- EDITION_ALIASES.fetch(envelope.fetch("edition", 1))
75
+ EDITION_ALIASES.fetch(envelope.fetch("edition", 2))
79
76
  end
80
77
 
81
78
  # Freshness (parsanol-ruby#209): what source revision and compiler
@@ -36,11 +36,14 @@ module Parsanol
36
36
  # bound map (parsanol-ruby#413): a capture present in the parse
37
37
  # but bound nowhere is silent data loss, the one case the
38
38
  # binding layer's other checks miss. Absence in the TREE is
39
- # legitimate optionality and never raises. Coverage is checked
40
- # against every hash key anywhere in the bound map, not just the
41
- # binding's own leaf: a `(raw)` binding carries its entire
39
+ # legitimate optionality and never raises. Delivery is EITHER
40
+ # the binding's own leaf/prefix reaching the map (the capture
41
+ # may rename on the way — capture "doc_year" binds under path
42
+ # "year", parsanol-ruby#434) OR the capture name appearing as a
43
+ # key anywhere in the map: a `(raw)` binding carries its entire
42
44
  # subtree, so captures nested inside a raw-bound ancestor are
43
- # delivered through it (parsanol-ruby#427 — BS 9113 bundled_list).
45
+ # delivered through it (parsanol-ruby#427 — BS 9113
46
+ # bundled_list).
44
47
  bound_keys = {}
45
48
  walk_keys = lambda do |node|
46
49
  case node
@@ -53,7 +56,7 @@ module Parsanol
53
56
  walk_keys.call(out)
54
57
  lost = bindings.select do |binding|
55
58
  capture = binding["capture"].to_sym
56
- present.include?(capture) && !bound_keys.key?(capture)
59
+ present.include?(capture) && !bound?(out, binding) && !bound_keys.key?(capture)
57
60
  end
58
61
  unless lost.empty?
59
62
  raise BindError,
@@ -63,6 +66,23 @@ module Parsanol
63
66
  out
64
67
  end
65
68
 
69
+ # Did this binding contribute anything to the bound map? Scalars
70
+ # bind under their leaf key; array groups bind under their prefix.
71
+ # The leaf is the PATH's tail, so a capture-to-path rename reads
72
+ # as delivered when its own path landed (parsanol-ruby#434).
73
+ def bound?(out, binding)
74
+ path = binding["path"].to_s
75
+ if path.include?("[]")
76
+ prefix = path.split("[]").first.to_sym
77
+ rows = out[prefix]
78
+ rows.is_a?(Array) && rows.any? do |row|
79
+ row.is_a?(Hash) && row.key?(leaf_key(binding))
80
+ end
81
+ else
82
+ out.key?(leaf_key(binding))
83
+ end
84
+ end
85
+
66
86
  # Canonical test-value form: one equality surface for capture and
67
87
  # example expectations on both sides of the comparison (Slice vs
68
88
  # source literal was comparing heterogeneous types). Terminals
@@ -116,7 +116,6 @@ module Parsanol
116
116
  # upgrade suggestions on top.
117
117
  def lint
118
118
  source = @argv.shift
119
- @captures_radar = @argv.delete("--captures") ? true : false
120
119
  tables = @tables_dir || default_tables_dir(source)
121
120
  document = Parsanol::PARG::Parser.new(PARG.read_utf8(source)).parse
122
121
  Parsanol::PARG::Imports.merge!(document, [File.dirname(source)])
@@ -132,10 +131,6 @@ module Parsanol
132
131
  Lints::CoreRuleDuplicates.new.warnings(document, compiler)
133
132
  .each { |upgrade| puts "upgrade: #{upgrade}" }
134
133
  end
135
- if @captures_radar
136
- # The migration radar (ruby#304): what modern mode would name.
137
- compiler.modern_radar.each { |line| puts "captures: #{line}" }
138
- end
139
134
  0
140
135
  rescue Parsanol::PARG::ParseError, Parsanol::PARG::Error => e
141
136
  warn "#{e.class}: #{e.message}"
@@ -252,18 +252,17 @@ module Parsanol
252
252
 
253
253
  # Modern mode (ruby#304, the #315 spec): every rule reference
254
254
  # that produces no capture is wrapped in Named(rule_name) at
255
- # compile time — the tree shape consumers read, opt-in via
256
- # `mode` in the grammar header. Engines see ordinary
257
- # Named atoms; identity rides the differential corpus.
255
+ # compile time — the tree shape consumers read. Edition 2 is the
256
+ # only edition, so the wrap is unconditional. Engines see
257
+ # ordinary Named atoms; identity rides the differential corpus.
258
258
  def apply_modern_captures(atom, rule_name)
259
- return atom if @document.edition == "v1"
260
259
  # A glue rule's own body compiles unwrapped (parsanol-ruby#364):
261
260
  # the declaration means the tree never sees this subtree named,
262
261
  # inside or out.
263
262
  return atom if glue_rule?(rule_name)
264
263
  # A capture spans the rules it references (ruby#400): their
265
264
  # bodies compile unwrapped so the capture's value equals its
266
- # edition-1 value.
265
+ # span-joined value.
267
266
  return atom if captured_reachable?(rule_name)
268
267
 
269
268
  wrap_uncaptured(atom)
@@ -505,52 +504,6 @@ module Parsanol
505
504
  end
506
505
  end
507
506
 
508
- # The migration radar (ruby#304 `parg lint --captures`): for a
509
- # LEGACY grammar, every rule reference modern mode would wrap —
510
- # reference site, target rule. The compiler's state is warm
511
- # (all rules built) when the lint calls this.
512
- def modern_radar
513
- # The radar is the classic dialect's migration tool: on a v2
514
- # grammar every reference is already named.
515
- return [] if @document.edition != "v1"
516
-
517
- lines = []
518
- @document.rules.each_key do |name|
519
- atom = @atom_cache[name]
520
- next unless atom
521
-
522
- radar_walk(atom, name, lines, [])
523
- end
524
- lines
525
- end
526
-
527
- def radar_walk(atom, site, lines, seen)
528
- return if seen.include?(atom.object_id)
529
-
530
- seen << atom.object_id
531
- case atom
532
- when Atoms::Named then nil
533
- when Atoms::Entity
534
- # Mirror wrap_uncaptured's verdicts: trivia glue, declared
535
- # glue, capture-reachable refs (ruby#400 — a capture spans
536
- # them, so modern mode never names them), and
537
- # capture-producing refs all stay bare.
538
- unless trivia_only?(atom.rule_name.to_s, { atom.rule_name.to_s => true }) ||
539
- glue_rule?(atom.rule_name.to_s) ||
540
- captured_reachable?(atom.rule_name.to_s) ||
541
- produces_capture?(atom.parslet)
542
- lines << "rule #{site}: reference to #{atom.rule_name} produces no capture -- " \
543
- "modern mode would name it #{atom.rule_name}"
544
- end
545
- radar_walk(atom.parslet, site, lines, seen)
546
- when Atoms::Sequence, Atoms::Alternative
547
- kids = atom.respond_to?(:alternatives) ? atom.alternatives : atom.parslets
548
- kids.each { |child| radar_walk(child, site, lines, seen) }
549
- when Atoms::Repetition
550
- radar_walk(atom.parslet, site, lines, seen)
551
- end
552
- end
553
-
554
507
  def atom_for(name)
555
508
  inject_core_rules!
556
509
  expand_left_recursion! unless @expanded
@@ -1424,9 +1377,9 @@ module Parsanol
1424
1377
  }
1425
1378
  # ruby#304: the envelope always names the capture edition —
1426
1379
  # consumers read the tree-shape contract before parsing. The
1427
- # numeric form is canonical: 1 = the legacy shapes, 2 = fully
1428
- # named trees + explicit spans.
1429
- envelope["edition"] = @document.edition == "v2" ? 2 : 1
1380
+ # numeric form is canonical: 2 = fully named trees + explicit
1381
+ # spans, the only edition.
1382
+ envelope["edition"] = 2
1430
1383
  if @document.skip_declaration
1431
1384
  # parsanol-ruby#134: declared trivia rule. Injection is baked
1432
1385
  # into the compiled trees (plain atom kinds), so consumers
@@ -181,9 +181,12 @@ module Parsanol
181
181
  end
182
182
 
183
183
  # Artifacts baked before the numeric surface spell the edition
184
- # "v1"/"v2"; they mean the same levels, not a change.
184
+ # Edition 2 is the only edition; envelopes that omit the field or
185
+ # spell it "v2" normalize to 2. Removed spellings (1/"v1"/"classic")
186
+ # pass through, so a legacy envelope still diffs as an edition
187
+ # change.
185
188
  def edition_level(envelope)
186
- declared = envelope.fetch("edition", 1)
189
+ declared = envelope.fetch("edition", 2)
187
190
  Artifact::EDITION_ALIASES.fetch(declared, declared)
188
191
  end
189
192
 
@@ -35,11 +35,9 @@ module Parsanol
35
35
 
36
36
  def initialize
37
37
  @grammar_name = nil
38
- # The default capture dialect is v1 (the owner's reversal,
39
- # 2026-10-28): runtime compiles of unpinned sources keep the
40
- # legacy shapes — the pubid fleet froze against them. edition
41
- # "v2" is the named-trees opt-in via the grammar header.
42
- @edition = "v1"
38
+ # Edition 2 (named trees + explicit spans) is the only edition —
39
+ # edition 1 was removed. Header declaration stays optional.
40
+ @edition = "v2"
43
41
  @version = "0.0.0"
44
42
  @source = nil
45
43
  @rules = {}
@@ -123,12 +123,13 @@ module Parsanol
123
123
  document.grammar_name = Regexp.last_match(1)
124
124
  document.version = Regexp.last_match(2)
125
125
  tail = stripped.match(EDITION_TAIL)
126
- document.edition = if tail.nil?
127
- "v1"
128
- else
129
- level = tail[:number] || tail[:quoted] || tail[:mode]
130
- ["2", "v2"].include?(level) ? "v2" : "v1"
131
- end
126
+ level = tail.nil? ? "2" : (tail[:number] || tail[:quoted] || tail[:mode])
127
+ unless ["2", "v2"].include?(level)
128
+ raise ParseError,
129
+ "edition #{level.inspect} is not supported -- edition 1 was " \
130
+ "removed; write edition \"v2\" (named trees + spans)"
131
+ end
132
+ document.edition = "v2"
132
133
  doc_comments = []
133
134
  when NAMED_SECTION
134
135
  state[:section] = Regexp.last_match(1)
@@ -524,8 +524,10 @@ module Parsanol
524
524
  if SelfHost.available?
525
525
  begin
526
526
  SelfHost.validate(source)
527
- rescue Parsanol::ParseFailed
528
- # fall through to line 0
527
+ rescue Parsanol::ParseFailed, ArtifactError
528
+ # a stale artifact (e.g. a sibling baked at a removed
529
+ # edition) must not break diagnostics — fall through to
530
+ # line 0
529
531
  end
530
532
  end
531
533
  diagnostics << diagnostic(line, e.message)
@@ -18,11 +18,11 @@ module Parsanol
18
18
 
19
19
  IN_BLOCK_SECTIONS = %w[entry bindings preprocess test].freeze
20
20
 
21
- # The header's edition spellings: the bare numbers are canonical
22
- # (Rust's Cargo.toml model); the quoted forms stay accepted as
23
- # aliases for grammars written before the numeric surface.
21
+ # The header's edition spellings: the bare number is canonical
22
+ # (Rust's Cargo.toml model); the quoted form stays accepted as an
23
+ # alias. Edition 1 was removed — grammars declaring it fail with
24
+ # the fix named.
24
25
  EDITIONS = {
25
- "1" => "v1", "v1" => "v1", "classic" => "v1",
26
26
  "2" => "v2", "v2" => "v2"
27
27
  }.freeze
28
28
 
@@ -242,13 +242,12 @@ module Parsanol
242
242
  when :str then unquote(token.value)
243
243
  else
244
244
  raise ParseError,
245
- "edition must be a number (1 or 2) or a quoted alias " \
246
- "(\"v1\", \"v2\", \"classic\")"
245
+ "edition must be the number 2 or the quoted alias \"v2\""
247
246
  end
248
247
  EDITIONS.fetch(raw) do
249
248
  raise ParseError,
250
- "unknown edition #{raw.inspect} -- supported editions are " \
251
- "1 (default) and 2 (named trees)"
249
+ "edition #{raw.inspect} is not supported -- edition 1 was " \
250
+ "removed; write edition \"v2\" (named trees + spans)"
252
251
  end
253
252
  end
254
253
 
@@ -258,11 +257,9 @@ module Parsanol
258
257
  document.version = unquote(expect(:str).value)
259
258
  # `edition` — the language edition (ruby#304, ruby#357's
260
259
  # consolidation; Rust's Cargo.toml `edition` is the model):
261
- # the author declares, per grammar, which tree semantics the
262
- # grammar means. THE DEFAULT IS 1 (the legacy shapes — the
263
- # owner's 2026-10-28 reversal). 2 = fully named trees +
264
- # explicit spans. The edition is canonicalized here —
265
- # everything downstream only ever sees "v1"/"v2". The
260
+ # edition 2 = fully named trees + explicit spans, and the ONLY
261
+ # edition (edition 1 was removed). The edition is canonicalized
262
+ # here — everything downstream only ever sees "v2". The
266
263
  # pre-1.3.113 `mode` alias was removed (the owner's
267
264
  # 2026-10-31 ruling): the header fails with the fix named.
268
265
  if peek&.type == :ident && peek.value == "edition"
@@ -270,7 +267,7 @@ module Parsanol
270
267
  document.edition = edition_value
271
268
  elsif peek&.type == :ident && peek.value == "mode"
272
269
  raise ParseError,
273
- 'the grammar header keyword is edition; mode (the pre-1.3.113 alias) was removed — write edition "v1" or edition "v2"'
270
+ 'the grammar header keyword is edition; mode (the pre-1.3.113 alias) was removed — write edition "v2"'
274
271
  end
275
272
  punct("{")
276
273
  skip_newlines
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Parsanol
4
- VERSION = "1.3.127"
4
+ VERSION = "1.3.129"
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.127
4
+ version: 1.3.129
5
5
  platform: arm-linux
6
6
  authors:
7
7
  - Ribose Inc.