Skip to content

Commit 93ad50b

Browse files
committed
source string is now a global state
1 parent 89f7091 commit 93ad50b

File tree

1 file changed

+24
-26
lines changed

1 file changed

+24
-26
lines changed

src/parser/parser_lib.ts

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ import { assertGreater } from "@std/assert/greater";
22
import { MemoizationCacheResult, memoize } from "@std/cache/memoize";
33
import { ArrayResult, ArrayResultError } from "../array_result.ts";
44

5-
type Input = Readonly<{ source: string; position: number }>;
65
type ParserResult<T> = ArrayResult<Readonly<{ value: T; length: number }>>;
7-
type InnerParser<T> = (input: Input) => ParserResult<T>;
6+
type InnerParser<T> = (input: number) => ParserResult<T>;
87
type Memo<T> = Map<number, MemoizationCacheResult<ParserResult<T>>>;
98

9+
let currentSource = "";
1010
const allMemo: Set<WeakRef<Memo<unknown>>> = new Set();
1111

1212
export class Parser<T> {
@@ -16,11 +16,12 @@ export class Parser<T> {
1616
allMemo.add(new WeakRef(cache));
1717
this.rawParser = memoize<InnerParser<T>, number, Memo<T>>(
1818
parser,
19-
{ getKey: ({ position }) => position, cache },
19+
{ cache },
2020
);
2121
}
2222
generateParser(): (source: string) => ArrayResult<T> {
23-
return (input) => {
23+
return (source) => {
24+
currentSource = source;
2425
for (const memo of allMemo) {
2526
const ref = memo.deref();
2627
if (ref == null) {
@@ -29,7 +30,7 @@ export class Parser<T> {
2930
ref.clear();
3031
}
3132
}
32-
return this.rawParser({ source: input, position: 0 })
33+
return this.rawParser(0)
3334
.map(({ value }) => value);
3435
};
3536
}
@@ -45,14 +46,11 @@ export class Parser<T> {
4546
);
4647
}
4748
then<U>(mapper: (value: T) => Parser<U>): Parser<U> {
48-
return new Parser((input) =>
49-
this.rawParser(input)
49+
return new Parser((position) =>
50+
this.rawParser(position)
5051
.flatMap(({ value, length }) =>
5152
mapper(value)
52-
.rawParser({
53-
source: input.source,
54-
position: input.position + length,
55-
})
53+
.rawParser(position + length)
5654
.map(({ value, length: addedLength }) => ({
5755
value,
5856
length: length + addedLength,
@@ -207,8 +205,8 @@ export function matchCapture(
207205
description: string,
208206
): Parser<RegExpMatchArray> {
209207
const newRegex = new RegExp(`^${regex.source}`, regex.flags);
210-
return new Parser(({ source, position }) => {
211-
const sourceString = source.slice(position);
208+
return new Parser((position) => {
209+
const sourceString = currentSource.slice(position);
212210
const match = sourceString.match(newRegex);
213211
if (match != null) {
214212
return new ArrayResult([{ value: match, length: match[0].length }]);
@@ -226,10 +224,10 @@ export function matchString(
226224
match: string,
227225
description = `"${match}"`,
228226
): Parser<string> {
229-
return new Parser(({ source, position }) => {
227+
return new Parser((position) => {
230228
if (
231-
source.length - position >= match.length &&
232-
source.slice(position, position + match.length) === match
229+
currentSource.length - position >= match.length &&
230+
currentSource.slice(position, position + match.length) === match
233231
) {
234232
return new ArrayResult([{
235233
value: match,
@@ -238,38 +236,38 @@ export function matchString(
238236
} else {
239237
return new ArrayResult(
240238
new UnexpectedError(
241-
describeSource(source.slice(position)),
239+
describeSource(currentSource.slice(position)),
242240
description,
243241
),
244242
);
245243
}
246244
});
247245
}
248-
export const everything = new Parser(({ source, position }) =>
246+
export const everything = new Parser((position) =>
249247
new ArrayResult([{
250-
value: source.slice(position),
251-
length: source.length - position,
248+
value: currentSource.slice(position),
249+
length: currentSource.length - position,
252250
}])
253251
);
254252
export const character = match(/./us, "character");
255-
export const end = new Parser((input) =>
256-
input.position === input.source.length
253+
export const end = new Parser((position) =>
254+
position === currentSource.length
257255
? new ArrayResult([{ value: null, length: 0 }])
258256
: new ArrayResult(
259257
new UnexpectedError(
260-
describeSource(input.source.slice(input.position)),
258+
describeSource(currentSource.slice(position)),
261259
"end of text",
262260
),
263261
)
264262
);
265263
export function withSource<T>(
266264
parser: Parser<T>,
267265
): Parser<readonly [value: T, source: string]> {
268-
return new Parser((input) =>
269-
parser.rawParser(input).map(({ value, length }) => ({
266+
return new Parser((position) =>
267+
parser.rawParser(position).map(({ value, length }) => ({
270268
value: [
271269
value,
272-
input.source.slice(input.position, input.position + length),
270+
currentSource.slice(position, position + length),
273271
] as const,
274272
length,
275273
}))

0 commit comments

Comments
 (0)