@mattwca/little-parser-lib 1.0.1 → 1.0.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.
- package/README.md +42 -1
- package/package.json +2 -1
- package/src/index.ts +2 -1
- package/src/parsers/index.ts +3 -0
- package/src/{parser/parser.ts → parsers/parsers.ts} +15 -18
- package/src/utils.ts +17 -0
- package/src/parser/index.ts +0 -3
- /package/src/{parser → parsers}/ParsingError.ts +0 -0
- /package/src/{parser → parsers}/types.ts +0 -0
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ A lightweight, flexible TypeScript library for building parsers using parser com
|
|
|
9
9
|
- 📝 **TypeScript First**: Full type safety and IntelliSense support
|
|
10
10
|
- 🎯 **Backtracking Support**: Automatic position restoration on parse failures
|
|
11
11
|
- 📦 **Zero Dependencies**: Lightweight with no external runtime dependencies
|
|
12
|
-
- ✨ Packaged with [tsdown](https://tsdown.dev)
|
|
12
|
+
- ✨ **Widely Compatible**: Packaged with [tsdown](https://tsdown.dev)
|
|
13
13
|
|
|
14
14
|
## Installation
|
|
15
15
|
|
|
@@ -199,6 +199,46 @@ Convenience method to tokenize and parse in one step.
|
|
|
199
199
|
const result = runParserOnString(myParser, 'input string', tokenizer);
|
|
200
200
|
```
|
|
201
201
|
|
|
202
|
+
## Utilities
|
|
203
|
+
|
|
204
|
+
The library provides utility functions to help with common parser result manipulation tasks.
|
|
205
|
+
|
|
206
|
+
### `unwrapResult(items)`
|
|
207
|
+
|
|
208
|
+
Flattens nested arrays that result from combining parsers like `and` and `many`. This is particularly useful when you have deeply nested parser structures and need a flat array of results.
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
import { unwrapResult } from '@mattwca/little-parser-lib';
|
|
212
|
+
|
|
213
|
+
// Parser results can be nested
|
|
214
|
+
const parser = and(
|
|
215
|
+
many(anyOf('letter')),
|
|
216
|
+
many(anyOf('digit'))
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
const result = runParser(parser, stream);
|
|
220
|
+
// result.result might be: [[token1, token2], [token3, token4]]
|
|
221
|
+
|
|
222
|
+
const flattened = unwrapResult(result.result);
|
|
223
|
+
// flattened is: [token1, token2, token3, token4]
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
**Parameters:**
|
|
227
|
+
- `items: (T | T[])[]` - An array that may contain nested arrays
|
|
228
|
+
|
|
229
|
+
**Returns:**
|
|
230
|
+
- `T[]` - A flattened array with all nested items extracted
|
|
231
|
+
|
|
232
|
+
**Example Use Cases:**
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
// Use with map to process flattened results
|
|
236
|
+
const tokenParser = map(
|
|
237
|
+
and(many(anyOf('letter')), many(anyOf('digit'))),
|
|
238
|
+
(results) => unwrapResult(results).map(t => t.value).join('')
|
|
239
|
+
);
|
|
240
|
+
```
|
|
241
|
+
|
|
202
242
|
## Example: Simple Expression Parser
|
|
203
243
|
|
|
204
244
|
```typescript
|
|
@@ -301,6 +341,7 @@ try {
|
|
|
301
341
|
- `runParserOnString(parser, input, tokenizer)`: Execute parser on string
|
|
302
342
|
- `isSuccessfulResult(result)`: Type guard for successful results
|
|
303
343
|
- `isFailedResult(result)`: Type guard for failed results
|
|
344
|
+
- `unwrapResult(results)`: Unwrap nested parser results
|
|
304
345
|
|
|
305
346
|
## License
|
|
306
347
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mattwca/little-parser-lib",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
"node": ">=14"
|
|
43
43
|
},
|
|
44
44
|
"repository": {
|
|
45
|
+
"type": "git",
|
|
45
46
|
"url": "https://github.com/mattwca/little-parser-lib"
|
|
46
47
|
}
|
|
47
48
|
}
|
package/src/index.ts
CHANGED
|
@@ -92,8 +92,8 @@ export function or<T>(...parsers: ParseFn<T>[]): ParseFn<T> {
|
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
/**
|
|
95
|
-
* Applies a parser repeatedly until it fails
|
|
96
|
-
* If the parser fails on the first attempt, returns a failure.
|
|
95
|
+
* Applies a parser repeatedly until it fails or doesn't make progress (move the position), collecting
|
|
96
|
+
* all successful results into an array. If the parser fails on the first attempt, returns a failure.
|
|
97
97
|
*/
|
|
98
98
|
export function many(parser: ParseFn<any>): ParseFn<any> {
|
|
99
99
|
return (tokenStream: TokenStream) => {
|
|
@@ -102,10 +102,20 @@ export function many(parser: ParseFn<any>): ParseFn<any> {
|
|
|
102
102
|
let parseFailure = null;
|
|
103
103
|
|
|
104
104
|
while (true) {
|
|
105
|
+
const positionBefore = tokenStream.position;
|
|
105
106
|
tokenStream.storePosition();
|
|
106
107
|
|
|
107
108
|
const result = parser(tokenStream);
|
|
109
|
+
|
|
108
110
|
if (isSuccessfulResult(result)) {
|
|
111
|
+
const positionAfter = tokenStream.position;
|
|
112
|
+
|
|
113
|
+
// Check if the parser made any progress - if it didn't, we break out to avoid infinite loops.
|
|
114
|
+
if (positionAfter === positionBefore) {
|
|
115
|
+
tokenStream.restorePosition();
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
|
|
109
119
|
results.push(result.result);
|
|
110
120
|
tokenStream.clearPosition();
|
|
111
121
|
} else {
|
|
@@ -197,24 +207,11 @@ export function endOfInput(): ParseFn {
|
|
|
197
207
|
};
|
|
198
208
|
}
|
|
199
209
|
|
|
200
|
-
export function parseName(): ParseFn<any> {
|
|
201
|
-
return (tokenStream: TokenStream) => {
|
|
202
|
-
const validTokenTypes: TokenType[] = ['letter', 'digit', 'minus', 'underscore'];
|
|
203
|
-
const parseValidToken = anyOf(...validTokenTypes);
|
|
204
|
-
|
|
205
|
-
const parser = and(anyOf('letter'), many(parseValidToken));
|
|
206
|
-
const result = parser(tokenStream);
|
|
207
|
-
|
|
208
|
-
if (isSuccessfulResult(result)) {
|
|
209
|
-
console.log(result);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
return result;
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
210
|
/**
|
|
217
211
|
* Transforms the result of a parser using a given mapping function.
|
|
212
|
+
* @param parser The parser whose result is to be transformed.
|
|
213
|
+
* @param mapFn A function that takes the parser's result and returns a new value.
|
|
214
|
+
* @returns A new parser that applies the mapping function to the result of the original parser.
|
|
218
215
|
*/
|
|
219
216
|
export function map<T, U>(parser: ParseFn<T>, mapFn: (value: T) => U): ParseFn<U> {
|
|
220
217
|
return (tokenStream: TokenStream) => {
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A method which unwraps a given generic array, taking each element and accumulating them, if the given item is a nested array, it is flattened into the result.
|
|
3
|
+
* Useful for flattening parser results built with the `and` and `many` combinators, which can produce nested arrays.
|
|
4
|
+
* @param items - An array of items or nested arrays of items to be unwrapped.
|
|
5
|
+
* @returns A flattened array containing all individual items.
|
|
6
|
+
*/
|
|
7
|
+
export const unwrapResult = <T>(items: (T | T[])[]): T[] => {
|
|
8
|
+
const result: T[] = [];
|
|
9
|
+
for (const item of items) {
|
|
10
|
+
if (Array.isArray(item)) {
|
|
11
|
+
result.push(...unwrapResult(item));
|
|
12
|
+
} else {
|
|
13
|
+
result.push(item);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return result;
|
|
17
|
+
};
|
package/src/parser/index.ts
DELETED
|
File without changes
|
|
File without changes
|