parsanol 1.3.70-aarch64-linux → 1.3.72-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: ad959864e0602ce21fcaf7bfb65f129a839a3edf2cdcde4c9b3c0a7873aad3cf
4
- data.tar.gz: 83e386bde70fe57d16fda75c2c435d04d7f1d7923e8810b5537f4ccebee8a441
3
+ metadata.gz: d8b7b5097114e65d7d72074732dc20073d34c7afbc5331be4120835cce2248d4
4
+ data.tar.gz: a383b0f2015b12d60a68761d9be2ac9767d1b7f7e85cd0f8d614410b2d441cc4
5
5
  SHA512:
6
- metadata.gz: cf8e3598041fe4c871423d4ec0ce3b310029959b6b0f58c86fe26855ad1ff9eadccfd4844315afd7f3703562281b7bc5fe560f1f14cb7d24ff33e7caf3c7a21a
7
- data.tar.gz: feaf49623ed5dd39f73f5744d1207fc26ff4a5b63cc1e80a2baf510edf132ead17d76ef0eeae1e59436cebb1eb66bef895e834928516e38af1068899afe1dead
6
+ metadata.gz: f8f13a39f5112deb6e1ac35b819feb710ca5373f4c16dbc118b8522bd38f200b205e534b400bfe1bbf4283f50d8577872fb6b4ba6fdaf9e9703de3e9f6604db1
7
+ data.tar.gz: 8981e9c539c0afbe57058a1a9293b518c2d5002ba65a734d856c13a7db879f90cff771f185e453221e4ae9829c7db1174775e345b530ef80772385536e7dfadc
@@ -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: 38985448 bytes
4
- sha256: 5deca3c49c16862198a49c09501814569b36753ef5ff5bde0dcc237ce10131a6
3
+ size: 39097672 bytes
4
+ sha256: 503e24e59de87efda3090bc01fcf7a2cb100225bee3001607112c3d70214c0ed
@@ -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: 39228816 bytes
4
- sha256: b488278de783d41fcaf427d65270a6a6e69ebf3330b39ed3a38c1f466f3f418c
3
+ size: 39332704 bytes
4
+ sha256: a789c4bf8878d1541defa7d5581495c8b16c0f63b28dfb015d212b06c5b65455
@@ -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: 39220296 bytes
4
- sha256: 4c9067ae6b717e8763a28e5e498e5ec7db9ddf503d6e1c5afb0a8e34c6c5f5cf
3
+ size: 39332560 bytes
4
+ sha256: 92ca65756238005b89c3f4eef6efc85231967d1f67bd2b6776a81725224e387e
@@ -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: 39230344 bytes
4
- sha256: 1d0f4a65b15b9f32b8f6a5e8cf7910ed7d55e79c1d34f106b51e82e84d298586
3
+ size: 39342616 bytes
4
+ sha256: 12e580b24f8fb88243ee35fe7af2917d144d3e0649ae3170b301211fc66bcb5f
@@ -67,6 +67,11 @@ module Parsanol
67
67
  # Injected-trivia depth: while positive, reported causes are
68
68
  # marked trivia and never surface in diagnostics.
69
69
  @trivia_depth = 0
70
+ # Captured trivia channel (parsanol-ruby#152): when the grammar
71
+ # declares `skip ... capture:`, matched trivia units land here
72
+ # and the NEXT successful Named capture attaches (and drains)
73
+ # them under `comments:`.
74
+ @pending_trivia = []
70
75
  @evict_threshold = 200
71
76
  @evict_counter = 0
72
77
  @evict_interval = 100
@@ -258,6 +263,34 @@ module Parsanol
258
263
  [false, @reporter.err(*)]
259
264
  end
260
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 }
270
+ nil
271
+ end
272
+
273
+ # Snapshot for backtracking: a failed branch must not leak its
274
+ # half-recorded trivia into the successful alternative.
275
+ def take_pending_trivia_snapshot
276
+ @pending_trivia.dup
277
+ end
278
+
279
+ def restore_pending_trivia(snapshot)
280
+ @pending_trivia = snapshot
281
+ nil
282
+ end
283
+
284
+ # Drains pending captured trivia (attached by the next
285
+ # successful Named capture). Backtracking discards whatever has
286
+ # not been attached yet — the caller snapshots position and
287
+ # restores this list alongside.
288
+ def take_pending_trivia
289
+ list = @pending_trivia
290
+ @pending_trivia = []
291
+ list
292
+ end
293
+
261
294
  # Brackets a parse inside injected trivia: causes reported while
262
295
  # the depth is positive carry the trivia flag and never surface
263
296
  # in rendered trees or deepest-failure positions.
@@ -32,10 +32,32 @@ module Parsanol
32
32
  # @param consume_all [Boolean] require full consumption
33
33
  # @return [Array(Boolean, Object)] result
34
34
  def apply(source, context, consume_all)
35
+ trivia_before = context.take_pending_trivia_snapshot
35
36
  success, value = @parslet.apply(source, context, consume_all)
36
- return [false, value] unless success
37
+ unless success
38
+ context.restore_pending_trivia(trivia_before)
39
+ return [false, value]
40
+ end
37
41
 
38
- ok(wrap_result(value))
42
+ comments = context.take_pending_trivia
43
+ result = wrap_result(value)
44
+ result = attach_comments(result, comments) unless comments.empty?
45
+ ok(result)
46
+ end
47
+
48
+ private
49
+
50
+ # parsanol-ruby#152: trivia captured ahead of this capture rides
51
+ # with it under `comments:`. The attachment only fires when the
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] } }
56
+ if result.is_a?(Hash)
57
+ result.merge(comments: list)
58
+ else
59
+ { @name => result, comments: list }
60
+ end
39
61
  end
40
62
 
41
63
  # Named wrappers skip caching (inner parser handles it).
@@ -60,8 +82,6 @@ module Parsanol
60
82
  @parslet.first_set
61
83
  end
62
84
 
63
- private
64
-
65
85
  # Wraps matched value in labeled hash.
66
86
  #
67
87
  # @param matched [Object] matched value
@@ -17,5 +17,53 @@ module Parsanol
17
17
  "trivia(#{@wrapped_atom.to_s(prec)})"
18
18
  end
19
19
  end
20
+
21
+ # parsanol-ruby#152: the skip-declared capture wrapper. Whitespace
22
+ # trivia stays Ignored; comment-shaped units (the grammar names the
23
+ # capture rules in the declaration) are recorded into the context
24
+ # channel for attachment to the next successful Named capture.
25
+ # Span discipline is unchanged: the matched bytes still contribute
26
+ # nothing to values or capture spans.
27
+ class TriviaCapture < Trivia
28
+ # +capturers+ maps leading-literal marker -> kind label (the
29
+ # compiler derives markers from each capturer rule's first Str
30
+ # atom, e.g. "//" => :line_comment); units not matching any
31
+ # marker are whitespace-shaped and stay unrecorded.
32
+ def initialize(atom, capturers)
33
+ super(atom)
34
+ @capturers = capturers
35
+ end
36
+
37
+ def apply(source, context, consume_all)
38
+ context.with_trivia do
39
+ start = source.bytepos
40
+ ok, _value = @wrapped_atom.apply(source, context, consume_all)
41
+ if ok && source.bytepos > start
42
+ record(source, context, start, source.bytepos)
43
+ return ok(nil)
44
+ end
45
+ [ok, _value]
46
+ end
47
+ end
48
+
49
+ def to_s_inner(_prec)
50
+ "trivia!(@wrapped_atom.to_s(prec))"
51
+ end
52
+
53
+ private
54
+
55
+ def record(source, context, start_pos, end_pos)
56
+ return unless @capturers
57
+
58
+ text = source.input[start_pos...end_pos]
59
+ # A trivia unit may lead with whitespace before the comment
60
+ # shape; markers test the comment head.
61
+ stripped = text.lstrip
62
+ marker, label = @capturers.find { |m, _label| stripped.start_with?(m) }
63
+ return unless marker
64
+
65
+ context.push_captured_trivia(label, stripped.strip)
66
+ end
67
+ end
20
68
  end
21
69
  end
@@ -1,4 +1,4 @@
1
1
  [diffend] Oversized file quarantined before diffing.
2
2
  name: data/lib/parsanol/native/libparsanol.so
3
- size: 34261680 bytes
4
- sha256: 384067c37f3351470b67dea550d77a6cdfd743988040da614df5ce02b8bcb1c2
3
+ size: 34958328 bytes
4
+ sha256: 9cb91403adcb340e2538e3e8012a9d8330681ea22bee53a7647b059d6a1b2a24
@@ -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
  {
@@ -71,7 +71,10 @@ module Parsanol
71
71
 
72
72
  root_atom(entry_name).parse(input)
73
73
  when :ruby
74
- root_atom(entry_name).parse(input)
74
+ # Deepest-failure reporting parity with the native engine: the
75
+ # default Tree reporter keeps the most recent (root) failure,
76
+ # which reports position 1:1 for grammars with entry wrappers.
77
+ root_atom(entry_name).parse(input, reporter: ErrorReporter::Deepest.new)
75
78
  else
76
79
  raise ArgumentError, "unknown mode #{mode.inspect} (use :native or :ruby)"
77
80
  end
@@ -141,6 +141,51 @@ module Parsanol
141
141
  end
142
142
  end
143
143
 
144
+ # parsanol-ruby#152: capturer rules are the rules transitively
145
+ # referenced by the skip declaration whose leading literal is a
146
+ # non-whitespace marker — the comment shapes ("//", "/*", ...).
147
+ # Whitespace rules stay unrecorded trivia.
148
+ def skip_capturer_markers
149
+ @skip_capturer_markers ||= begin
150
+ markers = {}
151
+ seen = {}
152
+ collect = lambda do |node|
153
+ case node.kind
154
+ when :ref
155
+ next if seen[node.a]
156
+
157
+ seen[node.a] = true
158
+ literal = leading_literal(node.a)
159
+ markers[literal] = node.a.to_sym if literal && !literal.strip.empty?
160
+ collect.call(@document.rules[node.a]) if @document.rules.key?(node.a)
161
+ when :alt, :seq then node.a.each { |b| collect.call(b) }
162
+ when :rep, :opt, :cap then collect.call(node.a)
163
+ when :pred then collect.call(node.b)
164
+ end
165
+ end
166
+ collect.call(@document.skip_declaration)
167
+ markers
168
+ end
169
+ end
170
+
171
+ def leading_literal(rule_name)
172
+ node = @document.rules[rule_name]
173
+ return nil unless node
174
+
175
+ literal = nil
176
+ walk = lambda do |n|
177
+ break if literal
178
+
179
+ case n.kind
180
+ when :lit then literal = n.a
181
+ when :seq, :alt then n.a.each { |c| walk.call(c) unless literal }
182
+ when :rep, :opt, :cap, :pred then walk.call(n.a || n.b) unless literal
183
+ end
184
+ end
185
+ walk.call(node)
186
+ literal
187
+ end
188
+
144
189
  def skip_wrapper?(atom)
145
190
  @skip_wrapper_ids&.key?(atom)
146
191
  end
@@ -163,7 +208,13 @@ module Parsanol
163
208
  # span-joined captures — and failures inside it never surface
164
209
  # in diagnostics (rendered trees and deepest-failure
165
210
  # positions skip trivia causes).
166
- wrapper = Atoms::Trivia.new(Atoms::Repetition.new(atom, 0, 1))
211
+ inner = Atoms::Repetition.new(atom, 0, 1)
212
+ wrapper =
213
+ if @document.skip_capture_key
214
+ Atoms::TriviaCapture.new(inner, skip_capturer_markers)
215
+ else
216
+ Atoms::Trivia.new(inner)
217
+ end
167
218
  (@skip_wrapper_ids ||= {}.compare_by_identity)[wrapper] = true
168
219
  wrapper
169
220
  end
@@ -10,7 +10,7 @@ module Parsanol
10
10
  Test = Struct.new(:entry, :kind, :input, :expect)
11
11
 
12
12
  attr_accessor :grammar_name, :version, :source, :uses, :skip_declaration, :skip_source,
13
- :atomic_rules
13
+ :atomic_rules, :skip_capture_key
14
14
  attr_reader :rules, :bindings, :preprocess, :entries, :docs, :tests, :render, :derive,
15
15
  :customs, :states
16
16
  # Entries authored in this file (pre-import); nil-entry tests resolve
@@ -21,7 +21,7 @@ module Parsanol
21
21
  STATE_KEYWORDS = %w[custom state].freeze
22
22
  KEYWORDS = %w[grammar as alt from_table column bindings render derive
23
23
  preprocess entry table_lookup custom state set switch
24
- skip until atomic].freeze
24
+ skip until atomic capture].freeze
25
25
 
26
26
  def initialize(text)
27
27
  @tokens = Lexer.new(text).tokens
@@ -170,6 +170,15 @@ module Parsanol
170
170
  end
171
171
 
172
172
  node = parse_choice
173
+ # parsanol-ruby#152 phase 2: `skip = trivia capture:
174
+ # comments` attaches comment-shaped trivia (the rules the
175
+ # declaration references, identified by leading literal)
176
+ # to the next successful capture under `comments:`.
177
+ if peek&.type == :ident && peek.value == "capture"
178
+ advance
179
+ punct(":")
180
+ document.skip_capture_key = ident.value.to_sym
181
+ end
173
182
  document.skip_declaration = validate_skip_node(node)
174
183
  document.skip_source = skip_source_string(node)
175
184
  skip_newlines
@@ -260,7 +269,12 @@ module Parsanol
260
269
 
261
270
  def stop_element?
262
271
  peek.nil? || peek.type == :newline ||
263
- (peek.type == :punct && ["/", ")", "]", "}"].include?(peek.value))
272
+ (peek.type == :punct && ["/", ")", "]", "}"].include?(peek.value)) ||
273
+ # `capture:` suffix terminates the skip declaration's RHS
274
+ # (parsanol-ruby#152); everywhere else parse_element's guard
275
+ # rejects it.
276
+ (peek&.type == :ident && peek.value == "capture" &&
277
+ @tokens[@pos + 1]&.type == :punct && @tokens[@pos + 1]&.value == ":")
264
278
  end
265
279
 
266
280
  def parse_element
@@ -269,6 +283,13 @@ module Parsanol
269
283
  raise ParseError, "unexpected end of input inside sequence"
270
284
  end
271
285
 
286
+ # `capture:` is a skip-declaration suffix, never an expression
287
+ # element (reserved keyword; parsanol-ruby#152).
288
+ if token.type == :ident && token.value == "capture" &&
289
+ @tokens[@pos + 1]&.type == :punct && @tokens[@pos + 1]&.value == ":"
290
+ raise ParseError, "capture: only modifies the skip declaration"
291
+ end
292
+
272
293
  if token.type == :num
273
294
  advance
274
295
  min = token.value.to_i
@@ -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.70"
4
+ VERSION = "1.3.72"
5
5
  end
data/lib/parsanol/vm.rb CHANGED
@@ -649,6 +649,12 @@ module Parsanol
649
649
  compile_entity(atom, consume_all)
650
650
  when Parsanol::Atoms::Lookahead
651
651
  compile_lookahead(atom, consume_all)
652
+ when Parsanol::Atoms::TriviaCapture
653
+ # Captured trivia records into the context channel at match
654
+ # time (parsanol-ruby#152); the bytecode program has no
655
+ # channel, so the interpreter (which does) must own the
656
+ # grammar. Declining here routes program_for to :fallback.
657
+ nil
652
658
  when Parsanol::Atoms::Ignored
653
659
  inner = atom.wrapped_atom
654
660
  return nil if inner.nil?
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.70
4
+ version: 1.3.72
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