parsanol 1.2.2 → 1.3.3
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 +29 -41
- data/Cargo.toml +8 -2
- data/HISTORY.txt +33 -3
- data/README.adoc +103 -9
- data/ext/parsanol_native/Cargo.toml +9 -6
- data/lib/parsanol/native/batch_decoder.rb +252 -0
- data/lib/parsanol/native/parser.rb +28 -574
- data/lib/parsanol/native/transformer.rb +125 -58
- data/lib/parsanol/native.rb +107 -183
- data/lib/parsanol/parser.rb +2 -6
- data/lib/parsanol/slice.rb +51 -105
- data/lib/parsanol/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bac63e41077cf9eed82a69de397d2248e532e09f5b26f149b2af88daed9b669c
|
|
4
|
+
data.tar.gz: 777066f81425836b34c629c0a3ef53b2297cfb4a2f963925be699a515f5d0751
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dd2fc966df72d3422c489d9e588260e54c298ea694ae96e0e3bf178ecc979b22e541593dfe8011d3cd9e1857625097b382cdfcfe5f4c65a9cf10a1372704ed0a
|
|
7
|
+
data.tar.gz: 58e95adb43e19330469176920fc8eb05f0b5f79b074552ae3d54805c40fbf324cf998e49ca4b5b73bc1ec65e3e0aab47472f8fafb7a6e3567ea8948c95eae539
|
data/Cargo.lock
CHANGED
|
@@ -38,16 +38,14 @@ checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
|
|
|
38
38
|
|
|
39
39
|
[[package]]
|
|
40
40
|
name = "bindgen"
|
|
41
|
-
version = "0.
|
|
41
|
+
version = "0.72.1"
|
|
42
42
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
43
|
-
checksum = "
|
|
43
|
+
checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895"
|
|
44
44
|
dependencies = [
|
|
45
45
|
"bitflags",
|
|
46
46
|
"cexpr",
|
|
47
47
|
"clang-sys",
|
|
48
48
|
"itertools",
|
|
49
|
-
"lazy_static",
|
|
50
|
-
"lazycell",
|
|
51
49
|
"proc-macro2",
|
|
52
50
|
"quote",
|
|
53
51
|
"regex",
|
|
@@ -125,9 +123,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
|
125
123
|
checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
|
|
126
124
|
dependencies = [
|
|
127
125
|
"cfg-if",
|
|
126
|
+
"js-sys",
|
|
128
127
|
"libc",
|
|
129
128
|
"r-efi 5.3.0",
|
|
130
129
|
"wasip2",
|
|
130
|
+
"wasm-bindgen",
|
|
131
131
|
]
|
|
132
132
|
|
|
133
133
|
[[package]]
|
|
@@ -197,9 +197,9 @@ dependencies = [
|
|
|
197
197
|
|
|
198
198
|
[[package]]
|
|
199
199
|
name = "itertools"
|
|
200
|
-
version = "0.
|
|
200
|
+
version = "0.13.0"
|
|
201
201
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
202
|
-
checksum = "
|
|
202
|
+
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
|
|
203
203
|
dependencies = [
|
|
204
204
|
"either",
|
|
205
205
|
]
|
|
@@ -226,12 +226,6 @@ version = "1.5.0"
|
|
|
226
226
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
227
227
|
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
|
228
228
|
|
|
229
|
-
[[package]]
|
|
230
|
-
name = "lazycell"
|
|
231
|
-
version = "1.3.0"
|
|
232
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
233
|
-
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
|
234
|
-
|
|
235
229
|
[[package]]
|
|
236
230
|
name = "leb128fmt"
|
|
237
231
|
version = "0.1.0"
|
|
@@ -240,9 +234,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
|
|
|
240
234
|
|
|
241
235
|
[[package]]
|
|
242
236
|
name = "libc"
|
|
243
|
-
version = "0.2.
|
|
237
|
+
version = "0.2.183"
|
|
244
238
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
245
|
-
checksum = "
|
|
239
|
+
checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d"
|
|
246
240
|
|
|
247
241
|
[[package]]
|
|
248
242
|
name = "libloading"
|
|
@@ -262,9 +256,8 @@ checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
|
|
262
256
|
|
|
263
257
|
[[package]]
|
|
264
258
|
name = "magnus"
|
|
265
|
-
version = "0.
|
|
266
|
-
source = "
|
|
267
|
-
checksum = "3b36a5b126bbe97eb0d02d07acfeb327036c6319fd816139a49824a83b7f9012"
|
|
259
|
+
version = "0.9.0"
|
|
260
|
+
source = "git+https://github.com/matsadler/magnus?rev=4e46772#4e46772050e47cd6cd988fa935263cc5c583e388"
|
|
268
261
|
dependencies = [
|
|
269
262
|
"magnus-macros",
|
|
270
263
|
"rb-sys",
|
|
@@ -274,9 +267,8 @@ dependencies = [
|
|
|
274
267
|
|
|
275
268
|
[[package]]
|
|
276
269
|
name = "magnus-macros"
|
|
277
|
-
version = "0.
|
|
278
|
-
source = "
|
|
279
|
-
checksum = "47607461fd8e1513cb4f2076c197d8092d921a1ea75bd08af97398f593751892"
|
|
270
|
+
version = "0.9.0"
|
|
271
|
+
source = "git+https://github.com/matsadler/magnus?rev=4e46772#4e46772050e47cd6cd988fa935263cc5c583e388"
|
|
280
272
|
dependencies = [
|
|
281
273
|
"proc-macro2",
|
|
282
274
|
"quote",
|
|
@@ -307,23 +299,22 @@ dependencies = [
|
|
|
307
299
|
|
|
308
300
|
[[package]]
|
|
309
301
|
name = "once_cell"
|
|
310
|
-
version = "1.21.
|
|
302
|
+
version = "1.21.4"
|
|
311
303
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
312
|
-
checksum = "
|
|
304
|
+
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
|
313
305
|
|
|
314
306
|
[[package]]
|
|
315
307
|
name = "parsanol"
|
|
316
|
-
version = "0.
|
|
317
|
-
source = "
|
|
318
|
-
checksum = "40e84f8cdc9f85960871f57d5fff33cf9e03deae0fd7f87b1f9655f35451fdf7"
|
|
308
|
+
version = "0.4.1"
|
|
309
|
+
source = "git+https://github.com/parsanol/parsanol-rs?rev=4667017#46670172240420221089cb4da6eaecadb23a0015"
|
|
319
310
|
dependencies = [
|
|
320
311
|
"ahash",
|
|
312
|
+
"getrandom 0.3.4",
|
|
321
313
|
"getrandom 0.4.2",
|
|
322
314
|
"hashbrown 0.16.1",
|
|
323
315
|
"magnus",
|
|
324
316
|
"memchr",
|
|
325
317
|
"parsanol-derive",
|
|
326
|
-
"rb-sys",
|
|
327
318
|
"regex",
|
|
328
319
|
"serde",
|
|
329
320
|
"serde_json",
|
|
@@ -331,9 +322,8 @@ dependencies = [
|
|
|
331
322
|
|
|
332
323
|
[[package]]
|
|
333
324
|
name = "parsanol-derive"
|
|
334
|
-
version = "0.
|
|
335
|
-
source = "
|
|
336
|
-
checksum = "bbd12999fd4452b4713c3d32ca200de0894da2636a215ed54e83c42a553c1aae"
|
|
325
|
+
version = "0.4.1"
|
|
326
|
+
source = "git+https://github.com/parsanol/parsanol-rs?rev=4667017#46670172240420221089cb4da6eaecadb23a0015"
|
|
337
327
|
dependencies = [
|
|
338
328
|
"proc-macro2",
|
|
339
329
|
"quote",
|
|
@@ -371,9 +361,9 @@ dependencies = [
|
|
|
371
361
|
|
|
372
362
|
[[package]]
|
|
373
363
|
name = "quote"
|
|
374
|
-
version = "1.0.
|
|
364
|
+
version = "1.0.45"
|
|
375
365
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
376
|
-
checksum = "
|
|
366
|
+
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
|
|
377
367
|
dependencies = [
|
|
378
368
|
"proc-macro2",
|
|
379
369
|
]
|
|
@@ -393,8 +383,7 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
|
|
|
393
383
|
[[package]]
|
|
394
384
|
name = "rb-sys"
|
|
395
385
|
version = "0.9.124"
|
|
396
|
-
source = "
|
|
397
|
-
checksum = "c85c4188462601e2aa1469def389c17228566f82ea72f137ed096f21591bc489"
|
|
386
|
+
source = "git+https://github.com/oxidize-rb/rb-sys.git?rev=b42b5fba0424fcc6778fed9a01e05215eaa53f85#b42b5fba0424fcc6778fed9a01e05215eaa53f85"
|
|
398
387
|
dependencies = [
|
|
399
388
|
"rb-sys-build",
|
|
400
389
|
]
|
|
@@ -402,8 +391,7 @@ dependencies = [
|
|
|
402
391
|
[[package]]
|
|
403
392
|
name = "rb-sys-build"
|
|
404
393
|
version = "0.9.124"
|
|
405
|
-
source = "
|
|
406
|
-
checksum = "568068db4102230882e6d4ae8de6632e224ca75fe5970f6e026a04e91ed635d3"
|
|
394
|
+
source = "git+https://github.com/oxidize-rb/rb-sys.git?rev=b42b5fba0424fcc6778fed9a01e05215eaa53f85#b42b5fba0424fcc6778fed9a01e05215eaa53f85"
|
|
407
395
|
dependencies = [
|
|
408
396
|
"bindgen",
|
|
409
397
|
"lazy_static",
|
|
@@ -451,9 +439,9 @@ checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
|
|
|
451
439
|
|
|
452
440
|
[[package]]
|
|
453
441
|
name = "rustc-hash"
|
|
454
|
-
version = "1.1
|
|
442
|
+
version = "2.1.1"
|
|
455
443
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
456
|
-
checksum = "
|
|
444
|
+
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
|
|
457
445
|
|
|
458
446
|
[[package]]
|
|
459
447
|
name = "rustversion"
|
|
@@ -750,18 +738,18 @@ dependencies = [
|
|
|
750
738
|
|
|
751
739
|
[[package]]
|
|
752
740
|
name = "zerocopy"
|
|
753
|
-
version = "0.8.
|
|
741
|
+
version = "0.8.42"
|
|
754
742
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
755
|
-
checksum = "
|
|
743
|
+
checksum = "f2578b716f8a7a858b7f02d5bd870c14bf4ddbbcf3a4c05414ba6503640505e3"
|
|
756
744
|
dependencies = [
|
|
757
745
|
"zerocopy-derive",
|
|
758
746
|
]
|
|
759
747
|
|
|
760
748
|
[[package]]
|
|
761
749
|
name = "zerocopy-derive"
|
|
762
|
-
version = "0.8.
|
|
750
|
+
version = "0.8.42"
|
|
763
751
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
764
|
-
checksum = "
|
|
752
|
+
checksum = "7e6cc098ea4d3bd6246687de65af3f920c430e236bee1e3bf2e441463f08a02f"
|
|
765
753
|
dependencies = [
|
|
766
754
|
"proc-macro2",
|
|
767
755
|
"quote",
|
data/Cargo.toml
CHANGED
|
@@ -4,6 +4,12 @@ members = ["ext/parsanol_native"]
|
|
|
4
4
|
|
|
5
5
|
[profile.release]
|
|
6
6
|
opt-level = 3
|
|
7
|
-
lto = "
|
|
7
|
+
lto = "off"
|
|
8
8
|
codegen-units = 1
|
|
9
|
-
debug = true
|
|
9
|
+
debug = true
|
|
10
|
+
|
|
11
|
+
# Patches for Ruby 4.0 support (not yet on crates.io)
|
|
12
|
+
[patch.crates-io]
|
|
13
|
+
magnus = { git = "https://github.com/matsadler/magnus", rev = "4e46772" }
|
|
14
|
+
magnus-macros = { git = "https://github.com/matsadler/magnus", rev = "4e46772" }
|
|
15
|
+
rb-sys = { git = "https://github.com/oxidize-rb/rb-sys.git", rev = "b42b5fba0424fcc6778fed9a01e05215eaa53f85" }
|
data/HISTORY.txt
CHANGED
|
@@ -1,3 +1,33 @@
|
|
|
1
|
+
== Parsanol 1.3.0 (unreleased)
|
|
2
|
+
|
|
3
|
+
Breaking changes:
|
|
4
|
+
|
|
5
|
+
* Simplified API: Single `parse()` method with lazy line/column
|
|
6
|
+
* Removed deprecated methods: `parse_parslet`, `parse_parslet_with_positions`,
|
|
7
|
+
`parse_with_transform`, `parse_to_objects`, `parse_raw`
|
|
8
|
+
|
|
9
|
+
New features:
|
|
10
|
+
|
|
11
|
+
* Lazy line/column computation in `Slice#line_and_column` - computed only when accessed
|
|
12
|
+
* `BatchDecoder` module for efficient batch AST processing
|
|
13
|
+
* Grammar accepts Ruby atoms directly - no JSON serialization step needed
|
|
14
|
+
|
|
15
|
+
Bug fixes:
|
|
16
|
+
|
|
17
|
+
* Fixed grammar cache cycle detection to prevent stack overflow on recursive grammars
|
|
18
|
+
* Fixed wrapper vs repetition pattern detection in `AstTransformer`:
|
|
19
|
+
- Same inner keys → Repetition pattern (keep as array)
|
|
20
|
+
- Different inner keys → Wrapper pattern (merge inner hashes)
|
|
21
|
+
* Correct entity extraction for grammars with multiple declarations
|
|
22
|
+
|
|
23
|
+
== Parsanol 1.2.2 (2026-03-07)
|
|
24
|
+
|
|
25
|
+
Syncs with parsanol-rs 0.3.0:
|
|
26
|
+
|
|
27
|
+
* Full FFI support for capture, scope, and dynamic atoms
|
|
28
|
+
* Native extension performance for all new features
|
|
29
|
+
* BuilderCallbacks module for streaming parsing
|
|
30
|
+
|
|
1
31
|
== Parsanol 1.2.1 (2026-03-07)
|
|
2
32
|
|
|
3
33
|
Bug fix:
|
|
@@ -34,12 +64,12 @@ Runtime-determined parsing via FFI callbacks:
|
|
|
34
64
|
|
|
35
65
|
=== Native Extension Updates
|
|
36
66
|
|
|
37
|
-
* Updated to parsanol-rs 0.
|
|
67
|
+
* Updated to parsanol-rs 0.3.0
|
|
38
68
|
* New backend abstraction (Packrat, Bytecode, Auto)
|
|
39
69
|
* Streaming parser with capture extraction
|
|
40
70
|
* Performance improvements
|
|
41
71
|
|
|
42
|
-
== Parsanol 1.1.0 (
|
|
72
|
+
== Parsanol 1.1.0 (2026-03-05)
|
|
43
73
|
|
|
44
74
|
Position information is now returned by default:
|
|
45
75
|
|
|
@@ -54,7 +84,7 @@ Performance improvements:
|
|
|
54
84
|
* ZeroCopy API for direct FFI object construction
|
|
55
85
|
* Parallel batch parsing with `Parsanol::Parallel`
|
|
56
86
|
|
|
57
|
-
== Parsanol 1.0.0 (
|
|
87
|
+
== Parsanol 1.0.0 (2026-03-03)
|
|
58
88
|
|
|
59
89
|
Initial release of Parsanol, a high-performance PEG parser library for Ruby.
|
|
60
90
|
|
data/README.adoc
CHANGED
|
@@ -21,7 +21,7 @@ While maintaining full API compatibility with Parslet, Parsanol features a compl
|
|
|
21
21
|
|
|
22
22
|
* <<basic-parsing,PEG-based Parser Construction>> - Declarative grammar definition
|
|
23
23
|
* <<error-reporting,Detailed Error Reporting>> - Precise failure location and context
|
|
24
|
-
* <<native-extension,Rust Native Extension>> - Up to
|
|
24
|
+
* <<native-extension,Rust Native Extension>> - **Up to 1300x faster parsing**
|
|
25
25
|
* <<slice-support,Slice Support>> - Source position preservation for linters and IDEs
|
|
26
26
|
* <<transformation,Tree Transformation>> - Pattern-based AST construction
|
|
27
27
|
* <<streaming-builder,Streaming Builder API>> - Single-pass parsing with callbacks
|
|
@@ -29,6 +29,7 @@ While maintaining full API compatibility with Parslet, Parsanol features a compl
|
|
|
29
29
|
* <<infix-expressions,Infix Expression Parsing>> - Built-in operator precedence support
|
|
30
30
|
* <<security-features,Security Features>> - Input size and recursion limits
|
|
31
31
|
* <<debug-tools,Debug Tools>> - Tracing and grammar visualization
|
|
32
|
+
* <<benchmarking,Benchmarking>> - Built-in performance testing tools
|
|
32
33
|
|
|
33
34
|
== Installation
|
|
34
35
|
|
|
@@ -53,6 +54,23 @@ Or install it yourself as:
|
|
|
53
54
|
gem install parsanol
|
|
54
55
|
----
|
|
55
56
|
|
|
57
|
+
== Examples
|
|
58
|
+
|
|
59
|
+
The repository includes several example files demonstrating different use cases:
|
|
60
|
+
|
|
61
|
+
* link:examples/benchmark_examples.rb[] - Basic performance benchmarks
|
|
62
|
+
* link:examples/benchmark_full.rb[] - Comprehensive benchmark suite
|
|
63
|
+
* link:examples/parsing_modes.rb[] - Demonstrates all parsing modes
|
|
64
|
+
* link:examples/parslet_migration.rb[] - Migration guide from Parslet
|
|
65
|
+
|
|
66
|
+
[source,ruby]
|
|
67
|
+
----
|
|
68
|
+
# Run examples
|
|
69
|
+
bundle exec ruby examples/benchmark_examples.rb
|
|
70
|
+
bundle exec ruby examples/parsing_modes.rb
|
|
71
|
+
bundle exec ruby examples/parslet_migration.rb
|
|
72
|
+
----
|
|
73
|
+
|
|
56
74
|
== Usage
|
|
57
75
|
|
|
58
76
|
[[basic-parsing]]
|
|
@@ -103,6 +121,23 @@ ast = MyTransform.new.apply(parse_tree)
|
|
|
103
121
|
|
|
104
122
|
[[native-extension]]
|
|
105
123
|
=== Native Extension
|
|
124
|
+
|
|
125
|
+
The Rust native extension provides significant performance improvements over pure Ruby parsing:
|
|
126
|
+
|
|
127
|
+
[cols="2,1,1,1"]
|
|
128
|
+
|===
|
|
129
|
+
| Pattern Type | Ruby (i/s) | Native (i/s) | Speedup
|
|
130
|
+
|
|
131
|
+
| Simple string match | ~575 | ~775,000 | **1,340x**
|
|
132
|
+
| Sequence (3 parts) | ~580 | ~530,000 | **910x**
|
|
133
|
+
| Named capture | ~575 | ~510,000 | **880x**
|
|
134
|
+
| Repetition (10x digits) | ~560 | ~740,000 | **1,310x**
|
|
135
|
+
| Alternative (3 options) | ~575 | ~720,000 | **1,250x**
|
|
136
|
+
| Calculator expression | ~570 | ~180,000 | **315x**
|
|
137
|
+
| Repetition with name | ~575 | ~125,000 | **220x**
|
|
138
|
+
| Repetition (20x) | ~560 | ~720,000 | **1,280x**
|
|
139
|
+
|===
|
|
140
|
+
|
|
106
141
|
For maximum performance, compile the Rust native extension:
|
|
107
142
|
|
|
108
143
|
[source,shell]
|
|
@@ -114,6 +149,13 @@ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
|
|
114
149
|
bundle exec rake compile
|
|
115
150
|
----
|
|
116
151
|
|
|
152
|
+
Run your own benchmarks with:
|
|
153
|
+
|
|
154
|
+
[source,ruby]
|
|
155
|
+
----
|
|
156
|
+
bundle exec ruby examples/benchmark_examples.rb
|
|
157
|
+
----
|
|
158
|
+
|
|
117
159
|
[[slice-support]]
|
|
118
160
|
=== Slice Support
|
|
119
161
|
|
|
@@ -247,9 +289,9 @@ parser.parse('123') # Works exactly the same
|
|
|
247
289
|
| `sequence(:x)` | ✅ | Match array of values
|
|
248
290
|
| `subtree(:x)` | ✅ | Match any subtree
|
|
249
291
|
| `Parslet::Slice` | ✅ | Parsanol::Slice compatible
|
|
250
|
-
| `.capture(:name)` | ✅ | Named capture extraction (NEW in 1.
|
|
251
|
-
| `scope { }` | ✅ | Isolated capture context (NEW in 1.
|
|
252
|
-
| `dynamic { \|ctx\| }` | ✅ | Runtime-determined parsing (NEW in 1.
|
|
292
|
+
| `.capture(:name)` | ✅ | Named capture extraction (NEW in 1.2.0)
|
|
293
|
+
| `scope { }` | ✅ | Isolated capture context (NEW in 1.2.0)
|
|
294
|
+
| `dynamic { \|ctx\| }` | ✅ | Runtime-determined parsing (NEW in 1.2.0)
|
|
253
295
|
|===
|
|
254
296
|
|
|
255
297
|
NOTE: The new capture, scope, and dynamic atoms provide powerful extraction and context-sensitive parsing capabilities. See the <<captures,Captures>> section for details.
|
|
@@ -475,7 +517,7 @@ For more details on backend selection and grammar analysis, see the https://pars
|
|
|
475
517
|
[[captures]]
|
|
476
518
|
== Captures, Scopes, and Dynamic Atoms
|
|
477
519
|
|
|
478
|
-
Parsanol 1.
|
|
520
|
+
Parsanol 1.2.0 introduces powerful new features for extracting and managing parsed data.
|
|
479
521
|
|
|
480
522
|
[[capture-atoms]]
|
|
481
523
|
=== Capture Atoms
|
|
@@ -789,12 +831,64 @@ ruby -I lib -e "require 'parsanol'; puts Parsanol::Native.available?"
|
|
|
789
831
|
|
|
790
832
|
[source,shell]
|
|
791
833
|
----
|
|
792
|
-
# Quick benchmarks
|
|
793
|
-
bundle exec
|
|
834
|
+
# Quick benchmarks (examples provided in the repository)
|
|
835
|
+
bundle exec ruby examples/benchmark_examples.rb
|
|
836
|
+
|
|
837
|
+
# Full benchmark suite
|
|
838
|
+
bundle exec ruby examples/benchmark_full.rb
|
|
839
|
+
|
|
840
|
+
# Compare parsing modes
|
|
841
|
+
bundle exec ruby examples/parsing_modes.rb
|
|
842
|
+
|
|
843
|
+
# Parslet migration examples
|
|
844
|
+
bundle exec ruby examples/parslet_migration.rb
|
|
845
|
+
----
|
|
846
|
+
|
|
847
|
+
[[benchmarking]]
|
|
848
|
+
== Benchmarking Your Own Code
|
|
794
849
|
|
|
795
|
-
|
|
796
|
-
|
|
850
|
+
Parsanol includes built-in benchmarking tools to measure performance:
|
|
851
|
+
|
|
852
|
+
[source,ruby]
|
|
797
853
|
----
|
|
854
|
+
require 'parsanol'
|
|
855
|
+
require 'benchmark/ips'
|
|
856
|
+
|
|
857
|
+
# Your grammar
|
|
858
|
+
grammar = Parsanol.str("hello").as(:greeting)
|
|
859
|
+
json = Parsanol::Native.serialize_grammar(grammar)
|
|
860
|
+
|
|
861
|
+
# Benchmark
|
|
862
|
+
Benchmark.ips do |x|
|
|
863
|
+
x.config(warmup: 5, time: 3)
|
|
864
|
+
|
|
865
|
+
x.report("Ruby mode") { grammar.parse("hello", mode: :ruby) }
|
|
866
|
+
x.report("Native mode") { Parsanol::Native.parse(json, "hello") }
|
|
867
|
+
|
|
868
|
+
x.compare!
|
|
869
|
+
end
|
|
870
|
+
----
|
|
871
|
+
|
|
872
|
+
=== Performance Factors
|
|
873
|
+
|
|
874
|
+
The actual speedup depends on several factors:
|
|
875
|
+
|
|
876
|
+
1. **Grammar complexity** - More complex grammars have more transformation overhead
|
|
877
|
+
2. **Named captures** - More named captures mean more hash construction
|
|
878
|
+
3. **Repetition patterns** - Named repetitions have more overhead than unnamed
|
|
879
|
+
4. **Input size** - Larger inputs benefit more from native parsing
|
|
880
|
+
|
|
881
|
+
[cols="1,2,2"]
|
|
882
|
+
|===
|
|
883
|
+
| Pattern | Speedup | Reason for Difference
|
|
884
|
+
|
|
885
|
+
| Simple strings | ~1,300x | Minimal transformation
|
|
886
|
+
| Sequences | ~900x | String joining overhead
|
|
887
|
+
| Alternatives | ~1,250x | Fast path in Rust
|
|
888
|
+
| Repetitions (unnamed) | ~1,300x | Minimal transformation
|
|
889
|
+
| Repetitions (named) | ~220x | Array of hashes construction
|
|
890
|
+
| Complex expressions | ~315x | More grammar elements
|
|
891
|
+
|===
|
|
798
892
|
|
|
799
893
|
== License
|
|
800
894
|
|
|
@@ -20,16 +20,19 @@ rust-version = "1.75"
|
|
|
20
20
|
crate-type = ["cdylib"]
|
|
21
21
|
|
|
22
22
|
[dependencies]
|
|
23
|
-
# rb-sys for Ruby C API -
|
|
23
|
+
# rb-sys for Ruby C API - WITHOUT link-ruby for dynamic extension
|
|
24
24
|
# On Windows ARM64, we need to build from source since pre-built binaries aren't available
|
|
25
|
-
rb-sys = { version = "0.9.124", features = ["
|
|
25
|
+
rb-sys = { version = "0.9.124", features = ["global-allocator"] }
|
|
26
26
|
|
|
27
|
-
# magnus for Ruby bindings (
|
|
28
|
-
magnus = "0.
|
|
27
|
+
# magnus for Ruby bindings (from crates.io, patched locally for Ruby 4.0 support)
|
|
28
|
+
magnus = { version = "0.9" }
|
|
29
29
|
|
|
30
|
-
# parsanol parser library
|
|
31
|
-
parsanol = {
|
|
30
|
+
# parsanol parser library (from git for latest features)
|
|
31
|
+
parsanol = { git = "https://github.com/parsanol/parsanol-rs", rev = "4667017", features = ["ruby"] }
|
|
32
32
|
|
|
33
33
|
# Logging
|
|
34
34
|
log = "0.4"
|
|
35
35
|
|
|
36
|
+
[profile.release]
|
|
37
|
+
lto = "off"
|
|
38
|
+
|