parsanol 1.3.114-arm-linux → 1.3.115-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: 9ccfe53145a4fbf2af4f7c2cc47071231be0016d8047e9bb0f75386738ff0480
4
- data.tar.gz: 395d7bccac544d4842b29e5764d1198816ab823e1f9defdc3874009395caaa24
3
+ metadata.gz: 87e094abf1d96459b9558d746f9a436b32e0b3ac58d6529b565159a771e1a9e9
4
+ data.tar.gz: a4331601780b6d3681b45ed55dfbdbe94c227d59cff2c743d3804b5ad2a263bf
5
5
  SHA512:
6
- metadata.gz: b1436b7af7ea025b302e14fc14970c42252c75f5aa6a2252f1701862ebca604ccc05349a39fdbd77b09fef78c7e633b9a6ff15c3f22e3a36845f49133a84eb7a
7
- data.tar.gz: 188fe5c41d516ab6f3372ca339d0c313b0460e912e122a9e32ed5f8b948deb743c3a38f406997dddbb97cc9e3a5a7a25587640273eb44c97dde75d518d24ad6b
6
+ metadata.gz: 491dd96953046d5f729a5bbb403cdb4ce0ce7d1db7365b14fbd395145067e26e1a43968dae4d31176f6e77dc19978039a6297363e27ea63dfbd225370b42430d
7
+ data.tar.gz: 01e15a6809c13dde391770ba64eac2edca3c794df440278e8099832696d212f6c8446d7eded2c03d443879c11b7877314a1178cf1b328c5c6f0da576aaf3edec
data/README.adoc CHANGED
@@ -31,6 +31,17 @@ While maintaining full API compatibility with Parslet, Parsanol features a compl
31
31
  * <<debug-tools,Debug Tools>> - Tracing and grammar visualization
32
32
  * <<benchmarking,Benchmarking>> - Built-in performance testing tools
33
33
 
34
+ == Releases
35
+
36
+ parsanol is one product on **four runtimes**: **rs** (crates.io +
37
+ `@parsanol/wasm` + release binaries), **ruby** (rubygems), **python**
38
+ (PyPI, `parsanol`), and **typescript** (npm, `parsanol` — the
39
+ wasm-backed runtime). **Every engine update releases all four
40
+ together**; a release that ships some runtimes and not the rest is
41
+ incomplete. If the runtime you use lags the latest grammar-language
42
+ features, check the other registries' changelogs and the release train
43
+ on the https://github.com/parsanol/parsanol-ruby/actions[Release workflow].
44
+
34
45
  == Installation
35
46
 
36
47
  Add this line to your application's Gemfile:
@@ -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: 39082700 bytes
4
- sha256: d252dd306fb0dcb4726ed8a1deb826cecfc1ca8bf5528603f50ac20058e0aea9
3
+ size: 39170404 bytes
4
+ sha256: bbab9454dfa91df09fdcc00143cf18ff89d277657f975d13959c01255f7c5707
@@ -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: 39267920 bytes
4
- sha256: 4f500faf69c8b85dff0055043e37d08bdb897cabd0bc814ce1a5a7f31db0fad4
3
+ size: 39355636 bytes
4
+ sha256: 808eb780f0317adb4f98e7323b90e7d99e55d729a8d961b1b63fcf4660ab4562
@@ -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: 39262108 bytes
4
- sha256: b24c02b2f5d0848c59dba33cf4751107b1799ec8f96c961c3952114e96eb10f7
3
+ size: 39349796 bytes
4
+ sha256: bbc22c4d658fc4a0a9a72344e5765a44ec9985e0ef1373704cc31014565e711d
@@ -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: 39271824 bytes
4
- sha256: 3bc6176aec3d4bb697ce024b174ddeca6a4b50a297bdd84492a277205e46efed
3
+ size: 39359512 bytes
4
+ sha256: 017f6f3c4909e39c878a6f28f562d577a8b02442de38a0ac9760b48873871426
@@ -1,4 +1,4 @@
1
1
  [diffend] Oversized file quarantined before diffing.
2
2
  name: data/lib/parsanol/native/libparsanol.so
3
- size: 35442920 bytes
4
- sha256: 0a129844ae8acce2330a6b009be2fc9d918a6f46d53f744429ae02b9bf039aea
3
+ size: 35531016 bytes
4
+ sha256: 968ae4d54093a740fd7ce2e59fe10ab73dd853e23a852e5d22e292168a3f9c5a
@@ -20,9 +20,24 @@ module Parsanol
20
20
  ENTRY_LINE = /\Aentry\s+(\w+)\s*:\s*(\w+)/
21
21
  USE_LINE = /\Ause\s+(\w+)/
22
22
  GRAMMAR_LINE = /\Agrammar\s+(\w+)\s+version\s+"([^"]+)"/
23
+ # The capture-edition tail: the canonical numeric spelling or the
24
+ # quoted aliases (ruby#361); `mode` stays the deprecated keyword.
25
+ EDITION_TAIL = /
26
+ \s+(?:edition\s+(?:"(?<quoted>[^"]+)"|(?<number>\d+))|mode\s+"(?<mode>[^"]+)")
27
+ /x
28
+ GLUE_LINE = /\Aglue\s+([a-z_][a-z0-9_]*(?:\s+[a-z_][a-z0-9_]*)*)\s*\z/
23
29
 
24
30
  module_function
25
31
 
32
+ # Brace depth for the line-oriented collection: braces inside
33
+ # string literals are grammar data — test pins quote whole
34
+ # language forms, including deliberately malformed ones whose
35
+ # unbalanced braces would push the section depth off (ruby#369).
36
+ def brace_delta(line)
37
+ bare = line.gsub(/"(?:[^"\\]|\\.)*"/, "")
38
+ bare.scan("{").count - bare.scan("}").count
39
+ end
40
+
26
41
  def parse(source)
27
42
  SelfHost.validate(source) unless SelfHost.available? && !SelfHost.valid?(source)
28
43
 
@@ -43,7 +58,17 @@ module Parsanol
43
58
  end
44
59
  next if stripped.empty? || stripped.start_with?("#")
45
60
 
46
- if state[:section]
61
+ if state[:rule_depth]&.positive?
62
+ # A brace-form rule body spans lines (ruby#311): keep
63
+ # appending until its braces balance.
64
+ state[:rule_lines][state[:rule_depth_name]] << line
65
+ state[:rule_depth] += brace_delta(line)
66
+ if state[:rule_depth].zero?
67
+ merge_rule(document, state[:rule_lines][state[:rule_depth_name]])
68
+ state[:rule_depth] = nil
69
+ state[:rule_depth_name] = nil
70
+ end
71
+ elsif state[:section]
47
72
  advance_section(document, state, line, deferred, preprocess_texts)
48
73
  else
49
74
  route_top_level(document, stripped, line, state,
@@ -59,7 +84,7 @@ module Parsanol
59
84
  # Consumes one line inside a deferred/closed-by-brace section.
60
85
  def advance_section(document, state, line, deferred, preprocess_texts)
61
86
  section = state[:section]
62
- state[:depth] += line.scan("{").count - line.scan("}").count
87
+ state[:depth] += brace_delta(line)
63
88
  if state[:depth].positive?
64
89
  preprocess_texts.last << line if section == "preprocess"
65
90
  state[:section_lines] << line
@@ -91,9 +116,19 @@ module Parsanol
91
116
  when USE_LINE
92
117
  document.uses << Regexp.last_match(1)
93
118
  doc_comments = []
119
+ when GLUE_LINE
120
+ document.glue_rules.concat(Regexp.last_match(1).split)
121
+ doc_comments = []
94
122
  when GRAMMAR_LINE
95
123
  document.grammar_name = Regexp.last_match(1)
96
124
  document.version = Regexp.last_match(2)
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
97
132
  doc_comments = []
98
133
  when NAMED_SECTION
99
134
  state[:section] = Regexp.last_match(1)
@@ -128,7 +163,15 @@ module Parsanol
128
163
  document.docs[rule_name] = doc_comments.join("\n") unless doc_comments.empty?
129
164
  doc_comments = []
130
165
  state[:rule_lines][rule_name] = line
131
- merge_rule(document, line)
166
+ depth = brace_delta(line)
167
+ if depth.positive?
168
+ # Brace-form body opens (ruby#311): the rule completes on a
169
+ # later line; the continuation loop appends and merges then.
170
+ state[:rule_depth] = depth
171
+ state[:rule_depth_name] = rule_name
172
+ else
173
+ merge_rule(document, line)
174
+ end
132
175
  else
133
176
  doc_comments = []
134
177
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Parsanol
4
- VERSION = "1.3.114"
4
+ VERSION = "1.3.115"
5
5
  end
data/lib/parsanol/vm.rb CHANGED
@@ -452,6 +452,11 @@ module Parsanol
452
452
  @subs = {} # [obj_id, flag] => pc or :pending
453
453
  @pending = {} # [obj_id, flag] => [[call_idx, body], ...]
454
454
  @backtracking_prone = false
455
+ # Grammar rules form a shared graph. Re-analyzing every reference
456
+ # repeats whole alternative trees during inlining. These caches
457
+ # live only for this compiler and retain the depth limit's meaning.
458
+ @first_byte_tables = {}.compare_by_identity
459
+ @nullability = {}.compare_by_identity
455
460
  end
456
461
 
457
462
  attr_reader :ops, :backtracking_prone
@@ -484,6 +489,13 @@ module Parsanol
484
489
  def first_byte_table(atom, depth = 0)
485
490
  return nil if depth > 10
486
491
 
492
+ cached = (@first_byte_tables[atom] ||= {})
493
+ return cached[depth] if cached.key?(depth)
494
+
495
+ cached[depth] = compute_first_byte_table(atom, depth)&.freeze
496
+ end
497
+
498
+ def compute_first_byte_table(atom, depth)
487
499
  case atom
488
500
  when Parsanol::Atoms::Str
489
501
  b = atom.str.getbyte(0)
@@ -508,7 +520,7 @@ module Parsanol
508
520
  i += 1
509
521
  end
510
522
  else
511
- t = ct
523
+ t = ct.dup
512
524
  end
513
525
  unless nullable?(child, depth + 1)
514
526
  nullable_all = false
@@ -529,7 +541,7 @@ module Parsanol
529
541
  i += 1
530
542
  end
531
543
  else
532
- t = bt
544
+ t = bt.dup
533
545
  end
534
546
  end
535
547
  t
@@ -572,6 +584,13 @@ module Parsanol
572
584
  def nullable?(atom, depth = 0)
573
585
  return false if depth > 10
574
586
 
587
+ cached = (@nullability[atom] ||= {})
588
+ return cached[depth] if cached.key?(depth)
589
+
590
+ cached[depth] = compute_nullable(atom, depth)
591
+ end
592
+
593
+ def compute_nullable(atom, depth)
575
594
  case atom
576
595
  when Parsanol::Atoms::Str then atom.str.bytesize.zero?
577
596
  when Parsanol::Atoms::Re then false
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.114
4
+ version: 1.3.115
5
5
  platform: arm-linux
6
6
  authors:
7
7
  - Ribose Inc.