parsanol 1.3.71-aarch64-linux → 1.3.73-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: 7521a5d8e982e8a4790eb217b8c3a3f21190247b411b6862bacb4e4a3a919af3
4
- data.tar.gz: 581f51a2fb7b68a7ff5a79c149338fccd63ff4e09398fa5e5a73f1479e895104
3
+ metadata.gz: d44785098f80ef9ed51a27badccb31294e3866fffe8e889ab97c67f6db8a5588
4
+ data.tar.gz: d69ac94f5284eab7b6e6c40bfd993b62f1bab34b92e3a08532d3d1bbe8fe5686
5
5
  SHA512:
6
- metadata.gz: 398da535c6500293148c92a6616cfa9bbc7834893e8911fa38f515dad0f81dce3ab0bec8ff5281c5a1ec2f1ade77b4b8d9c23244e07606f82b10fd24b802a123
7
- data.tar.gz: '0293cc80cd29a221f10bb739af8b7f41a2f33c85e23598ba1599edc67edb05a6606eb36ae119c3e929034f93a33bb0e2f31546855c5b987299a18378f31209ba'
6
+ metadata.gz: 4c8efa1d096a9d0320ec7326d8d498a1cfa96202d23faf4b8b1f808c38e87ef63c33d706a43b2e2b65c639edaa4f1ea1f5f6c229dcdb3ec6b5dd7771d87f81de
7
+ data.tar.gz: f8d6456b7db1a205397117360c39335c6d9cc565cc7ebacb32ef79811f453a1061f77b8ff2abf683232c0ffbc5527572c3aa1596d951ea1f2b7dbe19557b59cd
@@ -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: 39067688 bytes
4
- sha256: 1336a78f2ee05d8e4599a6ee7dc70263b6774bedb1234ae109c02013c76be06c
3
+ size: 39109176 bytes
4
+ sha256: b3467d47089b0c1b52ea453bd75478547a0bfeeaf8a7623ee66660190afcf6c9
@@ -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: 39306936 bytes
4
- sha256: 1981488f1c97656d97bd2c6b2b63bcfc0bc4ca98c27ab28743dfaf32150c4ffc
3
+ size: 39344224 bytes
4
+ sha256: afe35b8257f519860d7baf36decde544b3ad56680ea70cbbb3d9253dab9b817c
@@ -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: 39310816 bytes
4
- sha256: c4e57e00acce9397e2a7607e74b5bf679e572db69db4a32659990f59ded86028
3
+ size: 39344064 bytes
4
+ sha256: c831fc32e5395b1eeeb08b6a7896ef18e19a3669eef191e26049886f260d1829
@@ -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: 39320888 bytes
4
- sha256: 23eb16a3cc0a3204738f7b315571c530bdeaad70c7fee4c5e20846f4ea13064d
3
+ size: 39354120 bytes
4
+ sha256: decd9a091dc652a9d564723516770ccb1520577cc243e41b3d7a8a5812c2b13a
@@ -1,4 +1,4 @@
1
1
  [diffend] Oversized file quarantined before diffing.
2
2
  name: data/lib/parsanol/native/libparsanol.so
3
- size: 34928224 bytes
4
- sha256: 30c136ad62e8cd47f56529bd1f61218985ade298ac6f0965b4a8ec43bcef8e38
3
+ size: 34952888 bytes
4
+ sha256: fa8b3f171de5974c942b0d7ae3900c818e42919e7ad54873a21d30b5e2413b66
@@ -78,6 +78,13 @@ module Parsanol
78
78
  serialize_custom_ref(atom)
79
79
  when Parsanol::Atoms::Dynamic
80
80
  serialize_dynamic(atom)
81
+ when Parsanol::Atoms::Trivia
82
+ # Wire-distinct from Ignore (rs#172): the Rust
83
+ # engine suppresses trivia-position diagnostics by
84
+ # atom kind. Engines predating the Trivia tag
85
+ # reject skip-carrying artifacts loudly (unknown
86
+ # variant), which is the declared gate.
87
+ serialize_trivia(atom)
81
88
  when Parsanol::Atoms::Ignored
82
89
  serialize_ignored(atom)
83
90
  else
@@ -276,6 +283,15 @@ module Parsanol
276
283
  "parse this grammar with mode: :ruby"
277
284
  end
278
285
 
286
+ def serialize_trivia(atom)
287
+ inner_id = serialize_atom(atom.wrapped_atom)
288
+ {
289
+ "Trivia" => {
290
+ "atom" => inner_id,
291
+ },
292
+ }
293
+ end
294
+
279
295
  def serialize_ignored(atom)
280
296
  inner_id = serialize_atom(atom.wrapped_atom)
281
297
  {
@@ -49,7 +49,38 @@ module Parsanol
49
49
  def root(rule_name)
50
50
  # Remove any existing root method before redefining
51
51
  undef_method :root if method_defined?(:root)
52
- define_method(:root) { __send__(rule_name) }
52
+ define_method(:root) do
53
+ atom = __send__(rule_name)
54
+ skip_name = self.class.skip_rule_name
55
+ skip_name ? Parsanol::Skip.inject(self, atom, skip_name)[0] : atom
56
+ end
57
+ end
58
+
59
+ # Declares the grammar's skip rule (parsanol-ruby#134 DSL
60
+ # surface): an optional match of the named rule is injected
61
+ # before every terminal of the root's rule tree, and the entry
62
+ # takes leading and trailing skips. The referenced rule (and
63
+ # everything it references) builds without injection; it must be
64
+ # non-nullable. Order-independent with +root+.
65
+ #
66
+ # @example
67
+ # class MyParser < Parsanol::Parser
68
+ # rule(:spaces) { match(/[ \t]/).repeat(1) }
69
+ # rule(:word) { match(/[a-z]/).repeat(1).as(:w) }
70
+ # rule(:doc) { word >> str(",") >> word }
71
+ # skip :spaces
72
+ # root :doc
73
+ # end
74
+ #
75
+ def skip(rule_name)
76
+ @skip_rule_name = rule_name
77
+ nil
78
+ end
79
+
80
+ # The declared skip rule name, or nil (class-level; subclasses
81
+ # inherit unless they declare their own).
82
+ def skip_rule_name
83
+ @skip_rule_name
53
84
  end
54
85
  end
55
86
 
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Parsanol
4
+ # Skip-rule trivia injection for Ruby-DSL grammars (the PARG surface
5
+ # compiles the same semantics into artifacts; see
6
+ # Parsanol::PARG::Compiler#inject_skip_trivia). A parser declares
7
+ # `skip :trivia`; the resolved rule's atom becomes the injected
8
+ # optional trivia wrapper before every terminal of every rule body,
9
+ # with the declaration's transitive closure exempt (the skip atom
10
+ # must not contain itself).
11
+ module Skip
12
+ # +skip_rule_name+ resolves against the parser instance's rule
13
+ # methods. Returns [injected_root, skip_atom] with the wrapper
14
+ # built and the lint applied, or raises GrammarError for a
15
+ # nullable skip.
16
+ def self.inject(parser_instance, root_atom, skip_rule_name)
17
+ skip_atom = parser_instance.__send__(skip_rule_name)
18
+ skip_atom = skip_atom.parslet while skip_atom.is_a?(Atoms::Entity)
19
+
20
+ if VM::Compiler.new.nullable?(skip_atom)
21
+ raise GrammarError,
22
+ "skip rule must be non-nullable: a skip that can match " \
23
+ "empty loops forever at injection points"
24
+ end
25
+
26
+ injector = Injector.new(skip_atom)
27
+ [injector.inject(root_atom, entry: true), skip_atom]
28
+ end
29
+
30
+ # The injection walk. Mirrors the PARG compiler's semantics:
31
+ # sequences interleave the wrapper before every child, alternatives
32
+ # and repetitions descend, named captures descend (spans stay
33
+ # clean — the wrapper is Trivia: Ignored + diagnostics
34
+ # transparency), bare terminals gain a leading wrapper, and the
35
+ # entry root takes leading and trailing wrappers.
36
+ class Injector
37
+ def initialize(skip_atom)
38
+ @skip_atom = skip_atom
39
+ @wrapper_ids = {}.compare_by_identity
40
+ end
41
+
42
+ def inject(atom, entry: false)
43
+ injected = walk(atom, {})
44
+ return injected unless entry
45
+
46
+ Atoms::Sequence.new(maybe, injected, maybe)
47
+ end
48
+
49
+ private
50
+
51
+ def maybe
52
+ @maybe ||= begin
53
+ wrapper = Atoms::Trivia.new(Atoms::Repetition.new(@skip_atom, 0, 1))
54
+ @wrapper_ids[wrapper] = true
55
+ wrapper
56
+ end
57
+ end
58
+
59
+ def wrapper?(atom)
60
+ @wrapper_ids.key?(atom)
61
+ end
62
+
63
+ def walk(atom, visited)
64
+ return atom if visited.key?(atom)
65
+ return atom if atom.equal?(@skip_atom)
66
+
67
+ visited = visited.merge(atom => true)
68
+ case atom
69
+ when Atoms::Sequence
70
+ out = []
71
+ atom.parslets.each do |child|
72
+ injected = walk(child, visited)
73
+ out << maybe unless wrapper?(injected) || injected.is_a?(Atoms::Trivia)
74
+ out << injected
75
+ end
76
+ out.length == 1 ? out.first : Atoms::Sequence.new(*out)
77
+ when Atoms::Alternative
78
+ Atoms::Alternative.new(*atom.alternatives.map { |a| walk(a, visited) })
79
+ when Atoms::Repetition
80
+ if wrapper?(atom)
81
+ atom
82
+ else
83
+ Atoms::Repetition.new(walk(atom.parslet, visited), atom.min, atom.max,
84
+ atom.result_tag)
85
+ end
86
+ when Atoms::Named
87
+ Atoms::Named.new(walk(atom.parslet, visited), atom.name)
88
+ when Atoms::Lookahead
89
+ Atoms::Lookahead.new(walk(atom.bound_parslet, visited), atom.positive)
90
+ when Atoms::Ignored
91
+ Atoms::Ignored.new(walk(atom.wrapped_atom, visited))
92
+ when Atoms::Entity
93
+ # Rule bodies own their injection when the grammar declares
94
+ # skip on every rule (PARG); in the DSL surface the root tree
95
+ # is walked once, so descend through resolved bodies with the
96
+ # identity visited-set guarding recursion.
97
+ begin
98
+ walk(atom.parslet, visited)
99
+ rescue StandardError
100
+ atom
101
+ end
102
+ when Atoms::Str, Atoms::Re
103
+ Atoms::Sequence.new(maybe, atom)
104
+ else
105
+ atom
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Parsanol
4
- VERSION = "1.3.71"
4
+ VERSION = "1.3.73"
5
5
  end
data/lib/parsanol.rb CHANGED
@@ -290,6 +290,7 @@ module Parsanol
290
290
  autoload :Pattern, "parsanol/pattern"
291
291
  autoload :Transform, "parsanol/transform"
292
292
  autoload :VM, "parsanol/vm"
293
+ autoload :Skip, "parsanol/skip"
293
294
  autoload :Parser, "parsanol/parser"
294
295
  autoload :ErrorReporter, "parsanol/error_reporter"
295
296
  autoload :Scope, "parsanol/scope"
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.71
4
+ version: 1.3.73
5
5
  platform: aarch64-linux
6
6
  authors:
7
7
  - Ribose Inc.
@@ -138,6 +138,7 @@ files:
138
138
  - lib/parsanol/rig/rspec.rb
139
139
  - lib/parsanol/rope.rb
140
140
  - lib/parsanol/scope.rb
141
+ - lib/parsanol/skip.rb
141
142
  - lib/parsanol/slice.rb
142
143
  - lib/parsanol/source.rb
143
144
  - lib/parsanol/source/line_cache.rb