@@ -2,11 +2,11 @@ import { assertGreater } from "@std/assert/greater";
2
2
import { MemoizationCacheResult , memoize } from "@std/cache/memoize" ;
3
3
import { ArrayResult , ArrayResultError } from "../array_result.ts" ;
4
4
5
- type Input = Readonly < { source : string ; position : number } > ;
6
5
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 > ;
8
7
type Memo < T > = Map < number , MemoizationCacheResult < ParserResult < T > > > ;
9
8
9
+ let currentSource = "" ;
10
10
const allMemo : Set < WeakRef < Memo < unknown > > > = new Set ( ) ;
11
11
12
12
export class Parser < T > {
@@ -16,11 +16,12 @@ export class Parser<T> {
16
16
allMemo . add ( new WeakRef ( cache ) ) ;
17
17
this . rawParser = memoize < InnerParser < T > , number , Memo < T > > (
18
18
parser ,
19
- { getKey : ( { position } ) => position , cache } ,
19
+ { cache } ,
20
20
) ;
21
21
}
22
22
generateParser ( ) : ( source : string ) => ArrayResult < T > {
23
- return ( input ) => {
23
+ return ( source ) => {
24
+ currentSource = source ;
24
25
for ( const memo of allMemo ) {
25
26
const ref = memo . deref ( ) ;
26
27
if ( ref == null ) {
@@ -29,7 +30,7 @@ export class Parser<T> {
29
30
ref . clear ( ) ;
30
31
}
31
32
}
32
- return this . rawParser ( { source : input , position : 0 } )
33
+ return this . rawParser ( 0 )
33
34
. map ( ( { value } ) => value ) ;
34
35
} ;
35
36
}
@@ -45,14 +46,11 @@ export class Parser<T> {
45
46
) ;
46
47
}
47
48
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 )
50
51
. flatMap ( ( { value, length } ) =>
51
52
mapper ( value )
52
- . rawParser ( {
53
- source : input . source ,
54
- position : input . position + length ,
55
- } )
53
+ . rawParser ( position + length )
56
54
. map ( ( { value, length : addedLength } ) => ( {
57
55
value,
58
56
length : length + addedLength ,
@@ -207,8 +205,8 @@ export function matchCapture(
207
205
description : string ,
208
206
) : Parser < RegExpMatchArray > {
209
207
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 ) ;
212
210
const match = sourceString . match ( newRegex ) ;
213
211
if ( match != null ) {
214
212
return new ArrayResult ( [ { value : match , length : match [ 0 ] . length } ] ) ;
@@ -226,10 +224,10 @@ export function matchString(
226
224
match : string ,
227
225
description = `"${ match } "` ,
228
226
) : Parser < string > {
229
- return new Parser ( ( { source , position } ) => {
227
+ return new Parser ( ( position ) => {
230
228
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
233
231
) {
234
232
return new ArrayResult ( [ {
235
233
value : match ,
@@ -238,38 +236,38 @@ export function matchString(
238
236
} else {
239
237
return new ArrayResult (
240
238
new UnexpectedError (
241
- describeSource ( source . slice ( position ) ) ,
239
+ describeSource ( currentSource . slice ( position ) ) ,
242
240
description ,
243
241
) ,
244
242
) ;
245
243
}
246
244
} ) ;
247
245
}
248
- export const everything = new Parser ( ( { source , position } ) =>
246
+ export const everything = new Parser ( ( position ) =>
249
247
new ArrayResult ( [ {
250
- value : source . slice ( position ) ,
251
- length : source . length - position ,
248
+ value : currentSource . slice ( position ) ,
249
+ length : currentSource . length - position ,
252
250
} ] )
253
251
) ;
254
252
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
257
255
? new ArrayResult ( [ { value : null , length : 0 } ] )
258
256
: new ArrayResult (
259
257
new UnexpectedError (
260
- describeSource ( input . source . slice ( input . position ) ) ,
258
+ describeSource ( currentSource . slice ( position ) ) ,
261
259
"end of text" ,
262
260
) ,
263
261
)
264
262
) ;
265
263
export function withSource < T > (
266
264
parser : Parser < T > ,
267
265
) : 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 } ) => ( {
270
268
value : [
271
269
value ,
272
- input . source . slice ( input . position , input . position + length ) ,
270
+ currentSource . slice ( position , position + length ) ,
273
271
] as const ,
274
272
length,
275
273
} ) )
0 commit comments