tarsec 0.1.0 → 0.1.2
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/dist/combinators.d.ts +49 -1
- package/dist/combinators.js +88 -14
- package/dist/tarsecError.d.ts +3 -0
- package/dist/tarsecError.js +6 -0
- package/dist/trace.d.ts +9 -1
- package/dist/trace.js +14 -1
- package/package.json +1 -1
package/dist/combinators.d.ts
CHANGED
|
@@ -142,12 +142,22 @@ export declare function between<O, C, P>(open: Parser<O>, close: Parser<C>, pars
|
|
|
142
142
|
export declare function between1<O, C, P>(open: Parser<O>, close: Parser<C>, parser: Parser<P>): Parser<P[]>;
|
|
143
143
|
/**
|
|
144
144
|
* Parses many instances of the parser separated by separator.
|
|
145
|
-
* The parser
|
|
145
|
+
* The parser will succeed even if it consumes zero instances.
|
|
146
|
+
* To require at least one instance, use `sepBy1`.
|
|
146
147
|
* @param separator
|
|
147
148
|
* @param parser
|
|
148
149
|
* @returns a parser that runs the given parser zero to many times, separated by the separator parser.
|
|
149
150
|
*/
|
|
150
151
|
export declare function sepBy<S, P>(separator: Parser<S>, parser: Parser<P>): Parser<P[]>;
|
|
152
|
+
/**
|
|
153
|
+
* Parses many instances of the parser separated by separator.
|
|
154
|
+
* The parser needs to succeed at least once, otherwise sepBy fails.
|
|
155
|
+
* To not require at least one instance, use `sepBy`.
|
|
156
|
+
* @param separator
|
|
157
|
+
* @param parser
|
|
158
|
+
* @returns a parser that runs the given parser one to many times, separated by the separator parser.
|
|
159
|
+
*/
|
|
160
|
+
export declare function sepBy1<S, P>(separator: Parser<S>, parser: Parser<P>): Parser<P[]>;
|
|
151
161
|
/**
|
|
152
162
|
* Convenience function to use as the second argument to `seq` to get all the results from `seq`
|
|
153
163
|
* @param results
|
|
@@ -390,3 +400,41 @@ export declare function manyParsers<const T extends readonly GeneralParser<any,
|
|
|
390
400
|
* @returns - An array of results, or a failure.
|
|
391
401
|
*/
|
|
392
402
|
export declare function and<const T extends readonly GeneralParser<any, any>[]>(...parsers: T): PickParserType<T>;
|
|
403
|
+
/**
|
|
404
|
+
* If any of the parsers fail, this parser throws an error. This can be handy for showing
|
|
405
|
+
* more specific error messages to users. For example, if you have a parser that parses these two statements:
|
|
406
|
+
*
|
|
407
|
+
* ```
|
|
408
|
+
* import "foo";
|
|
409
|
+
* greet "name"
|
|
410
|
+
* ```
|
|
411
|
+
*
|
|
412
|
+
* And the user gives this input:
|
|
413
|
+
*
|
|
414
|
+
* ```
|
|
415
|
+
* import;
|
|
416
|
+
* ```
|
|
417
|
+
*
|
|
418
|
+
* You don't want the parser to fail with a generic message, such as 'all parsers have failed'.
|
|
419
|
+
* You want a more specific error, such as 'expected string after `import` keyword'.
|
|
420
|
+
*
|
|
421
|
+
* You could accomplish that with `throwErrorUnless`:
|
|
422
|
+
*
|
|
423
|
+
* ```ts
|
|
424
|
+
* const parser = seqC(
|
|
425
|
+
* str("import"),
|
|
426
|
+
* captureCaptures(
|
|
427
|
+
* throwErrorUnless(
|
|
428
|
+
* "expected string after `import` keyword",
|
|
429
|
+
* spaces,
|
|
430
|
+
* capture(quotedString, "moduleName")
|
|
431
|
+
* )
|
|
432
|
+
* )
|
|
433
|
+
* )
|
|
434
|
+
*```
|
|
435
|
+
|
|
436
|
+
* @param _message message to fail with
|
|
437
|
+
* @param parsers parsers to run
|
|
438
|
+
* @returns
|
|
439
|
+
*/
|
|
440
|
+
export declare function parseError<const T extends readonly GeneralParser<any, any>[]>(_message: string, ...parsers: T): Parser<MergedCaptures<T>>;
|
package/dist/combinators.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { within } from "./parsers/within.js";
|
|
2
|
-
import {
|
|
2
|
+
import { TarsecError } from "./tarsecError.js";
|
|
3
|
+
import { getInputStr, trace } from "./trace.js";
|
|
3
4
|
import { captureSuccess, createTree, failure, isCaptureResult, isSuccess, success, } from "./types.js";
|
|
4
5
|
import { escape, findAncestorWithNextParser, popMany } from "./utils.js";
|
|
5
6
|
/**
|
|
@@ -300,7 +301,8 @@ export function between1(open, close, parser) {
|
|
|
300
301
|
}
|
|
301
302
|
/**
|
|
302
303
|
* Parses many instances of the parser separated by separator.
|
|
303
|
-
* The parser
|
|
304
|
+
* The parser will succeed even if it consumes zero instances.
|
|
305
|
+
* To require at least one instance, use `sepBy1`.
|
|
304
306
|
* @param separator
|
|
305
307
|
* @param parser
|
|
306
308
|
* @returns a parser that runs the given parser zero to many times, separated by the separator parser.
|
|
@@ -312,28 +314,37 @@ export function sepBy(separator, parser) {
|
|
|
312
314
|
while (true) {
|
|
313
315
|
const result = parser(rest);
|
|
314
316
|
if (!result.success) {
|
|
315
|
-
|
|
316
|
-
return failure(result.message, input);
|
|
317
|
-
}
|
|
318
|
-
else {
|
|
319
|
-
return success(results, rest);
|
|
320
|
-
}
|
|
317
|
+
return success(results, rest);
|
|
321
318
|
}
|
|
322
319
|
results.push(result.result);
|
|
323
320
|
rest = result.rest;
|
|
324
321
|
const sepResult = separator(rest);
|
|
325
322
|
if (!sepResult.success) {
|
|
326
|
-
|
|
327
|
-
return failure(sepResult.message, input);
|
|
328
|
-
}
|
|
329
|
-
else {
|
|
330
|
-
return success(results, rest);
|
|
331
|
-
}
|
|
323
|
+
return success(results, rest);
|
|
332
324
|
}
|
|
333
325
|
rest = sepResult.rest;
|
|
334
326
|
}
|
|
335
327
|
};
|
|
336
328
|
}
|
|
329
|
+
/**
|
|
330
|
+
* Parses many instances of the parser separated by separator.
|
|
331
|
+
* The parser needs to succeed at least once, otherwise sepBy fails.
|
|
332
|
+
* To not require at least one instance, use `sepBy`.
|
|
333
|
+
* @param separator
|
|
334
|
+
* @param parser
|
|
335
|
+
* @returns a parser that runs the given parser one to many times, separated by the separator parser.
|
|
336
|
+
*/
|
|
337
|
+
export function sepBy1(separator, parser) {
|
|
338
|
+
return (input) => {
|
|
339
|
+
const result = sepBy(separator, parser)(input);
|
|
340
|
+
if (result.success) {
|
|
341
|
+
if (result.result.length === 0) {
|
|
342
|
+
return failure("expected at least one match", input);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
return result;
|
|
346
|
+
};
|
|
347
|
+
}
|
|
337
348
|
/**
|
|
338
349
|
* Convenience function to use as the second argument to `seq` to get all the results from `seq`
|
|
339
350
|
* @param results
|
|
@@ -816,3 +827,66 @@ export function and(...parsers) {
|
|
|
816
827
|
return results;
|
|
817
828
|
});
|
|
818
829
|
}
|
|
830
|
+
/**
|
|
831
|
+
* If any of the parsers fail, this parser throws an error. This can be handy for showing
|
|
832
|
+
* more specific error messages to users. For example, if you have a parser that parses these two statements:
|
|
833
|
+
*
|
|
834
|
+
* ```
|
|
835
|
+
* import "foo";
|
|
836
|
+
* greet "name"
|
|
837
|
+
* ```
|
|
838
|
+
*
|
|
839
|
+
* And the user gives this input:
|
|
840
|
+
*
|
|
841
|
+
* ```
|
|
842
|
+
* import;
|
|
843
|
+
* ```
|
|
844
|
+
*
|
|
845
|
+
* You don't want the parser to fail with a generic message, such as 'all parsers have failed'.
|
|
846
|
+
* You want a more specific error, such as 'expected string after `import` keyword'.
|
|
847
|
+
*
|
|
848
|
+
* You could accomplish that with `throwErrorUnless`:
|
|
849
|
+
*
|
|
850
|
+
* ```ts
|
|
851
|
+
* const parser = seqC(
|
|
852
|
+
* str("import"),
|
|
853
|
+
* captureCaptures(
|
|
854
|
+
* throwErrorUnless(
|
|
855
|
+
* "expected string after `import` keyword",
|
|
856
|
+
* spaces,
|
|
857
|
+
* capture(quotedString, "moduleName")
|
|
858
|
+
* )
|
|
859
|
+
* )
|
|
860
|
+
* )
|
|
861
|
+
*```
|
|
862
|
+
|
|
863
|
+
* @param _message message to fail with
|
|
864
|
+
* @param parsers parsers to run
|
|
865
|
+
* @returns
|
|
866
|
+
*/
|
|
867
|
+
export function parseError(_message, ...parsers) {
|
|
868
|
+
return (input) => {
|
|
869
|
+
const result = seqC(...parsers)(input);
|
|
870
|
+
if (result.success) {
|
|
871
|
+
return result;
|
|
872
|
+
}
|
|
873
|
+
else {
|
|
874
|
+
const inputStr = getInputStr();
|
|
875
|
+
const messages = [];
|
|
876
|
+
const prefix = "Near: ";
|
|
877
|
+
if (input.length > 0) {
|
|
878
|
+
const index = inputStr.length - input.length;
|
|
879
|
+
const start = Math.max(0, input.length - 20);
|
|
880
|
+
const end = Math.min(inputStr.length, input.length + 20);
|
|
881
|
+
messages.push(`${prefix}${inputStr.substring(start, end)}`);
|
|
882
|
+
messages.push(`${" ".repeat(index + prefix.length)}^`);
|
|
883
|
+
}
|
|
884
|
+
else {
|
|
885
|
+
messages.push(`${prefix}${input.substring(1, 100)}`);
|
|
886
|
+
}
|
|
887
|
+
messages.push(_message);
|
|
888
|
+
const message = messages.join("\n");
|
|
889
|
+
throw new TarsecError(message);
|
|
890
|
+
}
|
|
891
|
+
};
|
|
892
|
+
}
|
package/dist/trace.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { ParserResult, Parser, PlainObject, CaptureParser } from "./types.js";
|
|
|
4
4
|
* @param name - debug name for parser
|
|
5
5
|
* @param result - parser result
|
|
6
6
|
* @returns - A formatted string that describes the parser's result
|
|
7
|
-
*/
|
|
7
|
+
*/
|
|
8
8
|
export declare function resultToString<T>(name: string, result: ParserResult<T>): string;
|
|
9
9
|
/**
|
|
10
10
|
* This function is used internally with debug mode. Given a parser and a debug name for it,
|
|
@@ -111,3 +111,11 @@ export declare function parserDebug(name: string, callback: Function): void;
|
|
|
111
111
|
* @param callback - callback to run
|
|
112
112
|
*/
|
|
113
113
|
export declare function limitSteps(limit: number, callback: Function): void;
|
|
114
|
+
/**
|
|
115
|
+
* Use this function in conjunction with the parseError combinator. Before running your parser,
|
|
116
|
+
* call this function, giving it the entire input. Then, if the parseError combinator throws an error,
|
|
117
|
+
* it will print out a nice message showing exactly what part of the string triggered the error.
|
|
118
|
+
* @param s full string to parse
|
|
119
|
+
*/
|
|
120
|
+
export declare function setInputStr(s: string): void;
|
|
121
|
+
export declare function getInputStr(): string;
|
package/dist/trace.js
CHANGED
|
@@ -16,7 +16,7 @@ let debugMessages = [];
|
|
|
16
16
|
* @param name - debug name for parser
|
|
17
17
|
* @param result - parser result
|
|
18
18
|
* @returns - A formatted string that describes the parser's result
|
|
19
|
-
*/
|
|
19
|
+
*/
|
|
20
20
|
export function resultToString(name, result) {
|
|
21
21
|
if (result.success) {
|
|
22
22
|
return `✅ ${name} -- match: ${escape(result.result)}, rest: ${escape(result.rest)}`;
|
|
@@ -152,3 +152,16 @@ export function limitSteps(limit, callback) {
|
|
|
152
152
|
callback();
|
|
153
153
|
stepLimit = -1;
|
|
154
154
|
}
|
|
155
|
+
let inputStr = "";
|
|
156
|
+
/**
|
|
157
|
+
* Use this function in conjunction with the parseError combinator. Before running your parser,
|
|
158
|
+
* call this function, giving it the entire input. Then, if the parseError combinator throws an error,
|
|
159
|
+
* it will print out a nice message showing exactly what part of the string triggered the error.
|
|
160
|
+
* @param s full string to parse
|
|
161
|
+
*/
|
|
162
|
+
export function setInputStr(s) {
|
|
163
|
+
inputStr = s;
|
|
164
|
+
}
|
|
165
|
+
export function getInputStr() {
|
|
166
|
+
return inputStr;
|
|
167
|
+
}
|