yini-parser 1.5.0 → 1.6.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.
- package/CHANGELOG.md +41 -0
- package/LICENSE +1 -1
- package/README.md +199 -37
- package/dist/YINI.d.ts +22 -7
- package/dist/YINI.js +104 -0
- package/dist/core/astBuilder.d.ts +94 -15
- package/dist/core/astBuilder.js +396 -364
- package/dist/core/errorDataHandler.d.ts +29 -1
- package/dist/core/errorDataHandler.js +120 -63
- package/dist/core/internalTypes.d.ts +10 -1
- package/dist/core/objectBuilder.js +21 -6
- package/dist/core/options/defaultParserOptions.d.ts +3 -2
- package/dist/core/options/defaultParserOptions.js +2 -1
- package/dist/core/options/optionsFunctions.js +5 -1
- package/dist/core/pipeline/pipeline.js +31 -12
- package/dist/core/runtime.js +29 -34
- package/dist/grammar/generated/YiniLexer.d.ts +28 -35
- package/dist/grammar/generated/YiniLexer.js +323 -310
- package/dist/grammar/generated/YiniParser.d.ts +158 -80
- package/dist/grammar/generated/YiniParser.js +1141 -620
- package/dist/grammar/generated/YiniParserVisitor.d.ts +77 -14
- package/dist/grammar/generated/YiniParserVisitor.js +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +6 -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 +42 -21
- package/dist/parsers/validateShebangPlacement.d.ts +4 -0
- package/dist/parsers/validateShebangPlacement.js +115 -0
- package/dist/types/index.d.ts +19 -2
- 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/basic.yini +1 -0
- package/examples/compare-formats.md +1 -1
- package/examples/nested.yini +1 -1
- package/examples/parse-example.ts +1 -0
- 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 -139
- 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
package/dist/core/runtime.js
CHANGED
|
@@ -16,8 +16,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
16
16
|
var _YiniRuntime_runtime;
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
18
|
exports.YiniRuntime = void 0;
|
|
19
|
+
// src/core/runtime.ts
|
|
19
20
|
const fs_1 = __importDefault(require("fs"));
|
|
20
21
|
const env_1 = require("../config/env");
|
|
22
|
+
const validateShebangPlacement_1 = require("../parsers/validateShebangPlacement");
|
|
21
23
|
const pathAndFileName_1 = require("../utils/pathAndFileName");
|
|
22
24
|
const print_1 = require("../utils/print");
|
|
23
25
|
const string_1 = require("../utils/string");
|
|
@@ -54,6 +56,7 @@ class YiniRuntime {
|
|
|
54
56
|
timeIoMs: null,
|
|
55
57
|
preferredBailSensitivity: null,
|
|
56
58
|
sha256: null,
|
|
59
|
+
preflightIssues: [],
|
|
57
60
|
};
|
|
58
61
|
}
|
|
59
62
|
// --- Single implementation --------------------------------------------
|
|
@@ -62,21 +65,6 @@ class YiniRuntime {
|
|
|
62
65
|
runParse(yiniContent, arg2, // strictMode | options
|
|
63
66
|
failLevel = 'auto', includeMetadata = false) {
|
|
64
67
|
(0, print_1.debugPrint)('-> Entered runParse(..) in YiniRuntime class\n');
|
|
65
|
-
// Handle optional UTF-8 BOM content of file.
|
|
66
|
-
if (yiniContent.startsWith('\uFEFF')) {
|
|
67
|
-
// (!) NOTE: slice(1) only because UTF-8 BOM appears as one single Unicode code characte, even though it is 3 bytes (EF BB BF) on disk.
|
|
68
|
-
yiniContent = yiniContent.slice(1);
|
|
69
|
-
(0, print_1.devPrint)('runParse(..): BOM was detected and stripped BOM in UTF-8 content');
|
|
70
|
-
}
|
|
71
|
-
// Handle optional shebang line (if line starts with "#!").
|
|
72
|
-
if (yiniContent.startsWith('#!')) {
|
|
73
|
-
const newlineIndex = yiniContent.indexOf('\n');
|
|
74
|
-
(0, print_1.devPrint)('runParse(..): Shebang detected at first line, stripped line 1.');
|
|
75
|
-
if (newlineIndex < 2) {
|
|
76
|
-
throw new Error('Syntax-Error: Unexpected YINI input');
|
|
77
|
-
}
|
|
78
|
-
yiniContent = yiniContent.slice(newlineIndex + 1);
|
|
79
|
-
}
|
|
80
68
|
// Runtime guard to catch illegal/ambiguous calls coming from JS or any-cast code
|
|
81
69
|
if ((0, optionsFunctions_1.isOptionsObjectForm)(arg2) &&
|
|
82
70
|
(failLevel !== 'auto' || includeMetadata !== false)) {
|
|
@@ -102,6 +90,20 @@ class YiniRuntime {
|
|
|
102
90
|
includeMetadata,
|
|
103
91
|
};
|
|
104
92
|
}
|
|
93
|
+
const shebangIssue = (0, validateShebangPlacement_1.getShebangPlacementIssue)(yiniContent, userOpts.strictMode);
|
|
94
|
+
if (shebangIssue) {
|
|
95
|
+
__classPrivateFieldGet(this, _YiniRuntime_runtime, "f").preflightIssues.push(shebangIssue);
|
|
96
|
+
}
|
|
97
|
+
const originalContent = yiniContent;
|
|
98
|
+
yiniContent = (0, validateShebangPlacement_1.stripBomAndValidShebang)(yiniContent);
|
|
99
|
+
yiniContent = (0, validateShebangPlacement_1.normalizeShebangCommentLines)(yiniContent);
|
|
100
|
+
if (originalContent.startsWith('\uFEFF')) {
|
|
101
|
+
(0, print_1.devPrint)('runParse(..): BOM was detected and stripped from UTF-8 content.');
|
|
102
|
+
}
|
|
103
|
+
if (originalContent.startsWith('#!') ||
|
|
104
|
+
originalContent.startsWith('\uFEFF#!')) {
|
|
105
|
+
(0, print_1.devPrint)('runParse(..): Shebang detected on first line and ignored.');
|
|
106
|
+
}
|
|
105
107
|
if (userOpts.includeMetadata && __classPrivateFieldGet(this, _YiniRuntime_runtime, "f").sourceType === 'Inline') {
|
|
106
108
|
const lineCount = yiniContent.split(/\r?\n/).length; // Counts the lines.
|
|
107
109
|
const sha256 = (0, string_1.computeSha256)(yiniContent); // NOTE: Compute BEFORE any possible tampering of content.
|
|
@@ -111,9 +113,13 @@ class YiniRuntime {
|
|
|
111
113
|
}
|
|
112
114
|
// NOTE: Important: Do not trim or mutate the yiniContent here, due
|
|
113
115
|
// to it will mess up the line numbers in error reporting.
|
|
114
|
-
if (!yiniContent) {
|
|
115
|
-
|
|
116
|
+
// if (!yiniContent) {
|
|
117
|
+
// throw new Error('Syntax-Error: Unexpected blank YINI input')
|
|
118
|
+
// }
|
|
119
|
+
if (yiniContent === null || yiniContent === undefined) {
|
|
120
|
+
throw new Error('Syntax-Error: Missing YINI input');
|
|
116
121
|
}
|
|
122
|
+
// IMPORTANT: Makes sure input ends with an empty NL!
|
|
117
123
|
if (!yiniContent.endsWith('\n')) {
|
|
118
124
|
yiniContent += '\n';
|
|
119
125
|
}
|
|
@@ -166,13 +172,6 @@ class YiniRuntime {
|
|
|
166
172
|
};
|
|
167
173
|
}
|
|
168
174
|
if ((0, pathAndFileName_1.getFileNameExtension)(filePath).toLowerCase() !== '.yini') {
|
|
169
|
-
// IMPORTANT: If "silent" option is set, do not log anything to console!
|
|
170
|
-
if (!userOpts.silent) {
|
|
171
|
-
// In quiet-mode we still show errors (these are fine).
|
|
172
|
-
console.error('Invalid file extension for YINI file:');
|
|
173
|
-
console.error(`"${filePath}"`);
|
|
174
|
-
console.error('File does not have a valid ".yini" extension (case-insensitive).');
|
|
175
|
-
}
|
|
176
175
|
throw new Error('Error: Unexpected file extension for YINI file');
|
|
177
176
|
}
|
|
178
177
|
// ---- Phase 0: I/O ----
|
|
@@ -192,22 +191,18 @@ class YiniRuntime {
|
|
|
192
191
|
__classPrivateFieldGet(this, _YiniRuntime_runtime, "f").preferredBailSensitivity = userOpts.failLevel;
|
|
193
192
|
__classPrivateFieldGet(this, _YiniRuntime_runtime, "f").sha256 = (0, string_1.computeSha256)(content); // NOTE: Compute BEFORE any possible tampering of content.
|
|
194
193
|
}
|
|
195
|
-
let hasNoNewlineAtEOF = false;
|
|
196
194
|
if (!content.endsWith('\n')) {
|
|
195
|
+
__classPrivateFieldGet(this, _YiniRuntime_runtime, "f").preflightIssues.push({
|
|
196
|
+
locInput: undefined,
|
|
197
|
+
type: 'Syntax-Warning',
|
|
198
|
+
msgWhat: 'No newline at end of file.',
|
|
199
|
+
msgWhy: `It's recommended to end a YINI file with a newline. File: "${filePath}"`,
|
|
200
|
+
});
|
|
197
201
|
content += '\n';
|
|
198
|
-
hasNoNewlineAtEOF = true;
|
|
199
202
|
}
|
|
200
203
|
const result = this.runParse(content, {
|
|
201
204
|
...userOpts,
|
|
202
205
|
});
|
|
203
|
-
// if (hasNoNewlineAtEOF && !userOpts.quiet && !userOpts.silent) {
|
|
204
|
-
if (hasNoNewlineAtEOF && !userOpts.quiet) {
|
|
205
|
-
// IMPORTANT: If "silent" option is set, do not log anything to console!
|
|
206
|
-
if (!userOpts.silent) {
|
|
207
|
-
//@todo: (or maybe not, 20250917) Maybe let errorHandler emit message
|
|
208
|
-
console.warn(`No newline at end of file, it's recommended to end a file with a newline. File:\n"${filePath}"`);
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
206
|
return result;
|
|
212
207
|
}
|
|
213
208
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ATN, CharStream, DFA, Lexer
|
|
1
|
+
import { ATN, CharStream, DFA, Lexer } from "antlr4";
|
|
2
2
|
export default class YiniLexer extends Lexer {
|
|
3
3
|
static readonly SHEBANG = 1;
|
|
4
4
|
static readonly YINI_TOKEN = 2;
|
|
@@ -13,44 +13,39 @@ export default class YiniLexer extends Lexer {
|
|
|
13
13
|
static readonly EMPTY_OBJECT = 11;
|
|
14
14
|
static readonly EMPTY_LIST = 12;
|
|
15
15
|
static readonly STRING = 13;
|
|
16
|
-
static readonly
|
|
17
|
-
static readonly
|
|
18
|
-
static readonly
|
|
19
|
-
static readonly
|
|
20
|
-
static readonly
|
|
21
|
-
static readonly
|
|
22
|
-
static readonly
|
|
23
|
-
static readonly
|
|
24
|
-
static readonly
|
|
25
|
-
static readonly
|
|
26
|
-
static readonly
|
|
27
|
-
static readonly
|
|
28
|
-
static readonly
|
|
29
|
-
static readonly
|
|
30
|
-
static readonly
|
|
31
|
-
static readonly
|
|
32
|
-
static readonly
|
|
33
|
-
static readonly
|
|
34
|
-
static readonly
|
|
35
|
-
static readonly
|
|
36
|
-
static readonly
|
|
37
|
-
static readonly
|
|
38
|
-
static readonly
|
|
39
|
-
static readonly
|
|
40
|
-
static readonly
|
|
41
|
-
static readonly
|
|
42
|
-
static readonly
|
|
43
|
-
static readonly KEY = 41;
|
|
44
|
-
static readonly IDENT_INVALID = 42;
|
|
45
|
-
static readonly REST = 43;
|
|
46
|
-
static readonly META_INVALID = 44;
|
|
16
|
+
static readonly NUMBER = 14;
|
|
17
|
+
static readonly CARET = 15;
|
|
18
|
+
static readonly SS = 16;
|
|
19
|
+
static readonly GT = 17;
|
|
20
|
+
static readonly LT = 18;
|
|
21
|
+
static readonly EQ = 19;
|
|
22
|
+
static readonly COMMA = 20;
|
|
23
|
+
static readonly COLON = 21;
|
|
24
|
+
static readonly OB = 22;
|
|
25
|
+
static readonly CB = 23;
|
|
26
|
+
static readonly OC = 24;
|
|
27
|
+
static readonly CC = 25;
|
|
28
|
+
static readonly PLUS = 26;
|
|
29
|
+
static readonly DOLLAR = 27;
|
|
30
|
+
static readonly PC = 28;
|
|
31
|
+
static readonly AT = 29;
|
|
32
|
+
static readonly SEMICOLON = 30;
|
|
33
|
+
static readonly NL = 31;
|
|
34
|
+
static readonly WS = 32;
|
|
35
|
+
static readonly BLOCK_COMMENT = 33;
|
|
36
|
+
static readonly DISABLED_LINE = 34;
|
|
37
|
+
static readonly FULL_LINE_COMMENT = 35;
|
|
38
|
+
static readonly INLINE_COMMENT = 36;
|
|
39
|
+
static readonly KEY = 37;
|
|
40
|
+
static readonly IDENT_INVALID = 38;
|
|
41
|
+
static readonly REST = 39;
|
|
42
|
+
static readonly META_INVALID = 40;
|
|
47
43
|
static readonly EOF: number;
|
|
48
44
|
static readonly channelNames: string[];
|
|
49
45
|
static readonly literalNames: (string | null)[];
|
|
50
46
|
static readonly symbolicNames: (string | null)[];
|
|
51
47
|
static readonly modeNames: string[];
|
|
52
48
|
static readonly ruleNames: string[];
|
|
53
|
-
atLineStart(): boolean;
|
|
54
49
|
constructor(input: CharStream);
|
|
55
50
|
get grammarFileName(): string;
|
|
56
51
|
get literalNames(): (string | null)[];
|
|
@@ -59,8 +54,6 @@ export default class YiniLexer extends Lexer {
|
|
|
59
54
|
get serializedATN(): number[];
|
|
60
55
|
get channelNames(): string[];
|
|
61
56
|
get modeNames(): string[];
|
|
62
|
-
sempred(localctx: RuleContext, ruleIndex: number, predIndex: number): boolean;
|
|
63
|
-
private LINE_COMMENT_sempred;
|
|
64
57
|
static readonly _serializedATN: number[];
|
|
65
58
|
private static __ATN;
|
|
66
59
|
static get _ATN(): ATN;
|