yini-parser 1.5.0 → 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 +33 -0
- package/README.md +183 -37
- package/dist/YINI.d.ts +22 -7
- package/dist/YINI.js +101 -0
- package/dist/core/astBuilder.d.ts +94 -15
- package/dist/core/astBuilder.js +394 -362
- 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.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 -10
- package/dist/core/runtime.js +28 -19
- 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 +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 +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/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 -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
|
@@ -2,24 +2,33 @@ import { ParseTreeVisitor } from 'antlr4';
|
|
|
2
2
|
import { YiniContext } from "./YiniParser.js";
|
|
3
3
|
import { PrologContext } from "./YiniParser.js";
|
|
4
4
|
import { Terminal_stmtContext } from "./YiniParser.js";
|
|
5
|
+
import { Terminal_triviaContext } from "./YiniParser.js";
|
|
5
6
|
import { StmtContext } from "./YiniParser.js";
|
|
7
|
+
import { Full_line_comment_stmtContext } from "./YiniParser.js";
|
|
8
|
+
import { Disabled_line_stmtContext } from "./YiniParser.js";
|
|
6
9
|
import { Invalid_section_stmtContext } from "./YiniParser.js";
|
|
7
10
|
import { Meta_stmtContext } from "./YiniParser.js";
|
|
8
11
|
import { DirectiveContext } from "./YiniParser.js";
|
|
12
|
+
import { Yini_directiveContext } from "./YiniParser.js";
|
|
13
|
+
import { Yini_mode_declarationContext } from "./YiniParser.js";
|
|
9
14
|
import { AnnotationContext } from "./YiniParser.js";
|
|
10
15
|
import { EolContext } from "./YiniParser.js";
|
|
11
16
|
import { AssignmentContext } from "./YiniParser.js";
|
|
12
17
|
import { MemberContext } from "./YiniParser.js";
|
|
13
18
|
import { ValueContext } from "./YiniParser.js";
|
|
19
|
+
import { Scalar_valueContext } from "./YiniParser.js";
|
|
20
|
+
import { Concat_expressionContext } from "./YiniParser.js";
|
|
21
|
+
import { Concat_tailContext } from "./YiniParser.js";
|
|
22
|
+
import { Concat_operandContext } from "./YiniParser.js";
|
|
23
|
+
import { String_literalContext } from "./YiniParser.js";
|
|
14
24
|
import { Object_literalContext } from "./YiniParser.js";
|
|
15
25
|
import { Object_membersContext } from "./YiniParser.js";
|
|
16
26
|
import { Object_memberContext } from "./YiniParser.js";
|
|
27
|
+
import { Object_member_separatorContext } from "./YiniParser.js";
|
|
17
28
|
import { List_literalContext } from "./YiniParser.js";
|
|
18
29
|
import { ElementsContext } from "./YiniParser.js";
|
|
19
30
|
import { Number_literalContext } from "./YiniParser.js";
|
|
20
31
|
import { Null_literalContext } from "./YiniParser.js";
|
|
21
|
-
import { String_literalContext } from "./YiniParser.js";
|
|
22
|
-
import { String_concatContext } from "./YiniParser.js";
|
|
23
32
|
import { Boolean_literalContext } from "./YiniParser.js";
|
|
24
33
|
import { Bad_meta_textContext } from "./YiniParser.js";
|
|
25
34
|
import { Bad_memberContext } from "./YiniParser.js";
|
|
@@ -49,12 +58,30 @@ export default class YiniParserVisitor<Result> extends ParseTreeVisitor<Result>
|
|
|
49
58
|
* @return the visitor result
|
|
50
59
|
*/
|
|
51
60
|
visitTerminal_stmt?: (ctx: Terminal_stmtContext) => Result;
|
|
61
|
+
/**
|
|
62
|
+
* Visit a parse tree produced by `YiniParser.terminal_trivia`.
|
|
63
|
+
* @param ctx the parse tree
|
|
64
|
+
* @return the visitor result
|
|
65
|
+
*/
|
|
66
|
+
visitTerminal_trivia?: (ctx: Terminal_triviaContext) => Result;
|
|
52
67
|
/**
|
|
53
68
|
* Visit a parse tree produced by `YiniParser.stmt`.
|
|
54
69
|
* @param ctx the parse tree
|
|
55
70
|
* @return the visitor result
|
|
56
71
|
*/
|
|
57
72
|
visitStmt?: (ctx: StmtContext) => Result;
|
|
73
|
+
/**
|
|
74
|
+
* Visit a parse tree produced by `YiniParser.full_line_comment_stmt`.
|
|
75
|
+
* @param ctx the parse tree
|
|
76
|
+
* @return the visitor result
|
|
77
|
+
*/
|
|
78
|
+
visitFull_line_comment_stmt?: (ctx: Full_line_comment_stmtContext) => Result;
|
|
79
|
+
/**
|
|
80
|
+
* Visit a parse tree produced by `YiniParser.disabled_line_stmt`.
|
|
81
|
+
* @param ctx the parse tree
|
|
82
|
+
* @return the visitor result
|
|
83
|
+
*/
|
|
84
|
+
visitDisabled_line_stmt?: (ctx: Disabled_line_stmtContext) => Result;
|
|
58
85
|
/**
|
|
59
86
|
* Visit a parse tree produced by `YiniParser.invalid_section_stmt`.
|
|
60
87
|
* @param ctx the parse tree
|
|
@@ -73,6 +100,18 @@ export default class YiniParserVisitor<Result> extends ParseTreeVisitor<Result>
|
|
|
73
100
|
* @return the visitor result
|
|
74
101
|
*/
|
|
75
102
|
visitDirective?: (ctx: DirectiveContext) => Result;
|
|
103
|
+
/**
|
|
104
|
+
* Visit a parse tree produced by `YiniParser.yini_directive`.
|
|
105
|
+
* @param ctx the parse tree
|
|
106
|
+
* @return the visitor result
|
|
107
|
+
*/
|
|
108
|
+
visitYini_directive?: (ctx: Yini_directiveContext) => Result;
|
|
109
|
+
/**
|
|
110
|
+
* Visit a parse tree produced by `YiniParser.yini_mode_declaration`.
|
|
111
|
+
* @param ctx the parse tree
|
|
112
|
+
* @return the visitor result
|
|
113
|
+
*/
|
|
114
|
+
visitYini_mode_declaration?: (ctx: Yini_mode_declarationContext) => Result;
|
|
76
115
|
/**
|
|
77
116
|
* Visit a parse tree produced by `YiniParser.annotation`.
|
|
78
117
|
* @param ctx the parse tree
|
|
@@ -103,6 +142,36 @@ export default class YiniParserVisitor<Result> extends ParseTreeVisitor<Result>
|
|
|
103
142
|
* @return the visitor result
|
|
104
143
|
*/
|
|
105
144
|
visitValue?: (ctx: ValueContext) => Result;
|
|
145
|
+
/**
|
|
146
|
+
* Visit a parse tree produced by `YiniParser.scalar_value`.
|
|
147
|
+
* @param ctx the parse tree
|
|
148
|
+
* @return the visitor result
|
|
149
|
+
*/
|
|
150
|
+
visitScalar_value?: (ctx: Scalar_valueContext) => Result;
|
|
151
|
+
/**
|
|
152
|
+
* Visit a parse tree produced by `YiniParser.concat_expression`.
|
|
153
|
+
* @param ctx the parse tree
|
|
154
|
+
* @return the visitor result
|
|
155
|
+
*/
|
|
156
|
+
visitConcat_expression?: (ctx: Concat_expressionContext) => Result;
|
|
157
|
+
/**
|
|
158
|
+
* Visit a parse tree produced by `YiniParser.concat_tail`.
|
|
159
|
+
* @param ctx the parse tree
|
|
160
|
+
* @return the visitor result
|
|
161
|
+
*/
|
|
162
|
+
visitConcat_tail?: (ctx: Concat_tailContext) => Result;
|
|
163
|
+
/**
|
|
164
|
+
* Visit a parse tree produced by `YiniParser.concat_operand`.
|
|
165
|
+
* @param ctx the parse tree
|
|
166
|
+
* @return the visitor result
|
|
167
|
+
*/
|
|
168
|
+
visitConcat_operand?: (ctx: Concat_operandContext) => Result;
|
|
169
|
+
/**
|
|
170
|
+
* Visit a parse tree produced by `YiniParser.string_literal`.
|
|
171
|
+
* @param ctx the parse tree
|
|
172
|
+
* @return the visitor result
|
|
173
|
+
*/
|
|
174
|
+
visitString_literal?: (ctx: String_literalContext) => Result;
|
|
106
175
|
/**
|
|
107
176
|
* Visit a parse tree produced by `YiniParser.object_literal`.
|
|
108
177
|
* @param ctx the parse tree
|
|
@@ -121,6 +190,12 @@ export default class YiniParserVisitor<Result> extends ParseTreeVisitor<Result>
|
|
|
121
190
|
* @return the visitor result
|
|
122
191
|
*/
|
|
123
192
|
visitObject_member?: (ctx: Object_memberContext) => Result;
|
|
193
|
+
/**
|
|
194
|
+
* Visit a parse tree produced by `YiniParser.object_member_separator`.
|
|
195
|
+
* @param ctx the parse tree
|
|
196
|
+
* @return the visitor result
|
|
197
|
+
*/
|
|
198
|
+
visitObject_member_separator?: (ctx: Object_member_separatorContext) => Result;
|
|
124
199
|
/**
|
|
125
200
|
* Visit a parse tree produced by `YiniParser.list_literal`.
|
|
126
201
|
* @param ctx the parse tree
|
|
@@ -145,18 +220,6 @@ export default class YiniParserVisitor<Result> extends ParseTreeVisitor<Result>
|
|
|
145
220
|
* @return the visitor result
|
|
146
221
|
*/
|
|
147
222
|
visitNull_literal?: (ctx: Null_literalContext) => Result;
|
|
148
|
-
/**
|
|
149
|
-
* Visit a parse tree produced by `YiniParser.string_literal`.
|
|
150
|
-
* @param ctx the parse tree
|
|
151
|
-
* @return the visitor result
|
|
152
|
-
*/
|
|
153
|
-
visitString_literal?: (ctx: String_literalContext) => Result;
|
|
154
|
-
/**
|
|
155
|
-
* Visit a parse tree produced by `YiniParser.string_concat`.
|
|
156
|
-
* @param ctx the parse tree
|
|
157
|
-
* @return the visitor result
|
|
158
|
-
*/
|
|
159
|
-
visitString_concat?: (ctx: String_concatContext) => Result;
|
|
160
223
|
/**
|
|
161
224
|
* Visit a parse tree produced by `YiniParser.boolean_literal`.
|
|
162
225
|
* @param ctx the parse tree
|
package/dist/index.d.ts
CHANGED
|
@@ -25,6 +25,7 @@ import YINI from './YINI';
|
|
|
25
25
|
export default YINI;
|
|
26
26
|
export declare const parse: typeof YINI.parse;
|
|
27
27
|
export declare const parseFile: typeof YINI.parseFile;
|
|
28
|
+
export declare const parseForTooling: typeof YINI.parseForTooling;
|
|
28
29
|
export declare const getTabSize: typeof YINI.getTabSize;
|
|
29
30
|
export declare const setTabSize: typeof YINI.setTabSize;
|
|
30
31
|
/**
|
|
@@ -42,4 +43,4 @@ export declare const setTabSize: typeof YINI.setTabSize;
|
|
|
42
43
|
*
|
|
43
44
|
* @packageDocumentation
|
|
44
45
|
*/
|
|
45
|
-
export type { ParsedObject, AllUserOptions, YiniParseResult, OnDuplicateKey, DuplicateKeyPolicy, DocumentTerminatorRule, EmptyValueRule, FailLevelKey, PreferredFailLevel, BasicOptions, PrimaryUserParams, ParseOptions, IssuePayload, MetaSchemaVersion, OrderGuarantee, ResultMetadata, } from './types';
|
|
46
|
+
export type { ParsedObject, AllUserOptions, YiniParseResult, YiniToolingParseResult, ToolingDiagnostic, ToolingDiagnosticSeverity, OnDuplicateKey, DuplicateKeyPolicy, DocumentTerminatorRule, EmptyValueRule, FailLevelKey, PreferredFailLevel, BasicOptions, PrimaryUserParams, ParseOptions, ParseForToolingOptions, IssuePayload, MetaSchemaVersion, OrderGuarantee, ResultMetadata, } from './types';
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
5
|
};
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.setTabSize = exports.getTabSize = exports.parseFile = exports.parse = void 0;
|
|
7
|
+
exports.setTabSize = exports.getTabSize = exports.parseForTooling = exports.parseFile = exports.parse = void 0;
|
|
8
8
|
/*
|
|
9
9
|
This file is a pure barrel file.
|
|
10
10
|
|
|
@@ -13,9 +13,9 @@ exports.setTabSize = exports.getTabSize = exports.parseFile = exports.parse = vo
|
|
|
13
13
|
Run the code with the following command:
|
|
14
14
|
npm start
|
|
15
15
|
or
|
|
16
|
-
npm run start:
|
|
16
|
+
npm run start:main
|
|
17
17
|
or
|
|
18
|
-
npm run start:dev:debug
|
|
18
|
+
npm run start:main:dev:debug
|
|
19
19
|
|
|
20
20
|
/END
|
|
21
21
|
*/
|
|
@@ -47,6 +47,7 @@ const YINI_1 = __importDefault(require("./YINI"));
|
|
|
47
47
|
exports.default = YINI_1.default; // Public package API.
|
|
48
48
|
exports.parse = YINI_1.default.parse;
|
|
49
49
|
exports.parseFile = YINI_1.default.parseFile;
|
|
50
|
+
exports.parseForTooling = YINI_1.default.parseForTooling;
|
|
50
51
|
exports.getTabSize = YINI_1.default.getTabSize;
|
|
51
52
|
exports.setTabSize = YINI_1.default.setTabSize;
|
|
52
53
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,27 +1,20 @@
|
|
|
1
1
|
import { ErrorDataHandler } from '../core/errorDataHandler';
|
|
2
2
|
import { StmtContext } from '../grammar/generated/YiniParser';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* marker will be identified. E.g. does the header start with '^^^' or '^3'
|
|
7
|
-
* and then some identifier.
|
|
4
|
+
* Extracts the marker sequence, optional numeric shorthand depth,
|
|
5
|
+
* section name, and backticked-name flag from a YINI section header line.
|
|
8
6
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* -
|
|
12
|
-
* -
|
|
13
|
-
* -
|
|
14
|
-
* -
|
|
15
|
-
* -
|
|
7
|
+
* Examples:
|
|
8
|
+
* - ^ Section
|
|
9
|
+
* - ^^ Section
|
|
10
|
+
* - ^^^_^^^_^ Section
|
|
11
|
+
* - ^10 Section
|
|
12
|
+
* - §2 Section
|
|
13
|
+
* - < `Backticked Section`
|
|
16
14
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* - Special control characters (U+0000–U+001F) must be escaped.
|
|
21
|
-
*
|
|
22
|
-
* @note Implemented without regexp to keep it less cryptic, etc.
|
|
23
|
-
* @note Returns the parts as strings; each part needs to be analyzed separately against the contraints in the specifications.
|
|
24
|
-
* @returns An object with the identified header parts: marker characters, parsed name, and parsed level string.
|
|
15
|
+
* @note This function only splits the header into parts.
|
|
16
|
+
* Validation of marker depth, marker separator placement, mixed markers,
|
|
17
|
+
* and section name rules is handled by parseSectionHeader.ts.
|
|
25
18
|
*/
|
|
26
19
|
declare const extractHeaderParts: (rawLine: string, errorHandler?: ErrorDataHandler | null, ctx?: StmtContext | null) => {
|
|
27
20
|
strMarkerChars: string;
|
|
@@ -1,31 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
// src/parsers/extractHeaderParts.ts
|
|
3
4
|
const errorDataHandler_1 = require("../core/errorDataHandler");
|
|
4
5
|
const print_1 = require("../utils/print");
|
|
5
6
|
const yiniHelpers_1 = require("../utils/yiniHelpers");
|
|
6
7
|
const extractSignificantYiniLine_1 = require("./extractSignificantYiniLine");
|
|
7
8
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* marker will be identified. E.g. does the header start with '^^^' or '^3'
|
|
11
|
-
* and then some identifier.
|
|
9
|
+
* Extracts the marker sequence, optional numeric shorthand depth,
|
|
10
|
+
* section name, and backticked-name flag from a YINI section header line.
|
|
12
11
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* -
|
|
16
|
-
* -
|
|
17
|
-
* -
|
|
18
|
-
* -
|
|
19
|
-
* -
|
|
12
|
+
* Examples:
|
|
13
|
+
* - ^ Section
|
|
14
|
+
* - ^^ Section
|
|
15
|
+
* - ^^^_^^^_^ Section
|
|
16
|
+
* - ^10 Section
|
|
17
|
+
* - §2 Section
|
|
18
|
+
* - < `Backticked Section`
|
|
20
19
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* - Special control characters (U+0000–U+001F) must be escaped.
|
|
25
|
-
*
|
|
26
|
-
* @note Implemented without regexp to keep it less cryptic, etc.
|
|
27
|
-
* @note Returns the parts as strings; each part needs to be analyzed separately against the contraints in the specifications.
|
|
28
|
-
* @returns An object with the identified header parts: marker characters, parsed name, and parsed level string.
|
|
20
|
+
* @note This function only splits the header into parts.
|
|
21
|
+
* Validation of marker depth, marker separator placement, mixed markers,
|
|
22
|
+
* and section name rules is handled by parseSectionHeader.ts.
|
|
29
23
|
*/
|
|
30
24
|
const extractHeaderParts = (rawLine, errorHandler = null, ctx = null) => {
|
|
31
25
|
(0, print_1.debugPrint)('-> Entered extractHeaderParts(..)');
|
|
@@ -33,9 +27,13 @@ const extractHeaderParts = (rawLine, errorHandler = null, ctx = null) => {
|
|
|
33
27
|
const str = (0, extractSignificantYiniLine_1.extractYiniLine)(rawLine);
|
|
34
28
|
(0, print_1.debugPrint)('rawLine: >>>' + rawLine + '<<<');
|
|
35
29
|
(0, print_1.debugPrint)(' str: >>>' + str + '<<<');
|
|
36
|
-
// Edge case: empty line.
|
|
37
30
|
if (!str) {
|
|
38
|
-
|
|
31
|
+
if (errorHandler) {
|
|
32
|
+
errorHandler.pushOrBail((0, errorDataHandler_1.toErrorLocation)(ctx), 'Internal-Error', 'Received blank argument in extractHeaderParts(..)', 'Sorry, an unintended internal error happened.');
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
throw new Error('Internal error: extractHeaderParts(..) received a blank argument.');
|
|
36
|
+
}
|
|
39
37
|
}
|
|
40
38
|
let pos = 0;
|
|
41
39
|
const len = str.length;
|
|
@@ -43,48 +41,61 @@ const extractHeaderParts = (rawLine, errorHandler = null, ctx = null) => {
|
|
|
43
41
|
let numberPart = '';
|
|
44
42
|
let sectionNamePart = '';
|
|
45
43
|
let isBacktickedName = false;
|
|
46
|
-
// 1. Skip leading whitespace.
|
|
47
|
-
while (pos < len && (str[pos] === ' ' || str[pos] === '\t'))
|
|
44
|
+
// 1. Skip leading horizontal whitespace.
|
|
45
|
+
while (pos < len && (str[pos] === ' ' || str[pos] === '\t')) {
|
|
48
46
|
pos++;
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
}
|
|
48
|
+
// 2. Collect the first section marker character.
|
|
49
|
+
if (pos < len && (0, yiniHelpers_1.isMarkerCharacter)(str[pos])) {
|
|
51
50
|
markerCharsPart += str[pos];
|
|
52
51
|
pos++;
|
|
53
52
|
}
|
|
54
|
-
// 3. Numeric
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
str[pos] >= '1' &&
|
|
58
|
-
str[pos] <= '9') {
|
|
59
|
-
// Start collecting number part.
|
|
53
|
+
// 3. Numeric shorthand: only allowed after a single marker character,
|
|
54
|
+
// for example ^10 Section or §2 Section.
|
|
55
|
+
if (pos < len && str[pos] >= '1' && str[pos] <= '9') {
|
|
60
56
|
while (pos < len && str[pos] >= '0' && str[pos] <= '9') {
|
|
61
57
|
numberPart += str[pos];
|
|
62
58
|
pos++;
|
|
63
59
|
}
|
|
64
|
-
|
|
60
|
+
const hasWhitespaceAfterNumber = pos >= len || str[pos] === ' ' || str[pos] === '\t';
|
|
61
|
+
if (!hasWhitespaceAfterNumber && errorHandler) {
|
|
62
|
+
errorHandler.pushOrBail((0, errorDataHandler_1.toErrorLocation)(ctx), 'Syntax-Error', 'Missing whitespace after numeric shorthand section marker.', `Numeric shorthand section headers require whitespace after the number. Got '${str}'.`, "Use a form such as '^10 Section', not '^10Section'.");
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
// 4. Repeated marker sequence. Separators '_' are collected here too,
|
|
67
|
+
// so parseSectionHeader.ts can validate their placement.
|
|
68
|
+
while (pos < len && (str[pos] === '_' || (0, yiniHelpers_1.isMarkerCharacter)(str[pos]))) {
|
|
69
|
+
markerCharsPart += str[pos];
|
|
70
|
+
pos++;
|
|
71
|
+
}
|
|
65
72
|
}
|
|
66
|
-
//
|
|
67
|
-
while (pos < len && (str[pos] === ' ' || str[pos] === '\t'))
|
|
73
|
+
// 5. Skip horizontal whitespace between marker and section name.
|
|
74
|
+
while (pos < len && (str[pos] === ' ' || str[pos] === '\t')) {
|
|
68
75
|
pos++;
|
|
69
|
-
|
|
76
|
+
}
|
|
77
|
+
// 6. Collect section name.
|
|
70
78
|
if (pos < len && str[pos] === '`') {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
pos
|
|
74
|
-
|
|
79
|
+
const start = pos;
|
|
80
|
+
pos++; // Skip opening backtick.
|
|
81
|
+
while (pos < len) {
|
|
82
|
+
const ch = str[pos];
|
|
83
|
+
// Skip escaped character inside backticked identifier.
|
|
84
|
+
if (ch === '\\') {
|
|
85
|
+
pos += 2;
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (ch === '`') {
|
|
89
|
+
pos++; // Include closing backtick.
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
75
92
|
pos++;
|
|
76
|
-
|
|
93
|
+
}
|
|
77
94
|
sectionNamePart = str.slice(start, pos).trim();
|
|
78
95
|
isBacktickedName = true;
|
|
79
96
|
}
|
|
80
97
|
else {
|
|
81
|
-
// Non-backticked: take the rest of the line, trim off any trailing comments, etc.
|
|
82
98
|
sectionNamePart = str.slice(pos).trim();
|
|
83
|
-
// Optionally, strip trailing comments or newlines here if needed.
|
|
84
|
-
}
|
|
85
|
-
if (isBacktickedName) {
|
|
86
|
-
(0, print_1.debugPrint)('Backticed sectionNamePart: ' + sectionNamePart);
|
|
87
|
-
// sectionNamePart = trimBackticks(sectionNamePart)
|
|
88
99
|
}
|
|
89
100
|
(0, print_1.debugPrint)();
|
|
90
101
|
(0, print_1.debugPrint)('------');
|
|
@@ -1,11 +1,29 @@
|
|
|
1
1
|
/**
|
|
2
|
+
* Parses a YINI number literal into a JavaScript number.
|
|
3
|
+
*
|
|
2
4
|
* @property {string | undefined} [tag]
|
|
3
|
-
* This
|
|
4
|
-
*
|
|
5
|
-
*
|
|
5
|
+
* This property is for debugging only. Its contents may change
|
|
6
|
+
* at any time and should not be relied upon for any significant
|
|
7
|
+
* purpose.
|
|
8
|
+
* @examples
|
|
9
|
+
* scientific = 1.23e4
|
|
10
|
+
* binary_alt = %1010
|
|
11
|
+
* duodecimal = 0z2EX9
|
|
12
|
+
* positive = +123
|
|
13
|
+
*
|
|
14
|
+
* a = 1_000
|
|
15
|
+
* b = +1_000
|
|
16
|
+
* c = 1.23_45e4
|
|
17
|
+
* d = 1.23e+4_5
|
|
18
|
+
* e = 0x_FF_AA
|
|
19
|
+
* f = hex:_FF_AA
|
|
20
|
+
* g = 0b_1010_1100
|
|
21
|
+
* h = %_1010_1100
|
|
22
|
+
* i = 0o_755_644
|
|
23
|
+
* j = 0z_2E_X9
|
|
6
24
|
*/
|
|
7
|
-
declare
|
|
8
|
-
|
|
9
|
-
|
|
25
|
+
export declare function parseNumberLiteral(rawText: string): {
|
|
26
|
+
value: number;
|
|
27
|
+
tag?: string;
|
|
10
28
|
};
|
|
11
29
|
export default parseNumberLiteral;
|
|
@@ -1,84 +1,149 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
|
|
3
|
+
exports.parseNumberLiteral = parseNumberLiteral;
|
|
4
|
+
// src/parsers/parseNumber.ts
|
|
4
5
|
const print_1 = require("../utils/print");
|
|
5
6
|
/**
|
|
7
|
+
* Parses a YINI number literal into a JavaScript number.
|
|
8
|
+
*
|
|
6
9
|
* @property {string | undefined} [tag]
|
|
7
|
-
* This
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
+
* This property is for debugging only. Its contents may change
|
|
11
|
+
* at any time and should not be relied upon for any significant
|
|
12
|
+
* purpose.
|
|
13
|
+
* @examples
|
|
14
|
+
* scientific = 1.23e4
|
|
15
|
+
* binary_alt = %1010
|
|
16
|
+
* duodecimal = 0z2EX9
|
|
17
|
+
* positive = +123
|
|
18
|
+
*
|
|
19
|
+
* a = 1_000
|
|
20
|
+
* b = +1_000
|
|
21
|
+
* c = 1.23_45e4
|
|
22
|
+
* d = 1.23e+4_5
|
|
23
|
+
* e = 0x_FF_AA
|
|
24
|
+
* f = hex:_FF_AA
|
|
25
|
+
* g = 0b_1010_1100
|
|
26
|
+
* h = %_1010_1100
|
|
27
|
+
* i = 0o_755_644
|
|
28
|
+
* j = 0z_2E_X9
|
|
10
29
|
*/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
30
|
+
function parseNumberLiteral(rawText) {
|
|
31
|
+
const raw = rawText.trim();
|
|
32
|
+
const signChar = raw.startsWith('-') || raw.startsWith('+') ? raw[0] : '';
|
|
33
|
+
const signFactor = signChar === '-' ? -1 : 1;
|
|
34
|
+
const unsigned = signChar ? raw.slice(1) : raw;
|
|
35
|
+
const decDigits = String.raw `\d(?:_?\d)*`;
|
|
36
|
+
const hexDigits = String.raw `[0-9a-fA-F](?:_?[0-9a-fA-F])*`;
|
|
37
|
+
const binDigits = String.raw `[01](?:_?[01])*`;
|
|
38
|
+
const octDigits = String.raw `[0-7](?:_?[0-7])*`;
|
|
39
|
+
const duoDigits = String.raw `[0-9aAbBxXeE](?:_?[0-9aAbBxXeE])*`;
|
|
40
|
+
// --- Exponent notation ---------
|
|
41
|
+
// Examples: 1e3, 1.23e4, 1_000e2, 1.23e-4, .5e2.
|
|
42
|
+
// Underscores may appear between digits, but not adjacent or at the end.
|
|
43
|
+
const expPattern = new RegExp(`^(?:${decDigits}(?:\\.${decDigits})?|\\.${decDigits})[eE][+-]?${decDigits}$`);
|
|
44
|
+
if (expPattern.test(unsigned)) {
|
|
15
45
|
(0, print_1.debugPrint)('* Identified as an exp number');
|
|
46
|
+
const normalized = `${signChar}${unsigned.replace(/_/g, '')}`;
|
|
16
47
|
return {
|
|
48
|
+
value: Number(normalized),
|
|
17
49
|
tag: 'From exp number, Number-Float',
|
|
18
|
-
// value: parseInt(txt.replace('#', '0x'), 16),
|
|
19
|
-
value: parseFloat(txt),
|
|
20
50
|
};
|
|
21
51
|
}
|
|
22
|
-
// --- Hexadecimal ---------
|
|
23
|
-
|
|
24
|
-
|
|
52
|
+
// --- Hexadecimal with prefix 0x / 0X ---------
|
|
53
|
+
// Prefix: 0x or 0X.
|
|
54
|
+
// Allows underscores immediately after the prefix or between hex digits.
|
|
55
|
+
// Examples: 0xFF, 0x_FF, 0xFF_AA.
|
|
56
|
+
const hexPattern = new RegExp(`^0[xX]_?${hexDigits}$`);
|
|
57
|
+
if (hexPattern.test(unsigned)) {
|
|
25
58
|
(0, print_1.debugPrint)('* Identified as a hex number');
|
|
26
|
-
|
|
59
|
+
const normalized = unsigned.replace(/^0[xX]_?/, '').replace(/_/g, '');
|
|
27
60
|
return {
|
|
61
|
+
value: signFactor * Number.parseInt(normalized, 16),
|
|
28
62
|
tag: 'From hex number, Number-Integer',
|
|
29
|
-
// value: parseInt(txt.replace('#', '0x'), 16),
|
|
30
|
-
value: parseInt(txt.replace(/0[xX]|#/, ''), 16),
|
|
31
63
|
};
|
|
32
64
|
}
|
|
33
|
-
// ---
|
|
34
|
-
|
|
35
|
-
|
|
65
|
+
// --- Hexadecimal with explicit prefix hex: ---------
|
|
66
|
+
// Prefix: hex: or HEX:.
|
|
67
|
+
// Whitespace after hex: is not allowed.
|
|
68
|
+
// Allows underscores immediately after the prefix or between hex digits.
|
|
69
|
+
// Examples: hex:FF, hex:_FF, hex:FF_AA.
|
|
70
|
+
const explicitHexPattern = new RegExp(`^hex:_?${hexDigits}$`, 'i');
|
|
71
|
+
if (explicitHexPattern.test(unsigned)) {
|
|
72
|
+
(0, print_1.debugPrint)('* Identified as an explicit hex number');
|
|
73
|
+
const normalized = unsigned.replace(/^hex:_?/i, '').replace(/_/g, '');
|
|
74
|
+
return {
|
|
75
|
+
value: signFactor * Number.parseInt(normalized, 16),
|
|
76
|
+
tag: 'From explicit hex number, Number-Integer',
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
// --- Binary with prefix 0b / 0B or % ---------
|
|
80
|
+
// Prefix: 0b, 0B, or %.
|
|
81
|
+
// Allows underscores immediately after the prefix or between binary digits.
|
|
82
|
+
// Examples: 0b1010, 0b_1010, 0b1010_1100, %1010, %_1010.
|
|
83
|
+
const binPattern = new RegExp(`^(?:0[bB]|%)_?${binDigits}$`);
|
|
84
|
+
if (binPattern.test(unsigned)) {
|
|
36
85
|
(0, print_1.debugPrint)('* Identified as a bin number');
|
|
37
|
-
|
|
86
|
+
const normalized = unsigned
|
|
87
|
+
.replace(/^(?:0[bB]|%)_?/, '')
|
|
88
|
+
.replace(/_/g, '');
|
|
38
89
|
return {
|
|
90
|
+
value: signFactor * Number.parseInt(normalized, 2),
|
|
39
91
|
tag: 'From bin number, Number-Integer',
|
|
40
|
-
value: parseInt(txt.replace(/0[bB]|%/, ''), 2),
|
|
41
92
|
};
|
|
42
93
|
}
|
|
43
|
-
// --- Octal ---------
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
94
|
+
// --- Octal with prefix 0o / 0O ---------
|
|
95
|
+
// Prefix: 0o or 0O.
|
|
96
|
+
// Allows underscores immediately after the prefix or between octal digits.
|
|
97
|
+
// Examples: 0o755, 0o_755, 0o755_644.
|
|
98
|
+
const octPattern = new RegExp(`^0[oO]_?${octDigits}$`);
|
|
99
|
+
if (octPattern.test(unsigned)) {
|
|
100
|
+
(0, print_1.debugPrint)('* Identified as an oct number');
|
|
101
|
+
const normalized = unsigned.replace(/^0[oO]_?/, '').replace(/_/g, '');
|
|
48
102
|
return {
|
|
103
|
+
value: signFactor * Number.parseInt(normalized, 8),
|
|
49
104
|
tag: 'From oct number, Number-Integer',
|
|
50
|
-
value: parseInt(txt.replace(/0[oO]/, ''), 8),
|
|
51
105
|
};
|
|
52
106
|
}
|
|
53
|
-
// --- Duodecimal ---------
|
|
54
|
-
|
|
55
|
-
|
|
107
|
+
// --- Duodecimal / dozenal with prefix 0z / 0Z ---------
|
|
108
|
+
// Prefix: 0z or 0Z.
|
|
109
|
+
// x/X = A/a = 10, e/E = B/b = 11.
|
|
110
|
+
// Allows underscores immediately after the prefix or between duodecimal digits.
|
|
111
|
+
// Examples: 0z2EX9, 0z_2EX9, 0z2E_X9.
|
|
112
|
+
const duoPattern = new RegExp(`^0[zZ]_?${duoDigits}$`);
|
|
113
|
+
if (duoPattern.test(unsigned)) {
|
|
56
114
|
(0, print_1.debugPrint)('* Identified as a duodecimal number');
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
115
|
+
const normalized = unsigned
|
|
116
|
+
.replace(/^0[zZ]_?/, '')
|
|
117
|
+
.replace(/_/g, '')
|
|
118
|
+
.replace(/[xX]/g, 'A')
|
|
119
|
+
.replace(/[eE]/g, 'B');
|
|
61
120
|
return {
|
|
121
|
+
value: signFactor * Number.parseInt(normalized, 12),
|
|
62
122
|
tag: 'From doz (duodecimal) number, Number-Integer',
|
|
63
|
-
value: parseInt(txt.replace(/0[zZ]/, ''), 12),
|
|
64
123
|
};
|
|
65
124
|
}
|
|
66
|
-
//
|
|
67
|
-
|
|
68
|
-
|
|
125
|
+
// --- Decimal integer / float ---------
|
|
126
|
+
// Allows underscores between decimal digits.
|
|
127
|
+
// Examples: 1000, +1000, -1000, 1_000, 3.14, 3.141_592, .5.
|
|
128
|
+
const decimalPattern = new RegExp(`^(?:${decDigits}(?:\\.${decDigits})?|\\.${decDigits})$`);
|
|
129
|
+
if (decimalPattern.test(unsigned)) {
|
|
130
|
+
(0, print_1.debugPrint)(/\./.test(unsigned)
|
|
131
|
+
? '* Identified as a float number'
|
|
132
|
+
: '* Identified as an int number');
|
|
133
|
+
const normalized = `${signChar}${unsigned.replace(/_/g, '')}`;
|
|
69
134
|
return {
|
|
70
|
-
|
|
71
|
-
|
|
135
|
+
value: Number(normalized),
|
|
136
|
+
tag: /\./.test(unsigned)
|
|
137
|
+
? 'From float number, Number-Float'
|
|
138
|
+
: 'From int number, Number-Integer',
|
|
72
139
|
};
|
|
73
140
|
}
|
|
74
|
-
//
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return { tag: 'From int number, Number-Integer', value: parseInt(txt) };
|
|
82
|
-
};
|
|
141
|
+
// --- Invalid number literal ---------
|
|
142
|
+
(0, print_1.debugPrint)('* Identified as invalid number');
|
|
143
|
+
return {
|
|
144
|
+
value: Number.NaN,
|
|
145
|
+
tag: 'From invalid number/value',
|
|
146
|
+
};
|
|
147
|
+
}
|
|
83
148
|
exports.default = parseNumberLiteral;
|
|
84
149
|
//# sourceMappingURL=parseNumber.js.map
|