yini-parser 1.0.0-alpha.4 → 1.0.0-alpha.6

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 CHANGED
@@ -0,0 +1,14 @@
1
+ # CHANGELOG
2
+
3
+ ## 1.0.0-alpha.6
4
+ - The YINI specificaiton discontinued alternative marker character `~` (visually ambiguous) in favor of `<`.
5
+ - The parser can now detect invalid . characters in identifiers (both keys and section names), allowing it to emit a clear error message to the user.
6
+ - Detect and emit error on defining already existing key or section name in a scope/section.
7
+ - Updated readme with "Intro to YINI Config Format" among other updates.
8
+
9
+ ## 1.0.0-alpha.5
10
+ - Readme updated with correct examples for CommonJS.
11
+
12
+ ## 1.0.0-alpha.4 - 2025-07-20
13
+
14
+ First public release.
package/README.md CHANGED
@@ -13,14 +13,43 @@ YINI is a simple, human-friendly configuration format inspired by INI and JSON.
13
13
 
14
14
  ---
15
15
 
16
+ ## Quick Start
17
+
18
+ A simple configuration:
19
+ ```yini
20
+ ^ App
21
+ name = 'My Title'
22
+ items = 25
23
+ enabled = true
24
+ ```
25
+
26
+ That's it!
27
+
28
+ ---
29
+
30
+ ## 💡 Why YINI?
31
+ - **Easy to read and write**, minimal syntax, maximum clarity.
32
+ - **Clear section nesting** without painful indentation rules.
33
+ - **Supports strict/lenient modes**, and all major data types.
34
+ - A perfect alternative to messy JSON, legacy INI, or complex YAML.
35
+ - Built for both **JavaScript and TypeScript**.
36
+ - Both **human-friendly**, and **machine-friendly**.
37
+
16
38
  ## ✨ Features
17
39
  - Simple syntax (supports both strict and lenient modes).
18
- - Familiar config file style (inspired by INI, YAML, TOML).
40
+ - Familiar config file style (inspired by INI, JSON, Python, and Markdown).
19
41
  - Easy programmatic usage.
20
42
  - Only the `YINI` class is exported; all internal details are private.
43
+ - --wip-- Supports alternative list notation (colon‑style lists):
44
+ ```yini
45
+ fruits:
46
+ 'Pear',
47
+ 'Cherry',
48
+ 'Banana'
49
+ ```
21
50
 
22
51
  ### Limitations
23
- Not all features of the full YINI specification are implemented yet.
52
+ Not all features of the full YINI are implemented yet.
24
53
 
25
54
  See [FEATURE-CHECKLIST.md](https://github.com/YINI-lang/yini-parser-typescript/blob/main/FEATURE-CHECKLIST.md) for the current list of implemented YINI features.
26
55
 
@@ -47,13 +76,26 @@ pnpm add yini-parser
47
76
 
48
77
  ## Usage
49
78
 
50
- > Only import the main class:
51
- >
52
- > ```ts
53
- > import YINI from 'yini-parser';
54
- > ```
79
+ ### Node.js (CommonJS)
80
+ **Note:** Only a default export (YINI) is provided. Named imports are not supported.
81
+ ```js
82
+ const YINI = require('yini-parser');
83
+ // If you get undefined, try:
84
+ const YINI = require('yini-parser').default;
85
+
86
+ // Parse from string.
87
+ const config = YINI.parse(`
88
+ ^ App
89
+ title = 'My App Title'
90
+ items = 25
91
+ isDarkTheme = true
92
+ `);
93
+
94
+ // Parse from file.
95
+ const configFromFile = YINI.parseFile('./config.yini');
96
+ ```
55
97
 
56
- ### Example:
98
+ ### TypeScript (with `"esModuleInterop": true`)
57
99
  ```ts
58
100
  import YINI from 'yini-parser';
59
101
 
@@ -105,8 +147,9 @@ Returns a JavaScript object representing the parsed YINI configuration file.
105
147
 
106
148
  ## Example Output
107
149
  ```js
150
+ // JS object
108
151
  {
109
- App:{
152
+ App: {
110
153
  title: "My App Title",
111
154
  items: 25,
112
155
  isDarkTheme: false
@@ -116,6 +159,228 @@ Returns a JavaScript object representing the parsed YINI configuration file.
116
159
 
117
160
  ---
118
161
 
162
+ ## Intro to YINI Config Format
163
+
164
+ ### 1. Sections
165
+ Group settings under a named header. A section header starts with `^`.
166
+
167
+ Start a section with `^`, e.g.:
168
+ ```yini
169
+ ^ App
170
+ title = "AppName"
171
+ ```
172
+
173
+ ### 2. Key = Value
174
+ Each line inside a section is a **key** (name) and **value**, separated by `=`.
175
+
176
+ Write settings as `key = value`:
177
+ ```yini
178
+ maxConnections = 100
179
+ enableLogging = true
180
+ ```
181
+
182
+ ### 3. Values
183
+ Values can be:
184
+ - **Strings** (always quoted): `"hello"` or `'world'` (either single or double quoted)
185
+ - **Numbers:** `42`, `3.14` or `-10`
186
+ - **Booleans:** `true`, `false`, `on`, `off`, `yes`, `no` (all case-insensitive)
187
+ - **Nulls:** `null` or a blank value after `=` (in lenient mode)
188
+ - --wip-- **Lists:**
189
+ * JSON‑style: `["red", "green", "blue"]`
190
+ * Colon‑style:
191
+ ```yini
192
+ fruits:
193
+ "Pear",
194
+ "Cherry",
195
+ "Banana"
196
+ ```
197
+
198
+ ### 4. Comments
199
+ Various commenting styles are supported:
200
+ ```yini
201
+ // This is a line comment
202
+ timeout = 30 // inline comment
203
+ # This is also a line comment (must have a space after #)
204
+ interval = 30 # inline comment (must have a space after #)
205
+ /* Block comment spanning
206
+ multiple lines */
207
+ ; Full line comment (must be whole line).
208
+ ```
209
+
210
+ Pick one style per file for consistency.
211
+
212
+ Caveat: Note that **there must be a space** after the `#` and start of the comment. Otherwise it will be misinterpreted as a hexadecimal number.
213
+
214
+ ### 5. Nested Sections
215
+ Use extra carets `^` for sub‑sections:
216
+ ```yini
217
+ ^ Parent
218
+ ^^ Child
219
+ ^^^ SubChild
220
+ ```
221
+
222
+ If you prefer, you can indent the nested section for visibility:
223
+ ```yini
224
+ ^ Main
225
+ ^^ Sub
226
+ host = "db.example.com"
227
+ ```
228
+
229
+ One can nest multiple sections:
230
+ ```yini
231
+ ^ Root
232
+ ^^ Sub
233
+ ^^^ SubSub
234
+ ^ BackToRoot
235
+ ```
236
+
237
+ Example with indented sections:
238
+ ```yini
239
+ ^ Root
240
+ value = 'At level 1'
241
+ ^^ Sub
242
+ value = 'At level 2'
243
+ ^^^ SubSub
244
+ value = 'At level 3'
245
+
246
+ ^ BackToRoot
247
+ value = 'Back at level 1'
248
+ ```
249
+
250
+ The above Yini code will produce the following JavaScript object:
251
+ ```js
252
+ // JS object
253
+ {
254
+ Root: {
255
+ value: 'At level 1',
256
+ Sub: { value: 'At level 2', SubSub: { value: 'At level 3' } }
257
+ },
258
+ BackToRoot: { value: 'Back at level 1' }
259
+ }
260
+ ```
261
+
262
+ ### 6. Lists
263
+ --Work-in-Progress--
264
+ ```yini
265
+ // JSON‑style list
266
+ colors = ["red", "green", "blue"]
267
+
268
+ // Colon‑style list
269
+ fruits:
270
+ "Pear",
271
+ "Cherry",
272
+ "Banana"
273
+ ```
274
+
275
+ ### 7. Document Terminator (strict mode)
276
+ End a file explicitly with:
277
+ ```yini
278
+ ^ App
279
+ title = "MyTitle"
280
+
281
+ /END // Must be included in strict mode.
282
+ ```
283
+
284
+ ### 8. Disabled Lines
285
+ Prefix any valid line with -- to skip it entirely:
286
+ ```yini
287
+ --maxRetries = 5
288
+ ```
289
+
290
+ ### 9. Complete Example
291
+
292
+ ```yini
293
+ @yini # Optional marker to identify YINI format.
294
+
295
+ ^ App
296
+ name = "MyApp"
297
+ version = "1.0.0"
298
+ debug = off // Turn on for debugging.
299
+
300
+ ^^ Database
301
+ host = "db.local"
302
+ port = 5432
303
+ --user = "secret" # This line is disabled!
304
+ --userList = ["alice", "bob", "carol"]
305
+
306
+ /END
307
+ ```
308
+
309
+ ---
310
+
311
+ ### Advanced Example
312
+
313
+ ```js
314
+ const YINI = require('yini-parser'); // Or: import YINI from 'yini-parser';
315
+
316
+ const config = YINI.parse(`
317
+ /*
318
+ This is a multi-line block comment.
319
+ */
320
+
321
+ @yini
322
+
323
+ ^ App
324
+ name = "Nested Example"
325
+ version = "1.0.0"
326
+ debug = OFF // This is a comment.
327
+
328
+ # Database settings.
329
+ ^^ Database
330
+ host = "db.example.com"
331
+ port = 3306
332
+ user = "appuser"
333
+ --password = "dbpassword" # Disabled line due to --.
334
+ //password = "dbpassword" # Not sure yet about this pw.
335
+ password = "dbpassword" # Keep this secret.
336
+
337
+ // Commenting with slashes works too.
338
+ ^^^ Pool
339
+ min = 2
340
+ max = 10
341
+ idleTimeout = 300
342
+
343
+ /* Block comment on a single line. */
344
+ ^^ Logging
345
+ level = "info"
346
+ logToFile = ON # This is a comment.
347
+ filePath = "./logs/app.log"
348
+
349
+ /END
350
+ `);
351
+
352
+ console.log(config);
353
+ ```
354
+
355
+ #### Output:
356
+ ```js
357
+ // JS object
358
+ {
359
+ App: {
360
+ name: "Nested Example",
361
+ version: "1.0.0",
362
+ debug: false,
363
+ Database: {
364
+ host: "db.example.com",
365
+ port: 3306,
366
+ user: "appuser",
367
+ password: "dbpassword",
368
+ Pool: {
369
+ min: 2,
370
+ max: 10,
371
+ idleTimeout: 300
372
+ }
373
+ },
374
+ Logging: {
375
+ level: "info",
376
+ logToFile: true,
377
+ filePath: "./logs/app.log"
378
+ }
379
+ }
380
+ }
381
+ ```
382
+ ---
383
+
119
384
  ## 📚 Documentation
120
385
  - [Development Setup](./docs/Development%20Setup.md) — How to run, test, and build the project, etc.
121
386
  - [Conventions](./docs/Conventions.md) — Project conventions, naming patterns, etc.
@@ -159,37 +159,37 @@ class ErrorDataHandler {
159
159
  this.emitFatalError = (msgWhat = 'Something went wrong!', msgWhy = '', msgHint = '') => {
160
160
  console.error(issueTitle[0]); // Print the issue title.
161
161
  msgWhat && console.error(msgWhat);
162
- msgWhy && console.error(msgWhy);
162
+ msgWhy && console.log(msgWhy);
163
163
  msgHint && console.log(msgHint);
164
164
  };
165
165
  this.emitInternalError = (msgWhat = 'Something went wrong!', msgWhy = '', msgHint = '') => {
166
166
  console.error(issueTitle[1]); // Print the issue title.
167
167
  msgWhat && console.error(msgWhat);
168
- msgWhy && console.error(msgWhy);
168
+ msgWhy && console.log(msgWhy);
169
169
  msgHint && console.log(msgHint);
170
170
  };
171
171
  this.emitSyntaxError = (msgWhat, msgWhy = '', msgHint = '') => {
172
172
  console.error(issueTitle[2]); // Print the issue title.
173
173
  msgWhat && console.error(msgWhat);
174
- msgWhy && console.error(msgWhy);
174
+ msgWhy && console.log(msgWhy);
175
175
  msgHint && console.log(msgHint);
176
176
  };
177
177
  this.emitSyntaxWarning = (msgWhat, msgWhy = '', msgHint = '') => {
178
178
  console.warn(issueTitle[3]); // Print the issue title.
179
179
  msgWhat && console.warn(msgWhat);
180
- msgWhy && console.warn(msgWhy);
180
+ msgWhy && console.log(msgWhy);
181
181
  msgHint && console.log(msgHint);
182
182
  };
183
183
  this.emitNotice = (msgWhat, msgWhy = '', msgHint = '') => {
184
184
  console.warn(issueTitle[4]); // Print the issue title.
185
185
  msgWhat && console.warn(msgWhat);
186
- msgWhy && console.warn(msgWhy);
186
+ msgWhy && console.log(msgWhy);
187
187
  msgHint && console.log(msgHint);
188
188
  };
189
189
  this.emitInfo = (msgWhat, msgWhy = '', msgHint = '') => {
190
190
  console.info(issueTitle[5]); // Print the issue title.
191
191
  msgWhat && console.info(msgWhat);
192
- msgWhy && console.info(msgWhy);
192
+ msgWhy && console.log(msgWhy);
193
193
  msgHint && console.log(msgHint);
194
194
  };
195
195
  this.persistThreshold = threshold;
@@ -23,6 +23,9 @@ export default class YINIVisitor<IResult> extends YiniParserVisitor<IResult> {
23
23
  private meta_numOfMembers;
24
24
  private meta_numOfChains;
25
25
  private meta_maxLevelSection;
26
+ private existingSectionTitlesAtLevels;
27
+ private hasDefinedSectionTitle;
28
+ private setDefineSectionTitle;
26
29
  constructor(errorHandler: ErrorDataHandler, isStrict: boolean);
27
30
  private pushOnTree;
28
31
  private getDepthOfLevels;
@@ -38,13 +38,47 @@ class YINIVisitor extends YiniParserVisitor_1.default {
38
38
  this.meta_numOfMembers = 0; // For stats.
39
39
  this.meta_numOfChains = 0; // For stats.
40
40
  this.meta_maxLevelSection = 0; // For stats.
41
- this.pushOnTree = (sReslult) => {
41
+ // private existingSectionTitles: Map<string, boolean> = new Map()
42
+ this.existingSectionTitlesAtLevels = [];
43
+ this.hasDefinedSectionTitle = (sectionName, level) => {
44
+ const mapAtCurrentLevel = this.existingSectionTitlesAtLevels[level - 1];
45
+ return mapAtCurrentLevel === null || mapAtCurrentLevel === void 0 ? void 0 : mapAtCurrentLevel.has(sectionName);
46
+ };
47
+ this.setDefineSectionTitle = (sectionName, level) => {
48
+ let mapAtCurrentLevel = this.existingSectionTitlesAtLevels[level - 1];
49
+ if (!mapAtCurrentLevel) {
50
+ mapAtCurrentLevel = new Map();
51
+ this.existingSectionTitlesAtLevels[level - 1] = mapAtCurrentLevel;
52
+ }
53
+ mapAtCurrentLevel.set(sectionName, true);
54
+ };
55
+ this.pushOnTree = (ctx, sReslult) => {
42
56
  if ((0, env_1.isDebug)()) {
43
57
  console.log();
44
58
  (0, system_1.debugPrint)('--- In pushOnTree(..) --------');
45
59
  (0, system_1.debugPrint)('sReslult:');
46
60
  (0, system_1.printObject)(sReslult);
47
61
  }
62
+ const key = sReslult.level + '-' + sReslult.name;
63
+ (0, system_1.debugPrint)('KKKKKK, key = ' + key);
64
+ // if (this.existingSectionTitles.has(key)) {
65
+ if (this.hasDefinedSectionTitle(key, sReslult.level)) {
66
+ this.errorHandler.pushOrBail(ctx, 'Syntax-Error', 'Section name already exists', 'Cannot redefine section name: "' +
67
+ sReslult.name +
68
+ '" at level ' +
69
+ sReslult.level +
70
+ '.');
71
+ }
72
+ else {
73
+ if (sReslult.members === undefined) {
74
+ (0, system_1.debugPrint)('This sReslult does not hold any valid members (=undefined)');
75
+ }
76
+ else {
77
+ // this.existingSectionTitles.set(key, true)
78
+ this.setDefineSectionTitle(key, sReslult.level);
79
+ // printObject(this.existingSectionTitles)
80
+ }
81
+ }
48
82
  // if (
49
83
  // sReslult.level === 0 &&
50
84
  // (!sReslult.name || sReslult.name === 'undefined')
@@ -115,7 +149,7 @@ class YINIVisitor extends YiniParserVisitor_1.default {
115
149
  // ctx?.section_list()?.forEach((section: any) => {
116
150
  (0, system_1.debugPrint)('\nStart of each element in forEeach(..) of section_list():');
117
151
  const topSectionResult = this.visitSection(section);
118
- this.pushOnTree(topSectionResult);
152
+ this.pushOnTree(ctx, topSectionResult);
119
153
  const topSectionName = topSectionResult === null || topSectionResult === void 0 ? void 0 : topSectionResult.name;
120
154
  const topSectionMembers = topSectionResult === null || topSectionResult === void 0 ? void 0 : topSectionResult.members;
121
155
  const topSectionLevel = topSectionResult === null || topSectionResult === void 0 ? void 0 : topSectionResult.level; // This must have a value of 1.
@@ -386,7 +420,7 @@ class YINIVisitor extends YiniParserVisitor_1.default {
386
420
  this.lastActiveSectionAtLevels[this.level - 1] = {
387
421
  [sectionName]: Object.assign({}, members),
388
422
  };
389
- this.pushOnTree({
423
+ this.pushOnTree(ctx, {
390
424
  level: sectionLevel,
391
425
  name: sectionName,
392
426
  members,
@@ -499,7 +533,8 @@ class YINIVisitor extends YiniParserVisitor_1.default {
499
533
  }
500
534
  else {
501
535
  this.meta_numOfMembers++;
502
- if ((value === null || value === void 0 ? void 0 : value.type) === 'Null') {
536
+ // if ((value?.type as TDataType) === 'Null') {
537
+ if (type === 'Null') {
503
538
  members[key] = null;
504
539
  }
505
540
  else {
@@ -507,6 +542,22 @@ class YINIVisitor extends YiniParserVisitor_1.default {
507
542
  // NOTE: (!) Only if nested section.
508
543
  (0, system_1.debugPrint)('About to mount a single member or section onto members...');
509
544
  (0, env_1.isDebug)() && console.log({ [key]: value });
545
+ // if ((type as TDataType) === 'Object') {
546
+ // const isExistingSectionName =
547
+ // this.hasDefinedSectionTitle(key, this.level)
548
+ // debugPrint(' type = "' + type + '"')
549
+ // debugPrint('this.level = "' + this.level + '"')
550
+ // debugPrint(
551
+ // 'DDDDDDDD: sectionName / objectKey: ' + key,
552
+ // )
553
+ // debugPrint(
554
+ // 'Is already defined at this level? ' +
555
+ // isExistingSectionName,
556
+ // )
557
+ // if (!isExistingSectionName) {
558
+ // this.setDefineSectionTitle(key, this.level)
559
+ // }
560
+ // }
510
561
  Object.assign(members, { [key]: value });
511
562
  (0, system_1.debugPrint)('+ Added member or section onto members: "' +
512
563
  key +
@@ -77,6 +77,9 @@ class Builder {
77
77
  }
78
78
  mountChainOntoLevel(chainC, workingSubTree) {
79
79
  (0, system_1.debugPrint)('-> Builder: mountChainOntoLevel(..)');
80
+ if ((0, env_1.isDebug)()) {
81
+ (0, system_1.printObject)(chainC);
82
+ }
80
83
  if (chainC.originLevel > 1) {
81
84
  // NOP
82
85
  }
@@ -101,7 +104,7 @@ class Builder {
101
104
  (0, system_1.printObject)(workingSubTree.chain);
102
105
  }
103
106
  (0, system_1.debugPrint)('Mount currentChain onto workingFullSubTree.');
104
- workingSubTree.chain = mountObjectAtLevel(workingSubTree.chain, chain, targetLevel);
107
+ workingSubTree.chain = mountObjectAtLevel(workingSubTree.chain, chain, targetLevel, this.errorHandler);
105
108
  if ((0, env_1.isDebug)()) {
106
109
  (0, system_1.debugPrint)('After mounting onto workingSubTree.chain:');
107
110
  (0, system_1.printObject)(workingSubTree.chain);
@@ -140,7 +143,7 @@ class Builder {
140
143
  * 1-based) in objectSrc.
141
144
  * @return Returns a new object without mutating input objects.
142
145
  */
143
- const mountObjectAtLevel = (objectSrc, objectDest, level) => {
146
+ const mountObjectAtLevel = (objectSrc, objectDest, level, errorHandler) => {
144
147
  // Deep copy to avoid mutating the input.
145
148
  const result = JSON.parse(JSON.stringify(objectSrc));
146
149
  let current = result;
@@ -160,6 +163,22 @@ const mountObjectAtLevel = (objectSrc, objectDest, level) => {
160
163
  current = current[nextKey];
161
164
  currentLevel++;
162
165
  }
166
+ (0, system_1.debugPrint)('--------');
167
+ (0, system_1.debugPrint)(' current = ' + (0, system_1.toPrettyJSON)(current));
168
+ const [firstKey] = Object.keys(objectDest);
169
+ (0, system_1.debugPrint)('objectDest = ' + firstKey);
170
+ if (Object.prototype.hasOwnProperty.call(current, firstKey)) {
171
+ //@todo Add metadata with line number, onto chainC, so can use line number in error reporting
172
+ (0, system_1.debugPrint)(`(!) sectionName already exist, name: "${firstKey}", in: `);
173
+ (0, system_1.debugPrint)((0, system_1.toPrettyJSON)(current));
174
+ // Note, after pushing processing may continue or exit, depending on the error and/or the bail threshold.
175
+ errorHandler.pushOrBail(null, 'Syntax-Error', 'Section name already exists', 'Cannot redefine section name: "' +
176
+ firstKey +
177
+ '" at level ' +
178
+ currentLevel +
179
+ '.');
180
+ return current;
181
+ }
163
182
  // Mount objectDest onto the object at the required level.
164
183
  Object.assign(current, objectDest);
165
184
  return result;
@@ -6,47 +6,46 @@ export default class YiniLexer extends Lexer {
6
6
  static readonly SS = 4;
7
7
  static readonly EUR = 5;
8
8
  static readonly CARET = 6;
9
- static readonly TILDE = 7;
10
- static readonly GT = 8;
11
- static readonly LT = 9;
12
- static readonly EQ = 10;
13
- static readonly HASH = 11;
14
- static readonly COMMA = 12;
15
- static readonly COLON = 13;
16
- static readonly OB = 14;
17
- static readonly CB = 15;
18
- static readonly OC = 16;
19
- static readonly CC = 17;
20
- static readonly PLUS = 18;
21
- static readonly DOLLAR = 19;
22
- static readonly PC = 20;
23
- static readonly AT = 21;
24
- static readonly SEMICOLON = 22;
25
- static readonly BOOLEAN_FALSE = 23;
26
- static readonly BOOLEAN_TRUE = 24;
27
- static readonly NULL = 25;
28
- static readonly EMPTY_OBJECT = 26;
29
- static readonly EMPTY_LIST = 27;
30
- static readonly SHEBANG = 28;
31
- static readonly NUMBER = 29;
32
- static readonly KEY = 30;
33
- static readonly IDENT = 31;
34
- static readonly IDENT_BACKTICKED = 32;
35
- static readonly STRING = 33;
36
- static readonly TRIPLE_QUOTED_STRING = 34;
37
- static readonly SINGLE_OR_DOUBLE = 35;
38
- static readonly R_AND_C_STRING = 36;
39
- static readonly HYPER_STRING = 37;
40
- static readonly ESC_SEQ = 38;
41
- static readonly ESC_SEQ_BASE = 39;
42
- static readonly NL = 40;
43
- static readonly SINGLE_NL = 41;
44
- static readonly WS = 42;
45
- static readonly BLOCK_COMMENT = 43;
46
- static readonly COMMENT = 44;
47
- static readonly LINE_COMMENT = 45;
48
- static readonly INLINE_COMMENT = 46;
49
- static readonly IDENT_INVALID = 47;
9
+ static readonly GT = 7;
10
+ static readonly LT = 8;
11
+ static readonly EQ = 9;
12
+ static readonly HASH = 10;
13
+ static readonly COMMA = 11;
14
+ static readonly COLON = 12;
15
+ static readonly OB = 13;
16
+ static readonly CB = 14;
17
+ static readonly OC = 15;
18
+ static readonly CC = 16;
19
+ static readonly PLUS = 17;
20
+ static readonly DOLLAR = 18;
21
+ static readonly PC = 19;
22
+ static readonly AT = 20;
23
+ static readonly SEMICOLON = 21;
24
+ static readonly BOOLEAN_FALSE = 22;
25
+ static readonly BOOLEAN_TRUE = 23;
26
+ static readonly NULL = 24;
27
+ static readonly EMPTY_OBJECT = 25;
28
+ static readonly EMPTY_LIST = 26;
29
+ static readonly SHEBANG = 27;
30
+ static readonly NUMBER = 28;
31
+ static readonly KEY = 29;
32
+ static readonly IDENT = 30;
33
+ static readonly IDENT_BACKTICKED = 31;
34
+ static readonly STRING = 32;
35
+ static readonly TRIPLE_QUOTED_STRING = 33;
36
+ static readonly SINGLE_OR_DOUBLE = 34;
37
+ static readonly R_AND_C_STRING = 35;
38
+ static readonly HYPER_STRING = 36;
39
+ static readonly ESC_SEQ = 37;
40
+ static readonly ESC_SEQ_BASE = 38;
41
+ static readonly NL = 39;
42
+ static readonly SINGLE_NL = 40;
43
+ static readonly WS = 41;
44
+ static readonly BLOCK_COMMENT = 42;
45
+ static readonly COMMENT = 43;
46
+ static readonly LINE_COMMENT = 44;
47
+ static readonly INLINE_COMMENT = 45;
48
+ static readonly IDENT_INVALID = 46;
50
49
  static readonly EOF: number;
51
50
  static readonly channelNames: string[];
52
51
  static readonly literalNames: (string | null)[];