roll-parser 3.0.0-alpha.0 → 3.0.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.
Files changed (163) hide show
  1. package/CHANGELOG.md +189 -0
  2. package/MIGRATION.md +147 -0
  3. package/README.md +985 -43
  4. package/dist/cli/args.d.ts +1 -0
  5. package/dist/cli/args.d.ts.map +1 -1
  6. package/dist/cli/args.js +81 -0
  7. package/dist/cli/args.js.map +1 -0
  8. package/dist/cli/format.d.ts +16 -4
  9. package/dist/cli/format.d.ts.map +1 -1
  10. package/dist/cli/format.js +17 -0
  11. package/dist/cli/format.js.map +1 -0
  12. package/dist/cli/index.d.ts +3 -0
  13. package/dist/cli/index.d.ts.map +1 -1
  14. package/dist/cli/index.js +14 -0
  15. package/dist/cli/index.js.map +1 -0
  16. package/dist/cli/main.d.ts +36 -0
  17. package/dist/cli/main.d.ts.map +1 -0
  18. package/dist/cli/main.js +83 -0
  19. package/dist/cli/main.js.map +1 -0
  20. package/dist/errors.d.ts +332 -14
  21. package/dist/errors.d.ts.map +1 -1
  22. package/dist/errors.js +141 -0
  23. package/dist/errors.js.map +1 -0
  24. package/dist/evaluator/die.d.ts +26 -0
  25. package/dist/evaluator/die.d.ts.map +1 -0
  26. package/dist/evaluator/die.js +19 -0
  27. package/dist/evaluator/die.js.map +1 -0
  28. package/dist/evaluator/env.d.ts +58 -0
  29. package/dist/evaluator/env.d.ts.map +1 -0
  30. package/dist/evaluator/env.js +11 -0
  31. package/dist/evaluator/env.js.map +1 -0
  32. package/dist/evaluator/evaluator.d.ts +62 -40
  33. package/dist/evaluator/evaluator.d.ts.map +1 -1
  34. package/dist/evaluator/evaluator.js +906 -0
  35. package/dist/evaluator/evaluator.js.map +1 -0
  36. package/dist/evaluator/modifiers/compare.d.ts +1 -1
  37. package/dist/evaluator/modifiers/compare.d.ts.map +1 -1
  38. package/dist/evaluator/modifiers/compare.js +15 -0
  39. package/dist/evaluator/modifiers/compare.js.map +1 -0
  40. package/dist/evaluator/modifiers/crit-threshold.d.ts +27 -0
  41. package/dist/evaluator/modifiers/crit-threshold.d.ts.map +1 -0
  42. package/dist/evaluator/modifiers/crit-threshold.js +23 -0
  43. package/dist/evaluator/modifiers/crit-threshold.js.map +1 -0
  44. package/dist/evaluator/modifiers/die-bound.d.ts +26 -0
  45. package/dist/evaluator/modifiers/die-bound.d.ts.map +1 -0
  46. package/dist/evaluator/modifiers/die-bound.js +14 -0
  47. package/dist/evaluator/modifiers/die-bound.js.map +1 -0
  48. package/dist/evaluator/modifiers/explode.d.ts +18 -6
  49. package/dist/evaluator/modifiers/explode.d.ts.map +1 -1
  50. package/dist/evaluator/modifiers/explode.js +103 -0
  51. package/dist/evaluator/modifiers/explode.js.map +1 -0
  52. package/dist/evaluator/modifiers/flags.d.ts +37 -0
  53. package/dist/evaluator/modifiers/flags.d.ts.map +1 -0
  54. package/dist/evaluator/modifiers/flags.js +18 -0
  55. package/dist/evaluator/modifiers/flags.js.map +1 -0
  56. package/dist/evaluator/modifiers/keep-drop.d.ts +12 -28
  57. package/dist/evaluator/modifiers/keep-drop.d.ts.map +1 -1
  58. package/dist/evaluator/modifiers/keep-drop.js +82 -0
  59. package/dist/evaluator/modifiers/keep-drop.js.map +1 -0
  60. package/dist/evaluator/modifiers/reroll.d.ts +14 -6
  61. package/dist/evaluator/modifiers/reroll.d.ts.map +1 -1
  62. package/dist/evaluator/modifiers/reroll.js +62 -0
  63. package/dist/evaluator/modifiers/reroll.js.map +1 -0
  64. package/dist/evaluator/modifiers/sort.d.ts +27 -0
  65. package/dist/evaluator/modifiers/sort.d.ts.map +1 -0
  66. package/dist/evaluator/modifiers/sort.js +13 -0
  67. package/dist/evaluator/modifiers/sort.js.map +1 -0
  68. package/dist/evaluator/modifiers/success-count.d.ts +2 -6
  69. package/dist/evaluator/modifiers/success-count.d.ts.map +1 -1
  70. package/dist/evaluator/modifiers/success-count.js +24 -0
  71. package/dist/evaluator/modifiers/success-count.js.map +1 -0
  72. package/dist/index.d.ts +35 -13
  73. package/dist/index.d.ts.map +1 -1
  74. package/dist/index.js +12 -1723
  75. package/dist/index.js.map +1 -0
  76. package/dist/lexer/lexer.d.ts +68 -8
  77. package/dist/lexer/lexer.d.ts.map +1 -1
  78. package/dist/lexer/lexer.js +260 -0
  79. package/dist/lexer/lexer.js.map +1 -0
  80. package/dist/lexer/tokens.d.ts +52 -7
  81. package/dist/lexer/tokens.d.ts.map +1 -1
  82. package/dist/lexer/tokens.js +42 -0
  83. package/dist/lexer/tokens.js.map +1 -0
  84. package/dist/parser/ast.d.ts +419 -80
  85. package/dist/parser/ast.d.ts.map +1 -1
  86. package/dist/parser/ast.js +52 -0
  87. package/dist/parser/ast.js.map +1 -0
  88. package/dist/parser/guards.d.ts +106 -0
  89. package/dist/parser/guards.d.ts.map +1 -0
  90. package/dist/parser/guards.js +121 -0
  91. package/dist/parser/guards.js.map +1 -0
  92. package/dist/parser/parser.d.ts +162 -15
  93. package/dist/parser/parser.d.ts.map +1 -1
  94. package/dist/parser/parser.js +751 -0
  95. package/dist/parser/parser.js.map +1 -0
  96. package/dist/rng/mock.d.ts +74 -13
  97. package/dist/rng/mock.d.ts.map +1 -1
  98. package/dist/rng/mock.js +30 -0
  99. package/dist/rng/mock.js.map +1 -0
  100. package/dist/rng/seeded.d.ts +149 -10
  101. package/dist/rng/seeded.d.ts.map +1 -1
  102. package/dist/rng/seeded.js +138 -0
  103. package/dist/rng/seeded.js.map +1 -0
  104. package/dist/rng/types.d.ts +57 -0
  105. package/dist/rng/types.d.ts.map +1 -1
  106. package/dist/rng/types.js +2 -0
  107. package/dist/rng/types.js.map +1 -0
  108. package/dist/roll.d.ts +59 -25
  109. package/dist/roll.d.ts.map +1 -1
  110. package/dist/roll.js +8 -0
  111. package/dist/roll.js.map +1 -0
  112. package/dist/testing.d.ts +5 -4
  113. package/dist/testing.d.ts.map +1 -1
  114. package/dist/testing.js +2 -38
  115. package/dist/testing.js.map +1 -0
  116. package/dist/types.d.ts +427 -24
  117. package/dist/types.d.ts.map +1 -1
  118. package/dist/types.js +8 -0
  119. package/dist/types.js.map +1 -0
  120. package/dist/version.d.ts +2 -0
  121. package/dist/version.d.ts.map +1 -0
  122. package/dist/version.js +2 -0
  123. package/dist/version.js.map +1 -0
  124. package/package.json +93 -40
  125. package/src/cli/args.ts +66 -9
  126. package/src/cli/format.ts +30 -7
  127. package/src/cli/index.ts +27 -67
  128. package/src/cli/main.ts +129 -0
  129. package/src/errors.ts +488 -23
  130. package/src/evaluator/die.ts +50 -0
  131. package/src/evaluator/env.ts +73 -0
  132. package/src/evaluator/evaluator.ts +1296 -349
  133. package/src/evaluator/modifiers/compare.ts +1 -1
  134. package/src/evaluator/modifiers/crit-threshold.ts +56 -0
  135. package/src/evaluator/modifiers/die-bound.ts +39 -0
  136. package/src/evaluator/modifiers/explode.ts +82 -76
  137. package/src/evaluator/modifiers/flags.ts +61 -0
  138. package/src/evaluator/modifiers/keep-drop.ts +124 -126
  139. package/src/evaluator/modifiers/reroll.ts +36 -64
  140. package/src/evaluator/modifiers/sort.ts +43 -0
  141. package/src/evaluator/modifiers/success-count.ts +6 -9
  142. package/src/index.ts +73 -34
  143. package/src/lexer/lexer.ts +201 -35
  144. package/src/lexer/tokens.ts +72 -7
  145. package/src/parser/ast.ts +453 -104
  146. package/src/parser/guards.ts +248 -0
  147. package/src/parser/parser.ts +835 -135
  148. package/src/rng/mock.ts +75 -14
  149. package/src/rng/seeded.ts +323 -58
  150. package/src/rng/types.ts +57 -0
  151. package/src/roll.ts +66 -41
  152. package/src/testing.ts +5 -9
  153. package/src/types.ts +416 -24
  154. package/src/version.ts +2 -0
  155. package/dist/cli.js +0 -1775
  156. package/dist/evaluator/index.d.ts +0 -8
  157. package/dist/evaluator/index.d.ts.map +0 -1
  158. package/dist/index.mjs +0 -1724
  159. package/dist/rng/index.d.ts +0 -8
  160. package/dist/rng/index.d.ts.map +0 -1
  161. package/dist/testing.mjs +0 -39
  162. package/src/evaluator/index.ts +0 -14
  163. package/src/rng/index.ts +0 -8
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Parser-internal AST guards.
3
+ *
4
+ * These helpers answer structural questions the parser's reject rules ask
5
+ * ("does this operand resolve to a dice pool?", "is a Versus buried in
6
+ * here?"). They are implementation detail of `parser.ts` — the public
7
+ * `isXxx` type guards stay in `ast.ts`.
8
+ *
9
+ * @module parser/guards
10
+ */
11
+ import type { ASTNode } from './ast.js';
12
+ /**
13
+ * Peels nested `Grouped` wrappers, returning the first descendant that is not
14
+ * one. The narrow unwrap for reject helpers whose forbidden node cannot live
15
+ * inside `KeepDrop`/`Sort`/`CritThreshold` — those parsers already reject it
16
+ * upstream, so peeling parentheses is all that is left to see through.
17
+ */
18
+ export declare function unwrapGrouped(node: ASTNode): ASTNode;
19
+ /**
20
+ * Peels every transparent wrapper — `Grouped`, `KeepDrop`, `Sort`,
21
+ * `CritThreshold`, `DieBound` — returning the first descendant that is none of
22
+ * them.
23
+ *
24
+ * "Transparent" is relative to the question being asked. These wrappers
25
+ * preserve `containsDicePool`'s answer for whatever they wrap, so they are
26
+ * transparent for "what is the underlying operand?" when deciding whether to
27
+ * reject a `Group` target (e.g., `Group` cannot be the target of `cs`/`cf`,
28
+ * even when wrapped in `KeepDrop` like `{1d6}kh1cs>5`). They are NOT
29
+ * transparent for "is this a `SuccessCount`?" or "is this a `Versus`?" —
30
+ * those questions use `unwrapGrouped`.
31
+ */
32
+ export declare function unwrapAllTransparent(node: ASTNode): ASTNode;
33
+ /**
34
+ * Returns `true` only when `node`'s direct result is a dice pool —
35
+ * `Dice`, `FateDice`, or a chained pool modifier (`KeepDrop` / `Explode` /
36
+ * `Reroll`). Does NOT recurse through arithmetic wrappers (`BinaryOp`,
37
+ * `UnaryOp`, `FunctionCall`), so `(1d6+5)` and `floor(1d6/2)` are rejected.
38
+ *
39
+ * Used by the parser to reject postfix pool-modifier targets (kh/kl/dh/dl,
40
+ * !/!!/!p, r/ro) that wrap a non-pool expression. Operating on the inner
41
+ * dice pool would silently drop the surrounding arithmetic.
42
+ */
43
+ export declare function containsDicePool(node: ASTNode): boolean;
44
+ /**
45
+ * Deeper variant of `containsDicePool` that recurses through arithmetic and
46
+ * function wrappers. Used from the `Group` case above (ordinary parenthesized
47
+ * arithmetic `(1d6+5)kh1` must still reject, so the shallow `containsDicePool`
48
+ * handles those directly) and from the Sort parser guard (sort accepts
49
+ * `(1d6+2d8)s` per Stage 3 spec).
50
+ *
51
+ * A multi-sub-roll `Group` counts as a pool in its own right (compound dice),
52
+ * matching `containsDicePool`'s Group rule.
53
+ */
54
+ export declare function deepContainsDicePool(node: ASTNode): boolean;
55
+ /**
56
+ * Returns `true` if the pool this node resolves to is (or wraps) a `FateDice`
57
+ * pool. Walks through chained pool modifiers (`KeepDrop` / `Explode` /
58
+ * `Reroll`) but not arithmetic wrappers — callers should run
59
+ * `containsDicePool` first to reject those.
60
+ *
61
+ * Used by the parser to reject `!`, `!!`, `!p` applied to Fate pools
62
+ * (`4dF!`, `(4dF)kh2!`, etc.). Fate explosion semantics are undefined, so
63
+ * parse-time rejection is preferred over a silent evaluator no-op.
64
+ *
65
+ * Inside a `Group`, recursion uses `deepContainsFatePool` to mirror
66
+ * `containsDicePool`'s deep walk through the same case — otherwise
67
+ * `{4dF+1d6}cf` slips past the bare-Fate guard and the default fumble
68
+ * check (`result === 1`) flips `+1` faces into fumbles.
69
+ */
70
+ export declare function containsFatePool(node: ASTNode): boolean;
71
+ /**
72
+ * Deeper variant of `containsFatePool` that recurses through arithmetic and
73
+ * function wrappers. Mirrors `deepContainsDicePool`. Used from
74
+ * `containsFatePool`'s `Group` case so single-sub-roll groups containing
75
+ * arithmetic-wrapped Fate (`{4dF+1d6}cf`) still trip the bare-Fate guard.
76
+ *
77
+ * Outside a `Group`, ordinary parenthesized arithmetic (`(4dF+1d6)cf`) is
78
+ * already rejected upstream by shallow `containsDicePool`, so this helper
79
+ * intentionally stays Group-internal.
80
+ */
81
+ export declare function deepContainsFatePool(node: ASTNode): boolean;
82
+ /**
83
+ * Deep-walks a node to find any descendant `Group` with two or more
84
+ * sub-expressions. Used by `rejectGroupTarget`'s single-sub-roll
85
+ * passthrough so a multi-sub Group buried under arithmetic
86
+ * (`{{1d6,2d8}+0}cs>5`), function calls (`{abs({1d6,2d8})}cs>5`), or any
87
+ * other non-transparent wrapper still rejects with the same error code.
88
+ *
89
+ * Without this walk, the unwrap inside `rejectGroupTarget` only peels
90
+ * `Grouped`/`KeepDrop`/`Sort`/`CritThreshold` — a multi-sub Group cloaked
91
+ * in a `BinaryOp`/`UnaryOp`/`FunctionCall` reaches the evaluator, where it
92
+ * flags crits on dice belonging to dropped sub-rolls.
93
+ */
94
+ export declare function containsMultiSubGroup(node: ASTNode): boolean;
95
+ /**
96
+ * Deep-walks a node to find any descendant `Versus`. A buried Versus
97
+ * (`floor(1d20 vs 15)`, `(1d20 vs 15)+0`, `{1+(1d20 vs 15)}`) must reject with
98
+ * `NESTED_VERSUS` rather than silently drop `versusMetadata` at the consumer.
99
+ *
100
+ * Two callers, both on that hole: `rejectVersusMetaOperand` guards every meta
101
+ * operand — dice count and sides, keep/drop count, thresholds, die bounds — and
102
+ * `rejectVersusTarget` uses it for its single-sub-roll Group passthrough.
103
+ * `evalMetaOperand` runs the same walk as the hand-built-AST backstop.
104
+ */
105
+ export declare function containsVersus(node: ASTNode): boolean;
106
+ //# sourceMappingURL=guards.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guards.d.ts","sourceRoot":"","sources":["../../src/parser/guards.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAExC;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAMpD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAiB3D;AA8DD;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAyBvD;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAE3D;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAkBvD;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAE3D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAE5D;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAErD"}
@@ -0,0 +1,121 @@
1
+ export function unwrapGrouped(node) {
2
+ let current = node;
3
+ while (current.type === 'Grouped') {
4
+ current = current.expression;
5
+ }
6
+ return current;
7
+ }
8
+ export function unwrapAllTransparent(node) {
9
+ let current = node;
10
+ while (true) {
11
+ switch (current.type) {
12
+ case 'Grouped':
13
+ current = current.expression;
14
+ break;
15
+ case 'KeepDrop':
16
+ case 'Sort':
17
+ case 'CritThreshold':
18
+ case 'DieBound':
19
+ current = current.target;
20
+ break;
21
+ default:
22
+ return current;
23
+ }
24
+ }
25
+ }
26
+ function someDescendant(node, isHit) {
27
+ if (isHit(node))
28
+ return true;
29
+ switch (node.type) {
30
+ case 'BinaryOp':
31
+ return someDescendant(node.left, isHit) || someDescendant(node.right, isHit);
32
+ case 'UnaryOp':
33
+ return someDescendant(node.operand, isHit);
34
+ case 'KeepDrop':
35
+ case 'Explode':
36
+ case 'Reroll':
37
+ case 'DieBound':
38
+ case 'SuccessCount':
39
+ case 'Sort':
40
+ case 'CritThreshold':
41
+ return someDescendant(node.target, isHit);
42
+ case 'Versus':
43
+ return someDescendant(node.roll, isHit) || someDescendant(node.dc, isHit);
44
+ case 'FunctionCall': {
45
+ for (const arg of node.args) {
46
+ if (someDescendant(arg, isHit))
47
+ return true;
48
+ }
49
+ return false;
50
+ }
51
+ case 'Grouped':
52
+ return someDescendant(node.expression, isHit);
53
+ case 'Group': {
54
+ for (const expression of node.expressions) {
55
+ if (someDescendant(expression, isHit))
56
+ return true;
57
+ }
58
+ return false;
59
+ }
60
+ default:
61
+ return false;
62
+ }
63
+ }
64
+ const isDicePoolHit = (current) => current.type === 'Dice' ||
65
+ current.type === 'FateDice' ||
66
+ (current.type === 'Group' && current.expressions.length >= 2);
67
+ const isFateDiceHit = (current) => current.type === 'FateDice';
68
+ const isMultiSubGroupHit = (current) => current.type === 'Group' && current.expressions.length >= 2;
69
+ const isVersusHit = (current) => current.type === 'Versus';
70
+ export function containsDicePool(node) {
71
+ switch (node.type) {
72
+ case 'Dice':
73
+ case 'FateDice':
74
+ case 'KeepDrop':
75
+ case 'Explode':
76
+ case 'Reroll':
77
+ case 'DieBound':
78
+ return true;
79
+ case 'Sort':
80
+ case 'CritThreshold':
81
+ return containsDicePool(node.target);
82
+ case 'Grouped':
83
+ return containsDicePool(node.expression);
84
+ case 'Group':
85
+ return node.expressions.length >= 2 || node.expressions.some(deepContainsDicePool);
86
+ default:
87
+ return false;
88
+ }
89
+ }
90
+ export function deepContainsDicePool(node) {
91
+ return someDescendant(node, isDicePoolHit);
92
+ }
93
+ export function containsFatePool(node) {
94
+ switch (node.type) {
95
+ case 'FateDice':
96
+ return true;
97
+ case 'KeepDrop':
98
+ case 'Explode':
99
+ case 'Reroll':
100
+ case 'DieBound':
101
+ case 'Sort':
102
+ case 'CritThreshold':
103
+ return containsFatePool(node.target);
104
+ case 'Grouped':
105
+ return containsFatePool(node.expression);
106
+ case 'Group':
107
+ return node.expressions.some(deepContainsFatePool);
108
+ default:
109
+ return false;
110
+ }
111
+ }
112
+ export function deepContainsFatePool(node) {
113
+ return someDescendant(node, isFateDiceHit);
114
+ }
115
+ export function containsMultiSubGroup(node) {
116
+ return someDescendant(node, isMultiSubGroupHit);
117
+ }
118
+ export function containsVersus(node) {
119
+ return someDescendant(node, isVersusHit);
120
+ }
121
+ //# sourceMappingURL=guards.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guards.js","sourceRoot":"","sources":["../../src/parser/guards.ts"],"names":[],"mappings":"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"}
@@ -3,19 +3,70 @@
3
3
  *
4
4
  * @module parser/parser
5
5
  */
6
- import type { RollParserErrorCode } from '../errors';
7
- import { RollParserError } from '../errors';
8
- import { type Token } from '../lexer/tokens';
9
- import type { ComparePoint } from '../types';
10
- import type { ASTNode } from './ast';
6
+ import type { RollParserErrorCode } from '../errors.js';
7
+ import { RollParserError } from '../errors.js';
8
+ import { type Token } from '../lexer/tokens.js';
9
+ import type { ASTNode } from './ast.js';
11
10
  /**
12
11
  * Error thrown when the parser encounters invalid syntax.
12
+ *
13
+ * `position` is a zero-based UTF-16 offset into the notation. It is
14
+ * deliberately absent from `message` — read it from the field, or uniformly
15
+ * across all roll-parser errors via `getErrorSpan`.
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * import { ParseError, roll, TokenType } from 'roll-parser';
20
+ *
21
+ * try {
22
+ * roll('4d6d1');
23
+ * } catch (error) {
24
+ * const typed = error as ParseError;
25
+ * typed.code; // 'AMBIGUOUS_DICE_CHAIN'
26
+ * typed.position; // 3
27
+ * typed.token?.type === TokenType.DICE; // true
28
+ * }
29
+ * ```
30
+ *
31
+ * @category Errors
13
32
  */
14
33
  export declare class ParseError extends RollParserError {
34
+ /** Zero-based UTF-16 offset in the notation where parsing failed. */
15
35
  readonly position: number;
36
+ /**
37
+ * The token the parser was looking at. `undefined` when the failure is not
38
+ * anchored to a token — currently only `UNEXPECTED_END`, raised when the
39
+ * input stops short.
40
+ */
16
41
  readonly token: Token | undefined;
17
- constructor(message: string, code: RollParserErrorCode, position: number, token?: Token);
42
+ constructor(message: string, code: RollParserErrorCode, position: number, token?: Token, options?: ErrorOptions);
18
43
  }
44
+ /**
45
+ * Maximum expression nesting depth. Far beyond any human-authored notation —
46
+ * exists so adversarial input like 20,000 nested parens throws a typed
47
+ * `ParseError` instead of an uncaught `RangeError` stack overflow (which
48
+ * would also break the `isRollParserError` contract). Bounding parse depth
49
+ * also bounds AST depth, protecting the recursive AST walkers and evaluator.
50
+ *
51
+ * Not configurable — unlike the {@link EvaluationOptions} caps, this one always
52
+ * applies, so untrusted notation can never blow the stack.
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * import { isRollParserError, MAX_PARSE_DEPTH, parse } from 'roll-parser';
57
+ *
58
+ * MAX_PARSE_DEPTH; // 128
59
+ *
60
+ * try {
61
+ * parse('('.repeat(20_000) + '1d6' + ')'.repeat(20_000));
62
+ * } catch (error) {
63
+ * isRollParserError(error) && error.code; // 'MAX_DEPTH_EXCEEDED'
64
+ * }
65
+ * ```
66
+ *
67
+ * @category Limits
68
+ */
69
+ export declare const MAX_PARSE_DEPTH = 128;
19
70
  /**
20
71
  * Pratt parser for dice notation.
21
72
  *
@@ -25,6 +76,7 @@ export declare class ParseError extends RollParserError {
25
76
  export declare class Parser {
26
77
  private readonly tokens;
27
78
  private pos;
79
+ private depth;
28
80
  constructor(tokens: Token[]);
29
81
  /**
30
82
  * Parse the token stream into an AST.
@@ -34,6 +86,11 @@ export declare class Parser {
34
86
  * Parse an expression with minimum binding power.
35
87
  */
36
88
  private parseExpression;
89
+ /**
90
+ * Throw once the AST under construction is deeper than the recursive walkers
91
+ * can safely descend.
92
+ */
93
+ private guardDepth;
37
94
  /**
38
95
  * NUD - Null Denotation.
39
96
  * Handles tokens that appear at the start of an expression (prefix position).
@@ -44,6 +101,11 @@ export declare class Parser {
44
101
  * Handles tokens that appear between expressions (infix/postfix position).
45
102
  */
46
103
  private parseLed;
104
+ /**
105
+ * Zero-width span for synthetic nodes (implicit counts, `d%` sides) that
106
+ * have no source text of their own — anchored at the governing token.
107
+ */
108
+ private static syntheticLiteral;
47
109
  private parseLiteral;
48
110
  private parseUnaryMinus;
49
111
  private parsePrefixDice;
@@ -53,26 +115,82 @@ export declare class Parser {
53
115
  private parsePrefixFateDice;
54
116
  private parseInfixFateDice;
55
117
  private parseGrouped;
118
+ private parseGroup;
119
+ private parseVariable;
56
120
  private parseFunctionCall;
57
121
  private parseBinaryOp;
122
+ /**
123
+ * Rejects a dice token whose count operand is itself a bare (unparenthesized)
124
+ * dice expression. `4d6d1` would otherwise silently parse as `(4d6)d1` —
125
+ * roll 4d6, then use the result as a count of d1 dice — which is almost
126
+ * never intended: every major dice dialect reads `4d6d1` as "drop lowest 1".
127
+ * Both meanings stay reachable through explicit forms: `4d6dl1` to drop,
128
+ * `(4d6)d1` for nested dice.
129
+ */
130
+ private rejectBareDiceChain;
58
131
  private rejectSuccessCountTarget;
59
- private parseModifier;
132
+ /**
133
+ * Rejects `GroupNode` (or a wrapper-cloaked group) as the target of `token`.
134
+ * Explode, reroll, and crit-threshold wrap bare dice pools only — a group
135
+ * is a container of sub-expressions, so these modifiers have no defined
136
+ * semantics. Walks `Grouped`/`KeepDrop`/`Sort`/`CritThreshold` so wrappers
137
+ * cannot smuggle a group past the check (`{1d6}kh1cs>5`, `({1d6})!`,
138
+ * `{1d6}scs>5` all reject the same as `{1d6}!`/`{1d6}cs>5`).
139
+ *
140
+ * `singleSubRollPasses` opts the caller into the single-sub-roll passthrough:
141
+ * a `Group` with one expression is the user's explicit flat-pool escape
142
+ * hatch and is equivalent to its unwrapped form. Currently only
143
+ * `parseCritThreshold` opts in — explode/reroll keep the strict reject so
144
+ * existing notation contracts don't shift.
145
+ */
146
+ private rejectGroupTarget;
147
+ /**
148
+ * Rejects a Versus anywhere inside a meta operand — a dice count, dice sides,
149
+ * a modifier count, or a threshold/bound value.
150
+ *
151
+ * Deep, unlike {@link rejectVersusTarget}: `evalMetaOperand` reduces the
152
+ * operand to a scalar and forwards rolls but not `versusMetadata`, so
153
+ * `floor(1d20 vs 15)` or `(1d20 vs 15)+0` buried in a count loses the degree
154
+ * exactly as a bare one does.
155
+ */
156
+ private rejectVersusMetaOperand;
157
+ /**
158
+ * The wording the meta-expression rejections share. Not every `NESTED_VERSUS`
159
+ * throw — `parseVersus` says "Cannot chain versus operators" for `a vs b vs c`,
160
+ * a different condition. Routing that one through here would silently rewrite
161
+ * its message, and `expectRollError` asserts only the code.
162
+ */
163
+ private static throwVersusMetaExpression;
164
+ private rejectVersusTarget;
165
+ private parseKeepDrop;
60
166
  private parseExplode;
61
167
  private parseReroll;
168
+ private parseDieBound;
169
+ private parseSort;
170
+ private parseCritThreshold;
62
171
  private parseSuccessCount;
172
+ /** Parses the `f...` suffix of a success count. Bare `fN` means `f=N`. */
173
+ private parseFailThreshold;
63
174
  private parseVersus;
64
175
  /**
65
176
  * Checks whether the next token is a comparison operator.
66
177
  */
67
- isComparePointAhead(): boolean;
178
+ private isComparePointAhead;
68
179
  /**
69
180
  * Parses a comparison operator followed by a value expression.
70
181
  * Called by modifier parsers (explode, reroll, success counting).
71
182
  *
183
+ * The threshold value is parsed at `BP.DICE_LEFT`, which binds tighter than
184
+ * arithmetic. This keeps the comparison bound to the dice pool on the left
185
+ * rather than letting arithmetic to the right be consumed into the
186
+ * threshold. As a consequence, `1d6>=5+2` parses as `(1d6>=5)+2` with
187
+ * threshold `5` — not `7`. Computed thresholds require parens:
188
+ * `1d6>=(5+2)`. Same binding applies to `parseSuccessCount` below.
189
+ *
72
190
  * @returns A ComparePoint with the operator and value AST node
73
191
  * @throws {ParseError} If the next token is not a comparison operator
74
192
  */
75
- parseComparePoint(): ComparePoint;
193
+ private parseComparePoint;
76
194
  private getCompareOp;
77
195
  private getOperatorSymbol;
78
196
  private getLeftBp;
@@ -83,20 +201,49 @@ export declare class Parser {
83
201
  private hasTokens;
84
202
  }
85
203
  /**
86
- * Parse a dice notation string into an AST.
204
+ * Parses a dice notation string into an {@link ASTNode} tree, lexing it first.
205
+ *
206
+ * {@link evaluate} never mutates the AST, so parse once and evaluate many times
207
+ * when rolling the same notation repeatedly — that skips the lexer and parser
208
+ * on every roll after the first. Use `parse` alone to validate notation
209
+ * without consuming randomness.
87
210
  *
88
211
  * @param notation - The dice notation to parse
89
- * @returns The root AST node
212
+ * @returns The root AST node, with `start`/`end` spans on every node
90
213
  * @throws {LexerError} If the input contains invalid characters
91
214
  * @throws {ParseError} If the input has invalid syntax
215
+ * @throws {RollParserError} `INVALID_NOTATION_TYPE` when `notation` is not a
216
+ * string — raised before lexing, so it carries no position
92
217
  *
93
218
  * @example
94
219
  * ```typescript
95
- * const ast = parse('2d6+3');
96
- * // { type: 'BinaryOp', operator: '+',
97
- * // left: { type: 'Dice', count: 2, sides: 6 },
98
- * // right: { type: 'Literal', value: 3 } }
220
+ * import { parse } from 'roll-parser';
221
+ *
222
+ * parse('2d6+3');
223
+ * // {
224
+ * // type: 'BinaryOp', operator: '+', start: 0, end: 5,
225
+ * // left: {
226
+ * // type: 'Dice', start: 0, end: 3,
227
+ * // count: { type: 'Literal', value: 2, start: 0, end: 1 },
228
+ * // sides: { type: 'Literal', value: 6, start: 2, end: 3 },
229
+ * // },
230
+ * // right: { type: 'Literal', value: 3, start: 4, end: 5 },
231
+ * // }
232
+ * ```
233
+ *
234
+ * `count` and `sides` are full nodes, not numbers — that is what makes
235
+ * computed dice like `(1d4)d6` expressible.
236
+ *
237
+ * @example Parse once, roll many
238
+ * ```typescript
239
+ * import { evaluate, parse, SeededRNG } from 'roll-parser';
240
+ *
241
+ * const ast = parse('4d6kh3');
242
+ * const rng = new SeededRNG('demo');
243
+ * const scores = Array.from({ length: 6 }, () => evaluate(ast, rng).total);
99
244
  * ```
245
+ *
246
+ * @category Core
100
247
  */
101
248
  export declare function parse(notation: string): ASTNode;
102
249
  //# sourceMappingURL=parser.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/parser/parser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAE5C,OAAO,EAAE,KAAK,KAAK,EAAa,MAAM,iBAAiB,CAAC;AACxD,OAAO,KAAK,EAAa,YAAY,EAAE,MAAM,UAAU,CAAC;AACxD,OAAO,KAAK,EACV,OAAO,EAYR,MAAM,OAAO,CAAC;AAGf;;GAEG;AACH,qBAAa,UAAW,SAAQ,eAAe;IAC7C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,CAAC;gBAEtB,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAMxF;AAkDD;;;;;GAKG;AACH,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;IACjC,OAAO,CAAC,GAAG,CAAK;gBAEJ,MAAM,EAAE,KAAK,EAAE;IAI3B;;OAEG;IACH,KAAK,IAAI,OAAO;IAqBhB;;OAEG;IACH,OAAO,CAAC,eAAe;IAgBvB;;;OAGG;IACH,OAAO,CAAC,QAAQ;IAsChB;;;OAGG;IACH,OAAO,CAAC,QAAQ;IAwDhB,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,eAAe;IASvB,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,cAAc;IAUtB,OAAO,CAAC,sBAAsB;IAS9B,OAAO,CAAC,qBAAqB;IAS7B,OAAO,CAAC,mBAAmB;IAQ3B,OAAO,CAAC,kBAAkB;IAU1B,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,iBAAiB;IAgDzB,OAAO,CAAC,aAAa;IAarB,OAAO,CAAC,wBAAwB;IAWhC,OAAO,CAAC,aAAa;IA2BrB,OAAO,CAAC,YAAY;IA4BpB,OAAO,CAAC,WAAW;IAmBnB,OAAO,CAAC,iBAAiB;IAgCzB,OAAO,CAAC,WAAW;IAenB;;OAEG;IACH,mBAAmB,IAAI,OAAO;IAW9B;;;;;;OAMG;IACH,iBAAiB,IAAI,YAAY;IAWjC,OAAO,CAAC,YAAY;IAwBpB,OAAO,CAAC,iBAAiB;IAwBzB,OAAO,CAAC,SAAS;IA8CjB,OAAO,CAAC,UAAU;IAoBlB,OAAO,CAAC,IAAI;IAIZ,OAAO,CAAC,OAAO;IAMf,OAAO,CAAC,MAAM;IAcd,OAAO,CAAC,SAAS;CAGlB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAI/C"}
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/parser/parser.ts"],"names":[],"mappings":"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"}