parseman 0.1.0 → 0.1.1

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.
package/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  <p align="center">
2
- <img src="assets/parseman.png" alt="Parmésan — 100% Pure Parsing" width="220" />
2
+ <img src="https://raw.githubusercontent.com/matthew-dean/parsecraft/main/assets/parseman.png" alt="Parmésan — 100% Pure Parsing" width="220" />
3
3
  </p>
4
4
 
5
5
  # Parmésan (PAR-zə-mahn)
@@ -8,6 +8,18 @@ Write parsers with combinators, then let the bundler plugin compile them to opti
8
8
 
9
9
  The same code runs without the plugin: the interpreter produces identical results. Use the macro build for production; skip it in tests and anywhere a bundler isn't in the picture.
10
10
 
11
+ ## Benchmarks
12
+
13
+ Measured on Apple M2 Pro. Bars show µs per parse — shorter is faster.
14
+
15
+ ![JSON parsing benchmarks](https://raw.githubusercontent.com/matthew-dean/parsecraft/main/assets/bench-json.svg)
16
+
17
+ ![CSV parsing benchmarks](https://raw.githubusercontent.com/matthew-dean/parsecraft/main/assets/bench-csv.svg)
18
+
19
+ Parmésan compiled edges out Peggy on small and medium JSON. At 12 kB Peggy pulls ahead by ~10% — it's been doing this a while. On CSV, where the grammar is non-recursive and fully inlines, Parmésan compiled wins going away.
20
+
21
+ ---
22
+
11
23
  ## Install
12
24
 
13
25
  ```bash
@@ -483,18 +495,6 @@ type CSTRawChild = CSTNode | CSTLeaf | CSTTrivia | CSTError
483
495
 
484
496
  ---
485
497
 
486
- ## Benchmarks
487
-
488
- Measured on Apple M2 Pro. Bars show µs per parse — shorter is faster.
489
-
490
- ![JSON parsing benchmarks](assets/bench-json.svg)
491
-
492
- ![CSV parsing benchmarks](assets/bench-csv.svg)
493
-
494
- Parmésan compiled edges out Peggy on small and medium JSON. At 12 kB Peggy pulls ahead by ~10% — it's been doing this a while. On CSV, where the grammar is non-recursive and fully inlines, Parmésan compiled wins going away.
495
-
496
- ---
497
-
498
498
  ## Developing
499
499
 
500
500
  ```bash
@@ -10,7 +10,7 @@ import type { NodeLike } from './types.ts';
10
10
  * doc.errors // ParseFail[], empty on success
11
11
  * doc.input // the source string that produced this tree
12
12
  *
13
- * const doc2 = doc.edit(newSrc, changeStart, changeEnd)
13
+ * const doc2 = doc.edit(changeStart, changeEnd, newText) // "select from→to, type newText"
14
14
  */
15
15
  export interface ParseDoc<N extends NodeLike = NodeLike> {
16
16
  readonly tree: N | null;
@@ -19,16 +19,20 @@ export interface ParseDoc<N extends NodeLike = NodeLike> {
19
19
  /**
20
20
  * Incrementally re-parse after a text change.
21
21
  *
22
- * @param changeStart Byte offset where the change begins (same in old and new text).
23
- * @param oldChangeEnd Byte offset where the replaced region ends in the OLD text (exclusive).
24
- * @param newText The replacement text (may be empty for a pure deletion).
22
+ * Think of it as "select from to, replace with replacement": both `from`
23
+ * and `to` are byte offsets in the OLD input. `replacement` is what fills
24
+ * that range in the new text.
25
+ *
26
+ * doc.edit(3, 7, 'hi') → old: "foo [XXXX] bar" new: "foo hi bar"
27
+ * ↑ ↑
28
+ * from to (both in old text)
25
29
  *
26
30
  * Maps directly to editor change events:
27
- * VSCode: doc.edit(change.rangeOffset, change.rangeOffset + change.rangeLength, change.text)
28
- * CodeMirror: doc.edit(change.from, change.to, change.insert)
29
- * LSP: doc.edit(startByte, endByte, change.text) // after line/col → byte conversion
31
+ * VSCode / Monaco: doc.edit(change.rangeOffset, change.rangeOffset + change.rangeLength, change.text)
32
+ * CodeMirror 6: doc.edit(change.from, change.to, change.insert)
33
+ * LSP: doc.edit(startByte, endByte, change.text) // after line/col → byte offset
30
34
  */
31
- edit(changeStart: number, oldChangeEnd: number, newText: string): ParseDoc<N>;
35
+ edit(from: number, to: number, replacement: string): ParseDoc<N>;
32
36
  }
33
37
  export declare function makeParseDoc<N extends NodeLike>(parser: Parser<N>, ruleName: string, input: string): ParseDoc<N>;
34
38
  //# sourceMappingURL=incremental.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"incremental.d.ts","sourceRoot":"","sources":["../../src/cst/incremental.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAgB,SAAS,EAAE,MAAM,aAAa,CAAA;AAC1D,OAAO,KAAK,EAAE,MAAM,EAAY,MAAM,cAAc,CAAA;AACpD,OAAO,KAAK,EAAqB,QAAQ,EAAE,MAAM,YAAY,CAAA;AAM7D;;;;;;;;;;GAUG;AACH,MAAM,WAAW,QAAQ,CAAC,CAAC,SAAS,QAAQ,GAAG,QAAQ;IACrD,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,CAAA;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB;;;;;;;;;;;OAWG;IACH,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;CAC9E;AA+GD,wBAAgB,YAAY,CAAC,CAAC,SAAS,QAAQ,EAC7C,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EACjB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,GACZ,QAAQ,CAAC,CAAC,CAAC,CAOb"}
1
+ {"version":3,"file":"incremental.d.ts","sourceRoot":"","sources":["../../src/cst/incremental.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAgB,SAAS,EAAE,MAAM,aAAa,CAAA;AAC1D,OAAO,KAAK,EAAE,MAAM,EAAY,MAAM,cAAc,CAAA;AACpD,OAAO,KAAK,EAAqB,QAAQ,EAAE,MAAM,YAAY,CAAA;AAM7D;;;;;;;;;;GAUG;AACH,MAAM,WAAW,QAAQ,CAAC,CAAC,SAAS,QAAQ,GAAG,QAAQ;IACrD,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,CAAA;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB;;;;;;;;;;;;;;;OAeG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;CACjE;AA+GD,wBAAgB,YAAY,CAAC,CAAC,SAAS,QAAQ,EAC7C,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EACjB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,GACZ,QAAQ,CAAC,CAAC,CAAC,CAOb"}
package/dist/index.cjs CHANGED
@@ -1646,11 +1646,11 @@ var ParseDocImpl = class _ParseDocImpl {
1646
1646
  this.errors = errors;
1647
1647
  this.input = input;
1648
1648
  }
1649
- edit(changeStart, oldChangeEnd, newText) {
1650
- const newInput = this.input.slice(0, changeStart) + newText + this.input.slice(oldChangeEnd);
1649
+ edit(from, to, replacement) {
1650
+ const newInput = this.input.slice(0, from) + replacement + this.input.slice(to);
1651
1651
  if (!this.tree) return makeParseDoc(this._parser, this._ruleName, newInput);
1652
- const delta = newText.length - (oldChangeEnd - changeStart);
1653
- const found = findContaining(this.tree, changeStart);
1652
+ const delta = replacement.length - (to - from);
1653
+ const found = findContaining(this.tree, from);
1654
1654
  if (!found) return makeParseDoc(this._parser, this._ruleName, newInput);
1655
1655
  const ancestors = ancestorsAt(this.tree, found.path);
1656
1656
  const candidates = [found];