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.
- package/CHANGELOG.md +189 -0
- package/MIGRATION.md +147 -0
- package/README.md +985 -43
- package/dist/cli/args.d.ts +1 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +81 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/format.d.ts +16 -4
- package/dist/cli/format.d.ts.map +1 -1
- package/dist/cli/format.js +17 -0
- package/dist/cli/format.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +14 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/main.d.ts +36 -0
- package/dist/cli/main.d.ts.map +1 -0
- package/dist/cli/main.js +83 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/errors.d.ts +332 -14
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +141 -0
- package/dist/errors.js.map +1 -0
- package/dist/evaluator/die.d.ts +26 -0
- package/dist/evaluator/die.d.ts.map +1 -0
- package/dist/evaluator/die.js +19 -0
- package/dist/evaluator/die.js.map +1 -0
- package/dist/evaluator/env.d.ts +58 -0
- package/dist/evaluator/env.d.ts.map +1 -0
- package/dist/evaluator/env.js +11 -0
- package/dist/evaluator/env.js.map +1 -0
- package/dist/evaluator/evaluator.d.ts +62 -40
- package/dist/evaluator/evaluator.d.ts.map +1 -1
- package/dist/evaluator/evaluator.js +906 -0
- package/dist/evaluator/evaluator.js.map +1 -0
- package/dist/evaluator/modifiers/compare.d.ts +1 -1
- package/dist/evaluator/modifiers/compare.d.ts.map +1 -1
- package/dist/evaluator/modifiers/compare.js +15 -0
- package/dist/evaluator/modifiers/compare.js.map +1 -0
- package/dist/evaluator/modifiers/crit-threshold.d.ts +27 -0
- package/dist/evaluator/modifiers/crit-threshold.d.ts.map +1 -0
- package/dist/evaluator/modifiers/crit-threshold.js +23 -0
- package/dist/evaluator/modifiers/crit-threshold.js.map +1 -0
- package/dist/evaluator/modifiers/die-bound.d.ts +26 -0
- package/dist/evaluator/modifiers/die-bound.d.ts.map +1 -0
- package/dist/evaluator/modifiers/die-bound.js +14 -0
- package/dist/evaluator/modifiers/die-bound.js.map +1 -0
- package/dist/evaluator/modifiers/explode.d.ts +18 -6
- package/dist/evaluator/modifiers/explode.d.ts.map +1 -1
- package/dist/evaluator/modifiers/explode.js +103 -0
- package/dist/evaluator/modifiers/explode.js.map +1 -0
- package/dist/evaluator/modifiers/flags.d.ts +37 -0
- package/dist/evaluator/modifiers/flags.d.ts.map +1 -0
- package/dist/evaluator/modifiers/flags.js +18 -0
- package/dist/evaluator/modifiers/flags.js.map +1 -0
- package/dist/evaluator/modifiers/keep-drop.d.ts +12 -28
- package/dist/evaluator/modifiers/keep-drop.d.ts.map +1 -1
- package/dist/evaluator/modifiers/keep-drop.js +82 -0
- package/dist/evaluator/modifiers/keep-drop.js.map +1 -0
- package/dist/evaluator/modifiers/reroll.d.ts +14 -6
- package/dist/evaluator/modifiers/reroll.d.ts.map +1 -1
- package/dist/evaluator/modifiers/reroll.js +62 -0
- package/dist/evaluator/modifiers/reroll.js.map +1 -0
- package/dist/evaluator/modifiers/sort.d.ts +27 -0
- package/dist/evaluator/modifiers/sort.d.ts.map +1 -0
- package/dist/evaluator/modifiers/sort.js +13 -0
- package/dist/evaluator/modifiers/sort.js.map +1 -0
- package/dist/evaluator/modifiers/success-count.d.ts +2 -6
- package/dist/evaluator/modifiers/success-count.d.ts.map +1 -1
- package/dist/evaluator/modifiers/success-count.js +24 -0
- package/dist/evaluator/modifiers/success-count.js.map +1 -0
- package/dist/index.d.ts +35 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -1723
- package/dist/index.js.map +1 -0
- package/dist/lexer/lexer.d.ts +68 -8
- package/dist/lexer/lexer.d.ts.map +1 -1
- package/dist/lexer/lexer.js +260 -0
- package/dist/lexer/lexer.js.map +1 -0
- package/dist/lexer/tokens.d.ts +52 -7
- package/dist/lexer/tokens.d.ts.map +1 -1
- package/dist/lexer/tokens.js +42 -0
- package/dist/lexer/tokens.js.map +1 -0
- package/dist/parser/ast.d.ts +419 -80
- package/dist/parser/ast.d.ts.map +1 -1
- package/dist/parser/ast.js +52 -0
- package/dist/parser/ast.js.map +1 -0
- package/dist/parser/guards.d.ts +106 -0
- package/dist/parser/guards.d.ts.map +1 -0
- package/dist/parser/guards.js +121 -0
- package/dist/parser/guards.js.map +1 -0
- package/dist/parser/parser.d.ts +162 -15
- package/dist/parser/parser.d.ts.map +1 -1
- package/dist/parser/parser.js +751 -0
- package/dist/parser/parser.js.map +1 -0
- package/dist/rng/mock.d.ts +74 -13
- package/dist/rng/mock.d.ts.map +1 -1
- package/dist/rng/mock.js +30 -0
- package/dist/rng/mock.js.map +1 -0
- package/dist/rng/seeded.d.ts +149 -10
- package/dist/rng/seeded.d.ts.map +1 -1
- package/dist/rng/seeded.js +138 -0
- package/dist/rng/seeded.js.map +1 -0
- package/dist/rng/types.d.ts +57 -0
- package/dist/rng/types.d.ts.map +1 -1
- package/dist/rng/types.js +2 -0
- package/dist/rng/types.js.map +1 -0
- package/dist/roll.d.ts +59 -25
- package/dist/roll.d.ts.map +1 -1
- package/dist/roll.js +8 -0
- package/dist/roll.js.map +1 -0
- package/dist/testing.d.ts +5 -4
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +2 -38
- package/dist/testing.js.map +1 -0
- package/dist/types.d.ts +427 -24
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +2 -0
- package/dist/version.js.map +1 -0
- package/package.json +93 -40
- package/src/cli/args.ts +66 -9
- package/src/cli/format.ts +30 -7
- package/src/cli/index.ts +27 -67
- package/src/cli/main.ts +129 -0
- package/src/errors.ts +488 -23
- package/src/evaluator/die.ts +50 -0
- package/src/evaluator/env.ts +73 -0
- package/src/evaluator/evaluator.ts +1296 -349
- package/src/evaluator/modifiers/compare.ts +1 -1
- package/src/evaluator/modifiers/crit-threshold.ts +56 -0
- package/src/evaluator/modifiers/die-bound.ts +39 -0
- package/src/evaluator/modifiers/explode.ts +82 -76
- package/src/evaluator/modifiers/flags.ts +61 -0
- package/src/evaluator/modifiers/keep-drop.ts +124 -126
- package/src/evaluator/modifiers/reroll.ts +36 -64
- package/src/evaluator/modifiers/sort.ts +43 -0
- package/src/evaluator/modifiers/success-count.ts +6 -9
- package/src/index.ts +73 -34
- package/src/lexer/lexer.ts +201 -35
- package/src/lexer/tokens.ts +72 -7
- package/src/parser/ast.ts +453 -104
- package/src/parser/guards.ts +248 -0
- package/src/parser/parser.ts +835 -135
- package/src/rng/mock.ts +75 -14
- package/src/rng/seeded.ts +323 -58
- package/src/rng/types.ts +57 -0
- package/src/roll.ts +66 -41
- package/src/testing.ts +5 -9
- package/src/types.ts +416 -24
- package/src/version.ts +2 -0
- package/dist/cli.js +0 -1775
- package/dist/evaluator/index.d.ts +0 -8
- package/dist/evaluator/index.d.ts.map +0 -1
- package/dist/index.mjs +0 -1724
- package/dist/rng/index.d.ts +0 -8
- package/dist/rng/index.d.ts.map +0 -1
- package/dist/testing.mjs +0 -39
- package/src/evaluator/index.ts +0 -14
- 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"}
|
package/dist/lexer/lexer.d.ts
CHANGED
|
@@ -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
|
-
*
|
|
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
|
|
66
|
-
*
|
|
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
|
-
* //
|
|
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,
|
|
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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"}
|
package/dist/lexer/tokens.d.ts
CHANGED
|
@@ -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
|
-
/**
|
|
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 =
|
|
94
|
+
EOF = 37
|
|
75
95
|
}
|
|
76
96
|
/**
|
|
77
|
-
* A token produced by the
|
|
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
|
|
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
|
|
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"}
|