yini-parser 1.0.0-alpha.1

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 (46) hide show
  1. package/CHANGELOG.md +0 -0
  2. package/LICENSE +201 -0
  3. package/README.md +120 -0
  4. package/dist/src/YINI.js +122 -0
  5. package/dist/src/config/env.js +15 -0
  6. package/dist/src/core/ErrorDataHandler.js +207 -0
  7. package/dist/src/core/YINIVisitor.js +856 -0
  8. package/dist/src/core/objectBuilder.js +166 -0
  9. package/dist/src/core/types.js +36 -0
  10. package/dist/src/grammar/YiniLexer.js +370 -0
  11. package/dist/src/grammar/YiniParser.js +2106 -0
  12. package/dist/src/grammar/YiniParserVisitor.js +14 -0
  13. package/dist/src/index.js +189 -0
  14. package/dist/src/parseEntry.js +155 -0
  15. package/dist/src/parsers/extractHeaderParts.js +103 -0
  16. package/dist/src/parsers/extractSignificantYiniLine.js +68 -0
  17. package/dist/src/parsers/parseBoolean.js +12 -0
  18. package/dist/src/parsers/parseNull.js +11 -0
  19. package/dist/src/parsers/parseNumber.js +49 -0
  20. package/dist/src/parsers/parseSectionHeader.js +111 -0
  21. package/dist/src/parsers/parseString.js +40 -0
  22. package/dist/src/utils/pathAndFileName.js +15 -0
  23. package/dist/src/utils/string.js +97 -0
  24. package/dist/src/utils/system.js +23 -0
  25. package/dist/src/yiniHelpers.js +141 -0
  26. package/dist/tests/integration/1-core-parsing/parse-bigger-section-nesting-as-object.test.js +83 -0
  27. package/dist/tests/integration/1-core-parsing/parse-section-nesting-w-classic-markers.test.js +170 -0
  28. package/dist/tests/integration/1-core-parsing/parse-section-nesting-w-nsh-markers.test.js +27 -0
  29. package/dist/tests/integration/1-core-parsing/read some values from level 1 and 2.test.js +77 -0
  30. package/dist/tests/integration/1-core-parsing/throw on bad section heads.test.js +162 -0
  31. package/dist/tests/integration/10-special-validation-modes/validation-modes.test.js +38 -0
  32. package/dist/tests/integration/2-file-structure-and-error/able to parse mixed case filenames.test.js +72 -0
  33. package/dist/tests/integration/2-file-structure-and-error/throw error on bad file extensions.test.js +36 -0
  34. package/dist/tests/integration/2-file-structure-and-error/throw error parsing bad content.test.js +80 -0
  35. package/dist/tests/smoke/A-general-smoke.test.js +259 -0
  36. package/dist/tests/smoke/B-parse-inline-smoke.test.js +270 -0
  37. package/dist/tests/smoke/C-traverse-file-smoke.test.js +141 -0
  38. package/dist/tests/smoke/D-parse-file-smoke.test.js +134 -0
  39. package/dist/tests/unit/parsers/extractHeaderParts.unit.test.js +490 -0
  40. package/dist/tests/unit/parsers/parseSectionHeader-classic.unit.test.js +421 -0
  41. package/dist/tests/unit/parsers/parseSectionHeader-nsh.unit.test.js +436 -0
  42. package/dist/tests/unit/parsers/parseSectionHeader-throw-on-invalid.unit.test.js +168 -0
  43. package/dist/tests/unit/utils/utils-pathAndFileName.unit.test.js +80 -0
  44. package/dist/tests/unit/utils/utils-string.unit.test.js +185 -0
  45. package/dist/tests/unit/yiniHelpers.unit.test.js +306 -0
  46. package/package.json +94 -0
@@ -0,0 +1,856 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const env_1 = require("../config/env");
7
+ const YiniParserVisitor_1 = __importDefault(require("../grammar/YiniParserVisitor"));
8
+ const extractSignificantYiniLine_1 = require("../parsers/extractSignificantYiniLine");
9
+ const parseBoolean_1 = __importDefault(require("../parsers/parseBoolean"));
10
+ const parseNull_1 = __importDefault(require("../parsers/parseNull"));
11
+ const parseNumber_1 = __importDefault(require("../parsers/parseNumber"));
12
+ const parseSectionHeader_1 = __importDefault(require("../parsers/parseSectionHeader"));
13
+ const parseString_1 = __importDefault(require("../parsers/parseString"));
14
+ const string_1 = require("../utils/string");
15
+ const system_1 = require("../utils/system");
16
+ const yiniHelpers_1 = require("../yiniHelpers");
17
+ const ErrorDataHandler_1 = require("./ErrorDataHandler");
18
+ /**
19
+ * This interface defines a complete generic visitor for a parse tree produced
20
+ * by `YiniParser`.
21
+ *
22
+ * @param <IResult> The return type of the visit operation. Use `void` for
23
+ * operations with no return type.
24
+ */
25
+ class YINIVisitor extends YiniParserVisitor_1.default {
26
+ constructor(errorHandler, isStrict) {
27
+ super();
28
+ //export default class YINIVisitor extends YiniParserVisitor<any> {
29
+ this.reversedTree = [];
30
+ this.errorHandler = null;
31
+ this.lastActiveSectionAtLevels = [];
32
+ this.lastActiveSectionNameAtLevels = []; // Last active section name at each level.
33
+ this.numOfLevelOnes = 0; // Num of Level-1 sections.
34
+ this.level = 0;
35
+ this.prevLevel = 0;
36
+ this.prevSectionName = ''; // For error reporting purposes.
37
+ this.meta_numOfSections = 0; // For stats.
38
+ this.meta_numOfMembers = 0; // For stats.
39
+ this.meta_numOfChains = 0; // For stats.
40
+ this.meta_maxLevelSection = 0; // For stats.
41
+ this.pushOnTree = (sReslult) => {
42
+ if ((0, env_1.isDebug)()) {
43
+ console.log();
44
+ (0, system_1.debugPrint)('--- In pushOnTree(..) --------');
45
+ (0, system_1.debugPrint)('sReslult:');
46
+ (0, system_1.printObject)(sReslult);
47
+ }
48
+ // if (
49
+ // sReslult.level === 0 &&
50
+ // (!sReslult.name || sReslult.name === 'undefined')
51
+ // ) {
52
+ // // NOTE: This is a nasty fix, should try to do another way!
53
+ // debugPrint('HIT, Doing NASTY fix!!')
54
+ // // A memberless section, e.g. `^ Section` and then input ends.
55
+ // // Lift up the member in "members" to top.
56
+ // // --- Get the key-name of the entry in "members" ----------
57
+ // // "members": {
58
+ // // "Title": {}
59
+ // // }
60
+ // const sectionName = Object.keys(sReslult.members)[0]
61
+ // // ---------------------------------------------------------
62
+ // debugPrint('sectionName = ' + sectionName)
63
+ // const chain: IChainContainer = {
64
+ // originLevel: 1,
65
+ // chain: { [sectionName]: {} },
66
+ // }
67
+ // this.reversedTree.push(chain)
68
+ // } else {
69
+ const chain = {
70
+ originLevel: sReslult.level,
71
+ chain: { [(0, string_1.trimBackticks)(sReslult.name)]: sReslult.members },
72
+ };
73
+ this.reversedTree.push(chain);
74
+ // }
75
+ this.meta_numOfChains++;
76
+ (0, system_1.debugPrint)('this.reversedTree: [list]');
77
+ (0, system_1.printObject)(this.reversedTree);
78
+ (0, system_1.debugPrint)('--- /end of pushOnTree(..) --------');
79
+ };
80
+ this.getDepthOfLevels = () => {
81
+ return this.lastActiveSectionNameAtLevels.length;
82
+ };
83
+ this.setLastActiveSection = (atLevel, sectionName) => {
84
+ if (atLevel >= 1) {
85
+ this.lastActiveSectionNameAtLevels[atLevel - 1] = sectionName;
86
+ }
87
+ else {
88
+ // Note, after pushing processing may continue or exit, depending on the error and/or the bail threshold.
89
+ this.errorHandler.pushOrBail(null, 'Internal-Error', 'Invalid section level (<1), level: ' +
90
+ atLevel +
91
+ ', sectionName: "' +
92
+ sectionName +
93
+ '"');
94
+ }
95
+ };
96
+ /**
97
+ * Visit a parse tree produced by `YiniParser.yini`.
98
+ * @param ctx the parse tree
99
+ * @return the visitor result
100
+ */
101
+ // visitYini?: (ctx: YiniContext) => IResult;
102
+ // visitYini = (ctx: YiniContext): IResult => {
103
+ this.visitYini = (ctx, isStrict = false) => {
104
+ var _a;
105
+ if (!this.errorHandler) {
106
+ // Note, after pushing processing may continue or exit, depending on the error and/or the bail threshold.
107
+ new ErrorDataHandler_1.ErrorDataHandler().pushOrBail(null, 'Fatal-Error', 'Has no ErrorDataHandler instance when calling visitYini(..)', 'Something in the code is done incorrectly in order for this to happen... :S');
108
+ }
109
+ (0, system_1.debugPrint)();
110
+ (0, system_1.debugPrint)('abcde99');
111
+ (0, env_1.isDebug)() && console.log();
112
+ (0, system_1.debugPrint)('-> Entered visitYini(..) in YINIVisitor');
113
+ (0, system_1.debugPrint)('QQQQ');
114
+ (_a = ctx.section_list()) === null || _a === void 0 ? void 0 : _a.forEach((section) => {
115
+ // ctx?.section_list()?.forEach((section: any) => {
116
+ (0, system_1.debugPrint)('\nStart of each element in forEeach(..) of section_list():');
117
+ const topSectionResult = this.visitSection(section);
118
+ this.pushOnTree(topSectionResult);
119
+ const topSectionName = topSectionResult === null || topSectionResult === void 0 ? void 0 : topSectionResult.name;
120
+ const topSectionMembers = topSectionResult === null || topSectionResult === void 0 ? void 0 : topSectionResult.members;
121
+ const topSectionLevel = topSectionResult === null || topSectionResult === void 0 ? void 0 : topSectionResult.level; // This must have a value of 1.
122
+ (0, system_1.debugPrint)('\ntopSectionResult (visitSection(..)):');
123
+ if ((0, env_1.isDebug)()) {
124
+ console.log(topSectionResult);
125
+ }
126
+ (0, system_1.debugPrint)('Found section head, topSectionName = "' + topSectionName + '"');
127
+ topSectionMembers &&
128
+ (0, system_1.debugPrint)('Num of Props of topSectionResult?.members: ' +
129
+ Object.keys(topSectionResult === null || topSectionResult === void 0 ? void 0 : topSectionResult.members).length);
130
+ (0, system_1.debugPrint)('topSectionMembers:');
131
+ if ((0, env_1.isDebug)()) {
132
+ console.log(topSectionMembers);
133
+ }
134
+ if (topSectionName) {
135
+ (0, system_1.debugPrint)();
136
+ (0, system_1.debugPrint)('-- Just extracted TOP/FIRST section info ---------------------------');
137
+ (0, system_1.debugPrint)(' TOP/FIRST topSectionName = ' + topSectionName);
138
+ (0, system_1.debugPrint)(' topSectionLevel = ' + topSectionLevel);
139
+ (0, system_1.debugPrint)(' this.level = ' + this.level);
140
+ (0, system_1.debugPrint)('Mounted/assigned section onto resultSections...');
141
+ }
142
+ (0, system_1.debugPrint)('\n=== resultSections: =====================================');
143
+ if ((0, env_1.isDebug)()) {
144
+ console.log('2222222222222');
145
+ console.log(`lastActiveSectionAtLevels[${this.level - 1}]`);
146
+ (0, system_1.printObject)(this.lastActiveSectionAtLevels[this.level - 1]);
147
+ }
148
+ (0, system_1.debugPrint)('==============================================\n');
149
+ (0, system_1.debugPrint)('End of each element in forEeach(..) of section_list().');
150
+ (0, system_1.debugPrint)();
151
+ });
152
+ const syntaxTree = this.reversedTree.reverse();
153
+ if ((0, env_1.isDebug)()) {
154
+ console.log();
155
+ console.log('=========================================================================');
156
+ console.log('=== syntaxTree: ==========================================================');
157
+ (0, system_1.printObject)(syntaxTree);
158
+ console.log('=========================================================================');
159
+ console.log('=========================================================================');
160
+ console.log();
161
+ }
162
+ const hasTerminal = !!ctx.terminal_line();
163
+ // Returns an Intermediate Tree (could even be an AST).
164
+ const syntaxTreeC = {
165
+ // _base: this.resultSections,
166
+ _syntaxTree: syntaxTree, // The Intermediate Tree, or AST.
167
+ _hasTerminal: hasTerminal,
168
+ _meta_numOfSections: this.meta_numOfSections,
169
+ _meta_numOfMembers: this.meta_numOfMembers,
170
+ _meta_numOfChains: this.meta_numOfChains,
171
+ };
172
+ return syntaxTreeC;
173
+ };
174
+ /**
175
+ * Will visit here on EVERY section.
176
+ * @param ctx the parse tree
177
+ * @returns { [sectionName]: sectionObj }
178
+ */
179
+ // visitSection?: (ctx: SectionContext) => IResult;
180
+ this.visitSection = (ctx) => {
181
+ // let headMarkerType: TSectionHeaderType =
182
+ // 'Classic-Header-Marker'
183
+ var _a, _b, _c;
184
+ (0, env_1.isDebug)() && console.log();
185
+ (0, system_1.debugPrint)('-> Entered visitSection(..)');
186
+ const res = {};
187
+ (0, system_1.debugPrint)('start');
188
+ (0, system_1.debugPrint)('XXXX0:ctx.getText() = ' + ctx.getText());
189
+ (0, system_1.debugPrint)('XXXX1:ctx.SECTION_HEAD() = ' + ctx.SECTION_HEAD());
190
+ (0, system_1.debugPrint)('XXXX1:SECTION_HEAD().getText() = ' +
191
+ ((_a = ctx.SECTION_HEAD()) === null || _a === void 0 ? void 0 : _a.getText().trim()));
192
+ (0, system_1.debugPrint)('end\n');
193
+ let line = '';
194
+ try {
195
+ (0, system_1.debugPrint)('S1');
196
+ line = ((_b = ctx.SECTION_HEAD()) === null || _b === void 0 ? void 0 : _b.getText().trim()) || '';
197
+ (0, system_1.debugPrint)('S2, line: >>>' + line + '<<<');
198
+ }
199
+ catch (error) {
200
+ const msgWhat = `Unexpected syntax while parsing a member or section head`;
201
+ const msgWhy = `Found unexpected syntax while trying to read a key-value pair or a section header (such as a section marker or section name).`;
202
+ // Note, after pushing processing may continue or exit, depending on the error and/or the bail threshold.
203
+ this.errorHandler.pushOrBail(ctx, 'Syntax-Error', msgWhat, msgWhy);
204
+ }
205
+ // If no section head can be found in the above SECTION_HEAD(),
206
+ // try alternative method of reading the section content.
207
+ (0, system_1.debugPrint)('S3, line: >>>' + line + '<<<');
208
+ if (!line) {
209
+ (0, system_1.debugPrint)();
210
+ (0, system_1.debugPrint)('Nothing in SECTION_HEAD() is found, trying to read the section content directly...');
211
+ (0, system_1.debugPrint)('--- Start: parse line from section content-----------------');
212
+ // const sectionContent = '' + ctx.getText().trim()
213
+ const sectionContent = ctx.getText().trim();
214
+ (0, system_1.debugPrint)('Section content: ' + ctx.getText());
215
+ line = (0, extractSignificantYiniLine_1.extractYiniLine)(sectionContent);
216
+ // const contentLines = splitLines(sectionContent)
217
+ // if (isDebug()) {
218
+ // console.log('contentLines:')
219
+ // printObject(contentLines)
220
+ // }
221
+ // // contentLines.forEach((row: string) => {
222
+ // for (let row of contentLines) {
223
+ // debugPrint('---')
224
+ // debugPrint('row (a): >>>' + row + '<<<')
225
+ // row = stripNLAndAfter(row)
226
+ // debugPrint('row (b): >>>' + row + '<<<')
227
+ // row = stripCommentsAndAfter(row)
228
+ // debugPrint('row (c): >>>' + row + '<<<')
229
+ // row = row.trim()
230
+ // debugPrint('row (d): >>>' + row + '<<<')
231
+ // if (row) {
232
+ // debugPrint(
233
+ // 'Found some content in split row (non-comments).',
234
+ // )
235
+ // debugPrint('Split row: >>>' + row + '<<<')
236
+ // // Use this as input in line.
237
+ // line = row
238
+ // debugPrint('Will use row as line input')
239
+ // break
240
+ // }
241
+ // }
242
+ // debugPrint(
243
+ // '--- End: parse line from section content-----------------',
244
+ // )
245
+ // debugPrint()
246
+ }
247
+ (0, system_1.debugPrint)('S4, line: >>>' + line + '<<<');
248
+ if (!line) {
249
+ (0, system_1.debugPrint)('*** ERROR: Nothing to parse in section line');
250
+ }
251
+ this.prevLevel = this.level;
252
+ let { sectionName, sectionLevel } = (0, parseSectionHeader_1.default)(line, this.errorHandler, ctx);
253
+ this.level = sectionLevel;
254
+ this.meta_numOfSections++;
255
+ // ---------------------------------------------------------------
256
+ let nestDirection;
257
+ if (this.level === this.prevLevel) {
258
+ nestDirection = 'same';
259
+ }
260
+ else if (this.level < this.prevLevel) {
261
+ nestDirection = 'lower';
262
+ }
263
+ else {
264
+ nestDirection = 'higher';
265
+ }
266
+ (0, system_1.debugPrint)('-- In visitSection(..) ---------------------------');
267
+ (0, system_1.debugPrint)(' sectionName = ' + sectionName);
268
+ (0, system_1.debugPrint)(' sectionLevel = ' + sectionLevel);
269
+ (0, system_1.debugPrint)(' this.level = ' + this.level);
270
+ (0, system_1.debugPrint)(' this.prevLevel = ' + this.prevLevel);
271
+ (0, system_1.debugPrint)(' this.prevSectionName = ' + this.prevSectionName);
272
+ (0, system_1.debugPrint)(' nestDirection = ' + nestDirection);
273
+ (0, system_1.debugPrint)(' this.numOfLevelOnes = ' + this.numOfLevelOnes);
274
+ (0, system_1.debugPrint)('this.getDepthOfLevels() = ' + this.getDepthOfLevels());
275
+ (0, system_1.debugPrint)();
276
+ if (nestDirection === 'higher') {
277
+ (0, system_1.debugPrint)(`Is level skipping: ${this.level - this.prevLevel} >= 2?`);
278
+ // if (Math.abs(this.prevLevel - this.level) >= 2) {
279
+ if (this.level - this.prevLevel >= 2) {
280
+ if (this.level === 2) {
281
+ // Note, after pushing processing may continue or exit, depending on the error and/or the bail threshold.
282
+ this.errorHandler.pushOrBail(ctx, 'Syntax-Error', 'Invalid section header level ' +
283
+ this.level +
284
+ ', with section name "' +
285
+ sectionName, 'A section header may not start directly at level ' +
286
+ this.level +
287
+ ', skipping previous section levels. Please start with one level further down.');
288
+ }
289
+ else {
290
+ // Note, after pushing processing may continue or exit, depending on the error and/or the bail threshold.
291
+ this.errorHandler.pushOrBail(ctx, 'Syntax-Error', 'Invalid section level jump of section header "' +
292
+ sectionName +
293
+ '"', 'Section header name "' +
294
+ sectionName +
295
+ '" with level ' +
296
+ this.level +
297
+ ' may not jump over (skip) intermediate section levels, from section header name "' +
298
+ this.prevSectionName +
299
+ '" with level ' +
300
+ this.prevLevel +
301
+ '. Section levels should increase one at a time. Please adjust your section headers accordingly.');
302
+ }
303
+ }
304
+ }
305
+ this.prevSectionName = sectionName;
306
+ (0, system_1.debugPrint)('About to visit members of section...');
307
+ let members;
308
+ if (!ctx.section_members()) {
309
+ (0, system_1.debugPrint)('(!) Section has no members!');
310
+ }
311
+ else {
312
+ members = this.visitSection_members(ctx.section_members());
313
+ }
314
+ // ---------------------------------------------------------------
315
+ (_c = ctx.children) === null || _c === void 0 ? void 0 : _c.forEach((child) => {
316
+ (0, system_1.debugPrint)('* child: ' + child);
317
+ });
318
+ if (this.level === 1) {
319
+ this.numOfLevelOnes++;
320
+ }
321
+ //------------------------
322
+ // if (nestDirection === 'higher') {
323
+ // debugPrint(
324
+ // `Is level skipping: ${this.level - this.prevLevel} >= 2?`,
325
+ // )
326
+ // // if (Math.abs(this.prevLevel - this.level) >= 2) {
327
+ // if (this.level - this.prevLevel >= 2) {
328
+ // // Note, after pushing processing may continue or exit, depending on the error and/or the bail threshold.
329
+ // this.errorHandler!.pushOrBail(
330
+ // ctx,
331
+ // 'Syntax-Error',
332
+ // 'Invalid section level jump of section header "' +
333
+ // sectionName +
334
+ // '"',
335
+ // 'Section header name "' +
336
+ // sectionName +
337
+ // '" with level ' +
338
+ // this.prevLevel +
339
+ // ' may not jump over previous section levels, from a section with level ' +
340
+ // this.level +
341
+ // ' (section name: "' +
342
+ // this.prevSectionName +
343
+ // '").',
344
+ // )
345
+ // }
346
+ // }
347
+ // this.prevSectionName = sectionName
348
+ if (nestDirection !== 'higher') {
349
+ (0, system_1.debugPrint)('About to reset result');
350
+ (0, system_1.printObject)({ [sectionName]: members });
351
+ (0, system_1.debugPrint)(`Current lastActiveSectionAtLevels[${this.level - 1}]`);
352
+ (0, system_1.printObject)(this.lastActiveSectionAtLevels[this.level - 1]);
353
+ if (
354
+ // (level === 0 && !sectionName) ||
355
+ // (sectionName === 'undefined' && !!members)
356
+ sectionLevel === 0 &&
357
+ sectionName === 'undefined' &&
358
+ !!members) {
359
+ (0, system_1.debugPrint)('HIT2!!!!');
360
+ (0, system_1.debugPrint)('(!) Detected a member (that does not have a sectionName), but a memberless object in "members"');
361
+ sectionName = Object.keys(members)[0];
362
+ (0, system_1.debugPrint)('sectionName = ' + sectionName);
363
+ members = {};
364
+ // this.lastActiveSectionAtLevels[0] = { [sectionName]: {} }
365
+ // this.pushOnTree({ level: 1, name: sectionName, members: {} })
366
+ (0, system_1.debugPrint)('(!) Skipping mounted since this is actually a memberless section');
367
+ (0, system_1.debugPrint)();
368
+ (0, system_1.debugPrint)('<- Leaving visitSection(..) EARLY');
369
+ if ((0, env_1.isDebug)()) {
370
+ console.log('returning (a memberless section):');
371
+ console.log({
372
+ level: 1,
373
+ name: sectionName,
374
+ members: members,
375
+ });
376
+ console.log();
377
+ }
378
+ return {
379
+ level: 1,
380
+ name: sectionName,
381
+ members: members,
382
+ };
383
+ }
384
+ else {
385
+ // Mount as append
386
+ this.lastActiveSectionAtLevels[this.level - 1] = {
387
+ [sectionName]: Object.assign({}, members),
388
+ };
389
+ this.pushOnTree({
390
+ level: sectionLevel,
391
+ name: sectionName,
392
+ members,
393
+ });
394
+ // this.lastActiveSectionNameAtLevels.push(sectionName)
395
+ (0, system_1.debugPrint)('Mounted as append');
396
+ }
397
+ (0, system_1.debugPrint)(`After: lastActiveSectionAtLevels[${this.level - 1}]`);
398
+ (0, system_1.printObject)(this.lastActiveSectionAtLevels[this.level - 1]);
399
+ if ((0, env_1.isDebug)()) {
400
+ console.log(`After append lastActiveSectionAtLevels[${this.level - 1}]`);
401
+ (0, system_1.printObject)(this.lastActiveSectionAtLevels[this.level - 1]);
402
+ (0, system_1.debugPrint)('Before this.lastActiveSectionNameAtLevels:');
403
+ (0, system_1.printObject)(this.lastActiveSectionNameAtLevels);
404
+ // Reset.
405
+ let i = this.level;
406
+ while (this.lastActiveSectionNameAtLevels[i]) {
407
+ this.lastActiveSectionNameAtLevels[i++] = undefined;
408
+ }
409
+ (0, system_1.debugPrint)('After this.lastActiveSectionNameAtLevels:');
410
+ (0, system_1.printObject)(this.lastActiveSectionNameAtLevels);
411
+ }
412
+ (0, system_1.debugPrint)('HIT!!! - Just a lower or same level section, a continues full (nested) section,');
413
+ (0, system_1.debugPrint)(`Has above in lastActiveSectionAtLevels[${this.level - 1}]`);
414
+ (0, system_1.debugPrint)(' this.level: ' + this.level);
415
+ (0, system_1.debugPrint)('this.prevLevel: ' + this.prevLevel);
416
+ (0, system_1.debugPrint)(' this.level: ' + this.level);
417
+ (0, system_1.debugPrint)();
418
+ (0, system_1.debugPrint)(' HERE.... Should mount section to correct section at this.level: ' +
419
+ this.level);
420
+ //this.lastActiveSectionNameAtLevels[this.level - 1] = sectionName
421
+ (0, system_1.debugPrint)();
422
+ (0, system_1.debugPrint)('Resetted local result');
423
+ sectionName = '';
424
+ members = undefined;
425
+ }
426
+ //------------------------
427
+ (0, system_1.debugPrint)();
428
+ if ((0, env_1.isDebug)()) {
429
+ if (members) {
430
+ (0, system_1.printObject)({ [sectionName]: members });
431
+ this.lastActiveSectionAtLevels[this.level - 1] = Object.assign({}, members);
432
+ // this.lastActiveSectionNameAtLevels[this.level - 1] = sectionName
433
+ (0, system_1.debugPrint)('Mounted as assigned');
434
+ (0, system_1.debugPrint)(`lastActiveSectionAtLevels[${this.level - 1}]`);
435
+ (0, system_1.printObject)(this.lastActiveSectionAtLevels[this.level - 1]);
436
+ }
437
+ }
438
+ (0, system_1.debugPrint)('-----------------------');
439
+ if ((0, env_1.isDebug)()) {
440
+ console.log('At end of visitSection(..), this.lastActiveSectionNameAtLevels:');
441
+ (0, system_1.printObject)(this.lastActiveSectionNameAtLevels);
442
+ (0, system_1.debugPrint)(' this.level: ' + this.level);
443
+ (0, system_1.debugPrint)('this.prevLevel: ' + this.prevLevel);
444
+ (0, system_1.debugPrint)(' this.level: ' + this.level);
445
+ (0, system_1.debugPrint)('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
446
+ (0, system_1.debugPrint)('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
447
+ console.log();
448
+ }
449
+ (0, system_1.debugPrint)('<- Leaving visitSection(..)');
450
+ if ((0, env_1.isDebug)()) {
451
+ console.log('returning:');
452
+ console.log({
453
+ sectionLevel: sectionLevel,
454
+ name: sectionName,
455
+ members: members,
456
+ });
457
+ console.log();
458
+ }
459
+ return {
460
+ level: sectionLevel,
461
+ name: sectionName,
462
+ members: members,
463
+ };
464
+ };
465
+ /**
466
+ * Visit a parse tree produced by `YiniParser.section_members`.
467
+ * In here will mount object onto members object.
468
+ * @param ctx the parse tree
469
+ * @returns { key: value, ... }
470
+ */
471
+ // visitSection_members = (ctx: Section_membersContext): Record<string, any> => {
472
+ // visitSection_members = (ctx: Section_membersContext): any => {
473
+ this.visitSection_members = (ctx) => {
474
+ (0, env_1.isDebug)() && console.log();
475
+ (0, system_1.debugPrint)('************************************************************');
476
+ (0, system_1.debugPrint)('-> Entered visitSection_members(..)');
477
+ const members = {};
478
+ (0, system_1.debugPrint)('Will loop through each member (or section head)...');
479
+ ctx.member_list().forEach((member) => {
480
+ const { type, key, value } = this.visitMember(member);
481
+ (0, system_1.debugPrint)('+++++++++++++++++++++++++++++++++++++++++++++++++++++');
482
+ (0, system_1.debugPrint)('* Item of member_list:');
483
+ if ((0, env_1.isDebug)()) {
484
+ console.log(value);
485
+ }
486
+ (0, system_1.debugPrint)(' type = >>>' + type + '<<<');
487
+ (0, system_1.debugPrint)(' key = >>>' + key + '<<<');
488
+ (0, system_1.debugPrint)('value = >>>' + value + '<<<');
489
+ (0, system_1.debugPrint)('value[key] = >>>' + (value === null || value === void 0 ? void 0 : value[key]) + '<<<');
490
+ (0, system_1.debugPrint)('--');
491
+ if (key === '') {
492
+ (0, system_1.debugPrint)('Skipping this member, due to key = ""');
493
+ }
494
+ else {
495
+ if (members[key] !== undefined) {
496
+ // Note, after pushing processing may continue or exit, depending on the error and/or the bail threshold.
497
+ this.errorHandler.pushOrBail(ctx, 'Syntax-Error', 'Key already exists in this section scope (in this main section), key name: ' +
498
+ key);
499
+ }
500
+ else {
501
+ this.meta_numOfMembers++;
502
+ if ((value === null || value === void 0 ? void 0 : value.type) === 'Null') {
503
+ members[key] = null;
504
+ }
505
+ else {
506
+ (0, env_1.isDebug)() && console.log();
507
+ // NOTE: (!) Only if nested section.
508
+ (0, system_1.debugPrint)('About to mount a single member or section onto members...');
509
+ (0, env_1.isDebug)() && console.log({ [key]: value });
510
+ Object.assign(members, { [key]: value });
511
+ (0, system_1.debugPrint)('+ Added member or section onto members: "' +
512
+ key +
513
+ '"');
514
+ }
515
+ }
516
+ }
517
+ });
518
+ if ((0, env_1.isDebug)()) {
519
+ (0, system_1.debugPrint)('~~~ After mounting in visitSection_members(..) ~~~~~~~~~~');
520
+ (0, system_1.debugPrint)('this.resultSections:');
521
+ (0, system_1.debugPrint)('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~');
522
+ }
523
+ //@todo handle member colon list
524
+ // ctx..member_colon_list().forEach((mcl) => {
525
+ // const { key, value } = this.visit(mcl)
526
+ // members[key] = value
527
+ // })
528
+ (0, system_1.debugPrint)();
529
+ (0, system_1.debugPrint)('<- Leaving visitSection_members(..)');
530
+ if ((0, env_1.isDebug)()) {
531
+ console.log('returning:');
532
+ console.log(members);
533
+ console.log();
534
+ }
535
+ return members;
536
+ };
537
+ /**
538
+ * Visit every single section or member (any key-value pair such as
539
+ * key=value or key=[...] etc.).
540
+ * @returns {
541
+ type: resultType,
542
+ key: resultKey,
543
+ value: resultValue,
544
+ }: IResult
545
+ */
546
+ // visitMember?: (ctx: MemberContext) => IResult;
547
+ this.visitMember = (ctx) => {
548
+ var _a, _b, _c, _d;
549
+ (0, env_1.isDebug)() && console.log();
550
+ (0, system_1.debugPrint)('-> Entered visitMember(..)');
551
+ (0, system_1.debugPrint)(' key = ' + ((_a = ctx.KEY()) === null || _a === void 0 ? void 0 : _a.getText().trim()));
552
+ (0, system_1.debugPrint)('Or, section head = ' +
553
+ ((_b = ctx.SECTION_HEAD()) === null || _b === void 0 ? void 0 : _b.getText().trim()) +
554
+ ' (head WITHOUT any members (ONLY detected here))');
555
+ (0, system_1.debugPrint)(' ctx.value() = ' + ctx.value());
556
+ // For logging and debugging purposes.
557
+ let entityType = 'Unknown';
558
+ let resultType = undefined;
559
+ let resultKey = '';
560
+ let resultValue = {};
561
+ let followingSection = null;
562
+ // NOTE: (!) It can never be both a key and section head.
563
+ if ((_c = ctx.KEY()) === null || _c === void 0 ? void 0 : _c.getText().trim()) {
564
+ entityType = 'Member-Key';
565
+ try {
566
+ resultKey = ctx.KEY().getText();
567
+ }
568
+ catch (error) {
569
+ (0, system_1.debugPrint)('in catch..');
570
+ const msg = `Unexpected syntax while parsing a member (key-value pair)`;
571
+ // Note, after pushing processing may continue or exit, depending on the error and/or the bail threshold.
572
+ this.errorHandler.pushOrBail(ctx, 'Syntax-Error', msg);
573
+ }
574
+ const result = ctx.value()
575
+ ? this.visitValue(ctx.value())
576
+ : null;
577
+ resultType = result === null || result === void 0 ? void 0 : result.type;
578
+ resultValue = result === null || result === void 0 ? void 0 : result.value;
579
+ (0, system_1.debugPrint)(' type = ' + resultType + ' @visitValue(..)');
580
+ (0, system_1.debugPrint)('value = ' + resultValue + ' @visitValue(..)');
581
+ }
582
+ else if ((_d = ctx.SECTION_HEAD()) === null || _d === void 0 ? void 0 : _d.getText().trim()) {
583
+ entityType = 'Section-Head';
584
+ //NOTE: There might be an issue here that some subsection gets missing!!
585
+ // const line = '' + ctx.SECTION_HEAD().getText().trim()
586
+ const line = ctx.SECTION_HEAD().getText().trim();
587
+ (0, system_1.debugPrint)('(!) Detected a section head instead: ' + line);
588
+ followingSection = this.visitSection(ctx);
589
+ // Object.assign(members, sectionObj)
590
+ (0, system_1.debugPrint)('Got constructed object of builtSection (visitSection(..):');
591
+ if ((0, env_1.isDebug)()) {
592
+ console.log(followingSection);
593
+ }
594
+ //@todo (Is this fixed now? 2025-07-10) Mount the nested object correctly!
595
+ resultType = 'Object';
596
+ // resultValue[nestedSection?.name] = nestedSection?.members
597
+ resultValue = (followingSection === null || followingSection === void 0 ? void 0 : followingSection.members) || {};
598
+ resultKey = followingSection.name;
599
+ (0, system_1.debugPrint)("resultKey = '" + resultKey + "'");
600
+ (0, system_1.debugPrint)('resultValue:');
601
+ if ((0, env_1.isDebug)()) {
602
+ (0, system_1.printObject)(resultValue);
603
+ }
604
+ (0, system_1.debugPrint)('Mounted/assigned a section onto resultValue...');
605
+ // Object.assign(value, { dummy: 6767 })
606
+ // Object.assign(resultValue, {
607
+ // dummy: 'That was detected a section head instead!',
608
+ // })
609
+ (0, system_1.debugPrint)();
610
+ }
611
+ (0, system_1.debugPrint)();
612
+ (0, system_1.debugPrint)("entity = '" + entityType + "'");
613
+ (0, system_1.debugPrint)("resultType = '" + resultType + "'");
614
+ (0, system_1.debugPrint)("resultKey = '" + resultKey + "'");
615
+ if (resultKey) {
616
+ (0, system_1.debugPrint)();
617
+ (0, system_1.debugPrint)('Has a key... Validate it either as a simple or a backticked ident...');
618
+ if ((0, string_1.isEnclosedInBackticks)(resultKey)) {
619
+ if (!(0, yiniHelpers_1.isValidBacktickedIdent)(resultKey)) {
620
+ this.errorHandler.pushOrBail(ctx, 'Syntax-Error', 'Invalid key name of this member, backticked key/identifier: "' +
621
+ resultKey +
622
+ '"', 'Section name should be backticked like e.g. `My section name`.');
623
+ }
624
+ resultKey = (0, string_1.trimBackticks)(resultKey);
625
+ (0, system_1.debugPrint)("resultKey = '" + resultKey + "' (trimBackticks)");
626
+ }
627
+ else {
628
+ if (!(0, yiniHelpers_1.isValidSimpleIdent)(resultKey)) {
629
+ this.errorHandler.pushOrBail(ctx, 'Syntax-Error', 'Invalid key name of this member, key/identifier: "' +
630
+ resultKey +
631
+ '"', 'Section name must start with: A-Z, a-z, or _, unless enclosed in backticks e.g. `' +
632
+ resultKey +
633
+ '`, `My key name`.');
634
+ }
635
+ }
636
+ }
637
+ if (resultValue === undefined) {
638
+ (0, system_1.debugPrint)('Detected value as undefined');
639
+ if (!this.isStrict) {
640
+ (0, system_1.debugPrint)('Overloading undefined value with null');
641
+ resultValue = null;
642
+ }
643
+ else {
644
+ this.errorHandler.pushOrBail(ctx, 'Syntax-Error', 'Encountered an empty/missing value in strict mode', 'Expected a value but found nothing, strict mode does not allow implicit null.', 'If you intend to have a null value, please specify "null" explicitly as the value.');
645
+ }
646
+ }
647
+ (0, system_1.debugPrint)('*** Constructed JS object ***');
648
+ (0, system_1.debugPrint)('resultValue:');
649
+ if ((0, env_1.isDebug)()) {
650
+ console.log(resultValue);
651
+ }
652
+ (0, system_1.debugPrint)();
653
+ (0, system_1.debugPrint)('<- About to leave visitMember(..)');
654
+ if ((0, env_1.isDebug)()) {
655
+ console.log('returning:');
656
+ console.log({
657
+ type: resultType,
658
+ key: resultKey,
659
+ value: resultValue,
660
+ });
661
+ console.log();
662
+ }
663
+ if (!resultType && !resultKey) {
664
+ // Note, after pushing processing may continue or exit, depending on the error and/or the bail threshold.
665
+ this.errorHandler.pushOrBail(ctx, 'Syntax-Error', 'Unknown input');
666
+ }
667
+ // if (!isValidSimpleIdent(resultKey)) {
668
+ // if (resultType !== 'Object' && !isValidSimpleIdent(resultKey)) {
669
+ // this.errorHandler!.pushOrBail(
670
+ // ctx,
671
+ // 'Syntax-Error',
672
+ // 'Invalid name of this key of a member, key name: "' +
673
+ // resultKey +
674
+ // '"',
675
+ // 'Key name must start with: A-Z, a-z, or _, unless enclosed in backticks e.g. `' +
676
+ // resultKey +
677
+ // '`, `My key name`.',
678
+ // )
679
+ // }
680
+ (0, system_1.debugPrint)();
681
+ (0, system_1.debugPrint)('<- Leaving visitMember(..)');
682
+ if ((0, env_1.isDebug)()) {
683
+ console.log('returning:');
684
+ console.log({
685
+ type: resultType,
686
+ key: resultKey,
687
+ value: resultValue,
688
+ });
689
+ console.log();
690
+ }
691
+ return {
692
+ type: resultType,
693
+ key: resultKey,
694
+ value: resultValue,
695
+ };
696
+ };
697
+ /**
698
+ * Visit a parse tree produced by `YiniParser.member_colon_list`.
699
+ * @param ctx the parse tree
700
+ * @return the visitor result
701
+ */
702
+ //visitMember_colon_list?: (ctx: Member_colon_listContext) => IResult
703
+ this.visitMember_colon_list = (ctx) => {
704
+ (0, env_1.isDebug)() && console.log();
705
+ (0, system_1.debugPrint)('-> Entered visitMember_colon_list(..)');
706
+ const key = ctx.KEY().getText();
707
+ const values = this.visit(ctx.elements());
708
+ return { key, value: values };
709
+ };
710
+ /**
711
+ * Visit a parse tree produced by `YiniParser.value`.
712
+ * @param ctx the parse tree
713
+ * @return the visitor result
714
+ */
715
+ // visitValue?: (ctx: ValueContext) => IResult
716
+ this.visitValue = (ctx) => {
717
+ (0, env_1.isDebug)() && console.log();
718
+ (0, system_1.debugPrint)('-> Entered visitValue(..)');
719
+ (0, system_1.debugPrint)('ctx.number_literal(): ' + ctx.number_literal());
720
+ (0, system_1.debugPrint)('ctx.boolean_literal(): ' + ctx.boolean_literal());
721
+ if (ctx.string_literal())
722
+ return this.visit(ctx.string_literal());
723
+ if (ctx.number_literal())
724
+ return this.visit(ctx.number_literal());
725
+ if (ctx.boolean_literal())
726
+ return this.visit(ctx.boolean_literal());
727
+ if (ctx.null_literal())
728
+ return this.visit(ctx.null_literal());
729
+ if (ctx.object_literal())
730
+ return this.visit(ctx.object_literal());
731
+ // if (ctx.list()) return this.visit(ctx.list())
732
+ // if (ctx.string_concat()) return this.visit(ctx.string_concat())
733
+ return null;
734
+ };
735
+ /**
736
+ * Visit a parse tree produced by `YiniParser.string_literal`.
737
+ * @param ctx the parse tree
738
+ * @return the visitor result
739
+ */
740
+ // visitString_literal?: (ctx: String_literalContext) => Result
741
+ this.visitString_literal = (ctx) => {
742
+ (0, system_1.debugPrint)('-> Entered visitString_literal(..)');
743
+ const raw = ctx.getText();
744
+ (0, system_1.debugPrint)('raw = >>>' + raw + '<<<');
745
+ const value = (0, parseString_1.default)(raw);
746
+ return { type: 'String', value };
747
+ };
748
+ /**
749
+ * Visit a parse tree produced by `YiniParser.number_literal`.
750
+ * @param ctx the parse tree
751
+ * @return the visitor result
752
+ */
753
+ // visitNumber_literal?: (ctx: Number_literalContext) => IResult
754
+ this.visitNumber_literal = (ctx) => {
755
+ (0, system_1.debugPrint)('-> Entered visitNumber_literal(..)');
756
+ const txt = ctx.getText();
757
+ const { type, value } = (0, parseNumber_1.default)(txt);
758
+ return { type, value };
759
+ };
760
+ /**
761
+ * Visit a parse tree produced by `YiniParser.boolean_literal`.
762
+ * @param ctx the parse tree
763
+ * @return the visitor result
764
+ */
765
+ //visitBoolean_literal?: (ctx: Boolean_literalContext) => IResult
766
+ this.visitBoolean_literal = (ctx) => {
767
+ (0, system_1.debugPrint)('-> Entered visitBoolean_literal(..)');
768
+ const txt = ctx.getText().toLowerCase();
769
+ // return ['true', 'yes', 'on'].includes(text) as IResult
770
+ const value = (0, parseBoolean_1.default)(txt);
771
+ return { type: 'Boolean', value };
772
+ };
773
+ /**
774
+ * Visit a parse tree produced by `YiniParser.null_literal`.
775
+ * @param ctx the parse tree
776
+ * @return the visitor result
777
+ */
778
+ this.visitNull_literal = (ctx) => {
779
+ (0, system_1.debugPrint)('-> Entered visitNull_literal(..)');
780
+ const txt = ctx.getText();
781
+ const value = (0, parseNull_1.default)(txt);
782
+ return { type: 'Null', value };
783
+ };
784
+ /**
785
+ * Visit a parse tree produced by `YiniParser.object_literal`.
786
+ * @param ctx the parse tree
787
+ * @return the visitor result
788
+ */
789
+ // visitObject_literal?: (ctx: Object_literalContext) => IResult
790
+ this.visitObject_literal = (ctx) => {
791
+ const members = ctx.objectMemberList()
792
+ ? this.visit(ctx.objectMemberList())
793
+ : {};
794
+ return { type: 'Object', value: members };
795
+ };
796
+ /**
797
+ * Visit a parse tree produced by `YiniParser.objectMemberList`.
798
+ * @param ctx the parse tree
799
+ * @return the visitor result
800
+ */
801
+ //visitObjectMemberList?: (ctx: ObjectMemberListContext) => IResult
802
+ this.visitObjectMemberList = (ctx) => {
803
+ const obj = {};
804
+ ctx.objectMember_list().forEach((member) => {
805
+ const { key, value } = this.visit(member);
806
+ obj[key] = value;
807
+ });
808
+ return obj;
809
+ };
810
+ /**
811
+ * Visit a parse tree produced by `YiniParser.objectMember`.
812
+ * @param ctx the parse tree
813
+ * @return the visitor result
814
+ */
815
+ // visitObjectMember?: (ctx: ObjectMemberContext) => IResult
816
+ this.visitObjectMember = (ctx) => {
817
+ const key = ctx.KEY().getText();
818
+ const value = ctx.value() ? this.visit(ctx.value()) : null;
819
+ return { key, value };
820
+ };
821
+ /**
822
+ * Visit a parse tree produced by `YiniParser.list`.
823
+ * @param ctx the parse tree
824
+ * @return the visitor result
825
+ */
826
+ // visitList?: (ctx: ListContext) => IResult
827
+ this.visitList = (ctx) => this.visit(ctx.list_in_brackets());
828
+ /**
829
+ * Visit a parse tree produced by `YiniParser.list_in_brackets`.
830
+ * @param ctx the parse tree
831
+ * @return the visitor result
832
+ */
833
+ // visitList_in_brackets?: (ctx: List_in_bracketsContext) => IResult
834
+ this.visitList_in_brackets = (ctx) => {
835
+ const elements = ctx.elements() ? this.visit(ctx.elements()) : [];
836
+ return { type: 'List', value: elements };
837
+ };
838
+ /**
839
+ * Visit a parse tree produced by `YiniParser.element`.
840
+ * @param ctx the parse tree
841
+ * @return the visitor result
842
+ */
843
+ // visitElement?: (ctx: ElementContext) => IResult
844
+ this.visitElement = (ctx) => {
845
+ if (ctx.value()) {
846
+ return this.visit(ctx.value());
847
+ }
848
+ else {
849
+ return { type: 'Null', value: null };
850
+ }
851
+ };
852
+ this.errorHandler = errorHandler;
853
+ this.isStrict = isStrict;
854
+ }
855
+ }
856
+ exports.default = YINIVisitor;