yini-parser 1.4.3 → 1.6.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 +52 -0
- package/README.md +187 -35
- package/dist/YINI.d.ts +29 -18
- package/dist/YINI.js +104 -3
- package/dist/core/astBuilder.d.ts +94 -18
- package/dist/core/astBuilder.js +439 -376
- package/dist/core/errorDataHandler.d.ts +6 -1
- package/dist/core/errorDataHandler.js +30 -43
- package/dist/core/internalTypes.d.ts +10 -1
- package/dist/core/objectBuilder.d.ts +8 -4
- package/dist/core/objectBuilder.js +47 -62
- package/dist/core/options/defaultParserOptions.d.ts +3 -2
- package/dist/core/options/defaultParserOptions.js +11 -2
- package/dist/core/options/optionsFunctions.js +6 -4
- package/dist/core/parsingRules/modeFromRulesMatcher.d.ts +1 -1
- package/dist/core/parsingRules/modeFromRulesMatcher.js +22 -13
- package/dist/core/pipeline/pipeline.js +35 -10
- package/dist/core/runtime.js +28 -19
- package/dist/grammar/generated/YiniLexer.d.ts +40 -53
- package/dist/grammar/generated/YiniLexer.js +357 -356
- package/dist/grammar/generated/YiniParser.d.ts +174 -118
- package/dist/grammar/generated/YiniParser.js +1185 -929
- package/dist/grammar/generated/YiniParserVisitor.d.ts +82 -19
- package/dist/grammar/generated/YiniParserVisitor.js +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +4 -3
- package/dist/parsers/extractHeaderParts.d.ts +12 -19
- package/dist/parsers/extractHeaderParts.js +57 -46
- package/dist/parsers/parseNumber.d.ts +24 -6
- package/dist/parsers/parseNumber.js +114 -49
- package/dist/parsers/parseSectionHeader.d.ts +11 -3
- package/dist/parsers/parseSectionHeader.js +55 -43
- package/dist/parsers/parseString.js +39 -20
- package/dist/parsers/validateShebangPlacement.d.ts +3 -0
- package/dist/parsers/validateShebangPlacement.js +52 -0
- package/dist/types/index.d.ts +20 -3
- package/dist/utils/print.d.ts +1 -0
- package/dist/utils/print.js +5 -1
- package/dist/utils/string.d.ts +1 -0
- package/dist/utils/string.js +17 -1
- package/dist/utils/system.d.ts +1 -0
- package/dist/utils/system.js +6 -1
- package/dist/utils/yiniHelpers.d.ts +44 -2
- package/dist/utils/yiniHelpers.js +134 -46
- package/examples/compare-formats.md +1 -1
- package/examples/nested.yini +1 -1
- package/package.json +11 -3
- package/dist/YINI.js.map +0 -1
- package/dist/config/env.js.map +0 -1
- package/dist/core/astBuilder.js.map +0 -1
- package/dist/core/errorDataHandler.js.map +0 -1
- package/dist/core/internalTypes.js.map +0 -1
- package/dist/core/objectBuilder.js.map +0 -1
- package/dist/core/options/defaultParserOptions.js.map +0 -1
- package/dist/core/options/failLevel.js.map +0 -1
- package/dist/core/options/optionsFunctions.js.map +0 -1
- package/dist/core/parsingRules/modeFromRulesMatcher.js.map +0 -1
- package/dist/core/parsingRules/rulesConstAndGuards.js.map +0 -1
- package/dist/core/pipeline/errorListeners.js.map +0 -1
- package/dist/core/pipeline/pipeline.js.map +0 -1
- package/dist/core/resultMetadataBuilder.js.map +0 -1
- package/dist/core/runtime.js.map +0 -1
- package/dist/dev/main.d.ts +0 -1
- package/dist/dev/main.js +0 -168
- package/dist/dev/main.js.map +0 -1
- package/dist/dev/quick-test-samples/defect-inputs.d.ts +0 -37
- package/dist/dev/quick-test-samples/defect-inputs.js +0 -106
- package/dist/dev/quick-test-samples/defect-inputs.js.map +0 -1
- package/dist/dev/quick-test-samples/valid-inputs.d.ts +0 -21
- package/dist/dev/quick-test-samples/valid-inputs.js +0 -422
- package/dist/dev/quick-test-samples/valid-inputs.js.map +0 -1
- package/dist/grammar/generated/YiniLexer.js.map +0 -1
- package/dist/grammar/generated/YiniParser.js.map +0 -1
- package/dist/grammar/generated/YiniParserVisitor.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/parsers/extractHeaderParts.js.map +0 -1
- package/dist/parsers/extractSignificantYiniLine.js.map +0 -1
- package/dist/parsers/parseBoolean.js.map +0 -1
- package/dist/parsers/parseNull.js.map +0 -1
- package/dist/parsers/parseNumber.js.map +0 -1
- package/dist/parsers/parseSectionHeader.js.map +0 -1
- package/dist/parsers/parseString.js.map +0 -1
- package/dist/types/index.js.map +0 -1
- package/dist/utils/number.js.map +0 -1
- package/dist/utils/object.js.map +0 -1
- package/dist/utils/pathAndFileName.js.map +0 -1
- package/dist/utils/print.js.map +0 -1
- package/dist/utils/string.js.map +0 -1
- package/dist/utils/system.js.map +0 -1
- package/dist/utils/yiniHelpers.js.map +0 -1
|
@@ -8,6 +8,7 @@ export declare class ErrorDataHandler {
|
|
|
8
8
|
private readonly subjectType;
|
|
9
9
|
private readonly fileName;
|
|
10
10
|
private readonly persistThreshold;
|
|
11
|
+
private readonly isDiagnosticOutputEnabled;
|
|
11
12
|
private readonly isQuiet;
|
|
12
13
|
private readonly isSilent;
|
|
13
14
|
private readonly isThrowOnError;
|
|
@@ -30,7 +31,8 @@ export declare class ErrorDataHandler {
|
|
|
30
31
|
- Level 1 = abort on errors only
|
|
31
32
|
- Level 2 = abort even on warnings
|
|
32
33
|
*/
|
|
33
|
-
constructor(subjectType: TSubjectType, fileName?: string | undefined, bailSensitivityLevel?: TBailSensitivityLevel,
|
|
34
|
+
constructor(subjectType: TSubjectType, fileName?: string | undefined, bailSensitivityLevel?: TBailSensitivityLevel, isDiagnosticOutputEnabled?: boolean, // Opt in to writing diagnostics to stderr.
|
|
35
|
+
isQuiet?: boolean, // When diagnostic output is enabled, show errors only.
|
|
34
36
|
isSilent?: boolean, // Suppress all output (even errors, exit code only).
|
|
35
37
|
isThrowOnError?: boolean);
|
|
36
38
|
private makeIssue;
|
|
@@ -50,6 +52,9 @@ export declare class ErrorDataHandler {
|
|
|
50
52
|
*/
|
|
51
53
|
pushOrBail(locInput: IErrorLocationInput | undefined, type: TIssueType, msgWhat: string, msgWhy?: string, msgHint?: string): void;
|
|
52
54
|
private formatSignificantMessageLine;
|
|
55
|
+
private shouldEmitDiagnostics;
|
|
56
|
+
private shouldEmitNonErrors;
|
|
57
|
+
private emitDiagnosticToStderr;
|
|
53
58
|
private emitFatalError;
|
|
54
59
|
private emitInternalError;
|
|
55
60
|
private emitSyntaxError;
|
|
@@ -42,7 +42,8 @@ class ErrorDataHandler {
|
|
|
42
42
|
- Level 1 = abort on errors only
|
|
43
43
|
- Level 2 = abort even on warnings
|
|
44
44
|
*/
|
|
45
|
-
constructor(subjectType, fileName = undefined, bailSensitivityLevel = '1-Abort-on-Errors',
|
|
45
|
+
constructor(subjectType, fileName = undefined, bailSensitivityLevel = '1-Abort-on-Errors', isDiagnosticOutputEnabled = false, // Opt in to writing diagnostics to stderr.
|
|
46
|
+
isQuiet = false, // When diagnostic output is enabled, show errors only.
|
|
46
47
|
isSilent = false, // Suppress all output (even errors, exit code only).
|
|
47
48
|
isThrowOnError = false) {
|
|
48
49
|
this.errors = [];
|
|
@@ -58,6 +59,7 @@ class ErrorDataHandler {
|
|
|
58
59
|
this.subjectType = subjectType;
|
|
59
60
|
this.fileName = fileName;
|
|
60
61
|
this.persistThreshold = bailSensitivityLevel;
|
|
62
|
+
this.isDiagnosticOutputEnabled = isDiagnosticOutputEnabled;
|
|
61
63
|
this.isQuiet = isQuiet;
|
|
62
64
|
this.isSilent = isSilent;
|
|
63
65
|
this.isThrowOnError = isThrowOnError;
|
|
@@ -118,8 +120,8 @@ class ErrorDataHandler {
|
|
|
118
120
|
lineNum: lineNum || 0, // 1-based, if n/a use 0.
|
|
119
121
|
colNum: colNum || 0, // 1-based, if n/a use 0.
|
|
120
122
|
};
|
|
121
|
-
if (
|
|
122
|
-
console.
|
|
123
|
+
if (this.shouldEmitDiagnostics()) {
|
|
124
|
+
console.error(); // Print an empty line before outputting message.
|
|
123
125
|
}
|
|
124
126
|
switch (type) {
|
|
125
127
|
case 'Internal-Error':
|
|
@@ -229,68 +231,53 @@ class ErrorDataHandler {
|
|
|
229
231
|
}
|
|
230
232
|
}
|
|
231
233
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
234
|
+
shouldEmitDiagnostics() {
|
|
235
|
+
return this.isDiagnosticOutputEnabled && !this.isSilent;
|
|
236
|
+
}
|
|
237
|
+
shouldEmitNonErrors() {
|
|
238
|
+
return this.shouldEmitDiagnostics() && !this.isQuiet;
|
|
239
|
+
}
|
|
240
|
+
emitDiagnosticToStderr(write, messageHeader, msgWhat = '', msgWhy = '', msgHint = '') {
|
|
241
|
+
write(messageHeader);
|
|
242
|
+
msgWhat && write(msgWhat);
|
|
243
|
+
msgWhy && write(msgWhy);
|
|
244
|
+
msgHint && write(msgHint);
|
|
245
|
+
write();
|
|
246
|
+
}
|
|
236
247
|
emitFatalError(loc, msgWhat = 'Something went wrong!', msgWhy = '', msgHint = '') {
|
|
237
248
|
const messageHeader = this.formatSignificantMessageLine(loc, issueTitle[0]);
|
|
238
|
-
if (
|
|
239
|
-
console.error(
|
|
240
|
-
msgWhat && console.log(msgWhat);
|
|
241
|
-
msgWhy && console.log(msgWhy);
|
|
242
|
-
msgHint && console.log(msgHint);
|
|
243
|
-
console.log(); // Emit an empty line before outputting message.
|
|
249
|
+
if (this.shouldEmitDiagnostics()) {
|
|
250
|
+
this.emitDiagnosticToStderr(console.error.bind(console), messageHeader, msgWhat, msgWhy, msgHint);
|
|
244
251
|
}
|
|
245
252
|
}
|
|
246
253
|
emitInternalError(loc, msgWhat = 'Something went wrong!', msgWhy = '', msgHint = '') {
|
|
247
254
|
const messageHeader = this.formatSignificantMessageLine(loc, issueTitle[1]);
|
|
248
|
-
if (
|
|
249
|
-
console.error(
|
|
250
|
-
msgWhat && console.log(msgWhat);
|
|
251
|
-
msgWhy && console.log(msgWhy);
|
|
252
|
-
msgHint && console.log(msgHint);
|
|
253
|
-
console.log(); // Emit an empty line before outputting message.
|
|
255
|
+
if (this.shouldEmitDiagnostics()) {
|
|
256
|
+
this.emitDiagnosticToStderr(console.error.bind(console), messageHeader, msgWhat, msgWhy, msgHint);
|
|
254
257
|
}
|
|
255
258
|
}
|
|
256
259
|
emitSyntaxError(loc, msgWhat, msgWhy = '', msgHint = '') {
|
|
257
260
|
const messageHeader = this.formatSignificantMessageLine(loc, issueTitle[2]);
|
|
258
|
-
if (
|
|
259
|
-
console.error(
|
|
260
|
-
msgWhat && console.log(msgWhat);
|
|
261
|
-
msgWhy && console.log(msgWhy);
|
|
262
|
-
msgHint && console.log(msgHint);
|
|
263
|
-
console.log(); // Emit an empty line before outputting message.
|
|
261
|
+
if (this.shouldEmitDiagnostics()) {
|
|
262
|
+
this.emitDiagnosticToStderr(console.error.bind(console), messageHeader, msgWhat, msgWhy, msgHint);
|
|
264
263
|
}
|
|
265
264
|
}
|
|
266
265
|
emitSyntaxWarning(loc, msgWhat, msgWhy = '', msgHint = '') {
|
|
267
266
|
const messageHeader = this.formatSignificantMessageLine(loc, issueTitle[3]);
|
|
268
|
-
if (
|
|
269
|
-
console.warn(
|
|
270
|
-
msgWhat && console.log(msgWhat);
|
|
271
|
-
msgWhy && console.log(msgWhy);
|
|
272
|
-
msgHint && console.log(msgHint);
|
|
273
|
-
console.log(); // Emit an empty line before outputting message.
|
|
267
|
+
if (this.shouldEmitNonErrors()) {
|
|
268
|
+
this.emitDiagnosticToStderr(console.warn.bind(console), messageHeader, msgWhat, msgWhy, msgHint);
|
|
274
269
|
}
|
|
275
270
|
}
|
|
276
271
|
emitNotice(loc, msgWhat, msgWhy = '', msgHint = '') {
|
|
277
272
|
const messageHeader = this.formatSignificantMessageLine(loc, issueTitle[4]);
|
|
278
|
-
if (
|
|
279
|
-
console.
|
|
280
|
-
msgWhat && console.log(msgWhat);
|
|
281
|
-
msgWhy && console.log(msgWhy);
|
|
282
|
-
msgHint && console.log(msgHint);
|
|
283
|
-
console.log(); // Emit an empty line before outputting message.
|
|
273
|
+
if (this.shouldEmitNonErrors()) {
|
|
274
|
+
this.emitDiagnosticToStderr(console.error.bind(console), messageHeader, msgWhat, msgWhy, msgHint);
|
|
284
275
|
}
|
|
285
276
|
}
|
|
286
277
|
emitInfo(loc, msgWhat, msgWhy = '', msgHint = '') {
|
|
287
278
|
const messageHeader = this.formatSignificantMessageLine(loc, issueTitle[5]);
|
|
288
|
-
if (
|
|
289
|
-
console.
|
|
290
|
-
msgWhat && console.log(msgWhat);
|
|
291
|
-
msgWhy && console.log(msgWhy);
|
|
292
|
-
msgHint && console.log(msgHint);
|
|
293
|
-
console.log(); // Emit an empty line before outputting message.
|
|
279
|
+
if (this.shouldEmitNonErrors()) {
|
|
280
|
+
this.emitDiagnosticToStderr(console.error.bind(console), messageHeader, msgWhat, msgWhy, msgHint);
|
|
294
281
|
}
|
|
295
282
|
}
|
|
296
283
|
getNumOfAllMessages() {
|
|
@@ -70,7 +70,7 @@ export type TObjectValue = {
|
|
|
70
70
|
entries: Readonly<Record<string, TValueLiteral>>;
|
|
71
71
|
tag: string | undefined;
|
|
72
72
|
};
|
|
73
|
-
type TStringKind = 'raw' | 'classic' | '
|
|
73
|
+
type TStringKind = 'raw' | 'classic' | 'triple-raw' | 'triple-classic';
|
|
74
74
|
export interface IParsedStringInput {
|
|
75
75
|
strKind: TStringKind;
|
|
76
76
|
value: string;
|
|
@@ -82,6 +82,13 @@ export interface IErrorLocationInput {
|
|
|
82
82
|
endColumn?: number;
|
|
83
83
|
}
|
|
84
84
|
export type TIssueType = 'Fatal-Error' | 'Internal-Error' | 'Syntax-Error' | 'Syntax-Warning' | 'Notice' | 'Info';
|
|
85
|
+
export interface IPreflightIssue {
|
|
86
|
+
locInput: IErrorLocationInput | undefined;
|
|
87
|
+
type: TIssueType;
|
|
88
|
+
msgWhat: string;
|
|
89
|
+
msgWhy?: string;
|
|
90
|
+
msgHint?: string;
|
|
91
|
+
}
|
|
85
92
|
interface IMetaBaseInfo {
|
|
86
93
|
sourceType: TSourceType;
|
|
87
94
|
fileName: string | undefined;
|
|
@@ -96,6 +103,7 @@ export interface IRuntimeInfo extends IMetaBaseInfo {
|
|
|
96
103
|
timeIoMs: number | null;
|
|
97
104
|
preferredBailSensitivity: null | PreferredFailLevel;
|
|
98
105
|
sha256: string | null;
|
|
106
|
+
preflightIssues: IPreflightIssue[];
|
|
99
107
|
}
|
|
100
108
|
export interface IParseCoreOptions {
|
|
101
109
|
rules: IParseRuleOptions;
|
|
@@ -104,6 +112,7 @@ export interface IParseCoreOptions {
|
|
|
104
112
|
isWithDiagnostics: boolean;
|
|
105
113
|
isWithTiming: boolean;
|
|
106
114
|
isKeepUndefinedInMeta: boolean;
|
|
115
|
+
isDiagnosticOutputEnabled: boolean;
|
|
107
116
|
isQuiet: boolean;
|
|
108
117
|
isSilent: boolean;
|
|
109
118
|
isThrowOnError: boolean;
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { ErrorDataHandler } from './errorDataHandler';
|
|
2
2
|
import { IYiniAST } from './internalTypes';
|
|
3
3
|
/**
|
|
4
|
-
* Construct the final JavaScript
|
|
5
|
-
* Transforms the AST
|
|
4
|
+
* Construct the final JavaScript object.
|
|
5
|
+
* Transforms the AST into a plain JS object.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
* -
|
|
7
|
+
* Behavior:
|
|
8
|
+
* - Explicit top-level sections are mounted directly on the result.
|
|
9
|
+
* - In lenient mode, orphan top-level members are also mounted directly
|
|
10
|
+
* on the result.
|
|
11
|
+
* - Any collision between an orphan member name and a top-level section
|
|
12
|
+
* name results in an error.
|
|
9
13
|
*
|
|
10
14
|
* @note All `tag` fields MUST be ignored.
|
|
11
15
|
*/
|
|
@@ -1,63 +1,71 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.astToObject = void 0;
|
|
4
|
+
// src/core/objectBuilder.ts
|
|
4
5
|
const env_1 = require("../config/env");
|
|
5
6
|
const print_1 = require("../utils/print");
|
|
6
7
|
/**
|
|
7
|
-
* Construct the final JavaScript
|
|
8
|
-
* Transforms the AST
|
|
8
|
+
* Construct the final JavaScript object.
|
|
9
|
+
* Transforms the AST into a plain JS object.
|
|
9
10
|
*
|
|
10
|
-
*
|
|
11
|
-
* -
|
|
11
|
+
* Behavior:
|
|
12
|
+
* - Explicit top-level sections are mounted directly on the result.
|
|
13
|
+
* - In lenient mode, orphan top-level members are also mounted directly
|
|
14
|
+
* on the result.
|
|
15
|
+
* - Any collision between an orphan member name and a top-level section
|
|
16
|
+
* name results in an error.
|
|
12
17
|
*
|
|
13
18
|
* @note All `tag` fields MUST be ignored.
|
|
14
19
|
*/
|
|
20
|
+
// src/core/objectBuilder.ts
|
|
15
21
|
const astToObject = (ast, errorHandler) => {
|
|
16
22
|
(0, print_1.debugPrint)('-> constructFinalObject(..)');
|
|
17
|
-
// return sectionChildrenToObject(ast.root)
|
|
18
23
|
const out = {};
|
|
24
|
+
// 1) In lenient mode, mount orphan root members directly onto result.
|
|
25
|
+
if (!ast.isStrict) {
|
|
26
|
+
for (const [key, val] of ast.root.members) {
|
|
27
|
+
define(out, key, literalToJS(val));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
// 2) Mount explicit top-level sections directly onto result.
|
|
19
31
|
for (const child of ast.root.children) {
|
|
20
|
-
|
|
32
|
+
if (Object.prototype.hasOwnProperty.call(out, child.sectionName)) {
|
|
33
|
+
errorHandler.pushOrBail(undefined, 'Syntax-Error', `Name collision between orphan member and section '${child.sectionName}'`, `The name '${child.sectionName}' is already used by a top-level member outside any explicit section and cannot also be used as a top-level section name.`, `Rename either the orphan member or the section to avoid the collision.`);
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
// define(out, child.sectionName, sectionToObject(child))
|
|
37
|
+
define(out, child.sectionName, sectionToObject(child, errorHandler));
|
|
21
38
|
}
|
|
22
39
|
return out;
|
|
23
40
|
};
|
|
24
41
|
exports.astToObject = astToObject;
|
|
25
|
-
/**
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
//
|
|
30
|
-
// for (const child of section.children) {
|
|
31
|
-
// out[child.sectionName] = sectionToObject(child)
|
|
32
|
-
// }
|
|
33
|
-
// return out
|
|
34
|
-
// }
|
|
35
|
-
/** Convert a section (its members + nested sections) to a plain object. */
|
|
36
|
-
// function sectionToObject(node: YiniSection): Record<string, unknown> {
|
|
42
|
+
/**
|
|
43
|
+
* Convert a section (members + nested sections) to a plain object,
|
|
44
|
+
* preserving insertion order.
|
|
45
|
+
*/
|
|
46
|
+
// const sectionToObject = (node: IYiniSection): Record<string, unknown> => {
|
|
37
47
|
// const obj: Record<string, unknown> = {}
|
|
38
|
-
// // Members
|
|
39
|
-
// for (const [key, val] of node.members
|
|
40
|
-
// obj
|
|
48
|
+
// // 1) Members (Map preserves insertion order).
|
|
49
|
+
// for (const [key, val] of node.members) {
|
|
50
|
+
// define(obj, key, literalToJS(val))
|
|
41
51
|
// }
|
|
42
|
-
// // Nested sections
|
|
52
|
+
// // 2) Nested sections (array order preserved).
|
|
43
53
|
// for (const child of node.children) {
|
|
44
|
-
// obj
|
|
54
|
+
// define(obj, child.sectionName, sectionToObject(child))
|
|
45
55
|
// }
|
|
46
56
|
// return obj
|
|
47
57
|
// }
|
|
48
|
-
|
|
49
|
-
* Convert a section (members + nested sections) to a plain
|
|
50
|
-
* object, preserving order.
|
|
51
|
-
*/
|
|
52
|
-
const sectionToObject = (node) => {
|
|
58
|
+
const sectionToObject = (node, errorHandler) => {
|
|
53
59
|
const obj = {};
|
|
54
|
-
// 1) Members (Map preserves insertion order).
|
|
55
60
|
for (const [key, val] of node.members) {
|
|
56
61
|
define(obj, key, literalToJS(val));
|
|
57
62
|
}
|
|
58
|
-
// 2) Nested sections (array order preserved).
|
|
59
63
|
for (const child of node.children) {
|
|
60
|
-
|
|
64
|
+
if (Object.prototype.hasOwnProperty.call(obj, child.sectionName)) {
|
|
65
|
+
errorHandler.pushOrBail(undefined, 'Syntax-Error', `Name collision between member and subsection '${child.sectionName}'`, `The name '${child.sectionName}' is already used by a member in section '${node.sectionName}' and cannot also be used as a subsection name.`, 'Rename either the member or the subsection.');
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
define(obj, child.sectionName, sectionToObject(child, errorHandler));
|
|
61
69
|
}
|
|
62
70
|
return obj;
|
|
63
71
|
};
|
|
@@ -72,12 +80,6 @@ const sectionToObject = (node) => {
|
|
|
72
80
|
const literalToJS = (v) => {
|
|
73
81
|
const IS_LOCAL_DEBUG = false;
|
|
74
82
|
(0, print_1.debugPrint)('In literalToJS(..)');
|
|
75
|
-
// if (!v) {
|
|
76
|
-
// // NOTE: Only in lenient-mode, if parsing a
|
|
77
|
-
// // member (key = value), but the value is invalid
|
|
78
|
-
// // key will get undefined
|
|
79
|
-
// return undefined
|
|
80
|
-
// }
|
|
81
83
|
switch (v.type) {
|
|
82
84
|
case 'String':
|
|
83
85
|
case 'Number':
|
|
@@ -96,37 +98,20 @@ const literalToJS = (v) => {
|
|
|
96
98
|
}
|
|
97
99
|
const out = v.elems.map((elem) => {
|
|
98
100
|
const ret = literalToJS(elem);
|
|
99
|
-
if (IS_LOCAL_DEBUG) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
(0, print_1.printObject)(elem);
|
|
103
|
-
}
|
|
101
|
+
if (IS_LOCAL_DEBUG && (0, env_1.isDebug)()) {
|
|
102
|
+
console.log('elem:');
|
|
103
|
+
(0, print_1.printObject)(elem);
|
|
104
104
|
}
|
|
105
105
|
return ret;
|
|
106
106
|
});
|
|
107
|
-
if (IS_LOCAL_DEBUG) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
(0, print_1.printObject)(out);
|
|
111
|
-
}
|
|
107
|
+
if (IS_LOCAL_DEBUG && (0, env_1.isDebug)()) {
|
|
108
|
+
console.log('Returning:');
|
|
109
|
+
(0, print_1.printObject)(out);
|
|
112
110
|
}
|
|
113
111
|
return out;
|
|
114
112
|
}
|
|
115
113
|
case 'Object': {
|
|
116
114
|
const out = {};
|
|
117
|
-
// for (const key of Object.keys(v.entries)) {
|
|
118
|
-
// const entry = v.entries[key]
|
|
119
|
-
// if (isScalar(entry)) {
|
|
120
|
-
// // Scalar entries in object-literals: value
|
|
121
|
-
// // out[key] = { type: entry.type, value: entry.value }
|
|
122
|
-
// out[key] = entry.value
|
|
123
|
-
// } else if (entry.type === 'List') {
|
|
124
|
-
// out[key] = entry.elems.map(literalToJS)
|
|
125
|
-
// } else {
|
|
126
|
-
// out[key] = literalToJS(entry) // nested object-literal
|
|
127
|
-
// }
|
|
128
|
-
// }
|
|
129
|
-
// Object.keys preserves property insertion order for plain objects
|
|
130
115
|
for (const k of Object.keys(v.entries)) {
|
|
131
116
|
define(out, k, literalToJS(v.entries[k]));
|
|
132
117
|
}
|
|
@@ -135,8 +120,8 @@ const literalToJS = (v) => {
|
|
|
135
120
|
}
|
|
136
121
|
};
|
|
137
122
|
/**
|
|
138
|
-
* Helper function
|
|
139
|
-
* order and enumerability.
|
|
123
|
+
* Helper function that defines a property while preserving explicit
|
|
124
|
+
* insertion order and enumerability.
|
|
140
125
|
*/
|
|
141
126
|
const define = (obj, key, value) => {
|
|
142
127
|
Object.defineProperty(obj, key, {
|
|
@@ -7,11 +7,12 @@ export declare const getDefaultUserOptions: (mode: TParserMode) => {
|
|
|
7
7
|
onDuplicateKey: import("../../types").OnDuplicateKey;
|
|
8
8
|
requireDocTerminator: import("../../types").DocumentTerminatorRule;
|
|
9
9
|
treatEmptyValueAsNull: import("../../types").EmptyValueRule;
|
|
10
|
+
logDiagnostics: boolean;
|
|
10
11
|
quiet: boolean;
|
|
11
12
|
silent: boolean;
|
|
12
13
|
throwOnError: boolean;
|
|
13
|
-
strictMode: boolean;
|
|
14
14
|
failLevel: import("../../types").PreferredFailLevel;
|
|
15
15
|
includeMetadata: boolean;
|
|
16
|
+
strictMode: boolean;
|
|
16
17
|
};
|
|
17
|
-
export type TNormalizedUserOptions = Required<Pick<ParseOptions, 'strictMode' | 'failLevel' | 'includeMetadata' | 'includeDiagnostics' | 'includeTiming' | 'preserveUndefinedInMeta' | 'onDuplicateKey' | 'requireDocTerminator' | 'treatEmptyValueAsNull' | 'quiet' | 'silent' | 'throwOnError'>>;
|
|
18
|
+
export type TNormalizedUserOptions = Required<Pick<ParseOptions, 'strictMode' | 'failLevel' | 'includeMetadata' | 'includeDiagnostics' | 'includeTiming' | 'preserveUndefinedInMeta' | 'onDuplicateKey' | 'requireDocTerminator' | 'treatEmptyValueAsNull' | 'logDiagnostics' | 'quiet' | 'silent' | 'throwOnError'>>;
|
|
@@ -14,11 +14,16 @@ const BASE_DEFAULTS = {
|
|
|
14
14
|
onDuplicateKey: 'error',
|
|
15
15
|
requireDocTerminator: 'optional',
|
|
16
16
|
treatEmptyValueAsNull: 'allow-with-warning',
|
|
17
|
-
|
|
17
|
+
logDiagnostics: false,
|
|
18
|
+
quiet: false, // When logDiagnostics is true, suppress warnings in stderr output.
|
|
18
19
|
silent: false,
|
|
19
20
|
//@todo: Change default throwOnError to false
|
|
20
21
|
throwOnError: true, // Will throw on first parse error encountered.
|
|
21
22
|
};
|
|
23
|
+
/**
|
|
24
|
+
* @note If editing any of these, the values in src/core/parsingRules/modeFromRulesMatcher.ts
|
|
25
|
+
* must match too.
|
|
26
|
+
*/
|
|
22
27
|
const DEFAULT_LENIENT_OPTS = {
|
|
23
28
|
...BASE_DEFAULTS,
|
|
24
29
|
strictMode: false,
|
|
@@ -28,13 +33,17 @@ const DEFAULT_LENIENT_OPTS = {
|
|
|
28
33
|
requireDocTerminator: 'optional',
|
|
29
34
|
treatEmptyValueAsNull: 'allow',
|
|
30
35
|
};
|
|
36
|
+
/**
|
|
37
|
+
* @note If editing any of these, the values in src/core/parsingRules/modeFromRulesMatcher.ts
|
|
38
|
+
* must match too.
|
|
39
|
+
*/
|
|
31
40
|
const DEFAULT_STRICT_OPTS = {
|
|
32
41
|
...BASE_DEFAULTS,
|
|
33
42
|
strictMode: true,
|
|
34
43
|
failLevel: 'errors',
|
|
35
44
|
// Below are options for pure rules:
|
|
36
45
|
onDuplicateKey: 'error',
|
|
37
|
-
requireDocTerminator: '
|
|
46
|
+
requireDocTerminator: 'required',
|
|
38
47
|
treatEmptyValueAsNull: 'disallow',
|
|
39
48
|
};
|
|
40
49
|
//# sourceMappingURL=defaultParserOptions.js.map
|
|
@@ -15,13 +15,16 @@ const toCoreOptions = (userOpts, bailLevel) => {
|
|
|
15
15
|
treatEmptyValueAsNull: userOpts.treatEmptyValueAsNull,
|
|
16
16
|
},
|
|
17
17
|
bailSensitivity: level,
|
|
18
|
-
isIncludeMeta: userOpts.includeMetadata
|
|
18
|
+
isIncludeMeta: userOpts.includeMetadata ||
|
|
19
|
+
userOpts.includeDiagnostics ||
|
|
20
|
+
userOpts.includeTiming,
|
|
19
21
|
// isWithDiagnostics: isDev() || isDebug() || userOpts.includeDiagnostics,
|
|
20
22
|
isWithDiagnostics: userOpts.includeDiagnostics,
|
|
21
23
|
// isWithTiming: isDev() || isDebug() || userOpts.includeTiming,
|
|
22
24
|
isWithTiming: userOpts.includeTiming,
|
|
23
25
|
// isKeepUndefinedInMeta: isDebug() || userOpts.preserveUndefinedInMeta,
|
|
24
26
|
isKeepUndefinedInMeta: userOpts.preserveUndefinedInMeta,
|
|
27
|
+
isDiagnosticOutputEnabled: userOpts.logDiagnostics,
|
|
25
28
|
isQuiet: userOpts.quiet, // Suppress warnings, etc.
|
|
26
29
|
isSilent: userOpts.silent,
|
|
27
30
|
isThrowOnError: userOpts.throwOnError,
|
|
@@ -32,8 +35,6 @@ exports.toCoreOptions = toCoreOptions;
|
|
|
32
35
|
const isOptionsObjectForm = (v) => {
|
|
33
36
|
return (v != null &&
|
|
34
37
|
typeof v === 'object' &&
|
|
35
|
-
// Note: If one wants, this can be relax to "typeof v === 'object'"
|
|
36
|
-
// but this keeps accidental booleans/strings out.
|
|
37
38
|
('strictMode' in v ||
|
|
38
39
|
'failLevel' in v ||
|
|
39
40
|
'includeMetadata' in v ||
|
|
@@ -43,9 +44,10 @@ const isOptionsObjectForm = (v) => {
|
|
|
43
44
|
'onDuplicateKey' in v ||
|
|
44
45
|
'requireDocTerminator' in v ||
|
|
45
46
|
'treatEmptyValueAsNull' in v ||
|
|
47
|
+
'logDiagnostics' in v ||
|
|
46
48
|
'quiet' in v ||
|
|
47
49
|
'silent' in v ||
|
|
48
|
-
'
|
|
50
|
+
'throwOnError' in v));
|
|
49
51
|
};
|
|
50
52
|
exports.isOptionsObjectForm = isOptionsObjectForm;
|
|
51
53
|
const inferModeFromArgs = (arg2) => {
|
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.matchModeFromCoreOptions = exports.matchModeFromParseOptions = void 0;
|
|
4
|
+
// src/core/parsingRules/modeFromRulesMatcher.ts
|
|
5
|
+
// import { ParseOptions } from 'querystring'
|
|
4
6
|
const env_1 = require("../../config/env");
|
|
5
7
|
const print_1 = require("../../utils/print");
|
|
6
8
|
const errorDataHandler_1 = require("../errorDataHandler");
|
|
7
9
|
const optionsFunctions_1 = require("../options/optionsFunctions");
|
|
10
|
+
/*
|
|
11
|
+
* Strict-mode defaults are:
|
|
12
|
+
* - onDuplicateKey: 'error' → 2
|
|
13
|
+
* - requireDocTerminator: 'required' → 2
|
|
14
|
+
* - treatEmptyValueAsNull: 'disallow' → 2
|
|
15
|
+
*/
|
|
8
16
|
const MODE_PROFILES = {
|
|
9
17
|
lenient: [0, 0, 0],
|
|
10
18
|
// moderate: [1, 0, 1],
|
|
11
|
-
strict: [2,
|
|
19
|
+
strict: [2, 2, 2],
|
|
12
20
|
//'pedantic'
|
|
13
21
|
//'paranoid'
|
|
14
22
|
};
|
|
@@ -22,7 +30,7 @@ const matchModeFromCoreOptions = (coreOptions) => {
|
|
|
22
30
|
(0, print_1.debugPrint)('-> matchModeFromRules(..):');
|
|
23
31
|
if (!coreOptions?.rules) {
|
|
24
32
|
// Note, after pushing processing may continue or exit, depending on the error and/or the bail threshold.
|
|
25
|
-
new errorDataHandler_1.ErrorDataHandler('None/Ignore').pushOrBail(undefined, 'Fatal-Error', `The passed input object is missing rules object.`, '
|
|
33
|
+
new errorDataHandler_1.ErrorDataHandler('None/Ignore').pushOrBail(undefined, 'Fatal-Error', `The passed input object is missing rules object.`, 'The passed option object may be of the wrong type; expected core options.');
|
|
26
34
|
}
|
|
27
35
|
// debugPrint(
|
|
28
36
|
// 'coreOptions.rules.?onDuplicateKey = ' +
|
|
@@ -60,11 +68,12 @@ const inferTParserModeExact = (rules) => {
|
|
|
60
68
|
// debugPrint('rules.onDuplicateKey = ' + rules.onDuplicateKey)
|
|
61
69
|
// debugPrint('rules.requireDocTerminator = ' + rules.requireDocTerminator)
|
|
62
70
|
// debugPrint('rules.treatEmptyValueAsNull = ' + rules.treatEmptyValueAsNull)
|
|
63
|
-
//
|
|
71
|
+
// Each rule is scored on a strictness scale:
|
|
72
|
+
// 0 = lenient / permissive, 1 = warning-level / intermediate, 2 = strict / enforcing.
|
|
64
73
|
const vector = [
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
74
|
+
scoreDuplicateKey(rules.onDuplicateKey),
|
|
75
|
+
scoreRequireDocTerminator(rules.requireDocTerminator),
|
|
76
|
+
scoreEmptyValue(rules.treatEmptyValueAsNull),
|
|
68
77
|
];
|
|
69
78
|
(0, print_1.debugPrint)('** vector:');
|
|
70
79
|
// isDebug() && printObject(vector)
|
|
@@ -76,29 +85,29 @@ const inferTParserModeExact = (rules) => {
|
|
|
76
85
|
}
|
|
77
86
|
return { mode: 'custom', vector };
|
|
78
87
|
};
|
|
79
|
-
const
|
|
88
|
+
const scoreDuplicateKey = (v) => {
|
|
80
89
|
switch (v) {
|
|
81
90
|
case 'keep-first':
|
|
82
91
|
case 'warn-and-keep-first':
|
|
83
|
-
return 0; //
|
|
92
|
+
return 0; // Lenient / permissive rule level.
|
|
84
93
|
case 'overwrite':
|
|
85
94
|
case 'warn-and-overwrite':
|
|
86
95
|
return 1;
|
|
87
96
|
case 'error':
|
|
88
|
-
return 2; //
|
|
97
|
+
return 2; // Strict / enforcing rule level.
|
|
89
98
|
}
|
|
90
99
|
};
|
|
91
|
-
const
|
|
100
|
+
const scoreRequireDocTerminator = (v) => {
|
|
92
101
|
switch (v) {
|
|
93
102
|
case 'optional':
|
|
94
|
-
return 0; //
|
|
103
|
+
return 0; // Lenient / permissive rule level.
|
|
95
104
|
case 'warn-if-missing':
|
|
96
105
|
return 1;
|
|
97
106
|
case 'required':
|
|
98
|
-
return 2;
|
|
107
|
+
return 2; // Strict / enforcing rule level.
|
|
99
108
|
}
|
|
100
109
|
};
|
|
101
|
-
const
|
|
110
|
+
const scoreEmptyValue = (v) => {
|
|
102
111
|
switch (v) {
|
|
103
112
|
case 'allow':
|
|
104
113
|
return 0; // Rule in lenient mode.
|