parsanol 1.3.86 → 1.3.88
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 +4 -4
- data/Cargo.lock +4 -4
- data/lib/parsanol/atoms/base.rb +5 -1
- data/lib/parsanol/atoms/context.rb +4 -4
- data/lib/parsanol/atoms/named.rb +8 -4
- data/lib/parsanol/atoms/trivia.rb +7 -3
- data/lib/parsanol/native/transformer.rb +10 -3
- data/lib/parsanol/parg/parser.rb +25 -5
- data/lib/parsanol/skip.rb +19 -5
- data/lib/parsanol/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c24632a252a0d882d2491b361a569d8e96132f5c25942660db5c531313ebe913
|
|
4
|
+
data.tar.gz: 6349b99005ed86363fc2a13943a2c4e5dd4ce3958a364d12cb82ceea4c660d64
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 81eca9be5955bc6e28413a88622392ad25c969307a9ee3d2d29255c4c59ad543f560c06c94cbcb34044b143365ad87622115a2786b4d8e7a5dd609cb91b5d4b6
|
|
7
|
+
data.tar.gz: 943d81f3c10eb2e2e662ca1312d41c25f5b0cff23e455f5aec1d605d0be868dd0e682104980f4b46333d5e262399814d9cf2a9fa8626a578297a045218fff52e
|
data/Cargo.lock
CHANGED
|
@@ -307,9 +307,9 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
|
|
307
307
|
|
|
308
308
|
[[package]]
|
|
309
309
|
name = "parsanol"
|
|
310
|
-
version = "0.18.
|
|
310
|
+
version = "0.18.2"
|
|
311
311
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
312
|
-
checksum = "
|
|
312
|
+
checksum = "b059d18a92c61ba7c7c6241bb446196729dadf618e6e34c0b79935f0292d7a27"
|
|
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.18.
|
|
329
|
+
version = "0.18.2"
|
|
330
330
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
331
|
-
checksum = "
|
|
331
|
+
checksum = "4b9a6de83c376137ccce01cb8890427a8879b34b6ac4832cc0413c5624923001"
|
|
332
332
|
dependencies = [
|
|
333
333
|
"proc-macro2",
|
|
334
334
|
"quote",
|
data/lib/parsanol/atoms/base.rb
CHANGED
|
@@ -157,7 +157,11 @@ module Parsanol
|
|
|
157
157
|
# @param outer [Integer] caller's precedence
|
|
158
158
|
# @return [String]
|
|
159
159
|
def to_s(outer = TOP)
|
|
160
|
-
text
|
|
160
|
+
# The inner text is cached per instance: renders walk the atom
|
|
161
|
+
# tree through shared references, and an uncached render is
|
|
162
|
+
# exponential on cross-referencing grammars (parsanol-ruby#190).
|
|
163
|
+
# The paren wrapper stays dynamic; the label is read live.
|
|
164
|
+
text = label || (@to_s_inner_cache ||= to_s_inner(precedence))
|
|
161
165
|
outer < precedence ? "(#{text})" : text
|
|
162
166
|
end
|
|
163
167
|
|
|
@@ -263,10 +263,10 @@ module Parsanol
|
|
|
263
263
|
[false, @reporter.err(*)]
|
|
264
264
|
end
|
|
265
265
|
|
|
266
|
-
# Records one captured trivia unit (kind, text
|
|
267
|
-
# the next successful Named capture.
|
|
268
|
-
def push_captured_trivia(kind, text)
|
|
269
|
-
@pending_trivia << { kind: kind, text: text }
|
|
266
|
+
# Records one captured trivia unit (kind, text, input offset)
|
|
267
|
+
# for attachment to the next successful Named capture.
|
|
268
|
+
def push_captured_trivia(kind, text, pos)
|
|
269
|
+
@pending_trivia << { kind: kind, text: text, pos: pos }
|
|
270
270
|
nil
|
|
271
271
|
end
|
|
272
272
|
|
data/lib/parsanol/atoms/named.rb
CHANGED
|
@@ -41,7 +41,7 @@ module Parsanol
|
|
|
41
41
|
|
|
42
42
|
comments = context.take_pending_trivia
|
|
43
43
|
result = wrap_result(value)
|
|
44
|
-
result = attach_comments(result, comments) unless comments.empty?
|
|
44
|
+
result = attach_comments(result, comments, source) unless comments.empty?
|
|
45
45
|
ok(result)
|
|
46
46
|
end
|
|
47
47
|
|
|
@@ -50,9 +50,13 @@ module Parsanol
|
|
|
50
50
|
# parsanol-ruby#152: trivia captured ahead of this capture rides
|
|
51
51
|
# with it under `comments:`. The attachment only fires when the
|
|
52
52
|
# grammar declared capture AND trivia actually preceded — key
|
|
53
|
-
# absence everywhere else keeps v1 trees byte-identical.
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
# absence everywhere else keeps v1 trees byte-identical. Units
|
|
54
|
+
# carry their input offset so the value is a positioned Slice,
|
|
55
|
+
# like every other capture value (native parity, ruby#180).
|
|
56
|
+
def attach_comments(result, comments, source)
|
|
57
|
+
list = comments.map do |unit|
|
|
58
|
+
{ unit[:kind] => Slice.new(unit[:pos], unit[:text], source.input) }
|
|
59
|
+
end
|
|
56
60
|
if result.is_a?(Hash)
|
|
57
61
|
result.merge(comments: list)
|
|
58
62
|
else
|
|
@@ -61,13 +61,17 @@ module Parsanol
|
|
|
61
61
|
def record(source, context, start_pos, end_pos)
|
|
62
62
|
text = source.input[start_pos...end_pos]
|
|
63
63
|
# A trivia unit may lead with whitespace before the comment
|
|
64
|
-
# shape; markers test the comment head.
|
|
64
|
+
# shape; markers test the comment head. The recorded offset
|
|
65
|
+
# must agree with the recorded content as a slice of the
|
|
66
|
+
# input: trimmed marker text starts after the unit's leading
|
|
67
|
+
# whitespace, not at the wrapper (native parity, ruby#180).
|
|
65
68
|
stripped = text.lstrip
|
|
66
69
|
marker, label = @capturers&.find { |m, _label| stripped.start_with?(m) }
|
|
67
70
|
if marker
|
|
68
|
-
context.push_captured_trivia(label, stripped.strip
|
|
71
|
+
context.push_captured_trivia(label, stripped.strip,
|
|
72
|
+
start_pos + (text.length - stripped.length))
|
|
69
73
|
elsif @whitespace_kind
|
|
70
|
-
context.push_captured_trivia(@whitespace_kind, text)
|
|
74
|
+
context.push_captured_trivia(@whitespace_kind, text, start_pos)
|
|
71
75
|
end
|
|
72
76
|
end
|
|
73
77
|
end
|
|
@@ -310,9 +310,16 @@ module Parsanol
|
|
|
310
310
|
transformed
|
|
311
311
|
elsif is_repetition
|
|
312
312
|
if transformed.is_a?(Array)
|
|
313
|
-
if transformed.all?
|
|
314
|
-
|
|
315
|
-
|
|
313
|
+
if transformed.all?(Hash)
|
|
314
|
+
# Hash items carry their own capture
|
|
315
|
+
# names (parslet semantics) — the
|
|
316
|
+
# single-key path
|
|
317
|
+
# (transform_repetition_value) already
|
|
318
|
+
# keeps them; this multi-key path (a
|
|
319
|
+
# Named with a trivia attachment, or
|
|
320
|
+
# merged siblings) must agree — only
|
|
321
|
+
# unnamed items take the parent name
|
|
322
|
+
# per item.
|
|
316
323
|
transformed
|
|
317
324
|
else
|
|
318
325
|
transformed.map { |item| { sym_key => item } }
|
data/lib/parsanol/parg/parser.rb
CHANGED
|
@@ -296,29 +296,49 @@ module Parsanol
|
|
|
296
296
|
if peek&.type == :punct && peek.value == "*"
|
|
297
297
|
advance
|
|
298
298
|
max = peek&.type == :num ? advance.value.to_i : nil
|
|
299
|
-
node = Node.new(:rep,
|
|
299
|
+
node = Node.new(:rep, parse_rep_body, min, max)
|
|
300
300
|
else
|
|
301
|
-
node = Node.new(:rep,
|
|
301
|
+
node = Node.new(:rep, parse_rep_body, min, min)
|
|
302
302
|
end
|
|
303
|
-
return node
|
|
303
|
+
return capture_postfix(node)
|
|
304
304
|
elsif token.type == :punct && token.value == "*"
|
|
305
305
|
advance
|
|
306
306
|
max = peek&.type == :num ? advance.value.to_i : nil
|
|
307
|
-
return Node.new(:rep,
|
|
307
|
+
return capture_postfix(Node.new(:rep, parse_rep_body, 0, max))
|
|
308
308
|
end
|
|
309
309
|
parse_postfixed
|
|
310
310
|
end
|
|
311
311
|
|
|
312
|
-
|
|
312
|
+
# A repetition's body must not claim the `as` that follows the
|
|
313
|
+
# repetition's own closing paren (parsanol-ruby#197): the body
|
|
314
|
+
# parser is postfix-blind, and the postfix wraps the REPETITION —
|
|
315
|
+
# `*( X ) as name` captures the whole repeated run, matching the
|
|
316
|
+
# Ruby DSL's `.repeat.as(:name)`. An `as` inside the body's own
|
|
317
|
+
# parens still binds the body — write `*( ( X ) as name )` for
|
|
318
|
+
# that (naming each iteration's X).
|
|
319
|
+
def parse_rep_body
|
|
313
320
|
sign = nil
|
|
314
321
|
if peek&.type == :punct && %w[! &].include?(peek.value)
|
|
315
322
|
sign = advance.value == "&"
|
|
316
323
|
end
|
|
317
324
|
node = parse_primary
|
|
325
|
+
sign.nil? ? node : Node.new(:pred, sign, node)
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
def capture_postfix(node)
|
|
318
329
|
if peek&.type == :ident && peek.value == "as"
|
|
319
330
|
advance
|
|
320
331
|
node = Node.new(:cap, ident.value, node)
|
|
321
332
|
end
|
|
333
|
+
node
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
def parse_postfixed
|
|
337
|
+
sign = nil
|
|
338
|
+
if peek&.type == :punct && %w[! &].include?(peek.value)
|
|
339
|
+
sign = advance.value == "&"
|
|
340
|
+
end
|
|
341
|
+
node = capture_postfix(parse_primary)
|
|
322
342
|
sign.nil? ? node : Node.new(:pred, sign, node)
|
|
323
343
|
end
|
|
324
344
|
|
data/lib/parsanol/skip.rb
CHANGED
|
@@ -201,12 +201,26 @@ module Parsanol
|
|
|
201
201
|
when Atoms::Entity
|
|
202
202
|
# Rule bodies own their injection when the grammar declares
|
|
203
203
|
# skip on every rule (PARG); in the DSL surface the root tree
|
|
204
|
-
# is walked once, so
|
|
205
|
-
#
|
|
206
|
-
#
|
|
207
|
-
#
|
|
204
|
+
# is walked once, so inject the resolved body as a fresh
|
|
205
|
+
# injection scope (even inside a repetition interior — the
|
|
206
|
+
# d54a29e exception is for rule-reference children). The
|
|
207
|
+
# reference itself stays an Entity pointing at the injected
|
|
208
|
+
# body: inlining the body into every referencing site makes
|
|
209
|
+
# every rendered string (to_s, and failure messages built
|
|
210
|
+
# from inspect) expand the grammar exponentially on
|
|
211
|
+
# cross-referencing grammars — one failing Sequence rendered
|
|
212
|
+
# a multi-gigabyte message (parsanol-ruby#190).
|
|
208
213
|
begin
|
|
209
|
-
walk(atom.parslet, mode == :exempt ? :exempt : false)
|
|
214
|
+
body = walk(atom.parslet, mode == :exempt ? :exempt : false)
|
|
215
|
+
if body.is_a?(Atoms::Lookahead)
|
|
216
|
+
# A whole-body lookahead keeps its #192 boundary visible
|
|
217
|
+
# to enclosing sequences (no wrapper before it).
|
|
218
|
+
body
|
|
219
|
+
else
|
|
220
|
+
ref = Atoms::Entity.new(atom.rule_name) { body }
|
|
221
|
+
ref.label = atom.label if atom.label
|
|
222
|
+
ref
|
|
223
|
+
end
|
|
210
224
|
rescue StandardError
|
|
211
225
|
atom
|
|
212
226
|
end
|
data/lib/parsanol/version.rb
CHANGED