parsanol 1.3.84 → 1.3.85
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/lib/parsanol/native.rb +44 -2
- 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: 38de1565e58ea110f8732c5eec590223281787eb7922f0b885ddfa76594353e4
|
|
4
|
+
data.tar.gz: 745175be31f92a3c40bac11e846b317954dfa4abe24628802aeefb1ee1adc460
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 133c7393222f9e29c776def04d6f7b5764d344bad9d8e7dd5ce054dcacaafca8720c266fb2f7ecd48cbcc036d462747028c42659b0b2ce271aed9ede9e56aded
|
|
7
|
+
data.tar.gz: 646eb2011402310a591dc4aec7c87a5ccf58e270d9177d5c3657dd776a0e0762765f3a7be731137cadbe57ac292922de7d58008ef2b0fc908268cc8a60433510
|
data/lib/parsanol/native.rb
CHANGED
|
@@ -202,6 +202,38 @@ module Parsanol
|
|
|
202
202
|
stats
|
|
203
203
|
end
|
|
204
204
|
|
|
205
|
+
# True when the grammar carries no atoms the native tier cannot
|
|
206
|
+
# express (Dynamic callbacks, artifact custom bindings). Cached by
|
|
207
|
+
# grammar identity — the scan walks the atom tree once.
|
|
208
|
+
def native_expressible?(grammar)
|
|
209
|
+
root = grammar.is_a?(Parsanol::Parser) ? grammar.root : grammar
|
|
210
|
+
cache = (@expressible_cache ||= {}.compare_by_identity)
|
|
211
|
+
cache.fetch(root) do
|
|
212
|
+
expressible = !contains_inexpressible?(root, {}.compare_by_identity)
|
|
213
|
+
cache[root] = expressible
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def contains_inexpressible?(atom, seen)
|
|
218
|
+
return false if seen.key?(atom)
|
|
219
|
+
|
|
220
|
+
seen[atom] = true
|
|
221
|
+
case atom
|
|
222
|
+
when Parsanol::Atoms::Dynamic, Parsanol::Atoms::CustomRef then true
|
|
223
|
+
when Parsanol::Atoms::Sequence, Parsanol::Atoms::Alternative
|
|
224
|
+
children = atom.respond_to?(:parslets) ? atom.parslets : atom.alternatives
|
|
225
|
+
children.any? { |child| contains_inexpressible?(child, seen) }
|
|
226
|
+
when Parsanol::Atoms::Entity, Parsanol::Atoms::Repetition,
|
|
227
|
+
Parsanol::Atoms::Named, Parsanol::Atoms::Capture, Parsanol::Atoms::Ignored,
|
|
228
|
+
Parsanol::Atoms::Trivia, Parsanol::Atoms::TriviaCapture, Parsanol::Atoms::Lookahead
|
|
229
|
+
inner = atom.respond_to?(:parslet) ? atom.parslet : nil
|
|
230
|
+
inner ||= atom.wrapped_atom if atom.respond_to?(:wrapped_atom)
|
|
231
|
+
inner && contains_inexpressible?(inner, seen)
|
|
232
|
+
else
|
|
233
|
+
false
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
|
|
205
237
|
# Translates a native backend failure into the Parsanol error protocol.
|
|
206
238
|
#
|
|
207
239
|
# When the grammar atom is at hand, reparses through the pure Ruby
|
|
@@ -227,9 +259,19 @@ module Parsanol
|
|
|
227
259
|
# across long parses (#123).
|
|
228
260
|
message = error.message
|
|
229
261
|
if parsanol_grammar && (pos_str = message[NATIVE_POS_MARKER, 1])
|
|
262
|
+
# The interpreter reparse exists to RECOVER grammars the
|
|
263
|
+
# native tier cannot express (Dynamic/CustomRef atoms —
|
|
264
|
+
# parsanol-ruby#80/#129). For grammars without them the
|
|
265
|
+
# native failure is authoritative and the deepest-position
|
|
266
|
+
# diagnostics ride in this message — reparsing through the
|
|
267
|
+
# interpreter buys nothing and, on capture-heavy injected
|
|
268
|
+
# grammars, explodes (#190: the interpreter memo never
|
|
269
|
+
# stores capture-spanning outcomes).
|
|
230
270
|
source = Parsanol::Source.new(input)
|
|
231
|
-
|
|
232
|
-
|
|
271
|
+
unless native_expressible?(grammar)
|
|
272
|
+
success, value = grammar.run_with_context(source, nil, true)
|
|
273
|
+
return grammar.finalize_result(value) if success
|
|
274
|
+
end
|
|
233
275
|
|
|
234
276
|
pos = pos_str.to_i
|
|
235
277
|
msg = message.sub(NATIVE_POS_MARKER, "")
|
data/lib/parsanol/version.rb
CHANGED