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
@@ -3,95 +3,196 @@
3
3
  *
4
4
  * @module parser/ast
5
5
  */
6
- import type { ComparePoint } from '../types';
6
+ import type { ComparePoint } from '../types.js';
7
7
  /**
8
- * Numeric literal node.
8
+ * Source span carried by every AST node.
9
+ *
10
+ * `start` is inclusive, `end` exclusive, both in UTF-16 code units into the
11
+ * original notation string. The parser sets both on every node it produces;
12
+ * they are typed optional so hand-constructed ASTs (tests, programmatic
13
+ * consumers) remain valid without positions.
14
+ *
15
+ * `notation.slice(start, end)` recovers the source text of any parsed node,
16
+ * which is how the CLI underlines the failing sub-expression.
17
+ *
18
+ * @category AST
9
19
  */
10
- export type LiteralNode = {
11
- type: 'Literal';
12
- value: number;
20
+ export type NodeSpan = {
21
+ readonly start?: number;
22
+ readonly end?: number;
13
23
  };
14
24
  /**
15
- * Dice roll node.
16
- * Count and sides can be expressions to support computed dice like (1+1)d(3*2).
25
+ * Numeric literal node — an integer or decimal written directly in the
26
+ * notation (`3`, `2.5`). Leaf node.
27
+ *
28
+ * Decimals are accepted and carried through arithmetic exactly as written;
29
+ * only dice counts and sides are required to resolve to integers.
30
+ *
31
+ * @category AST
17
32
  */
18
- export type DiceNode = {
19
- type: 'Dice';
20
- count: ASTNode;
21
- sides: ASTNode;
33
+ export type LiteralNode = NodeSpan & {
34
+ readonly type: 'Literal';
35
+ readonly value: number;
36
+ };
37
+ /**
38
+ * Dice roll node (`NdX`, `dX`, `d%`).
39
+ *
40
+ * `count` and `sides` are full sub-expressions, not numbers, which is what
41
+ * makes computed dice like `(1+1)d(3*2)` and `(1d4)d6` expressible. Both are
42
+ * evaluated first and must resolve to integers; `d%` desugars to a `sides`
43
+ * literal of `100`, and an omitted count to a `count` literal of `1`.
44
+ *
45
+ * Dice rolled by the `count`/`sides` sub-expressions are meta-expression dice
46
+ * — they land in `RollResult.rolls` tagged `'meta'` and belong to no pool.
47
+ *
48
+ * @category AST
49
+ */
50
+ export type DiceNode = NodeSpan & {
51
+ readonly type: 'Dice';
52
+ readonly count: ASTNode;
53
+ readonly sides: ASTNode;
22
54
  };
23
55
  /**
24
56
  * Fate/Fudge dice node (`dF`).
25
57
  * Each die produces a result in {-1, 0, +1}. No configurable sides.
58
+ *
59
+ * Fate dice carry `sides: 0` as a sentinel in their `DieResult`, and are
60
+ * never `critical` or `fumble` — there is no maximum face to hit.
61
+ *
62
+ * @category AST
26
63
  */
27
- export type FateDiceNode = {
28
- type: 'FateDice';
29
- count: ASTNode;
64
+ export type FateDiceNode = NodeSpan & {
65
+ readonly type: 'FateDice';
66
+ readonly count: ASTNode;
30
67
  };
31
68
  /**
32
- * Binary operation node.
69
+ * Binary operation node — the arithmetic backbone of an expression.
70
+ *
71
+ * | Operator | Meaning | Precedence | Associativity |
72
+ * |----------|---------|-----------:|---------------|
73
+ * | `+` `-` | add, subtract | 10 | left |
74
+ * | `*` `/` `%` | multiply, divide, modulo | 20 | left |
75
+ * | `**` | power (also spelled `^`) | 30 | right |
76
+ *
77
+ * Dice bind tighter than all of them (40), and postfix modifiers sit at 35,
78
+ * so `2d6+3` is `(2d6)+3` and `4d6kh3*2` is `(4d6kh3)*2`. The `vs` operator
79
+ * binds loosest of all (2) and has its own {@link VersusNode}.
80
+ *
81
+ * `/` and `%` throw `DIVISION_BY_ZERO` / `MODULO_BY_ZERO` on a zero right
82
+ * side; any operator producing a non-finite total throws `NON_FINITE_RESULT`.
83
+ * Division is not rounded — wrap it in `floor()` if you need an integer.
84
+ *
85
+ * @category AST
33
86
  */
34
- export type BinaryOpNode = {
35
- type: 'BinaryOp';
36
- operator: '+' | '-' | '*' | '/' | '%' | '**';
37
- left: ASTNode;
38
- right: ASTNode;
87
+ export type BinaryOpNode = NodeSpan & {
88
+ readonly type: 'BinaryOp';
89
+ readonly operator: '+' | '-' | '*' | '/' | '%' | '**';
90
+ readonly left: ASTNode;
91
+ readonly right: ASTNode;
39
92
  };
40
93
  /**
41
- * Unary operation node.
94
+ * Unary operation node — prefix negation, the only unary operator.
95
+ *
96
+ * Binding power 25 sits between multiplication and power, so `-1d4` is
97
+ * `-(1d4)` (negate the roll) rather than `(-1)d4`, while `-2**2` is `-(2**2)`.
98
+ *
99
+ * @category AST
42
100
  */
43
- export type UnaryOpNode = {
44
- type: 'UnaryOp';
45
- operator: '-';
46
- operand: ASTNode;
101
+ export type UnaryOpNode = NodeSpan & {
102
+ readonly type: 'UnaryOp';
103
+ readonly operator: '-';
104
+ readonly operand: ASTNode;
47
105
  };
48
106
  /**
49
- * Keep/drop modifier node.
107
+ * Keep/drop modifier node (`khN`, `klN`, `dhN`, `dlN`, and the `kN`
108
+ * shorthand for `khN`).
109
+ *
50
110
  * Wraps a dice expression with keep highest/lowest or drop highest/lowest.
111
+ * An omitted count defaults to 1, so `4d6kh` is `4d6kh1`. `count` is a full
112
+ * sub-expression, so `4d6kh(1d2)` is legal — and its dice are drawn *before*
113
+ * the pool.
114
+ *
115
+ * Chained modifiers (`4d6kh3dl1`) do not nest: the evaluator flattens the
116
+ * chain and applies each spec independently to the same pool, unioning the
117
+ * dropped sets, which is the Roll20 rule.
118
+ *
119
+ * @category AST
51
120
  */
52
- export type ModifierNode = {
53
- type: 'Modifier';
54
- modifier: 'keep' | 'drop';
55
- selector: 'highest' | 'lowest';
56
- count: ASTNode;
57
- target: ASTNode;
121
+ export type KeepDropNode = NodeSpan & {
122
+ readonly type: 'KeepDrop';
123
+ readonly kind: 'keep' | 'drop';
124
+ readonly selector: 'highest' | 'lowest';
125
+ readonly count: ASTNode;
126
+ readonly target: ASTNode;
58
127
  };
59
128
  /**
60
129
  * Exploding dice node (`!`, `!!`, `!p`, `!>Y`).
61
130
  * Wraps a dice expression with a standard, compounding, or penetrating
62
131
  * explosion. An absent `threshold` means "explode on the die's maximum face".
132
+ *
133
+ * Thresholds accept any comparator. In notation like `1d10!=10` (the
134
+ * Storyteller "10-again" rule) the `!` is the explode marker and `=10` the
135
+ * equality threshold — there is no `!=` comparator. Per-die explosion count
136
+ * is capped by `EvaluationOptions.maxExplodeIterations`.
137
+ *
138
+ * @category AST
63
139
  */
64
- export type ExplodeNode = {
65
- type: 'Explode';
66
- variant: 'standard' | 'compound' | 'penetrating';
67
- threshold?: ComparePoint;
68
- target: ASTNode;
140
+ export type ExplodeNode = NodeSpan & {
141
+ readonly type: 'Explode';
142
+ readonly variant: 'standard' | 'compound' | 'penetrating';
143
+ readonly threshold?: ComparePoint;
144
+ readonly target: ASTNode;
69
145
  };
70
146
  /**
71
147
  * Reroll node (`r<COND>`, `ro<COND>`).
72
148
  * Re-rolls dice that match a comparison condition. `once: true` for `ro`
73
149
  * keeps the second result regardless of match; `once: false` for `r`
74
- * re-rolls recursively until the condition no longer matches.
150
+ * re-rolls recursively until the condition no longer matches, bounded by
151
+ * `EvaluationOptions.maxRerollIterations`.
152
+ *
153
+ * @category AST
154
+ */
155
+ export type RerollNode = NodeSpan & {
156
+ readonly type: 'Reroll';
157
+ readonly once: boolean;
158
+ readonly condition: ComparePoint;
159
+ readonly target: ASTNode;
160
+ };
161
+ /**
162
+ * Per-die clamp node (`minN`, `maxN`).
163
+ * `4d6min2` raises every die below 2 to 2; `4d6max5` lowers every die above
164
+ * 5 to 5. The clamp rewrites `DieResult.result` (preserving the raw face in
165
+ * `initialResult`) and re-sums the pool; `critical`/`fumble` keep reflecting
166
+ * the natural face. The bound is a full sub-expression (`4d6min(1d2)`),
167
+ * drawn *after* the pool like other threshold arguments.
168
+ *
169
+ * Chained bounds nest and apply left to right: `4d6min2max5` clamps into
170
+ * [2, 5].
171
+ *
172
+ * @category AST
75
173
  */
76
- export type RerollNode = {
77
- type: 'Reroll';
78
- once: boolean;
79
- condition: ComparePoint;
174
+ export type DieBoundNode = NodeSpan & {
175
+ type: 'DieBound';
176
+ bound: 'min' | 'max';
177
+ value: ASTNode;
80
178
  target: ASTNode;
81
179
  };
82
180
  /**
83
181
  * Success counting node (`>=T`, `>T`, `<T`, `<=T`, `=T`, with optional `f=F`).
84
182
  *
85
183
  * Transforms a dice pool into a success count: each die meeting `threshold`
86
- * adds +1, each die meeting `failThreshold` subtracts 1. Terminal — no further
87
- * postfix modifiers may wrap a `SuccessCountNode`. The `failThreshold`
88
- * operator is always `=` (fail on an exact value).
184
+ * adds +1, each die meeting `failThreshold` subtracts 1. Terminal — a
185
+ * `SuccessCountNode` may not be wrapped by any postfix modifier, binary
186
+ * operator, unary operator, versus operand, or function argument. The
187
+ * `failThreshold` accepts any `CompareOp`; bare `fN` defaults to `operator: '='`.
188
+ *
189
+ * @category AST
89
190
  */
90
- export type SuccessCountNode = {
91
- type: 'SuccessCount';
92
- target: ASTNode;
93
- threshold: ComparePoint;
94
- failThreshold?: ComparePoint;
191
+ export type SuccessCountNode = NodeSpan & {
192
+ readonly type: 'SuccessCount';
193
+ readonly target: ASTNode;
194
+ readonly threshold: ComparePoint;
195
+ readonly failThreshold?: ComparePoint;
95
196
  };
96
197
  /**
97
198
  * Versus node (`<roll> vs <dc>`) — PF2e Degrees of Success.
@@ -102,11 +203,13 @@ export type SuccessCountNode = {
102
203
  * roll side. Lowest-precedence operator — chaining (`a vs b vs c`) is
103
204
  * rejected at parse time; nesting via parens (`a vs (b vs c)`) is rejected
104
205
  * at evaluation time.
206
+ *
207
+ * @category AST
105
208
  */
106
- export type VersusNode = {
107
- type: 'Versus';
108
- roll: ASTNode;
109
- dc: ASTNode;
209
+ export type VersusNode = NodeSpan & {
210
+ readonly type: 'Versus';
211
+ readonly roll: ASTNode;
212
+ readonly dc: ASTNode;
110
213
  };
111
214
  /**
112
215
  * Math function call node (`floor(expr)`, `max(a, b, ...)`, etc.).
@@ -115,69 +218,305 @@ export type VersusNode = {
115
218
  * variadic functions `max`, `min` (minimum 2 args). Arity is validated at
116
219
  * parse time against a static table; by the time the evaluator sees a
117
220
  * `FunctionCallNode`, `args.length` is guaranteed to match the function.
221
+ *
222
+ * `max`/`min` are variadic with no upper bound, so `max(1d20, 1d20, 1d20)`
223
+ * is a valid three-way advantage roll.
224
+ *
225
+ * @category AST
226
+ */
227
+ export type FunctionCallNode = NodeSpan & {
228
+ readonly type: 'FunctionCall';
229
+ readonly name: string;
230
+ readonly args: readonly ASTNode[];
231
+ };
232
+ /**
233
+ * Parenthesized group node (`(<expr>)`).
234
+ *
235
+ * Preserves explicit grouping typed by the user so that
236
+ * `RollResult.expression` and `RollResult.rendered` round-trip through
237
+ * `parse` without losing precedence information. Semantically transparent:
238
+ * evaluation returns the inner expression's value unchanged.
239
+ *
240
+ * @category AST
241
+ */
242
+ export type GroupedNode = NodeSpan & {
243
+ readonly type: 'Grouped';
244
+ readonly expression: ASTNode;
245
+ };
246
+ /**
247
+ * Variable reference node (`@name` or `@{name with spaces}`).
248
+ *
249
+ * Resolves to a numeric value from the evaluator's `context` map at
250
+ * evaluation time. Names are case-sensitive (`@StrMod` ≠ `@strmod`) — the
251
+ * lexer preserves case in the `AT` token's `value`, distinct from other
252
+ * identifier tokens which lowercase. Leaf node — no LED, never wraps a
253
+ * sub-expression.
254
+ *
255
+ * A name missing from `context` throws `UNDEFINED_VARIABLE` unless
256
+ * `onMissingVariable: 'zero'` is set.
257
+ *
258
+ * @category AST
259
+ */
260
+ export type VariableNode = NodeSpan & {
261
+ readonly type: 'Variable';
262
+ readonly name: string;
263
+ };
264
+ /**
265
+ * Grouped-roll node (`{expr}`, `{expr1, expr2, ...}`).
266
+ *
267
+ * Distinct from `GroupedNode` (parenthesized wrapper) — a `GroupNode`
268
+ * collects one or more sub-expressions whose evaluation semantics change
269
+ * with the sub-roll count. `expressions.length === 1` is a passthrough
270
+ * (flat-pool when wrapped by keep/drop); `expressions.length >= 2` treats
271
+ * each sub-roll's subtotal as a compound die for keep/drop selection.
272
+ *
273
+ * @category AST
274
+ */
275
+ export type GroupNode = NodeSpan & {
276
+ readonly type: 'Group';
277
+ readonly expressions: readonly ASTNode[];
278
+ };
279
+ /**
280
+ * Sort modifier node (`s`, `sa`, `sd`).
281
+ *
282
+ * Cosmetically reorders the dice produced by `target` in ascending or
283
+ * descending order. Purely visual — does not affect `total`,
284
+ * `successes`/`failures`, or any die-level flag (`kept`/`dropped`/
285
+ * `critical`/`fumble`). Dropped dice retain their `dropped` flag and
286
+ * appear in sorted position alongside kept dice.
287
+ *
288
+ * `s` and `sa` both mean ascending; `sd` is descending.
289
+ *
290
+ * @category AST
118
291
  */
119
- export type FunctionCallNode = {
120
- type: 'FunctionCall';
121
- name: string;
122
- args: ASTNode[];
292
+ export type SortNode = NodeSpan & {
293
+ readonly type: 'Sort';
294
+ readonly order: 'ascending' | 'descending';
295
+ readonly target: ASTNode;
123
296
  };
124
297
  /**
125
- * Union type of all AST nodes.
298
+ * Sentinel for bare `cs` / `cf` without a ComparePoint. Resolved to
299
+ * `result === sides` (for critical) or `result === 1` (for fumble) at
300
+ * evaluation time, using each die's own `sides`.
301
+ *
302
+ * @category AST
126
303
  */
127
- export type ASTNode = LiteralNode | DiceNode | FateDiceNode | BinaryOpNode | UnaryOpNode | ModifierNode | ExplodeNode | RerollNode | SuccessCountNode | VersusNode | FunctionCallNode;
304
+ export type CritThreshold = ComparePoint | 'default';
128
305
  /**
129
- * Type guard for LiteralNode.
306
+ * Critical threshold modifier node (`cs`, `cf`).
307
+ *
308
+ * Overrides the default `critical`/`fumble` flag logic for the dice
309
+ * produced by `target`. Bare `cs`/`cf` uses the `'default'` sentinel
310
+ * (max face / 1). Custom thresholds accept any ComparePoint. Chaining
311
+ * collapses into a single node — `1d20cs=20cs=1cf>18` has two success
312
+ * and one fail threshold. Display-only: does not change `total`,
313
+ * explosion triggers, or success counting. `cs` and `cf` are independent
314
+ * overrides — a side with no explicit thresholds keeps the default rule
315
+ * (the evaluator substitutes the `'default'` sentinel at apply time).
316
+ *
317
+ * @category AST
318
+ */
319
+ export type CritThresholdNode = NodeSpan & {
320
+ readonly type: 'CritThreshold';
321
+ readonly successThresholds: readonly CritThreshold[];
322
+ readonly failThresholds: readonly CritThreshold[];
323
+ readonly target: ASTNode;
324
+ };
325
+ /**
326
+ * Discriminated union of all 17 AST node types — what {@link parse} returns
327
+ * and what {@link evaluate} consumes.
328
+ *
329
+ * Narrow it either by switching on `node.type` (PascalCase discriminants, as
330
+ * opposed to the camelCase ones on {@link RollPart}) or with the exported
331
+ * type guards: {@link isLiteral}, {@link isDice}, {@link isFateDice},
332
+ * {@link isBinaryOp}, {@link isUnaryOp}, {@link isKeepDrop},
333
+ * {@link isExplode}, {@link isReroll}, {@link isDieBound},
334
+ * {@link isSuccessCount}, {@link isVersus}, {@link isFunctionCall},
335
+ * {@link isGrouped}, {@link isVariable}, {@link isGroup}, {@link isSort},
336
+ * {@link isCritThreshold}.
337
+ *
338
+ * Nodes are plain data with no methods, so they are structurally clonable and
339
+ * safe to cache. Every parser-produced node carries a {@link NodeSpan}.
340
+ *
341
+ * @example A guard-based walker — count the dice an expression can roll
342
+ * ```typescript
343
+ * import {
344
+ * type ASTNode, isBinaryOp, isDice, isFateDice, isGroup, isGrouped,
345
+ * isFunctionCall, isLiteral, isUnaryOp, isVersus, parse,
346
+ * } from 'roll-parser';
347
+ *
348
+ * function countPools(node: ASTNode): number {
349
+ * if (isDice(node) || isFateDice(node)) return 1;
350
+ * if (isLiteral(node)) return 0;
351
+ * if (isBinaryOp(node)) return countPools(node.left) + countPools(node.right);
352
+ * if (isUnaryOp(node)) return countPools(node.operand);
353
+ * if (isGrouped(node)) return countPools(node.expression);
354
+ * if (isVersus(node)) return countPools(node.roll) + countPools(node.dc);
355
+ * if (isGroup(node)) return node.expressions.reduce((n, e) => n + countPools(e), 0);
356
+ * if (isFunctionCall(node)) return node.args.reduce((n, a) => n + countPools(a), 0);
357
+ * // Every remaining variant is a postfix modifier wrapping `target`.
358
+ * return 'target' in node ? countPools(node.target) : 0;
359
+ * }
360
+ *
361
+ * countPools(parse('2d6+3')); // 1
362
+ * countPools(parse('{2d20kh1+5, 3d8!}kh1')); // 2
363
+ * countPools(parse('1+2')); // 0
364
+ * ```
365
+ *
366
+ * @category AST
367
+ */
368
+ export type ASTNode = LiteralNode | DiceNode | FateDiceNode | BinaryOpNode | UnaryOpNode | KeepDropNode | ExplodeNode | RerollNode | DieBoundNode | SuccessCountNode | VersusNode | FunctionCallNode | GroupedNode | VariableNode | GroupNode | SortNode | CritThresholdNode;
369
+ /**
370
+ * Narrows an {@link ASTNode} to a numeric literal (`3`, `2.5`).
371
+ *
372
+ * @param node - Any AST node
373
+ * @returns `true` when `node` is a {@link LiteralNode}
374
+ *
375
+ * @category AST
130
376
  */
131
377
  export declare function isLiteral(node: ASTNode): node is LiteralNode;
132
378
  /**
133
- * Type guard for DiceNode.
379
+ * Narrows an {@link ASTNode} to a dice pool (`2d6`, `d%`, `(1d4)d6`).
380
+ *
381
+ * @param node - Any AST node
382
+ * @returns `true` when `node` is a {@link DiceNode}
383
+ *
384
+ * @category AST
134
385
  */
135
386
  export declare function isDice(node: ASTNode): node is DiceNode;
136
387
  /**
137
- * Type guard for FateDiceNode.
388
+ * Narrows an {@link ASTNode} to a Fate/Fudge pool (`4dF`).
389
+ *
390
+ * @param node - Any AST node
391
+ * @returns `true` when `node` is a {@link FateDiceNode}
392
+ *
393
+ * @category AST
138
394
  */
139
395
  export declare function isFateDice(node: ASTNode): node is FateDiceNode;
140
396
  /**
141
- * Type guard for BinaryOpNode.
397
+ * Narrows an {@link ASTNode} to an arithmetic operation (`+ - * / % **`).
398
+ *
399
+ * @param node - Any AST node
400
+ * @returns `true` when `node` is a {@link BinaryOpNode}
401
+ *
402
+ * @category AST
142
403
  */
143
404
  export declare function isBinaryOp(node: ASTNode): node is BinaryOpNode;
144
405
  /**
145
- * Type guard for UnaryOpNode.
406
+ * Narrows an {@link ASTNode} to a prefix negation (`-1d4`).
407
+ *
408
+ * @param node - Any AST node
409
+ * @returns `true` when `node` is a {@link UnaryOpNode}
410
+ *
411
+ * @category AST
146
412
  */
147
413
  export declare function isUnaryOp(node: ASTNode): node is UnaryOpNode;
148
414
  /**
149
- * Type guard for ModifierNode.
415
+ * Narrows an {@link ASTNode} to a keep/drop modifier (`kh`, `kl`, `dh`, `dl`).
416
+ *
417
+ * @param node - Any AST node
418
+ * @returns `true` when `node` is a {@link KeepDropNode}
419
+ *
420
+ * @category AST
150
421
  */
151
- export declare function isModifier(node: ASTNode): node is ModifierNode;
422
+ export declare function isKeepDrop(node: ASTNode): node is KeepDropNode;
152
423
  /**
153
- * Type guard for ExplodeNode.
424
+ * Narrows an {@link ASTNode} to an explosion (`!`, `!!`, `!p`).
425
+ *
426
+ * @param node - Any AST node
427
+ * @returns `true` when `node` is a {@link ExplodeNode}
428
+ *
429
+ * @category AST
154
430
  */
155
431
  export declare function isExplode(node: ASTNode): node is ExplodeNode;
156
432
  /**
157
- * Type guard for RerollNode.
433
+ * Narrows an {@link ASTNode} to a reroll (`r`, `ro`).
434
+ *
435
+ * @param node - Any AST node
436
+ * @returns `true` when `node` is a {@link RerollNode}
437
+ *
438
+ * @category AST
158
439
  */
159
440
  export declare function isReroll(node: ASTNode): node is RerollNode;
160
441
  /**
161
- * Type guard for SuccessCountNode.
442
+ * Narrows an {@link ASTNode} to a success count (`>=6`, with optional `f1`).
443
+ *
444
+ * @param node - Any AST node
445
+ * @returns `true` when `node` is a {@link SuccessCountNode}
446
+ *
447
+ * @category AST
162
448
  */
163
449
  export declare function isSuccessCount(node: ASTNode): node is SuccessCountNode;
164
450
  /**
165
- * Type guard for VersusNode.
451
+ * Narrows an {@link ASTNode} to a PF2e degree-of-success check (`vs`).
452
+ *
453
+ * @param node - Any AST node
454
+ * @returns `true` when `node` is a {@link VersusNode}
455
+ *
456
+ * @category AST
166
457
  */
167
458
  export declare function isVersus(node: ASTNode): node is VersusNode;
168
459
  /**
169
- * Type guard for FunctionCallNode.
460
+ * Narrows an {@link ASTNode} to a math function call (`floor`, `max`, …).
461
+ *
462
+ * @param node - Any AST node
463
+ * @returns `true` when `node` is a {@link FunctionCallNode}
464
+ *
465
+ * @category AST
170
466
  */
171
467
  export declare function isFunctionCall(node: ASTNode): node is FunctionCallNode;
172
468
  /**
173
- * Returns `true` if the AST contains a `Dice` or `FateDice` node reachable
174
- * through structural composition (BinaryOp, UnaryOp, keep/drop, explode,
175
- * reroll, success-count wrappers). Meta-expressions dice count/sides,
176
- * modifier counts, and ComparePoint values are treated as leaves and
177
- * never recursed into.
469
+ * Narrows an {@link ASTNode} to a parenthesized group (`(1d6+2)`).
470
+ *
471
+ * @param node - Any AST node
472
+ * @returns `true` when `node` is a {@link GroupedNode}
473
+ *
474
+ * @category AST
475
+ */
476
+ export declare function isGrouped(node: ASTNode): node is GroupedNode;
477
+ /**
478
+ * Narrows an {@link ASTNode} to a variable reference (`@str`).
479
+ *
480
+ * @param node - Any AST node
481
+ * @returns `true` when `node` is a {@link VariableNode}
482
+ *
483
+ * @category AST
484
+ */
485
+ export declare function isVariable(node: ASTNode): node is VariableNode;
486
+ /**
487
+ * Narrows an {@link ASTNode} to a braced grouped roll (`{1d8, 1d10}`).
488
+ *
489
+ * @param node - Any AST node
490
+ * @returns `true` when `node` is a {@link GroupNode}
491
+ *
492
+ * @category AST
493
+ */
494
+ export declare function isGroup(node: ASTNode): node is GroupNode;
495
+ /**
496
+ * Narrows an {@link ASTNode} to a sort modifier (`s`, `sa`, `sd`).
497
+ *
498
+ * @param node - Any AST node
499
+ * @returns `true` when `node` is a {@link SortNode}
500
+ *
501
+ * @category AST
502
+ */
503
+ export declare function isSort(node: ASTNode): node is SortNode;
504
+ /**
505
+ * Narrows an {@link ASTNode} to a crit-threshold override (`cs`, `cf`).
506
+ *
507
+ * @param node - Any AST node
508
+ * @returns `true` when `node` is a {@link CritThresholdNode}
509
+ *
510
+ * @category AST
511
+ */
512
+ export declare function isCritThreshold(node: ASTNode): node is CritThresholdNode;
513
+ /**
514
+ * Narrows an {@link ASTNode} to a per-die clamp (`min2`, `max5`).
515
+ *
516
+ * @param node - Any AST node
517
+ * @returns `true` when `node` is a {@link DieBoundNode}
178
518
  *
179
- * Used by the parser to reject success-counting targets that don't actually
180
- * roll any dice (e.g. `1>=3`, `(1+2)>=3`).
519
+ * @category AST
181
520
  */
182
- export declare function containsDice(node: ASTNode): boolean;
521
+ export declare function isDieBound(node: ASTNode): node is DieBoundNode;
183
522
  //# sourceMappingURL=ast.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ast.d.ts","sourceRoot":"","sources":["../../src/parser/ast.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ast.d.ts","sourceRoot":"","sources":["../../src/parser/ast.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ export function isLiteral(node) {
2
+ return node.type === 'Literal';
3
+ }
4
+ export function isDice(node) {
5
+ return node.type === 'Dice';
6
+ }
7
+ export function isFateDice(node) {
8
+ return node.type === 'FateDice';
9
+ }
10
+ export function isBinaryOp(node) {
11
+ return node.type === 'BinaryOp';
12
+ }
13
+ export function isUnaryOp(node) {
14
+ return node.type === 'UnaryOp';
15
+ }
16
+ export function isKeepDrop(node) {
17
+ return node.type === 'KeepDrop';
18
+ }
19
+ export function isExplode(node) {
20
+ return node.type === 'Explode';
21
+ }
22
+ export function isReroll(node) {
23
+ return node.type === 'Reroll';
24
+ }
25
+ export function isSuccessCount(node) {
26
+ return node.type === 'SuccessCount';
27
+ }
28
+ export function isVersus(node) {
29
+ return node.type === 'Versus';
30
+ }
31
+ export function isFunctionCall(node) {
32
+ return node.type === 'FunctionCall';
33
+ }
34
+ export function isGrouped(node) {
35
+ return node.type === 'Grouped';
36
+ }
37
+ export function isVariable(node) {
38
+ return node.type === 'Variable';
39
+ }
40
+ export function isGroup(node) {
41
+ return node.type === 'Group';
42
+ }
43
+ export function isSort(node) {
44
+ return node.type === 'Sort';
45
+ }
46
+ export function isCritThreshold(node) {
47
+ return node.type === 'CritThreshold';
48
+ }
49
+ export function isDieBound(node) {
50
+ return node.type === 'DieBound';
51
+ }
52
+ //# sourceMappingURL=ast.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast.js","sourceRoot":"","sources":["../../src/parser/ast.ts"],"names":[],"mappings":"AA+ZA,MAAM,UAAU,SAAS,CAAC,IAAa;IACrC,OAAO,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC;AACjC,CAAC;AAUD,MAAM,UAAU,MAAM,CAAC,IAAa;IAClC,OAAO,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC;AAC9B,CAAC;AAUD,MAAM,UAAU,UAAU,CAAC,IAAa;IACtC,OAAO,IAAI,CAAC,IAAI,KAAK,UAAU,CAAC;AAClC,CAAC;AAUD,MAAM,UAAU,UAAU,CAAC,IAAa;IACtC,OAAO,IAAI,CAAC,IAAI,KAAK,UAAU,CAAC;AAClC,CAAC;AAUD,MAAM,UAAU,SAAS,CAAC,IAAa;IACrC,OAAO,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC;AACjC,CAAC;AAUD,MAAM,UAAU,UAAU,CAAC,IAAa;IACtC,OAAO,IAAI,CAAC,IAAI,KAAK,UAAU,CAAC;AAClC,CAAC;AAUD,MAAM,UAAU,SAAS,CAAC,IAAa;IACrC,OAAO,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC;AACjC,CAAC;AAUD,MAAM,UAAU,QAAQ,CAAC,IAAa;IACpC,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC;AAChC,CAAC;AAUD,MAAM,UAAU,cAAc,CAAC,IAAa;IAC1C,OAAO,IAAI,CAAC,IAAI,KAAK,cAAc,CAAC;AACtC,CAAC;AAUD,MAAM,UAAU,QAAQ,CAAC,IAAa;IACpC,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC;AAChC,CAAC;AAUD,MAAM,UAAU,cAAc,CAAC,IAAa;IAC1C,OAAO,IAAI,CAAC,IAAI,KAAK,cAAc,CAAC;AACtC,CAAC;AAUD,MAAM,UAAU,SAAS,CAAC,IAAa;IACrC,OAAO,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC;AACjC,CAAC;AAUD,MAAM,UAAU,UAAU,CAAC,IAAa;IACtC,OAAO,IAAI,CAAC,IAAI,KAAK,UAAU,CAAC;AAClC,CAAC;AAUD,MAAM,UAAU,OAAO,CAAC,IAAa;IACnC,OAAO,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC;AAC/B,CAAC;AAUD,MAAM,UAAU,MAAM,CAAC,IAAa;IAClC,OAAO,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC;AAC9B,CAAC;AAUD,MAAM,UAAU,eAAe,CAAC,IAAa;IAC3C,OAAO,IAAI,CAAC,IAAI,KAAK,eAAe,CAAC;AACvC,CAAC;AAUD,MAAM,UAAU,UAAU,CAAC,IAAa;IACtC,OAAO,IAAI,CAAC,IAAI,KAAK,UAAU,CAAC;AAClC,CAAC"}