0
# Configuration and Context
1
2
Configure parser behavior, manage parsing state, and access parse position and rule information. TatSu provides comprehensive configuration options and context management for fine-tuning parser behavior and accessing detailed parsing information.
3
4
## Capabilities
5
6
### Parser Configuration
7
8
Centralized configuration object for controlling all aspects of parser behavior and generation.
9
10
```python { .api }
11
class ParserConfig:
12
"""
13
Parser configuration with settings for parsing behavior.
14
15
Attributes:
16
- name: str, parser name for error reporting
17
- filename: str, source filename for error context
18
- encoding: str, input text encoding (default: 'utf-8')
19
- start: str, start rule name (default: first rule)
20
- semantics: object, semantic actions object
21
- trace: bool, enable verbose parsing output
22
- colorize: bool, use colored output in traces
23
- ignorecase: bool, case-insensitive parsing
24
- left_recursion: bool, enable left-recursion support
25
- nameguard: bool, prevent tokens that are prefixes of others
26
- whitespace: str, characters to skip during parsing
27
- parseinfo: bool, include parse position information in AST
28
"""
29
30
def new(self, **kwargs):
31
"""
32
Create new configuration with updated settings.
33
34
Returns:
35
ParserConfig: New configuration object with merged settings
36
"""
37
38
def replace(self, **kwargs):
39
"""
40
Replace specific configuration values.
41
42
Returns:
43
ParserConfig: New configuration with replaced values
44
"""
45
46
def merge(self, other_config):
47
"""
48
Merge with another configuration object.
49
50
Parameters:
51
- other_config (ParserConfig): Configuration to merge
52
53
Returns:
54
ParserConfig: Merged configuration
55
"""
56
57
def asdict(self):
58
"""
59
Convert configuration to dictionary.
60
61
Returns:
62
dict: Configuration as key-value pairs
63
"""
64
65
def effective_rule_name(self, rule_name):
66
"""
67
Get effective rule name with configuration context.
68
69
Returns:
70
str: Effective rule name for given input
71
"""
72
```
73
74
Usage example:
75
76
```python
77
import tatsu
78
from tatsu.infos import ParserConfig
79
80
# Create custom configuration
81
config = ParserConfig(
82
name="MyParser",
83
trace=True,
84
colorize=True,
85
left_recursion=True,
86
whitespace=r'\s+',
87
parseinfo=True
88
)
89
90
# Use configuration with parsing
91
model = tatsu.compile(grammar, config=config)
92
result = model.parse(input_text, config=config)
93
94
# Create derived configurations
95
debug_config = config.new(trace=True, colorize=True)
96
production_config = config.new(trace=False, colorize=False)
97
```
98
99
### Parse Information
100
101
Access detailed information about parse position, rules, and context during and after parsing.
102
103
```python { .api }
104
class ParseInfo:
105
"""
106
Parse position and rule information with line tracking.
107
108
Attributes:
109
- tokenizer: Tokenizer, input tokenizer object
110
- rule: str, current rule name
111
- pos: int, character position in input
112
- endpos: int, end position after parsing
113
- line: int, line number (1-based)
114
- endline: int, end line number
115
- alerts: list, parse alerts and warnings
116
"""
117
118
def text_lines(self):
119
"""
120
Get source text lines for this parse info.
121
122
Returns:
123
list: List of source lines covered by this parse
124
"""
125
126
def line_index(self):
127
"""
128
Get line index information.
129
130
Returns:
131
LineInfo: Detailed line position information
132
"""
133
```
134
135
Usage example:
136
137
```python
138
import tatsu
139
140
grammar = '''
141
@@parseinfo :: True
142
143
expr = term ("+" term)*;
144
term = factor ("*" factor)*;
145
factor = number;
146
number = /\d+/;
147
'''
148
149
model = tatsu.compile(grammar)
150
result = model.parse("2 + 3 * 4")
151
152
# Access parse information
153
def print_parse_info(node, depth=0):
154
indent = " " * depth
155
if hasattr(node, 'parseinfo') and node.parseinfo:
156
info = node.parseinfo
157
print(f"{indent}Rule: {info.rule}")
158
print(f"{indent}Position: {info.pos}-{info.endpos}")
159
print(f"{indent}Lines: {info.line}-{info.endline}")
160
161
if isinstance(node, list):
162
for item in node:
163
print_parse_info(item, depth + 1)
164
elif hasattr(node, '__dict__'):
165
for value in node.__dict__.values():
166
print_parse_info(value, depth + 1)
167
168
print_parse_info(result)
169
```
170
171
### Line Information
172
173
Detailed source line and position information for error reporting and IDE integration.
174
175
```python { .api }
176
class LineInfo:
177
"""
178
Source line information with position data.
179
180
Attributes:
181
- filename: str, source filename
182
- line: int, line number (1-based)
183
- col: int, column number (1-based)
184
- start: int, start position in line
185
- end: int, end position in line
186
- text: str, line text content
187
"""
188
```
189
190
### Comment Information
191
192
Handle and preserve comments during parsing for documentation generation and code analysis.
193
194
```python { .api }
195
class CommentInfo:
196
"""
197
Comment information for inline and end-of-line comments.
198
199
Attributes:
200
- inline: list, inline comments within expressions
201
- eol: list, end-of-line comments
202
"""
203
204
def new_comment(self, text, position, comment_type='inline'):
205
"""
206
Create new comment information.
207
208
Parameters:
209
- text (str): Comment text content
210
- position (int): Character position of comment
211
- comment_type (str): Type of comment ('inline', 'eol', 'block')
212
213
Returns:
214
CommentInfo: New comment information object
215
"""
216
```
217
218
### Parse Alerts and Warnings
219
220
System for collecting and reporting parse warnings, deprecation notices, and other non-fatal issues.
221
222
```python { .api }
223
class Alert:
224
"""
225
Parse alert/warning with severity level.
226
227
Attributes:
228
- level: str, alert level ('info', 'warning', 'error')
229
- message: str, alert message text
230
"""
231
```
232
233
### Rule Information
234
235
Metadata about grammar rules including parameters, flags, and analysis results.
236
237
```python { .api }
238
class RuleInfo:
239
"""
240
Rule metadata including analysis results.
241
242
Attributes:
243
- name: str, rule name
244
- impl: object, rule implementation object
245
- is_leftrec: bool, true if rule is left-recursive
246
- is_memoizable: bool, true if rule can be memoized
247
- is_name: bool, true if rule produces named results
248
- params: list, rule parameters
249
- kwparams: dict, keyword parameters
250
"""
251
```
252
253
### Parse State Management
254
255
Internal parsing state tracking for advanced use cases and debugging.
256
257
```python { .api }
258
class ParseState:
259
"""
260
Parser state with position and AST information.
261
262
Attributes:
263
- pos: int, current parse position
264
- ast: object, current AST being built
265
- cst: object, concrete syntax tree
266
- alerts: list, accumulated alerts
267
"""
268
269
class RuleResult:
270
"""
271
Rule parse result with position and state.
272
273
Attributes:
274
- node: object, parsed AST node
275
- newpos: int, new position after parsing
276
- newstate: ParseState, updated parse state
277
"""
278
279
class MemoKey:
280
"""
281
Memoization key for caching parse results.
282
283
Attributes:
284
- pos: int, parse position
285
- rule: str, rule name
286
- state: object, parse state identifier
287
"""
288
```
289
290
## Advanced Configuration
291
292
### Custom Configuration Classes
293
294
```python
295
from tatsu.infos import ParserConfig
296
297
class ProjectConfig(ParserConfig):
298
"""Project-specific parser configuration."""
299
300
def __init__(self, **kwargs):
301
defaults = {
302
'trace': False,
303
'left_recursion': True,
304
'parseinfo': True,
305
'whitespace': r'\s+',
306
'nameguard': True
307
}
308
defaults.update(kwargs)
309
super().__init__(**defaults)
310
311
def debug_mode(self):
312
"""Enable debug mode settings."""
313
return self.new(
314
trace=True,
315
colorize=True,
316
parseinfo=True
317
)
318
319
def production_mode(self):
320
"""Enable production mode settings."""
321
return self.new(
322
trace=False,
323
colorize=False,
324
parseinfo=False
325
)
326
```
327
328
### Environment-Based Configuration
329
330
```python
331
import os
332
from tatsu.infos import ParserConfig
333
334
def create_config_from_env():
335
"""Create parser configuration from environment variables."""
336
return ParserConfig(
337
trace=os.getenv('TATSU_TRACE', 'false').lower() == 'true',
338
colorize=os.getenv('TATSU_COLOR', 'true').lower() == 'true',
339
left_recursion=os.getenv('TATSU_LEFT_REC', 'true').lower() == 'true',
340
whitespace=os.getenv('TATSU_WHITESPACE', r'\s+'),
341
parseinfo=os.getenv('TATSU_PARSEINFO', 'false').lower() == 'true'
342
)
343
344
# Usage
345
config = create_config_from_env()
346
model = tatsu.compile(grammar, config=config)
347
```
348
349
### Configuration Validation
350
351
```python
352
class ValidatedConfig(ParserConfig):
353
"""Configuration with validation rules."""
354
355
def __init__(self, **kwargs):
356
super().__init__(**kwargs)
357
self._validate()
358
359
def _validate(self):
360
"""Validate configuration settings."""
361
if self.trace and not self.parseinfo:
362
import warnings
363
warnings.warn("Trace mode is more useful with parseinfo enabled")
364
365
if self.colorize and not self.trace:
366
import warnings
367
warnings.warn("Colorize has no effect without trace mode")
368
369
if self.whitespace is not None:
370
try:
371
import re
372
re.compile(self.whitespace)
373
except re.error as e:
374
raise ValueError(f"Invalid whitespace regex: {e}")
375
376
# Usage with validation
377
try:
378
config = ValidatedConfig(
379
whitespace="[invalid regex", # This will raise ValueError
380
trace=True,
381
parseinfo=True
382
)
383
except ValueError as e:
384
print(f"Configuration error: {e}")
385
```
386
387
### Runtime Configuration Updates
388
389
```python
390
class DynamicConfig:
391
"""Configuration that can be updated during parsing."""
392
393
def __init__(self, base_config):
394
self.base_config = base_config
395
self.overrides = {}
396
397
def with_override(self, **kwargs):
398
"""Temporarily override configuration values."""
399
old_overrides = self.overrides.copy()
400
self.overrides.update(kwargs)
401
return ConfigContext(self, old_overrides)
402
403
def get_effective_config(self):
404
"""Get configuration with current overrides applied."""
405
config_dict = self.base_config.asdict()
406
config_dict.update(self.overrides)
407
return ParserConfig(**config_dict)
408
409
class ConfigContext:
410
"""Context manager for temporary configuration overrides."""
411
412
def __init__(self, dynamic_config, old_overrides):
413
self.config = dynamic_config
414
self.old_overrides = old_overrides
415
416
def __enter__(self):
417
return self.config.get_effective_config()
418
419
def __exit__(self, exc_type, exc_val, exc_tb):
420
self.config.overrides = self.old_overrides
421
422
# Usage
423
dynamic_config = DynamicConfig(base_config)
424
425
# Temporarily enable tracing for debugging
426
with dynamic_config.with_override(trace=True, colorize=True) as config:
427
result = model.parse(input_text, config=config)
428
```