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 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,OAAO,EACL,YAAY,EACZ,eAAe,EACf,iBAAiB,EACjB,oBAAoB,EACpB,uBAAuB,EACvB,eAAe,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,gBAAgB,EAChB,8BAA8B,EAC9B,6BAA6B,EAC7B,cAAc,EACd,QAAQ,GACT,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAuB9C,OAAO,EACL,UAAU,EACV,eAAe,EACf,MAAM,EACN,UAAU,EACV,SAAS,EACT,UAAU,EACV,cAAc,EACd,OAAO,EACP,SAAS,EACT,UAAU,EACV,SAAS,EACT,QAAQ,EACR,MAAM,EACN,cAAc,EACd,SAAS,EACT,UAAU,EACV,QAAQ,GACT,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAExE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAgBjC,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAqB7C,MAAM,CAAC,MAAM,OAAO,GAAW,OAAO,CAAC"}
@@ -3,16 +3,45 @@
3
3
  *
4
4
  * @module lexer/lexer
5
5
  */
6
- import type { RollParserErrorCode } from '../errors';
7
- import { RollParserError } from '../errors';
8
- import { type Token } from './tokens';
6
+ import type { RollParserErrorCode } from '../errors.js';
7
+ import { RollParserError } from '../errors.js';
8
+ import { type Token } from './tokens.js';
9
9
  /**
10
10
  * Error thrown when the lexer encounters an invalid character.
11
+ *
12
+ * `position` is a zero-based UTF-16 offset into the input. It is deliberately
13
+ * absent from `message` — read it from the field, or uniformly across all
14
+ * roll-parser errors via `getErrorSpan`.
15
+ *
16
+ * Codes: `UNEXPECTED_CHARACTER` for a character that cannot start any token,
17
+ * `UNEXPECTED_IDENTIFIER` for a word that is not a known keyword.
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * import { LexerError, roll } from 'roll-parser';
22
+ *
23
+ * try {
24
+ * roll('2d6+&');
25
+ * } catch (error) {
26
+ * const typed = error as LexerError;
27
+ * typed.code; // 'UNEXPECTED_CHARACTER'
28
+ * typed.character; // '&'
29
+ * typed.position; // 4
30
+ * }
31
+ * ```
32
+ *
33
+ * @category Errors
11
34
  */
12
35
  export declare class LexerError extends RollParserError {
36
+ /** Zero-based UTF-16 offset of the offending character in the input. */
13
37
  readonly position: number;
38
+ /**
39
+ * The offending text — a single character for `UNEXPECTED_CHARACTER` (the
40
+ * whole code point, so astral symbols are not split into surrogates), or
41
+ * the unrecognized word for `UNEXPECTED_IDENTIFIER`.
42
+ */
14
43
  readonly character: string;
15
- constructor(message: string, code: RollParserErrorCode, position: number, character: string);
44
+ constructor(message: string, code: RollParserErrorCode, position: number, character: string, options?: ErrorOptions);
16
45
  }
17
46
  /**
18
47
  * Lexer for dice notation.
@@ -47,6 +76,19 @@ export declare class Lexer {
47
76
  * accumulation loop stops naturally and the post-loop check handles it.
48
77
  */
49
78
  private scanIdentifier;
79
+ /**
80
+ * Scans a variable reference introduced by `@`.
81
+ *
82
+ * Two forms:
83
+ * - Bare: `@name` where `name` matches `[A-Za-z_][A-Za-z0-9_]*` (case preserved).
84
+ * - Braced: `@{name}` where `name` is any run of printable characters except
85
+ * `}` and newline (permits spaces, hyphens, digits).
86
+ *
87
+ * Case is preserved — distinct from `scanIdentifier`, which lowercases the
88
+ * captured value. The emitted token's `value` is the variable name without
89
+ * the leading `@` or the surrounding braces.
90
+ */
91
+ private scanAt;
50
92
  private peek;
51
93
  private peekNext;
52
94
  private advance;
@@ -54,22 +96,40 @@ export declare class Lexer {
54
96
  private isAtEnd;
55
97
  private isDigit;
56
98
  private isAlpha;
99
+ private isIdentifierStart;
100
+ private isIdentifierPart;
57
101
  private isWhitespace;
58
102
  private createToken;
59
103
  private createTokenAt;
60
104
  }
61
105
  /**
62
- * Tokenize a dice notation string.
106
+ * Tokenizes a dice notation string. The first stage of the pipeline —
107
+ * {@link parse} calls it for you; reach for `lex` directly only to build a
108
+ * syntax highlighter or an editor integration.
109
+ *
110
+ * Notation is case-insensitive and whitespace-tolerant: `2D20 + 5` and
111
+ * `2d20+5` produce the same tokens, and identifier tokens carry a lowercased
112
+ * `value`. The one exception is `@name`, whose case is preserved.
63
113
  *
64
114
  * @param input - The dice notation to tokenize
65
- * @returns Array of tokens including EOF
66
- * @throws {LexerError} If an invalid character is encountered
115
+ * @returns Every token in source order, always ending with one
116
+ * `TokenType.EOF` token
117
+ * @throws {LexerError} If an invalid character or unknown identifier is found
118
+ * @throws {RollParserError} `INVALID_NOTATION_TYPE` when `input` is not a
119
+ * string — raised before scanning, so it carries no position
67
120
  *
68
121
  * @example
69
122
  * ```typescript
123
+ * import { lex, TokenType } from 'roll-parser';
124
+ *
70
125
  * const tokens = lex('2d20+5');
71
- * // [NUMBER(2), DICE, NUMBER(20), PLUS, NUMBER(5), EOF]
126
+ * tokens.length; // 6 — NUMBER DICE NUMBER PLUS NUMBER EOF
127
+ * tokens[0]; // { type: TokenType.NUMBER, value: '2', position: 0, end: 1 }
128
+ * tokens[1].type === TokenType.DICE; // true
129
+ * tokens.at(-1)?.type === TokenType.EOF; // true
72
130
  * ```
131
+ *
132
+ * @category Core
73
133
  */
74
134
  export declare function lex(input: string): Token[];
75
135
  //# sourceMappingURL=lexer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"lexer.d.ts","sourceRoot":"","sources":["../../src/lexer/lexer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,KAAK,KAAK,EAAa,MAAM,UAAU,CAAC;AAEjD;;GAEG;AACH,qBAAa,UAAW,SAAQ,eAAe;IAC7C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;gBAEf,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;CAM5F;AAsBD;;;;;GAKG;AACH,qBAAa,KAAK;IAChB,OAAO,CAAC,GAAG,CAAK;IAChB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;gBAEnB,KAAK,EAAE,MAAM;IAIzB;;OAEG;IACH,QAAQ,IAAI,KAAK,EAAE;IAYnB;;OAEG;IACH,SAAS,IAAI,KAAK;IAyElB,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,UAAU;IAoBlB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,cAAc;IAgCtB,OAAO,CAAC,IAAI;IAIZ,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,KAAK;IAOb,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,OAAO;IAKf,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,aAAa;CAGtB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,EAAE,CAE1C"}
1
+ {"version":3,"file":"lexer.d.ts","sourceRoot":"","sources":["../../src/lexer/lexer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAAiB,eAAe,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,KAAK,KAAK,EAAa,MAAM,aAAa,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBAAa,UAAW,SAAQ,eAAe;IAC7C,wEAAwE;IACxE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAE3B,YACE,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,mBAAmB,EACzB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,YAAY,EAMvB;CACF;AA0DD;;;;;GAKG;AACH,qBAAa,KAAK;IAChB,OAAO,CAAC,GAAG,CAAK;IAChB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAE/B,YAAY,KAAK,EAAE,MAAM,EAExB;IAED;;OAEG;IACH,QAAQ,IAAI,KAAK,EAAE,CAUlB;IAED;;OAEG;IACH,SAAS,IAAI,KAAK,CA8EjB;IAMD,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,UAAU;IAiBlB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,cAAc;IAkCtB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,MAAM;IA+Bd,OAAO,CAAC,IAAI;IAIZ,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,KAAK;IAOb,OAAO,CAAC,OAAO;IAMf,OAAO,CAAC,OAAO;IAKf,OAAO,CAAC,OAAO;IAQf,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,aAAa;CAGtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,EAAE,CAU1C"}
@@ -0,0 +1,260 @@
1
+ import { describeValue, RollParserError } from '../errors.js';
2
+ import { TokenType } from './tokens.js';
3
+ export class LexerError extends RollParserError {
4
+ position;
5
+ character;
6
+ constructor(message, code, position, character, options) {
7
+ super(`${message}: '${character}'`, code, options);
8
+ this.name = 'LexerError';
9
+ this.position = position;
10
+ this.character = character;
11
+ }
12
+ }
13
+ const CHAR_DIGIT_0 = 48;
14
+ const CHAR_DIGIT_9 = 57;
15
+ const CHAR_UPPER_A = 65;
16
+ const CHAR_UPPER_Z = 90;
17
+ const CHAR_LOWER_A = 97;
18
+ const CHAR_LOWER_Z = 122;
19
+ const IDENTIFIER_KEYWORDS = {
20
+ kh: TokenType.KEEP_HIGH,
21
+ kl: TokenType.KEEP_LOW,
22
+ k: TokenType.KEEP_HIGH,
23
+ dh: TokenType.DROP_HIGH,
24
+ dl: TokenType.DROP_LOW,
25
+ d: TokenType.DICE,
26
+ r: TokenType.REROLL,
27
+ ro: TokenType.REROLL_ONCE,
28
+ f: TokenType.FAIL,
29
+ vs: TokenType.VS,
30
+ floor: TokenType.FUNCTION,
31
+ ceil: TokenType.FUNCTION,
32
+ round: TokenType.FUNCTION,
33
+ abs: TokenType.FUNCTION,
34
+ sqrt: TokenType.FUNCTION,
35
+ pow: TokenType.FUNCTION,
36
+ max: TokenType.FUNCTION,
37
+ min: TokenType.FUNCTION,
38
+ s: TokenType.SORT_ASC,
39
+ sa: TokenType.SORT_ASC,
40
+ sd: TokenType.SORT_DESC,
41
+ cs: TokenType.CRIT_SUCCESS,
42
+ cf: TokenType.CRIT_FAIL,
43
+ };
44
+ function buildIdentifierHint(identifier) {
45
+ for (let length = identifier.length - 1; length >= 1; length--) {
46
+ const prefix = identifier.slice(0, length);
47
+ if (IDENTIFIER_KEYWORDS[prefix] == null)
48
+ continue;
49
+ const rest = identifier.slice(length);
50
+ return ` (did you mean '${prefix}' followed by '${rest}'? separate modifiers with a count or space, e.g. '${prefix}1${rest}')`;
51
+ }
52
+ return '';
53
+ }
54
+ export class Lexer {
55
+ pos = 0;
56
+ input;
57
+ constructor(input) {
58
+ this.input = input;
59
+ }
60
+ tokenize() {
61
+ const tokens = [];
62
+ while (true) {
63
+ const token = this.nextToken();
64
+ tokens.push(token);
65
+ if (token.type === TokenType.EOF)
66
+ break;
67
+ }
68
+ return tokens;
69
+ }
70
+ nextToken() {
71
+ this.skipWhitespace();
72
+ if (this.isAtEnd()) {
73
+ return this.createToken(TokenType.EOF, '');
74
+ }
75
+ const startPos = this.pos;
76
+ const char = this.peek();
77
+ if (this.isDigit(char)) {
78
+ return this.scanNumber();
79
+ }
80
+ if (this.isAlpha(char)) {
81
+ return this.scanIdentifier();
82
+ }
83
+ if (char === '@') {
84
+ return this.scanAt();
85
+ }
86
+ this.advance();
87
+ switch (char) {
88
+ case '+':
89
+ return this.createTokenAt(TokenType.PLUS, char, startPos);
90
+ case '-':
91
+ return this.createTokenAt(TokenType.MINUS, char, startPos);
92
+ case '*':
93
+ if (this.match('*')) {
94
+ return this.createTokenAt(TokenType.POWER, '**', startPos);
95
+ }
96
+ return this.createTokenAt(TokenType.MULTIPLY, char, startPos);
97
+ case '/':
98
+ return this.createTokenAt(TokenType.DIVIDE, char, startPos);
99
+ case '%':
100
+ return this.createTokenAt(TokenType.MODULO, char, startPos);
101
+ case '^':
102
+ return this.createTokenAt(TokenType.POWER, char, startPos);
103
+ case '(':
104
+ return this.createTokenAt(TokenType.LPAREN, char, startPos);
105
+ case ')':
106
+ return this.createTokenAt(TokenType.RPAREN, char, startPos);
107
+ case ',':
108
+ return this.createTokenAt(TokenType.COMMA, char, startPos);
109
+ case '{':
110
+ return this.createTokenAt(TokenType.LBRACE, char, startPos);
111
+ case '}':
112
+ return this.createTokenAt(TokenType.RBRACE, char, startPos);
113
+ case '>':
114
+ if (this.match('=')) {
115
+ return this.createTokenAt(TokenType.GREATER_EQUAL, '>=', startPos);
116
+ }
117
+ return this.createTokenAt(TokenType.GREATER, char, startPos);
118
+ case '<':
119
+ if (this.match('=')) {
120
+ return this.createTokenAt(TokenType.LESS_EQUAL, '<=', startPos);
121
+ }
122
+ return this.createTokenAt(TokenType.LESS, char, startPos);
123
+ case '=':
124
+ return this.createTokenAt(TokenType.EQUAL, char, startPos);
125
+ case '!':
126
+ if (this.match('!')) {
127
+ return this.createTokenAt(TokenType.EXPLODE_COMPOUND, '!!', startPos);
128
+ }
129
+ if (this.match('p') || this.match('P')) {
130
+ return this.createTokenAt(TokenType.EXPLODE_PENETRATING, '!p', startPos);
131
+ }
132
+ return this.createTokenAt(TokenType.EXPLODE, char, startPos);
133
+ default: {
134
+ const codePoint = this.input.codePointAt(startPos);
135
+ const display = codePoint == null ? char : String.fromCodePoint(codePoint);
136
+ throw new LexerError('Unexpected character', 'UNEXPECTED_CHARACTER', startPos, display);
137
+ }
138
+ }
139
+ }
140
+ skipWhitespace() {
141
+ while (!this.isAtEnd() && this.isWhitespace(this.peek())) {
142
+ this.advance();
143
+ }
144
+ }
145
+ scanNumber() {
146
+ const startPos = this.pos;
147
+ while (!this.isAtEnd() && this.isDigit(this.peek())) {
148
+ this.pos++;
149
+ }
150
+ if (!this.isAtEnd() && this.peek() === '.' && this.isDigit(this.peekNext())) {
151
+ this.pos++;
152
+ while (!this.isAtEnd() && this.isDigit(this.peek())) {
153
+ this.pos++;
154
+ }
155
+ }
156
+ return this.createTokenAt(TokenType.NUMBER, this.input.slice(startPos, this.pos), startPos);
157
+ }
158
+ scanIdentifier() {
159
+ const startPos = this.pos;
160
+ const first = this.peek();
161
+ const second = this.peekNext();
162
+ if ((first === 'd' || first === 'D') && (second === 'f' || second === 'F')) {
163
+ this.pos += 2;
164
+ return this.createTokenAt(TokenType.DICE_FATE, 'df', startPos);
165
+ }
166
+ while (!this.isAtEnd() && this.isAlpha(this.peek())) {
167
+ this.pos++;
168
+ }
169
+ const lower = this.input.slice(startPos, this.pos).toLowerCase();
170
+ if (lower === 'd' && !this.isAtEnd() && this.peek() === '%') {
171
+ this.advance();
172
+ return this.createTokenAt(TokenType.DICE_PERCENT, 'd%', startPos);
173
+ }
174
+ const tokenType = IDENTIFIER_KEYWORDS[lower];
175
+ if (tokenType != null) {
176
+ return this.createTokenAt(tokenType, lower, startPos);
177
+ }
178
+ throw new LexerError(`Unexpected identifier${buildIdentifierHint(lower)}`, 'UNEXPECTED_IDENTIFIER', startPos, lower);
179
+ }
180
+ scanAt() {
181
+ const startPos = this.pos;
182
+ this.advance();
183
+ let name;
184
+ if (!this.isAtEnd() && this.peek() === '{') {
185
+ this.advance();
186
+ const nameStart = this.pos;
187
+ while (!this.isAtEnd() && this.peek() !== '}' && this.peek() !== '\n') {
188
+ this.advance();
189
+ }
190
+ if (this.isAtEnd() || this.peek() !== '}') {
191
+ throw new LexerError('Unterminated @{...} variable', 'UNEXPECTED_CHARACTER', startPos, '@');
192
+ }
193
+ name = this.input.slice(nameStart, this.pos);
194
+ this.advance();
195
+ }
196
+ else {
197
+ const nameStart = this.pos;
198
+ if (this.isAtEnd() || !this.isIdentifierStart(this.peek())) {
199
+ throw new LexerError('Empty @ variable name', 'UNEXPECTED_CHARACTER', startPos, '@');
200
+ }
201
+ this.advance();
202
+ while (!this.isAtEnd() && this.isIdentifierPart(this.peek())) {
203
+ this.advance();
204
+ }
205
+ name = this.input.slice(nameStart, this.pos);
206
+ }
207
+ return this.createTokenAt(TokenType.AT, name, startPos);
208
+ }
209
+ peek() {
210
+ return this.input[this.pos] ?? '';
211
+ }
212
+ peekNext() {
213
+ return this.input[this.pos + 1] ?? '';
214
+ }
215
+ advance() {
216
+ return this.input[this.pos++] ?? '';
217
+ }
218
+ match(expected) {
219
+ if (this.isAtEnd())
220
+ return false;
221
+ if (this.input[this.pos] !== expected)
222
+ return false;
223
+ this.pos++;
224
+ return true;
225
+ }
226
+ isAtEnd() {
227
+ return this.pos >= this.input.length;
228
+ }
229
+ isDigit(char) {
230
+ const code = char.charCodeAt(0);
231
+ return code >= CHAR_DIGIT_0 && code <= CHAR_DIGIT_9;
232
+ }
233
+ isAlpha(char) {
234
+ const code = char.charCodeAt(0);
235
+ return ((code >= CHAR_LOWER_A && code <= CHAR_LOWER_Z) ||
236
+ (code >= CHAR_UPPER_A && code <= CHAR_UPPER_Z));
237
+ }
238
+ isIdentifierStart(char) {
239
+ return this.isAlpha(char) || char === '_';
240
+ }
241
+ isIdentifierPart(char) {
242
+ return this.isAlpha(char) || this.isDigit(char) || char === '_';
243
+ }
244
+ isWhitespace(char) {
245
+ return char === ' ' || char === '\t' || char === '\n' || char === '\r';
246
+ }
247
+ createToken(type, value) {
248
+ return { type, value, position: this.pos, end: this.pos };
249
+ }
250
+ createTokenAt(type, value, position) {
251
+ return { type, value, position, end: this.pos };
252
+ }
253
+ }
254
+ export function lex(input) {
255
+ if (typeof input !== 'string') {
256
+ throw new RollParserError(`Notation must be a string, received ${describeValue(input)}`, 'INVALID_NOTATION_TYPE');
257
+ }
258
+ return new Lexer(input).tokenize();
259
+ }
260
+ //# sourceMappingURL=lexer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lexer.js","sourceRoot":"","sources":["../../src/lexer/lexer.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,8 @@
8
8
  *
9
9
  * Grouped semantically. Numeric values are stable identifiers — the specific
10
10
  * numbers don't matter, but they must be unique.
11
+ *
12
+ * @category AST
11
13
  */
12
14
  export declare enum TokenType {
13
15
  /** Numeric literal: integer or decimal */
@@ -66,22 +68,65 @@ export declare enum TokenType {
66
68
  REROLL_ONCE = 26,
67
69
  /** Fail marker: 'f' */
68
70
  FAIL = 27,
69
- /** Math function: 'floor', 'ceil', 'round', 'abs', 'max', 'min' */
71
+ /**
72
+ * Math function: 'floor', 'ceil', 'round', 'abs', 'sqrt', 'pow', 'max',
73
+ * 'min'. In postfix position, 'min'/'max' double as per-die clamp
74
+ * modifiers (`4d6min2`) — the parser decides by position, not the lexer.
75
+ */
70
76
  FUNCTION = 28,
71
77
  /** Versus operator: 'vs' */
72
78
  VS = 29,
79
+ /** Left brace: '{' */
80
+ LBRACE = 30,
81
+ /** Right brace: '}' */
82
+ RBRACE = 31,
83
+ /** Variable reference prefix: '@' */
84
+ AT = 32,
85
+ /** Ascending sort: 's' or 'sa' */
86
+ SORT_ASC = 33,
87
+ /** Descending sort: 'sd' */
88
+ SORT_DESC = 34,
89
+ /** Critical success threshold: 'cs' */
90
+ CRIT_SUCCESS = 35,
91
+ /** Critical failure threshold: 'cf' */
92
+ CRIT_FAIL = 36,
73
93
  /** End of input marker */
74
- EOF = 30
94
+ EOF = 37
75
95
  }
76
96
  /**
77
- * A token produced by the lexer.
97
+ * A token produced by {@link lex}: what it is, the text it came from, and
98
+ * where in the input that text sits.
99
+ *
100
+ * `position`/`end` are a half-open range, so `input.slice(position, end)`
101
+ * recovers the original source text — useful for syntax highlighting, where
102
+ * `value` alone is lossy.
103
+ *
104
+ * @example
105
+ * ```typescript
106
+ * import { lex, TokenType } from 'roll-parser';
107
+ *
108
+ * const input = '4D6KH3';
109
+ * const tokens = lex(input);
110
+ * tokens[1]; // { type: TokenType.DICE, value: 'd', position: 1, end: 2 }
111
+ * tokens[3].type === TokenType.KEEP_HIGH; // true
112
+ * input.slice(tokens[3].position, tokens[3].end); // 'KH' — original casing
113
+ * tokens[3].value; // 'kh' — normalized
114
+ * ```
115
+ *
116
+ * @category AST
78
117
  */
79
118
  export type Token = {
80
119
  /** The type of this token */
81
- type: TokenType;
120
+ readonly type: TokenType;
82
121
  /** The raw string value from input (lowercased for identifiers) */
83
- value: string;
84
- /** Zero-based position in the input string */
85
- position: number;
122
+ readonly value: string;
123
+ /** Zero-based start offset in the input string (UTF-16 code units) */
124
+ readonly position: number;
125
+ /**
126
+ * Zero-based end offset (exclusive). Not always `position + value.length` —
127
+ * braced variables (`@{name}` stores only `name`) and case-normalized
128
+ * identifiers consume more input than their `value` retains.
129
+ */
130
+ readonly end: number;
86
131
  };
87
132
  //# sourceMappingURL=tokens.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/lexer/tokens.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;GAKG;AACH,oBAAY,SAAS;IAKnB,0CAA0C;IAC1C,MAAM,IAAI;IAMV,gCAAgC;IAChC,IAAI,IAAI;IACR,sDAAsD;IACtD,YAAY,IAAI;IAChB,qCAAqC;IACrC,SAAS,IAAI;IAMb,6BAA6B;IAC7B,IAAI,IAAI;IACR,gCAAgC;IAChC,KAAK,IAAI;IACT,mCAAmC;IACnC,QAAQ,IAAI;IACZ,6BAA6B;IAC7B,MAAM,IAAI;IACV,2BAA2B;IAC3B,MAAM,IAAI;IACV,kCAAkC;IAClC,KAAK,IAAI;IAMT,wBAAwB;IACxB,OAAO,KAAK;IACZ,kCAAkC;IAClC,aAAa,KAAK;IAClB,qBAAqB;IACrB,IAAI,KAAK;IACT,+BAA+B;IAC/B,UAAU,KAAK;IACf,iBAAiB;IACjB,KAAK,KAAK;IAMV,4BAA4B;IAC5B,MAAM,KAAK;IACX,6BAA6B;IAC7B,MAAM,KAAK;IACX,8BAA8B;IAC9B,KAAK,KAAK;IAMV,yCAAyC;IACzC,SAAS,KAAK;IACd,iCAAiC;IACjC,QAAQ,KAAK;IACb,kCAAkC;IAClC,SAAS,KAAK;IACd,iCAAiC;IACjC,QAAQ,KAAK;IAMb,4BAA4B;IAC5B,OAAO,KAAK;IACZ,gCAAgC;IAChC,gBAAgB,KAAK;IACrB,gCAAgC;IAChC,mBAAmB,KAAK;IAMxB,4BAA4B;IAC5B,MAAM,KAAK;IACX,wBAAwB;IACxB,WAAW,KAAK;IAMhB,uBAAuB;IACvB,IAAI,KAAK;IAMT,mEAAmE;IACnE,QAAQ,KAAK;IAMb,4BAA4B;IAC5B,EAAE,KAAK;IAMP,0BAA0B;IAC1B,GAAG,KAAK;CACT;AAED;;GAEG;AACH,MAAM,MAAM,KAAK,GAAG;IAClB,6BAA6B;IAC7B,IAAI,EAAE,SAAS,CAAC;IAChB,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;IACd,8CAA8C;IAC9C,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC"}
1
+ {"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/lexer/tokens.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;GAOG;AACH,oBAAY,SAAS;IAKnB,0CAA0C;IAC1C,MAAM,IAAI;IAMV,gCAAgC;IAChC,IAAI,IAAI;IACR,sDAAsD;IACtD,YAAY,IAAI;IAChB,qCAAqC;IACrC,SAAS,IAAI;IAMb,6BAA6B;IAC7B,IAAI,IAAI;IACR,gCAAgC;IAChC,KAAK,IAAI;IACT,mCAAmC;IACnC,QAAQ,IAAI;IACZ,6BAA6B;IAC7B,MAAM,IAAI;IACV,2BAA2B;IAC3B,MAAM,IAAI;IACV,kCAAkC;IAClC,KAAK,IAAI;IAMT,wBAAwB;IACxB,OAAO,KAAK;IACZ,kCAAkC;IAClC,aAAa,KAAK;IAClB,qBAAqB;IACrB,IAAI,KAAK;IACT,+BAA+B;IAC/B,UAAU,KAAK;IACf,iBAAiB;IACjB,KAAK,KAAK;IAMV,4BAA4B;IAC5B,MAAM,KAAK;IACX,6BAA6B;IAC7B,MAAM,KAAK;IACX,8BAA8B;IAC9B,KAAK,KAAK;IAMV,yCAAyC;IACzC,SAAS,KAAK;IACd,iCAAiC;IACjC,QAAQ,KAAK;IACb,kCAAkC;IAClC,SAAS,KAAK;IACd,iCAAiC;IACjC,QAAQ,KAAK;IAMb,4BAA4B;IAC5B,OAAO,KAAK;IACZ,gCAAgC;IAChC,gBAAgB,KAAK;IACrB,gCAAgC;IAChC,mBAAmB,KAAK;IAMxB,4BAA4B;IAC5B,MAAM,KAAK;IACX,wBAAwB;IACxB,WAAW,KAAK;IAMhB,uBAAuB;IACvB,IAAI,KAAK;IAMT;;;;OAIG;IACH,QAAQ,KAAK;IAMb,4BAA4B;IAC5B,EAAE,KAAK;IAMP,sBAAsB;IACtB,MAAM,KAAK;IACX,uBAAuB;IACvB,MAAM,KAAK;IAMX,qCAAqC;IACrC,EAAE,KAAK;IAMP,kCAAkC;IAClC,QAAQ,KAAK;IACb,4BAA4B;IAC5B,SAAS,KAAK;IAMd,uCAAuC;IACvC,YAAY,KAAK;IACjB,uCAAuC;IACvC,SAAS,KAAK;IAMd,0BAA0B;IAC1B,GAAG,KAAK;CACT;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,MAAM,KAAK,GAAG;IAClB,6BAA6B;IAC7B,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,mEAAmE;IACnE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB,CAAC"}
@@ -0,0 +1,42 @@
1
+ export var TokenType;
2
+ (function (TokenType) {
3
+ TokenType[TokenType["NUMBER"] = 0] = "NUMBER";
4
+ TokenType[TokenType["DICE"] = 1] = "DICE";
5
+ TokenType[TokenType["DICE_PERCENT"] = 2] = "DICE_PERCENT";
6
+ TokenType[TokenType["DICE_FATE"] = 3] = "DICE_FATE";
7
+ TokenType[TokenType["PLUS"] = 4] = "PLUS";
8
+ TokenType[TokenType["MINUS"] = 5] = "MINUS";
9
+ TokenType[TokenType["MULTIPLY"] = 6] = "MULTIPLY";
10
+ TokenType[TokenType["DIVIDE"] = 7] = "DIVIDE";
11
+ TokenType[TokenType["MODULO"] = 8] = "MODULO";
12
+ TokenType[TokenType["POWER"] = 9] = "POWER";
13
+ TokenType[TokenType["GREATER"] = 10] = "GREATER";
14
+ TokenType[TokenType["GREATER_EQUAL"] = 11] = "GREATER_EQUAL";
15
+ TokenType[TokenType["LESS"] = 12] = "LESS";
16
+ TokenType[TokenType["LESS_EQUAL"] = 13] = "LESS_EQUAL";
17
+ TokenType[TokenType["EQUAL"] = 14] = "EQUAL";
18
+ TokenType[TokenType["LPAREN"] = 15] = "LPAREN";
19
+ TokenType[TokenType["RPAREN"] = 16] = "RPAREN";
20
+ TokenType[TokenType["COMMA"] = 17] = "COMMA";
21
+ TokenType[TokenType["KEEP_HIGH"] = 18] = "KEEP_HIGH";
22
+ TokenType[TokenType["KEEP_LOW"] = 19] = "KEEP_LOW";
23
+ TokenType[TokenType["DROP_HIGH"] = 20] = "DROP_HIGH";
24
+ TokenType[TokenType["DROP_LOW"] = 21] = "DROP_LOW";
25
+ TokenType[TokenType["EXPLODE"] = 22] = "EXPLODE";
26
+ TokenType[TokenType["EXPLODE_COMPOUND"] = 23] = "EXPLODE_COMPOUND";
27
+ TokenType[TokenType["EXPLODE_PENETRATING"] = 24] = "EXPLODE_PENETRATING";
28
+ TokenType[TokenType["REROLL"] = 25] = "REROLL";
29
+ TokenType[TokenType["REROLL_ONCE"] = 26] = "REROLL_ONCE";
30
+ TokenType[TokenType["FAIL"] = 27] = "FAIL";
31
+ TokenType[TokenType["FUNCTION"] = 28] = "FUNCTION";
32
+ TokenType[TokenType["VS"] = 29] = "VS";
33
+ TokenType[TokenType["LBRACE"] = 30] = "LBRACE";
34
+ TokenType[TokenType["RBRACE"] = 31] = "RBRACE";
35
+ TokenType[TokenType["AT"] = 32] = "AT";
36
+ TokenType[TokenType["SORT_ASC"] = 33] = "SORT_ASC";
37
+ TokenType[TokenType["SORT_DESC"] = 34] = "SORT_DESC";
38
+ TokenType[TokenType["CRIT_SUCCESS"] = 35] = "CRIT_SUCCESS";
39
+ TokenType[TokenType["CRIT_FAIL"] = 36] = "CRIT_FAIL";
40
+ TokenType[TokenType["EOF"] = 37] = "EOF";
41
+ })(TokenType || (TokenType = {}));
42
+ //# sourceMappingURL=tokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../src/lexer/tokens.ts"],"names":[],"mappings":"AAcA,MAAM,CAAN,IAAY,SAgKX;AAhKD,WAAY,SAAS;IAMnB,6CAAU,CAAA;IAOV,yCAAQ,CAAA;IAER,yDAAgB,CAAA;IAEhB,mDAAa,CAAA;IAOb,yCAAQ,CAAA;IAER,2CAAS,CAAA;IAET,iDAAY,CAAA;IAEZ,6CAAU,CAAA;IAEV,6CAAU,CAAA;IAEV,2CAAS,CAAA;IAOT,gDAAY,CAAA;IAEZ,4DAAkB,CAAA;IAElB,0CAAS,CAAA;IAET,sDAAe,CAAA;IAEf,4CAAU,CAAA;IAOV,8CAAW,CAAA;IAEX,8CAAW,CAAA;IAEX,4CAAU,CAAA;IAOV,oDAAc,CAAA;IAEd,kDAAa,CAAA;IAEb,oDAAc,CAAA;IAEd,kDAAa,CAAA;IAOb,gDAAY,CAAA;IAEZ,kEAAqB,CAAA;IAErB,wEAAwB,CAAA;IAOxB,8CAAW,CAAA;IAEX,wDAAgB,CAAA;IAOhB,0CAAS,CAAA;IAWT,kDAAa,CAAA;IAOb,sCAAO,CAAA;IAOP,8CAAW,CAAA;IAEX,8CAAW,CAAA;IAOX,sCAAO,CAAA;IAOP,kDAAa,CAAA;IAEb,oDAAc,CAAA;IAOd,0DAAiB,CAAA;IAEjB,oDAAc,CAAA;IAOd,wCAAQ,CAAA;AACV,CAAC,EAhKW,SAAS,KAAT,SAAS,QAgKpB"}