Skip to content

Commit 32930ad

Browse files
committed
feat: override of imported grammar rules
1 parent f58d4cc commit 32930ad

File tree

10 files changed

+354
-233
lines changed

10 files changed

+354
-233
lines changed

docs/grammar_modularization.md

+36
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,42 @@ tests](https://github.com/igordejanovic/parglare/blob/master/tests/func/import/f
4444
for an example.
4545

4646

47+
## Imported rules override
48+
49+
Grammar rules defined in imported grammar can be overridden by using appropriate
50+
FQN rule name. For example, if we have following grammars:
51+
52+
file: `first.pg`
53+
```
54+
import 'second.pg' as s;
55+
...
56+
57+
```
58+
59+
file: `second.pg`
60+
```
61+
import 'third.pg' as t;
62+
...
63+
```
64+
65+
file `third.pg`
66+
```
67+
S: A B+;
68+
B: 'foo' C;
69+
```
70+
71+
In `first.pg` we could then write:
72+
```
73+
S: s.t.S;
74+
s.t.B: 'bar' C+;
75+
```
76+
Which will effectively override rule `B` from `third.pg` (note FQN `s.t.B`).
77+
78+
All grammar rules that used old `B` from `third.pg` will now use `s.t.B` rule
79+
from `first.pg`. This enables a flexible modification of existing grammars from
80+
importing grammars just in places where it is needed without having to rewrite
81+
all the rules that use the rule that needs to be modified.
82+
4783

4884
## Grammar file recognizers
4985

parglare/common.py

+14-28
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,14 @@ class Location:
2121
end and input_str.
2222
"""
2323

24-
__slots__ = ['context', 'file_name',
25-
'_line', '_column',
26-
'_line_end', '_column_end']
24+
__slots__ = ['start_position', 'end_position', 'input_str', 'file_name',
25+
'_line', '_column', '_line_end', '_column_end']
2726

2827
def __init__(self, context=None, file_name=None):
29-
30-
self.context = context
31-
self.file_name = file_name or context.file_name
28+
self.start_position = context.start_position if context else None
29+
self.end_position = context.end_position if context else None
30+
self.input_str = context.input_str if context else None
31+
self.file_name = file_name or context.file_name if context else None
3232

3333
# Evaluate this only when string representation is needed.
3434
# E.g. during error reporting
@@ -63,40 +63,26 @@ def column_end(self):
6363
return self._column_end
6464

6565
def evaluate_line_col(self):
66-
context = self.context
6766
self._line, self._column = pos_to_line_col(
68-
context.input_str, context.start_position)
67+
self.input_str, self.start_position)
6968

7069
def evaluate_line_col_end(self):
71-
context = self.context
72-
if hasattr(context, 'end_position') \
73-
and context.end_position:
70+
if self.end_position:
7471
self._line_end, self._column_end = \
75-
pos_to_line_col(context.input_str, context.end_position)
76-
77-
def __getattr__(self, name):
78-
if self.context is not None:
79-
return getattr(self.context, name)
80-
else:
81-
raise AttributeError(name)
72+
pos_to_line_col(self.input_str, self.end_position)
8273

8374
def __str__(self):
84-
if self.context is None:
85-
line, column = None, None
86-
else:
87-
line, column = self.line, self.column
88-
context = self.context
75+
line, column = self.line, self.column
8976
if line is not None:
9077
return ('{}{}:{}:"{}"'
9178
.format(f"{self.file_name}:"
9279
if self.file_name else "",
9380
line, column,
94-
position_context(context.input_str,
95-
context.start_position)))
96-
elif self.file_name:
81+
position_context(self.input_str,
82+
self.start_position)))
83+
if self.file_name:
9784
return _a(self.file_name)
98-
else:
99-
return "<Unknown location>"
85+
return "<Unknown location>"
10086

10187
def __repr__(self):
10288
return str(self)

parglare/glr.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,7 @@ def _do_error_recovery(self):
511511
successful = self.error_recovery(head, error)
512512

513513
if successful:
514-
error.location.context.end_position = head.position
514+
error.location.end_position = head.position
515515
if debug:
516516
a_print("New position is ",
517517
pos_to_line_col(input_str, head.position),

0 commit comments

Comments
 (0)