@ansi-tools/parser 1.0.11 → 1.0.13

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 (48) hide show
  1. package/dist/constants.d.ts +56 -0
  2. package/dist/constants.d.ts.map +1 -0
  3. package/dist/constants.js +55 -0
  4. package/dist/escaped.d.ts +6 -10
  5. package/dist/escaped.d.ts.map +1 -0
  6. package/dist/escaped.js +4 -279
  7. package/dist/index.d.ts +5 -7
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +3 -3
  10. package/dist/parse.d.ts +4 -0
  11. package/dist/parse.d.ts.map +1 -0
  12. package/dist/parse.escaped.d.ts +3 -0
  13. package/dist/parse.escaped.d.ts.map +1 -0
  14. package/dist/parse.escaped.js +5 -0
  15. package/dist/parse.js +109 -0
  16. package/dist/parsers/apc.d.ts +3 -0
  17. package/dist/parsers/apc.d.ts.map +1 -0
  18. package/dist/parsers/apc.js +6 -0
  19. package/dist/parsers/csi.d.ts +3 -0
  20. package/dist/parsers/csi.d.ts.map +1 -0
  21. package/dist/parsers/csi.js +63 -0
  22. package/dist/parsers/dcs.d.ts +3 -0
  23. package/dist/parsers/dcs.d.ts.map +1 -0
  24. package/dist/parsers/dcs.js +26 -0
  25. package/dist/parsers/esc.d.ts +3 -0
  26. package/dist/parsers/esc.d.ts.map +1 -0
  27. package/dist/parsers/esc.js +8 -0
  28. package/dist/parsers/osc.d.ts +3 -0
  29. package/dist/parsers/osc.d.ts.map +1 -0
  30. package/dist/parsers/osc.js +28 -0
  31. package/dist/parsers/pm.d.ts +3 -0
  32. package/dist/parsers/pm.d.ts.map +1 -0
  33. package/dist/parsers/pm.js +6 -0
  34. package/dist/parsers/sos.d.ts +3 -0
  35. package/dist/parsers/sos.d.ts.map +1 -0
  36. package/dist/parsers/sos.js +6 -0
  37. package/dist/tokenize.d.ts +4 -0
  38. package/dist/tokenize.d.ts.map +1 -0
  39. package/dist/tokenize.escaped.d.ts +4 -0
  40. package/dist/tokenize.escaped.d.ts.map +1 -0
  41. package/dist/tokenize.escaped.js +295 -0
  42. package/dist/tokenize.js +314 -0
  43. package/dist/types.d.ts +23 -0
  44. package/dist/types.d.ts.map +1 -0
  45. package/dist/types.js +1 -0
  46. package/package.json +27 -28
  47. package/dist/parse-BzJl6pBN.d.ts +0 -85
  48. package/dist/parse-DBLatt5c.js +0 -532
@@ -0,0 +1,314 @@
1
+ import { APC, BACKSLASH, BACKSLASH_CODE, BELL, BELL_CODE, CAN, CSI, CSI_CODE, CSI_OPEN, DCS, ESC, ESC_CODE, OSC, OSC_CODE, OSC_OPEN, PM, SOS, ST, ST_CODE, STRING_OPENERS, SUB, TOKEN_TYPES, } from "./constants.js";
2
+ function isInterrupter(c) {
3
+ return (c === CAN || c === SUB || c === ESC || c === CSI || c === OSC || c === DCS || c === APC || c === PM || c === SOS);
4
+ }
5
+ function isC0Interrupter(c) {
6
+ return c === CAN || c === SUB;
7
+ }
8
+ function isSequenceStart(c) {
9
+ return c === ESC || c === CSI || c === OSC || c === DCS || c === APC || c === PM || c === SOS;
10
+ }
11
+ function is8BitIntroducer(c) {
12
+ return c === CSI || c === OSC || c === DCS || c === APC || c === PM || c === SOS;
13
+ }
14
+ export function* tokenizer(input) {
15
+ let i = 0;
16
+ let state = 0; // 0 = GROUND, 1 = SEQUENCE
17
+ let currentCode = 0;
18
+ const len = input.length;
19
+ while (i < len) {
20
+ if (state === 0) {
21
+ const textStart = i;
22
+ let charCode = input.charCodeAt(i);
23
+ while (i < len && !isSequenceStart(charCode)) {
24
+ charCode = input.charCodeAt(++i);
25
+ }
26
+ if (i > textStart) {
27
+ yield { type: TOKEN_TYPES.TEXT, pos: textStart, raw: input.substring(textStart, i) };
28
+ }
29
+ if (i >= len)
30
+ break;
31
+ if (is8BitIntroducer(charCode)) {
32
+ yield { type: TOKEN_TYPES.INTRODUCER, pos: i, raw: input[i], code: input[i] };
33
+ i++;
34
+ state = 1;
35
+ currentCode = charCode;
36
+ }
37
+ else {
38
+ // ESC
39
+ const nextCode = input.charCodeAt(i + 1);
40
+ if (nextCode === CSI_OPEN) {
41
+ yield { type: TOKEN_TYPES.INTRODUCER, pos: i, raw: input.substring(i, i + 2), code: CSI_CODE };
42
+ i += 2;
43
+ state = 1;
44
+ currentCode = CSI;
45
+ }
46
+ else if (nextCode === OSC_OPEN) {
47
+ yield { type: TOKEN_TYPES.INTRODUCER, pos: i, raw: input.substring(i, i + 2), code: OSC_CODE };
48
+ i += 2;
49
+ state = 1;
50
+ currentCode = OSC;
51
+ }
52
+ else if (i + 1 < len && STRING_OPENERS.has(input[i + 1])) {
53
+ yield { type: TOKEN_TYPES.INTRODUCER, pos: i, raw: input.substring(i, i + 2), code: input[i + 1] };
54
+ i += 2;
55
+ state = 1;
56
+ currentCode = nextCode;
57
+ }
58
+ else if (i + 1 < len) {
59
+ let j = i + 1;
60
+ while (j < len && input.charCodeAt(j) >= 0x20 && input.charCodeAt(j) <= 0x2f)
61
+ j++;
62
+ if (j < len) {
63
+ if (j > i + 1) {
64
+ const intermediate = input.substring(i + 1, j);
65
+ yield { type: TOKEN_TYPES.INTRODUCER, pos: i, raw: input.substring(i, j), code: ESC_CODE, intermediate };
66
+ }
67
+ else {
68
+ yield { type: TOKEN_TYPES.INTRODUCER, pos: i, raw: input[i], code: ESC_CODE };
69
+ }
70
+ i = j;
71
+ state = 1;
72
+ currentCode = ESC;
73
+ }
74
+ else {
75
+ i = j;
76
+ }
77
+ }
78
+ else {
79
+ i++;
80
+ }
81
+ }
82
+ }
83
+ else {
84
+ const pos = i;
85
+ if (currentCode === CSI) {
86
+ const dataStart = i;
87
+ while (i < len) {
88
+ const charCode = input.charCodeAt(i);
89
+ if (isInterrupter(charCode)) {
90
+ if (i > dataStart)
91
+ yield { type: TOKEN_TYPES.DATA, pos, raw: input.substring(dataStart, i) };
92
+ state = 0;
93
+ if (isC0Interrupter(charCode))
94
+ i++;
95
+ break;
96
+ }
97
+ if (charCode >= 0x40 && charCode <= 0x7e) {
98
+ if (i > dataStart)
99
+ yield { type: TOKEN_TYPES.DATA, pos, raw: input.substring(dataStart, i) };
100
+ yield { type: TOKEN_TYPES.FINAL, pos: i, raw: input[i] };
101
+ i++;
102
+ state = 0;
103
+ break;
104
+ }
105
+ i++;
106
+ }
107
+ }
108
+ else if (currentCode === ESC) {
109
+ if (i < len) {
110
+ const charCode = input.charCodeAt(i);
111
+ if (isInterrupter(charCode)) {
112
+ state = 0;
113
+ if (isC0Interrupter(charCode))
114
+ i++;
115
+ }
116
+ else {
117
+ yield { type: TOKEN_TYPES.FINAL, pos: i, raw: input[i] };
118
+ i++;
119
+ state = 0;
120
+ }
121
+ }
122
+ }
123
+ else {
124
+ const dataStart = i;
125
+ while (i < len) {
126
+ const charCode = input.charCodeAt(i);
127
+ let terminator;
128
+ if (charCode === ESC && input.charCodeAt(i + 1) === BACKSLASH) {
129
+ terminator = ESC_CODE + BACKSLASH_CODE;
130
+ }
131
+ else if (charCode === ST) {
132
+ terminator = ST_CODE;
133
+ }
134
+ else if (charCode === BELL && currentCode === OSC) {
135
+ terminator = BELL_CODE;
136
+ }
137
+ if (terminator) {
138
+ if (i > dataStart)
139
+ yield { type: TOKEN_TYPES.DATA, pos, raw: input.substring(dataStart, i) };
140
+ yield { type: TOKEN_TYPES.FINAL, pos: i, raw: terminator };
141
+ i += terminator.length;
142
+ state = 0;
143
+ break;
144
+ }
145
+ if (isInterrupter(charCode)) {
146
+ if (i > dataStart)
147
+ yield { type: TOKEN_TYPES.DATA, pos, raw: input.substring(dataStart, i) };
148
+ state = 0;
149
+ if (isC0Interrupter(charCode))
150
+ i++;
151
+ break;
152
+ }
153
+ i++;
154
+ }
155
+ }
156
+ if (state === 1)
157
+ state = 0;
158
+ }
159
+ }
160
+ }
161
+ export function tokenize(input) {
162
+ const result = [];
163
+ let i = 0;
164
+ let state = 0;
165
+ let currentCode = 0;
166
+ const len = input.length;
167
+ while (i < len) {
168
+ if (state === 0) {
169
+ const textStart = i;
170
+ let charCode = input.charCodeAt(i);
171
+ while (i < len && !isSequenceStart(charCode)) {
172
+ charCode = input.charCodeAt(++i);
173
+ }
174
+ if (i > textStart) {
175
+ result.push({ type: TOKEN_TYPES.TEXT, pos: textStart, raw: input.substring(textStart, i) });
176
+ }
177
+ if (i >= len)
178
+ break;
179
+ if (is8BitIntroducer(charCode)) {
180
+ result.push({ type: TOKEN_TYPES.INTRODUCER, pos: i, raw: input[i], code: input[i] });
181
+ i++;
182
+ state = 1;
183
+ currentCode = charCode;
184
+ }
185
+ else {
186
+ const nextCode = input.charCodeAt(i + 1);
187
+ if (nextCode === CSI_OPEN) {
188
+ result.push({ type: TOKEN_TYPES.INTRODUCER, pos: i, raw: input.substring(i, i + 2), code: CSI_CODE });
189
+ i += 2;
190
+ state = 1;
191
+ currentCode = CSI;
192
+ }
193
+ else if (nextCode === OSC_OPEN) {
194
+ result.push({ type: TOKEN_TYPES.INTRODUCER, pos: i, raw: input.substring(i, i + 2), code: OSC_CODE });
195
+ i += 2;
196
+ state = 1;
197
+ currentCode = OSC;
198
+ }
199
+ else if (i + 1 < len && STRING_OPENERS.has(input[i + 1])) {
200
+ result.push({ type: TOKEN_TYPES.INTRODUCER, pos: i, raw: input.substring(i, i + 2), code: input[i + 1] });
201
+ i += 2;
202
+ state = 1;
203
+ currentCode = nextCode;
204
+ }
205
+ else if (i + 1 < len) {
206
+ let j = i + 1;
207
+ while (j < len && input.charCodeAt(j) >= 0x20 && input.charCodeAt(j) <= 0x2f)
208
+ j++;
209
+ if (j < len) {
210
+ if (j > i + 1) {
211
+ const intermediate = input.substring(i + 1, j);
212
+ result.push({
213
+ type: TOKEN_TYPES.INTRODUCER,
214
+ pos: i,
215
+ raw: input.substring(i, j),
216
+ code: ESC_CODE,
217
+ intermediate,
218
+ });
219
+ }
220
+ else {
221
+ result.push({ type: TOKEN_TYPES.INTRODUCER, pos: i, raw: input[i], code: ESC_CODE });
222
+ }
223
+ i = j;
224
+ state = 1;
225
+ currentCode = ESC;
226
+ }
227
+ else {
228
+ i = j;
229
+ }
230
+ }
231
+ else {
232
+ i++;
233
+ }
234
+ }
235
+ }
236
+ else {
237
+ const pos = i;
238
+ if (currentCode === CSI) {
239
+ const dataStart = i;
240
+ while (i < len) {
241
+ const charCode = input.charCodeAt(i);
242
+ if (isInterrupter(charCode)) {
243
+ if (i > dataStart)
244
+ result.push({ type: TOKEN_TYPES.DATA, pos, raw: input.substring(dataStart, i) });
245
+ state = 0;
246
+ if (isC0Interrupter(charCode))
247
+ i++;
248
+ break;
249
+ }
250
+ if (charCode >= 0x40 && charCode <= 0x7e) {
251
+ if (i > dataStart)
252
+ result.push({ type: TOKEN_TYPES.DATA, pos, raw: input.substring(dataStart, i) });
253
+ result.push({ type: TOKEN_TYPES.FINAL, pos: i, raw: input[i] });
254
+ i++;
255
+ state = 0;
256
+ break;
257
+ }
258
+ i++;
259
+ }
260
+ }
261
+ else if (currentCode === ESC) {
262
+ if (i < len) {
263
+ const charCode = input.charCodeAt(i);
264
+ if (isInterrupter(charCode)) {
265
+ state = 0;
266
+ if (isC0Interrupter(charCode))
267
+ i++;
268
+ }
269
+ else {
270
+ result.push({ type: TOKEN_TYPES.FINAL, pos: i, raw: input[i] });
271
+ i++;
272
+ state = 0;
273
+ }
274
+ }
275
+ }
276
+ else {
277
+ const dataStart = i;
278
+ while (i < len) {
279
+ const charCode = input.charCodeAt(i);
280
+ let terminator;
281
+ if (charCode === ESC && input.charCodeAt(i + 1) === BACKSLASH) {
282
+ terminator = ESC_CODE + BACKSLASH_CODE;
283
+ }
284
+ else if (charCode === ST) {
285
+ terminator = ST_CODE;
286
+ }
287
+ else if (charCode === BELL && currentCode === OSC) {
288
+ terminator = BELL_CODE;
289
+ }
290
+ if (terminator) {
291
+ if (i > dataStart)
292
+ result.push({ type: TOKEN_TYPES.DATA, pos, raw: input.substring(dataStart, i) });
293
+ result.push({ type: TOKEN_TYPES.FINAL, pos: i, raw: terminator });
294
+ i += terminator.length;
295
+ state = 0;
296
+ break;
297
+ }
298
+ if (isInterrupter(charCode)) {
299
+ if (i > dataStart)
300
+ result.push({ type: TOKEN_TYPES.DATA, pos, raw: input.substring(dataStart, i) });
301
+ state = 0;
302
+ if (isC0Interrupter(charCode))
303
+ i++;
304
+ break;
305
+ }
306
+ i++;
307
+ }
308
+ }
309
+ if (state === 1)
310
+ state = 0;
311
+ }
312
+ }
313
+ return result;
314
+ }
@@ -0,0 +1,23 @@
1
+ import type { CODE_TYPES, TOKEN_TYPES } from "./constants.ts";
2
+ export type TOKEN = {
3
+ type: keyof typeof TOKEN_TYPES;
4
+ pos: number;
5
+ raw: string;
6
+ code?: string;
7
+ intermediate?: string;
8
+ };
9
+ export type CONTROL_CODE_TYPE = Exclude<keyof typeof CODE_TYPES, TEXT["type"]>;
10
+ export type CONTROL_CODE = {
11
+ type: CONTROL_CODE_TYPE;
12
+ command: string;
13
+ raw: string;
14
+ params: string[];
15
+ pos: number;
16
+ };
17
+ export type TEXT = {
18
+ type: "TEXT";
19
+ raw: string;
20
+ pos: number;
21
+ };
22
+ export type CODE = CONTROL_CODE | TEXT;
23
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE9D,MAAM,MAAM,KAAK,GAAG;IAClB,IAAI,EAAE,MAAM,OAAO,WAAW,CAAC;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,OAAO,CAAC,MAAM,OAAO,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;AAE/E,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,iBAAiB,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,IAAI,GAAG;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,IAAI,GAAG,YAAY,GAAG,IAAI,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,9 +1,26 @@
1
1
  {
2
2
  "name": "@ansi-tools/parser",
3
- "version": "1.0.11",
3
+ "version": "1.0.13",
4
4
  "description": "Tokenize and parse strings containing ANSI escape sequences and control codes",
5
- "main": "./dist/index.js",
5
+ "keywords": [
6
+ "ansi",
7
+ "escape codes",
8
+ "web application"
9
+ ],
10
+ "homepage": "https://github.com/webpro/ANSI.tools/tree/main/packages/parser",
11
+ "bugs": "https://github.com/webpro/ANSI.tools/issues",
12
+ "license": "ISC",
13
+ "author": "Lars Kappert <lars@webpro.nl>",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "github:webpro/ANSI.tools",
17
+ "directory": "packages/parser"
18
+ },
19
+ "files": [
20
+ "dist"
21
+ ],
6
22
  "type": "module",
23
+ "main": "./dist/index.js",
7
24
  "exports": {
8
25
  ".": {
9
26
  "types": "./dist/index.d.ts",
@@ -16,37 +33,19 @@
16
33
  "default": "./dist/escaped.js"
17
34
  }
18
35
  },
19
- "files": [
20
- "dist"
21
- ],
22
- "scripts": {
23
- "prebuild": "pnpm type-check && pnpm test",
24
- "build": "tsdown --dts src/index.ts src/escaped.ts",
25
- "dev": "tsdown --dts src/index.ts src/escaped.ts --watch",
26
- "test": "node --import ./test/assertions.ts --test",
27
- "type-check": "tsc",
28
- "prepack": "pnpm build"
29
- },
30
- "keywords": [
31
- "ansi",
32
- "escape codes",
33
- "web application"
34
- ],
35
- "author": "Lars Kappert <lars@webpro.nl>",
36
- "license": "ISC",
37
36
  "publishConfig": {
38
37
  "access": "public"
39
38
  },
40
- "homepage": "https://github.com/webpro/ANSI.tools/tree/main/packages/parser",
41
- "bugs": "https://github.com/webpro/ANSI.tools/issues",
42
- "repository": {
43
- "type": "git",
44
- "url": "github:webpro/ANSI.tools",
45
- "directory": "packages/parser"
39
+ "scripts": {
40
+ "prebuild": "pnpm test",
41
+ "build": "tsc",
42
+ "dev": "tsc --watch",
43
+ "test": "node --import ./test/assertions.ts --test",
44
+ "prepack": "pnpm build"
46
45
  },
47
46
  "devDependencies": {
48
- "@types/node": "^24.6.1",
49
- "tsdown": "^0.15.6",
47
+ "@types/node": "^24.12.0",
48
+ "mitata": "^1.0.34",
50
49
  "typescript": "^5.9.3"
51
50
  }
52
51
  }
@@ -1,85 +0,0 @@
1
- //#region src/constants.d.ts
2
- declare const BELL = 7;
3
- declare const BELL_CODE: string;
4
- declare const CAN = 24;
5
- declare const CAN_CODE: string;
6
- declare const SUB = 26;
7
- declare const SUB_CODE: string;
8
- declare const ESC = 27;
9
- declare const ESC_CODE: string;
10
- declare const BACKSLASH = 92;
11
- declare const BACKSLASH_CODE: string;
12
- declare const DCS = 144;
13
- declare const DCS_CODE: string;
14
- declare const SOS = 152;
15
- declare const SOS_CODE: string;
16
- declare const CSI = 155;
17
- declare const CSI_CODE: string;
18
- declare const ST = 156;
19
- declare const ST_CODE: string;
20
- declare const OSC = 157;
21
- declare const OSC_CODE: string;
22
- declare const PM = 158;
23
- declare const PM_CODE: string;
24
- declare const APC = 159;
25
- declare const APC_CODE: string;
26
- declare const CSI_OPEN: number;
27
- declare const CSI_OPEN_CODE: string;
28
- declare const OSC_OPEN: number;
29
- declare const OSC_OPEN_CODE: string;
30
- declare const DEC_OPEN: number;
31
- declare const PRIVATE_OPENERS: Set<string>;
32
- declare const DCS_OPEN = "P";
33
- declare const APC_OPEN = "_";
34
- declare const SOS_OPEN = "^";
35
- declare const PM_OPEN = "X";
36
- declare const STRING_OPENERS: Set<string>;
37
- declare const INTERRUPTERS: Set<number>;
38
- declare const C0_INTERRUPTERS: Set<number>;
39
- declare const PARAM_SEPARATOR: RegExp;
40
- declare const TOKEN_TYPES: {
41
- readonly TEXT: "TEXT";
42
- readonly INTRODUCER: "INTRODUCER";
43
- readonly DATA: "DATA";
44
- readonly FINAL: "FINAL";
45
- };
46
- declare const CODE_TYPES: {
47
- readonly CSI: "CSI";
48
- readonly DCS: "DCS";
49
- readonly DEC: "DEC";
50
- readonly ESC: "ESC";
51
- readonly OSC: "OSC";
52
- readonly PRIVATE: "PRIVATE";
53
- readonly SGR: "SGR";
54
- readonly STRING: "STRING";
55
- readonly TEXT: "TEXT";
56
- };
57
- //#endregion
58
- //#region src/types.d.ts
59
- type TOKEN = {
60
- type: keyof typeof TOKEN_TYPES;
61
- pos: number;
62
- raw: string;
63
- code?: string;
64
- intermediate?: string;
65
- };
66
- type CONTROL_CODE_TYPE = Exclude<keyof typeof CODE_TYPES, TEXT["type"]>;
67
- type CONTROL_CODE = {
68
- type: CONTROL_CODE_TYPE;
69
- command: string;
70
- raw: string;
71
- params: string[];
72
- pos: number;
73
- };
74
- type TEXT = {
75
- type: "TEXT";
76
- raw: string;
77
- pos: number;
78
- };
79
- type CODE = CONTROL_CODE | TEXT;
80
- //#endregion
81
- //#region src/parse.d.ts
82
- declare function parser(tokens: IterableIterator<TOKEN>): IterableIterator<CODE>;
83
- declare function parse(input: string): CODE[];
84
- //#endregion
85
- export { APC, APC_CODE, APC_OPEN, BACKSLASH, BACKSLASH_CODE, BELL, BELL_CODE, C0_INTERRUPTERS, CAN, CAN_CODE, CODE, CODE_TYPES, CONTROL_CODE, CSI, CSI_CODE, CSI_OPEN, CSI_OPEN_CODE, DCS, DCS_CODE, DCS_OPEN, DEC_OPEN, ESC, ESC_CODE, INTERRUPTERS, OSC, OSC_CODE, OSC_OPEN, OSC_OPEN_CODE, PARAM_SEPARATOR, PM, PM_CODE, PM_OPEN, PRIVATE_OPENERS, SOS, SOS_CODE, SOS_OPEN, ST, STRING_OPENERS, ST_CODE, SUB, SUB_CODE, TEXT, TOKEN, TOKEN_TYPES, parse, parser };