generated from norskeld/serpent
-
Notifications
You must be signed in to change notification settings - Fork 3
/
defer.md
119 lines (97 loc) · 2.33 KB
/
defer.md
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
---
title: 'defer'
kind: 'primitive'
description: 'defer is a special parser that is tailored for creating mutually recursive parsers.'
---
# defer <Primitive />
## Signature
```ts
interface Deferred<T> extends Parser<T> {
with(parser: Parser<T>): void
}
function defer<T>(): Deferred<T>
```
## Description
`defer` is a special parser that has an additional `with` method, which should be used to define the parser. This parser is tailored for creating mutually recursive parsers.
## Example
::: info Combinators and parsers used in this section
- Combinators: [choice], [sepBy], [map], [takeMid]
- Parsers: [defer], [integer], [string]
:::
In the example below we are parsing simple nested tuples like `(1,2,(3,(4,5)))` into an AST, which then can be somehow manipulated. Every parsed node also has a span, that is location information.
```ts
interface NumberNode {
type: 'number'
span: Span
value: number
}
interface ListNode {
type: 'list'
span: Span
value: Array<NumberNode | ListNode>
}
const TupleList = defer<ListNode>()
const TupleNumber = defer<NumberNode>()
TupleNumber.with(
map(
integer(),
(value, span) => ({ type: 'number', span, value })
)
)
TupleList.with(
map(
takeMid(
string('('),
sepBy(choice(TupleList, TupleNumber), string(',')),
string(')')
),
(value, span) => ({ type: 'list', span, value })
)
)
```
If we run our parser and feed it with input:
```ts
run(TupleList).with('(1,2,(3,(4,5)))')
```
We will get the following result:
::: tip Success
```ts
{
isOk: true,
span: [ 0, 15 ],
pos: 15,
value: {
type: 'list',
span: [ 0, 15 ],
value: [
{ type: 'number', span: [ 1, 2 ], value: 1 },
{ type: 'number', span: [ 3, 4 ], value: 2 },
{
type: 'list',
span: [ 5, 14 ],
value: [
{ type: 'number', span: [ 6, 7 ], value: 3 },
{
type: 'list',
span: [ 8, 13 ],
value: [
{ type: 'number', span: [ 9, 10 ], value: 4 },
{ type: 'number', span: [ 11, 12 ], value: 5 }
]
}
]
}
]
}
}
```
:::
<!-- Combinators. -->
[choice]: ../combinators/choice
[map]: ../combinators/map
[sepBy]: ../combinators/sepBy
[takeMid]: ../combinators/takeMid
<!-- Parsers. -->
[defer]: ./defer
[integer]: ./integer
[string]: ./string