asciichem 0.24.0 → 0.25.0
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/CHANGELOG.md +11 -1
- data/benchmarks/README.md +46 -0
- data/benchmarks/engines.rb +31 -0
- data/lib/asciichem/cli.rb +27 -0
- data/lib/asciichem/version.rb +1 -1
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7748aa7fb152b3dad47ff42c2debe7335af35a2a36c21d2248ff4f5a5231c575
|
|
4
|
+
data.tar.gz: 4352b4fe40fc6998f9860d155e791d7cf2c4f3cd48f0184696346ba934adaa57
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6a22a8e911ec6a04498285f949f79c1ea5e7e6870d464e3229c3e783e744d151f0506b5200dba58e4e06f23177983dd80b24d172c6d5528e960907da821db64a
|
|
7
|
+
data.tar.gz: 9d57bab57705518c6f2b40d28f40b0b62c20237d26b9daf20ae4d65bd9b60ad8497ea304c60c163878c412cc6cf61a3c99a6a9179b027bef527e524758b87085
|
data/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,15 @@
|
|
|
3
3
|
All notable changes to AsciiChem are documented here.
|
|
4
4
|
This project follows [Semantic Versioning](https://semver.org/).
|
|
5
5
|
|
|
6
|
+
## [0.25.0] - 2026-09-14
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
- CLI `cite` — resolve a substance and emit the dataset-type Relaton
|
|
10
|
+
bibitem XML (the citation track's user-facing entry point).
|
|
11
|
+
- Cross-engine parsing benchmarks (`benchmarks/engines.rb`,
|
|
12
|
+
README with Ruby/TS/Python numbers) and the parsanol investigation
|
|
13
|
+
verdict (compat shim ~6x slower than parslet; not adopted).
|
|
14
|
+
|
|
6
15
|
## [0.24.0] - 2026-09-13
|
|
7
16
|
|
|
8
17
|
### Added
|
|
@@ -426,7 +435,8 @@ This project follows [Semantic Versioning](https://semver.org/).
|
|
|
426
435
|
`version`.
|
|
427
436
|
- Comprehensive RSpec suite with round-trip conformance.
|
|
428
437
|
|
|
429
|
-
[Unreleased]: https://github.com/asciichem/asciichem-ruby/compare/v0.
|
|
438
|
+
[Unreleased]: https://github.com/asciichem/asciichem-ruby/compare/v0.25.0...HEAD
|
|
439
|
+
[0.25.0]: https://github.com/asciichem/asciichem-ruby/compare/v0.24.0...v0.25.0
|
|
430
440
|
[0.24.0]: https://github.com/asciichem/asciichem-ruby/compare/v0.23.0...v0.24.0
|
|
431
441
|
[0.23.0]: https://github.com/asciichem/asciichem-ruby/compare/v0.22.0...v0.23.0
|
|
432
442
|
[0.22.0]: https://github.com/asciichem/asciichem-ruby/compare/v0.21.0...v0.22.0
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Parsing benchmarks
|
|
2
|
+
|
|
3
|
+
Shared workload (identical inputs in every implementation) so numbers
|
|
4
|
+
are comparable across engines:
|
|
5
|
+
|
|
6
|
+
```ruby
|
|
7
|
+
WORKLOAD = ["H_2O", "Ca^2+", "SO_4^2-", "(R)-CH_3CH(OH)COOH",
|
|
8
|
+
"2H_2 + O_2 -> 2H_2O", "N_2 + 3H_2 <=>[Fe][400C] 2NH_3",
|
|
9
|
+
"C1-C-C-C-C-C1", "CH_3-CH_2-OH",
|
|
10
|
+
"^14C @name(\"carbon-14\") @cas(\"14104-86-4\")",
|
|
11
|
+
"A ->[heat] B ->[cool] C"]
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
| Engine | Batch (10 inputs) | Per input | Notes |
|
|
15
|
+
|---|---|---|---|
|
|
16
|
+
| Ruby (parslet), 3.4.8 arm64 | 29.1 ms | ~2.9 ms | `bundle exec ruby benchmarks/engines.rb` |
|
|
17
|
+
| Ruby + parse+text | 35.3 ms | ~3.5 ms | round-trip adds the formatter |
|
|
18
|
+
| TypeScript (peggy), Node 24 | 0.19 ms | ~19 µs | `npm run bench` (asciichem-ts) |
|
|
19
|
+
| Python (RD), 3.10 | 3.94 ms | ~394 µs | `python benchmarks/engines.py` (asciichem-py) |
|
|
20
|
+
|
|
21
|
+
The peggy engine is ~15x faster than parslet and ~20x faster than the
|
|
22
|
+
Python recursive-descent parser on this workload — the grammar-port
|
|
23
|
+
TS implementation did not trade away speed. Same machine (arm64),
|
|
24
|
+
single-run medians; treat as order-of-magnitude comparison.
|
|
25
|
+
|
|
26
|
+
## Parsanol investigation (2026-09-14)
|
|
27
|
+
|
|
28
|
+
[Parsanol](https://github.com/parsanol/parsanol-ruby) (Ribose's
|
|
29
|
+
parslet-alternative PEG library with a Rust native core) was evaluated
|
|
30
|
+
as a drop-in speedup for the reference grammar:
|
|
31
|
+
|
|
32
|
+
1. **Parslet-compat shim** (zero code change — re-parent the grammar
|
|
33
|
+
onto `Parsanol::Parslet::Parser`): the identical grammar runs
|
|
34
|
+
unchanged (10/10 workload inputs), but measures **~6x slower**
|
|
35
|
+
than parslet (12.2 s vs 2.05 s per 300x10 parses, Ruby 3.4.8,
|
|
36
|
+
arm64). The shim is a compatibility layer, not the fast path.
|
|
37
|
+
2. **Native Parsanol DSL** (subset micro-benchmark): constructs run,
|
|
38
|
+
but boundary semantics differ from parslet on greedy-regex +
|
|
39
|
+
`maybe`/`repeat` interaction (`SO_4^2-` parses under parslet,
|
|
40
|
+
fails under Parsanol native). A full port would need per-rule
|
|
41
|
+
revalidation against the whole corpus with no measured win to
|
|
42
|
+
justify it yet.
|
|
43
|
+
|
|
44
|
+
**Verdict: not adopted.** Revisit when Parsanol's native backend can
|
|
45
|
+
be engaged for full grammars and shows measured wins on this
|
|
46
|
+
workload; the shim path is a documented no.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Cross-engine parsing benchmark (shared inputs across Ruby/TS/Python
|
|
4
|
+
# so numbers are comparable). Measures full parse (+ Text round-trip
|
|
5
|
+
# where cheap) over the canonical workload, reporting ops/sec and
|
|
6
|
+
# µs/op. Run: bundle exec ruby benchmarks/engines.rb
|
|
7
|
+
require "benchmark/ips"
|
|
8
|
+
require "asciichem"
|
|
9
|
+
|
|
10
|
+
WORKLOAD = [
|
|
11
|
+
"H_2O",
|
|
12
|
+
"Ca^2+",
|
|
13
|
+
"SO_4^2-",
|
|
14
|
+
"(R)-CH_3CH(OH)COOH",
|
|
15
|
+
"2H_2 + O_2 -> 2H_2O",
|
|
16
|
+
"N_2 + 3H_2 <=>[Fe][400C] 2NH_3",
|
|
17
|
+
"C1-C-C-C-C-C1",
|
|
18
|
+
"CH_3-CH_2-OH",
|
|
19
|
+
"^14C @name(\"carbon-14\") @cas(\"14104-86-4\")",
|
|
20
|
+
"A ->[heat] B ->[cool] C",
|
|
21
|
+
].freeze
|
|
22
|
+
|
|
23
|
+
Benchmark.ips do |x|
|
|
24
|
+
x.report("parse x10 (parslet)") do
|
|
25
|
+
WORKLOAD.each { |s| AsciiChem.parse(s) }
|
|
26
|
+
end
|
|
27
|
+
x.report("parse+text x10") do
|
|
28
|
+
WORKLOAD.each { |s| AsciiChem.parse(s).to_text }
|
|
29
|
+
end
|
|
30
|
+
x.compare!
|
|
31
|
+
end
|
data/lib/asciichem/cli.rb
CHANGED
|
@@ -119,6 +119,33 @@ module AsciiChem
|
|
|
119
119
|
exit 3
|
|
120
120
|
end
|
|
121
121
|
|
|
122
|
+
desc "cite --cas X | --name X | ...", "Resolve a substance and emit a dataset-type Relaton bibitem (XML)"
|
|
123
|
+
method_option :cas, type: :string, desc: "CAS registry number"
|
|
124
|
+
method_option :name, type: :string, desc: "Substance name"
|
|
125
|
+
method_option :cid, type: :string, desc: "PubChem CID"
|
|
126
|
+
method_option :inchikey, type: :string, desc: "InChIKey"
|
|
127
|
+
method_option :smiles, type: :string, desc: "SMILES"
|
|
128
|
+
method_option :source, type: :string, default: "pubchem", desc: "Resolver source"
|
|
129
|
+
method_option :refresh, type: :boolean, default: false, desc: "Bypass the cache"
|
|
130
|
+
def cite
|
|
131
|
+
convention, value = %i[cas name cid inchikey smiles]
|
|
132
|
+
.filter_map { |k| [k, options[k.to_s]] if options[k.to_s] }
|
|
133
|
+
.first
|
|
134
|
+
raise AsciiChem::Error, "give one of --cas/--name/--cid/--inchikey/--smiles" unless value
|
|
135
|
+
|
|
136
|
+
convention = { cas: "cas", name: "name", cid: "pubchem-cid",
|
|
137
|
+
inchikey: "inchikey", smiles: "smiles" }.fetch(convention)
|
|
138
|
+
substance = AsciiChem::Resolver[options[:source]].new.resolve(
|
|
139
|
+
value: value, convention: convention, refresh: options[:refresh]
|
|
140
|
+
)
|
|
141
|
+
raise AsciiChem::Error, "#{options[:source]} does not know #{value.inspect}" unless substance
|
|
142
|
+
|
|
143
|
+
puts AsciiChem::Citation.to_xml(substance)
|
|
144
|
+
rescue AsciiChem::Error => e
|
|
145
|
+
warn "Cite error: #{e.message}"
|
|
146
|
+
exit 4
|
|
147
|
+
end
|
|
148
|
+
|
|
122
149
|
desc "validate -i INPUT", "Offline identifier validation"
|
|
123
150
|
method_option :input, aliases: "-i", type: :string, required: true
|
|
124
151
|
def validate
|
data/lib/asciichem/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: asciichem
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.25.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
@@ -172,8 +172,10 @@ files:
|
|
|
172
172
|
- RELEASING.md
|
|
173
173
|
- Rakefile
|
|
174
174
|
- asciichem.gemspec
|
|
175
|
+
- benchmarks/README.md
|
|
175
176
|
- benchmarks/RESULTS.md
|
|
176
177
|
- benchmarks/benchmark.rb
|
|
178
|
+
- benchmarks/engines.rb
|
|
177
179
|
- exe/asciichem
|
|
178
180
|
- lib/asciichem.rb
|
|
179
181
|
- lib/asciichem/citation.rb
|