parser-combinators 1.2.1 → 1.2.3

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 (53) hide show
  1. package/README.md +0 -1
  2. package/dist/index.min.js +2 -2
  3. package/dist/index.min.mjs +4 -0
  4. package/dist/parsers/any.js +3 -14
  5. package/dist/parsers/anyString.d.ts +3 -6
  6. package/dist/parsers/anyString.js +4 -2
  7. package/dist/parsers/between.js +12 -8
  8. package/dist/parsers/many.d.ts +2 -2
  9. package/dist/parsers/many.js +89 -23
  10. package/dist/parsers/map.js +7 -2
  11. package/dist/parsers/optimizations.d.ts +11 -0
  12. package/dist/parsers/optimizations.js +23 -0
  13. package/dist/parsers/str.d.ts +2 -10
  14. package/dist/parsers/str.js +2 -2
  15. package/dist/parsers/utilities.d.ts +4 -7
  16. package/dist/parsers/utilities.js +11 -13
  17. package/dist-esm/index.d.ts +3 -0
  18. package/dist-esm/index.js +3 -0
  19. package/dist-esm/parser.d.ts +9 -0
  20. package/dist-esm/parser.js +18 -0
  21. package/dist-esm/parsers/any.d.ts +16 -0
  22. package/dist-esm/parsers/any.js +33 -0
  23. package/dist-esm/parsers/anyString.d.ts +12 -0
  24. package/dist-esm/parsers/anyString.js +84 -0
  25. package/dist-esm/parsers/between.d.ts +5 -0
  26. package/dist-esm/parsers/between.js +21 -0
  27. package/dist-esm/parsers/exhaust.d.ts +5 -0
  28. package/dist-esm/parsers/exhaust.js +22 -0
  29. package/dist-esm/parsers/index.d.ts +12 -0
  30. package/dist-esm/parsers/index.js +12 -0
  31. package/dist-esm/parsers/many.d.ts +17 -0
  32. package/dist-esm/parsers/many.js +121 -0
  33. package/dist-esm/parsers/map.d.ts +5 -0
  34. package/dist-esm/parsers/map.js +23 -0
  35. package/dist-esm/parsers/opt.d.ts +5 -0
  36. package/dist-esm/parsers/opt.js +13 -0
  37. package/dist-esm/parsers/optimizations.d.ts +11 -0
  38. package/dist-esm/parsers/optimizations.js +16 -0
  39. package/dist-esm/parsers/recovery.d.ts +14 -0
  40. package/dist-esm/parsers/recovery.js +49 -0
  41. package/dist-esm/parsers/regex.d.ts +5 -0
  42. package/dist-esm/parsers/regex.js +17 -0
  43. package/dist-esm/parsers/seq.d.ts +16 -0
  44. package/dist-esm/parsers/seq.js +14 -0
  45. package/dist-esm/parsers/str.d.ts +9 -0
  46. package/dist-esm/parsers/str.js +32 -0
  47. package/dist-esm/parsers/utilities.d.ts +30 -0
  48. package/dist-esm/parsers/utilities.js +85 -0
  49. package/dist-esm/parsers/values.d.ts +31 -0
  50. package/dist-esm/parsers/values.js +44 -0
  51. package/dist-esm/types.d.ts +40 -0
  52. package/dist-esm/types.js +38 -0
  53. package/package.json +61 -56
@@ -0,0 +1,85 @@
1
+ import { failure, isFailure, success } from '../types';
2
+ /** Allows to make a condition on the result of the parsing function.
3
+ * @returns A parser returning the same but also performing a given check on the result.
4
+ */
5
+ export function ref(parser, check, expected) {
6
+ return (ctx) => {
7
+ const res = parser(ctx);
8
+ if (!isFailure(res) && !check(res.value)) {
9
+ return failure(res.ctx, expected ?? 'check', [`ref: ${expected ?? 'check'}`]);
10
+ }
11
+ return res;
12
+ };
13
+ }
14
+ /** Changes the expected value for when the parser fails.
15
+ * @returns A parser returning the same but with a different expected value.
16
+ */
17
+ export function expect(parser, expected) {
18
+ return (ctx) => {
19
+ const res = parser(ctx);
20
+ if (isFailure(res)) {
21
+ return failure(res.ctx, expected, [expected, ...res.history]);
22
+ }
23
+ return res;
24
+ };
25
+ }
26
+ /** Changes the expected value for when the parser fails. Erases the previous history.
27
+ * @returns A parser returning the same but with a different expected value.
28
+ */
29
+ export function expectErase(parser, expected) {
30
+ return (ctx) => {
31
+ const res = parser(ctx);
32
+ if (isFailure(res)) {
33
+ return failure(res.ctx, expected, [expected]);
34
+ }
35
+ return res;
36
+ };
37
+ }
38
+ /**
39
+ * Marks a parser as a branch that has to be executed to the end by the {@link any} parser
40
+ */
41
+ export function surely(parser) {
42
+ return expect(parser, 'surely');
43
+ }
44
+ /**
45
+ * Wraps the value returned by the parser with the token information (the start and end index in the text)
46
+ * @returns A parser returning the value wrapped in token information.
47
+ */
48
+ export function token(parser) {
49
+ return (ctx) => {
50
+ const result = parser(ctx);
51
+ if (result.success) {
52
+ return {
53
+ ...result,
54
+ value: {
55
+ value: result.value,
56
+ start: ctx.index,
57
+ end: result.ctx.index
58
+ }
59
+ };
60
+ }
61
+ return result;
62
+ };
63
+ }
64
+ /**
65
+ * Checks whether the parser parses successfully, but doesn't move the cursor forward
66
+ */
67
+ export function lookaround(parser) {
68
+ return (ctx) => {
69
+ const result = parser(ctx);
70
+ if (result.success) {
71
+ return success(ctx, void 0);
72
+ }
73
+ return failure(ctx, result.expected, ['lookaround', ...result.history]);
74
+ };
75
+ }
76
+ /**
77
+ * Turns a function creating a parser into a parser. Useful for recursive grammars.
78
+ */
79
+ export function lazy(parserGetter) {
80
+ let parser;
81
+ return (ctx) => {
82
+ parser ??= parserGetter();
83
+ return parser(ctx);
84
+ };
85
+ }
@@ -0,0 +1,31 @@
1
+ import { Parser } from '../types';
2
+ /** Parses 0 or more spaces
3
+ */
4
+ export declare const spaces: Parser<string>;
5
+ /** Parses 1 or more spaces
6
+ */
7
+ export declare const spacesPlus: Parser<string>;
8
+ /** Parses 0 or more whitespace characters
9
+ */
10
+ export declare const wspaces: Parser<string | null>;
11
+ /** Parses a boolean (true or false) and returns a string
12
+ */
13
+ export declare const bool: Parser<'true' | 'false'>;
14
+ /** Parses a boolean (true or false) and returns a boolean
15
+ */
16
+ export declare const boolP: Parser<boolean>;
17
+ /** Parses an integer and returns a string
18
+ */
19
+ export declare const int: Parser<string>;
20
+ /** Parses an integer and returns a number
21
+ */
22
+ export declare const intP: Parser<number>;
23
+ /** Parses a standard real number (X.X) and returns a string
24
+ */
25
+ export declare const real: Parser<`${number}.${number}`>;
26
+ /** Parses a standard real number (X.X) and returns a number
27
+ */
28
+ export declare const realP: Parser<number>;
29
+ /** Parses an end of text/file. Fails if the parser is not at the end.
30
+ */
31
+ export declare const eof: Parser<void>;
@@ -0,0 +1,44 @@
1
+ import { failure, success } from '../types';
2
+ import { map } from './map';
3
+ import { opt } from './opt';
4
+ import { regex } from './regex';
5
+ import { seq } from './seq';
6
+ import { str } from './str';
7
+ import { expect } from './utilities';
8
+ /** Parses 0 or more spaces
9
+ */
10
+ export const spaces = regex(/ */, 'spaces');
11
+ /** Parses 1 or more spaces
12
+ */
13
+ export const spacesPlus = regex(/ +/, 'spaces');
14
+ /** Parses 0 or more whitespace characters
15
+ */
16
+ export const wspaces = opt(regex(/(?:\s|\t|\n|\r)+/, 'whitespace characters'));
17
+ /** Parses a boolean (true or false) and returns a string
18
+ */
19
+ export const bool = regex(/true|false/, 'boolean');
20
+ /** Parses a boolean (true or false) and returns a boolean
21
+ */
22
+ export const boolP = map(bool, val => val === 'true');
23
+ /** Parses an integer and returns a string
24
+ */
25
+ export const int = regex(/\d+/, 'integer');
26
+ /** Parses an integer and returns a number
27
+ */
28
+ export const intP = map(int, seq => parseInt(seq, 10));
29
+ /** Parses a standard real number (X.X) and returns a string
30
+ */
31
+ export const real = expect(map(seq(int, str('.'), int), ([intPart, , decimalPart]) => `${intPart}.${decimalPart}`), 'real');
32
+ /** Parses a standard real number (X.X) and returns a number
33
+ */
34
+ export const realP = map(real, (seq) => parseFloat(seq));
35
+ /** Parses an end of text/file. Fails if the parser is not at the end.
36
+ */
37
+ export const eof = (ctx) => {
38
+ if (ctx.index === ctx.text.length) {
39
+ return success(ctx, void 0);
40
+ }
41
+ else {
42
+ return failure(ctx, "End Of File", ["EOF"]);
43
+ }
44
+ };
@@ -0,0 +1,40 @@
1
+ export type Parser<T> = (ctx: Context) => Result<T>;
2
+ export type Context = Readonly<{
3
+ text: string;
4
+ path: string;
5
+ index: number;
6
+ }>;
7
+ export type Result<T> = Success<T> | Failure;
8
+ export type Success<T> = Readonly<{
9
+ success: true;
10
+ value: T;
11
+ ctx: Context;
12
+ }>;
13
+ export type Failure = Readonly<{
14
+ success: false;
15
+ expected: string;
16
+ ctx: Context;
17
+ history: string[];
18
+ }>;
19
+ export type TokenRange = {
20
+ start: number;
21
+ end: number;
22
+ };
23
+ export type Token<T> = TokenRange & {
24
+ value: T;
25
+ };
26
+ export declare function isFailure(input: unknown): input is Failure;
27
+ export declare function success<T>(ctx: Context, value: T): Success<T>;
28
+ export declare function failure(ctx: Context, expected: string, history: string[]): Failure;
29
+ export declare function result<T>(value: T): Parser<T>;
30
+ export declare function fail<T>(reason: string): Parser<T>;
31
+ export declare class ParseError extends Error {
32
+ readonly index: number;
33
+ readonly history: string[];
34
+ readonly line: string;
35
+ readonly column: number;
36
+ readonly row: number;
37
+ constructor(message: string, input: string, index: number, history: string[]);
38
+ private getInputData;
39
+ getPrettyErrorMessage(): string;
40
+ }
@@ -0,0 +1,38 @@
1
+ export function isFailure(input) {
2
+ return !input.success;
3
+ }
4
+ export function success(ctx, value) {
5
+ return { success: true, value, ctx };
6
+ }
7
+ export function failure(ctx, expected, history) {
8
+ return { success: false, expected, ctx, history };
9
+ }
10
+ export function result(value) {
11
+ return (ctx) => success(ctx, value);
12
+ }
13
+ export function fail(reason) {
14
+ return (ctx) => failure(ctx, reason, [reason]);
15
+ }
16
+ export class ParseError extends Error {
17
+ constructor(message, input, index, history) {
18
+ super(message);
19
+ this.index = index;
20
+ this.history = history;
21
+ [this.line, this.column, this.row] = this.getInputData(input, index);
22
+ }
23
+ getInputData(input, index) {
24
+ const lines = input.split('\n');
25
+ let row = 0;
26
+ while (index > 0) {
27
+ if (lines[row].length > index) {
28
+ return [lines[row], index + 1, row + 1];
29
+ }
30
+ index -= lines[row].length + 1;
31
+ row += 1;
32
+ }
33
+ return [lines[row], index + 1, row + 1];
34
+ }
35
+ getPrettyErrorMessage() {
36
+ return `${this.message} (line ${this.row}, col ${this.column}):\n${this.line}\n${(this.column > 0 ? '-'.repeat(this.column - 1) : '') + '^'}`;
37
+ }
38
+ }
package/package.json CHANGED
@@ -1,56 +1,61 @@
1
- {
2
- "name": "parser-combinators",
3
- "version": "1.2.1",
4
- "license": "ISC",
5
- "maintainers": [
6
- "Micha_i"
7
- ],
8
- "repository": {
9
- "type": "git",
10
- "url": "git+https://github.com/michalusio/Parser.git"
11
- },
12
- "bugs": {
13
- "url": "https://github.com/michalusio/Parser/issues"
14
- },
15
- "homepage": "https://github.com/michalusio/Parser#readme",
16
- "description": "A library of parser combinators, with which you can create your own parsers. The library will be continuously improved in time.",
17
- "scripts": {
18
- "start": "tsc && node .",
19
- "lint": "eslint src --ext .ts",
20
- "build": "tsc",
21
- "minify": "esbuild dist/index.js --minify=true --bundle --outfile=dist/index.min.js",
22
- "bundle": "npm run lint && npm run build && npm run minify",
23
- "test:mutate": "stryker run",
24
- "test:unit": "mocha",
25
- "test": "nyc -e '.ts' --r html -r lcov -r text npm run test:unit"
26
- },
27
- "author": "Micha_i <isalski.michal@gmail.com> (https://github.com/michalusio)",
28
- "main": "./dist/index.js",
29
- "types": "./dist/index.d.ts",
30
- "engines": {
31
- "node": ">=18"
32
- },
33
- "devDependencies": {
34
- "@stryker-mutator/core": "^9.4.0",
35
- "@stryker-mutator/mocha-runner": "^9.4.0",
36
- "@stryker-mutator/typescript-checker": "^9.4.0",
37
- "@types/mocha": "10.0.10",
38
- "@types/node": "25.0.9",
39
- "cross-env": "10.1.0",
40
- "esbuild": "0.27.2",
41
- "eslint": "9.39.2",
42
- "mocha": "11.7.5",
43
- "nyc": "17.1.0",
44
- "ts-node": "10.9.2",
45
- "typescript": "5.9.3",
46
- "typescript-eslint": "8.53.0"
47
- },
48
- "keywords": [
49
- "parser",
50
- "combinator",
51
- "parser-combinator",
52
- "parsing",
53
- "combining",
54
- "functional"
55
- ]
56
- }
1
+ {
2
+ "name": "parser-combinators",
3
+ "version": "1.2.3",
4
+ "license": "ISC",
5
+ "maintainers": [
6
+ "Micha_i"
7
+ ],
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/michalusio/Parser.git"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/michalusio/Parser/issues"
14
+ },
15
+ "homepage": "https://github.com/michalusio/Parser#readme",
16
+ "description": "A library of parser combinators, with which you can create your own parsers. The library will be continuously improved in time.",
17
+ "scripts": {
18
+ "start": "tsc && node .",
19
+ "lint": "eslint src --ext .ts",
20
+ "build": "tsc",
21
+ "build-esm": "tsc --project tsconfig.esm.json",
22
+ "bundle": "npm run lint && npm run build && npm run build-esm",
23
+ "test:mutate": "stryker run",
24
+ "test:unit": "mocha",
25
+ "test": "nyc -e '.ts' --r html -r lcov -r text npm run test:unit"
26
+ },
27
+ "author": "Micha_i <isalski.michal@gmail.com> (https://github.com/michalusio)",
28
+ "main": "./dist/index.js",
29
+ "types": "./dist/index.d.ts",
30
+ "type": "commonjs",
31
+ "engines": {
32
+ "node": ">=18"
33
+ },
34
+ "devDependencies": {
35
+ "@stryker-mutator/core": "^9.4.0",
36
+ "@stryker-mutator/mocha-runner": "^9.4.0",
37
+ "@stryker-mutator/typescript-checker": "^9.4.0",
38
+ "@types/mocha": "10.0.10",
39
+ "@types/node": "25.0.9",
40
+ "cross-env": "10.1.0",
41
+ "esbuild": "0.27.2",
42
+ "eslint": "9.39.2",
43
+ "mocha": "11.7.5",
44
+ "nyc": "17.1.0",
45
+ "ts-node": "10.9.2",
46
+ "typescript": "5.9.3",
47
+ "typescript-eslint": "8.53.0"
48
+ },
49
+ "keywords": [
50
+ "parser",
51
+ "combinator",
52
+ "parser-combinator",
53
+ "parsing",
54
+ "combining",
55
+ "functional"
56
+ ],
57
+ "prettier": {
58
+ "tabWidth": 4,
59
+ "useTabs": false
60
+ }
61
+ }