0
# Core Parser Class
1
2
The Parser class is the fundamental building block of parsy. It wraps parsing functions and provides methods for transformation, combination, and execution.
3
4
## Capabilities
5
6
### Parser Construction
7
8
Creates a new parser by wrapping a parsing function that takes a stream and index, returning a Result object.
9
10
```python { .api }
11
class Parser:
12
def __init__(self, wrapped_fn):
13
"""
14
Create a parser from a function.
15
16
Args:
17
wrapped_fn: Function that takes (stream, index) and returns Result
18
"""
19
20
def __call__(self, stream, index):
21
"""
22
Execute the parser on a stream at the given index.
23
24
Args:
25
stream: Input string or list of tokens to parse
26
index: Starting position in the stream
27
28
Returns:
29
Result: Result object with parsing outcome
30
"""
31
```
32
33
### Parse Execution
34
35
Execute the parser on input streams with complete or partial parsing options.
36
37
```python { .api }
38
def parse(self, stream):
39
"""
40
Parse a string completely and return the result or raise ParseError.
41
42
Args:
43
stream: Input string or list of tokens to parse
44
45
Returns:
46
Parsed result value
47
48
Raises:
49
ParseError: If parsing fails
50
"""
51
52
def parse_partial(self, stream):
53
"""
54
Parse the longest possible prefix of input.
55
56
Args:
57
stream: Input string or list of tokens to parse
58
59
Returns:
60
tuple: (result_value, remaining_stream)
61
62
Raises:
63
ParseError: If parsing fails
64
"""
65
```
66
67
### Parser Transformation
68
69
Transform parser results using mapping and binding operations.
70
71
```python { .api }
72
def bind(self, bind_fn):
73
"""
74
Monadic bind operation for parser chaining.
75
76
Args:
77
bind_fn: Function that takes parse result and returns new Parser
78
79
Returns:
80
Parser: New parser with bound computation
81
"""
82
83
def map(self, map_fn):
84
"""
85
Transform the result of successful parsing.
86
87
Args:
88
map_fn: Function to transform the parse result
89
90
Returns:
91
Parser: New parser with transformed result
92
"""
93
94
def combine(self, combine_fn):
95
"""
96
Transform parser result by unpacking as positional arguments.
97
98
Args:
99
combine_fn: Function to receive *args from parse result
100
101
Returns:
102
Parser: New parser with combined result
103
"""
104
105
def combine_dict(self, combine_fn):
106
"""
107
Transform parser result by unpacking as keyword arguments.
108
109
Args:
110
combine_fn: Function to receive **kwargs from parse result
111
112
Returns:
113
Parser: New parser with combined result
114
"""
115
116
def concat(self):
117
"""
118
Join string results using ''.join().
119
120
Returns:
121
Parser: New parser with concatenated string result
122
"""
123
124
def result(self, res):
125
"""
126
Replace parser result with constant value.
127
128
Args:
129
res: Constant value to return instead of parse result
130
131
Returns:
132
Parser: New parser that returns constant value
133
"""
134
```
135
136
### Parser Sequencing
137
138
Combine parsers in sequence with different result handling strategies.
139
140
```python { .api }
141
def then(self, other):
142
"""
143
Parse this parser then other, returning other's result.
144
145
Args:
146
other: Parser to execute after this one
147
148
Returns:
149
Parser: New parser returning right-hand result
150
"""
151
152
def skip(self, other):
153
"""
154
Parse this parser then other, returning this parser's result.
155
156
Args:
157
other: Parser to execute after this one (result ignored)
158
159
Returns:
160
Parser: New parser returning left-hand result
161
"""
162
```
163
164
### Repetition Parsers
165
166
Parse repeated occurrences of patterns with various quantifiers.
167
168
```python { .api }
169
def many(self):
170
"""
171
Parse zero or more occurrences.
172
173
Returns:
174
Parser: New parser returning list of results
175
"""
176
177
def times(self, min, max=None):
178
"""
179
Parse specific number of occurrences.
180
181
Args:
182
min: Minimum number of occurrences
183
max: Maximum number of occurrences (defaults to min)
184
185
Returns:
186
Parser: New parser returning list of results
187
"""
188
189
def at_most(self, n):
190
"""
191
Parse at most n occurrences.
192
193
Args:
194
n: Maximum number of occurrences
195
196
Returns:
197
Parser: New parser returning list of results
198
"""
199
200
def at_least(self, n):
201
"""
202
Parse at least n occurrences.
203
204
Args:
205
n: Minimum number of occurrences
206
207
Returns:
208
Parser: New parser returning list of results
209
"""
210
211
def optional(self):
212
"""
213
Parse zero or one occurrence.
214
215
Returns:
216
Parser: New parser returning result or None
217
"""
218
219
def sep_by(self, sep, *, min=0, max=float('inf')):
220
"""
221
Parse separated list of items.
222
223
Args:
224
sep: Parser for separator between items
225
min: Minimum number of items (default 0)
226
max: Maximum number of items (default infinity)
227
228
Returns:
229
Parser: New parser returning list of items
230
"""
231
```
232
233
### Parser Annotation
234
235
Add descriptions and position tracking to parsers for better error messages and debugging.
236
237
```python { .api }
238
def desc(self, description):
239
"""
240
Add description for error messages.
241
242
Args:
243
description: String description of what parser expects
244
245
Returns:
246
Parser: New parser with description
247
"""
248
249
def mark(self):
250
"""
251
Add position information to parse results.
252
253
Returns:
254
Parser: New parser returning (start_pos, result, end_pos)
255
"""
256
257
def tag(self, name):
258
"""
259
Tag result with name.
260
261
Args:
262
name: Tag name for the result
263
264
Returns:
265
Parser: New parser returning (name, result) tuple
266
"""
267
```
268
269
### Negative Parsing
270
271
Create parsers that succeed when other parsers fail.
272
273
```python { .api }
274
def should_fail(self, description):
275
"""
276
Succeed only if this parser fails.
277
278
Args:
279
description: Description for success case
280
281
Returns:
282
Parser: New parser that succeeds on failure
283
"""
284
```
285
286
### Operator Overloads
287
288
Convenient operators for common parser operations.
289
290
```python { .api }
291
def __add__(self, other):
292
"""Concatenate results using + operator."""
293
294
def __mul__(self, other):
295
"""Repeat parser using * operator (accepts int or range)."""
296
297
def __or__(self, other):
298
"""Alternative parser using | operator."""
299
300
def __rshift__(self, other):
301
"""Then operation using >> operator."""
302
303
def __lshift__(self, other):
304
"""Skip operation using << operator."""
305
```
306
307
## Usage Examples
308
309
```python
310
from parsy import string, regex, generate
311
312
# Basic transformation
313
number = regex(r'\d+').map(int)
314
result = number.parse('123') # Returns 123
315
316
# Sequencing with then/skip
317
quoted_string = (
318
string('"') >>
319
regex(r'[^"]*') <<
320
string('"')
321
)
322
result = quoted_string.parse('"hello"') # Returns 'hello'
323
324
# Repetition
325
numbers = regex(r'\d+').map(int).sep_by(string(','))
326
result = numbers.parse('1,2,3,4') # Returns [1, 2, 3, 4]
327
328
# Optional parsing
329
maybe_sign = string('-').optional()
330
signed_number = (maybe_sign + regex(r'\d+').map(int)).combine(
331
lambda sign, num: -num if sign else num
332
)
333
result = signed_number.parse('-42') # Returns -42
334
```