Skip to content

Commit

Permalink
Merge branch 'feat/rule-override'
Browse files Browse the repository at this point in the history
  • Loading branch information
igordejanovic committed Feb 23, 2024
2 parents f2889e0 + 32930ad commit f1c63f6
Show file tree
Hide file tree
Showing 10 changed files with 408 additions and 284 deletions.
36 changes: 36 additions & 0 deletions docs/grammar_modularization.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,42 @@ tests](https://github.com/igordejanovic/parglare/blob/master/tests/func/import/f
for an example.


## Imported rules override

Grammar rules defined in imported grammar can be overridden by using appropriate
FQN rule name. For example, if we have following grammars:

file: `first.pg`
```
import 'second.pg' as s;
...
```

file: `second.pg`
```
import 'third.pg' as t;
...
```

file `third.pg`
```
S: A B+;
B: 'foo' C;
```

In `first.pg` we could then write:
```
S: s.t.S;
s.t.B: 'bar' C+;
```
Which will effectively override rule `B` from `third.pg` (note FQN `s.t.B`).

All grammar rules that used old `B` from `third.pg` will now use `s.t.B` rule
from `first.pg`. This enables a flexible modification of existing grammars from
importing grammars just in places where it is needed without having to rewrite
all the rules that use the rule that needs to be modified.


## Grammar file recognizers

Expand Down
42 changes: 14 additions & 28 deletions parglare/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ class Location:
end and input_str.
"""

__slots__ = ['context', 'file_name',
'_line', '_column',
'_line_end', '_column_end']
__slots__ = ['start_position', 'end_position', 'input_str', 'file_name',
'_line', '_column', '_line_end', '_column_end']

def __init__(self, context=None, file_name=None):

self.context = context
self.file_name = file_name or context.file_name
self.start_position = context.start_position if context else None
self.end_position = context.end_position if context else None
self.input_str = context.input_str if context else None
self.file_name = file_name or context.file_name if context else None

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

def evaluate_line_col(self):
context = self.context
self._line, self._column = pos_to_line_col(
context.input_str, context.start_position)
self.input_str, self.start_position)

def evaluate_line_col_end(self):
context = self.context
if hasattr(context, 'end_position') \
and context.end_position:
if self.end_position:
self._line_end, self._column_end = \
pos_to_line_col(context.input_str, context.end_position)

def __getattr__(self, name):
if self.context is not None:
return getattr(self.context, name)
else:
raise AttributeError(name)
pos_to_line_col(self.input_str, self.end_position)

def __str__(self):
if self.context is None:
line, column = None, None
else:
line, column = self.line, self.column
context = self.context
line, column = self.line, self.column
if line is not None:
return ('{}{}:{}:"{}"'
.format(f"{self.file_name}:"
if self.file_name else "",
line, column,
position_context(context.input_str,
context.start_position)))
elif self.file_name:
position_context(self.input_str,
self.start_position)))
if self.file_name:
return _a(self.file_name)
else:
return "<Unknown location>"
return "<Unknown location>"

def __repr__(self):
return str(self)
Expand Down
2 changes: 1 addition & 1 deletion parglare/glr.py
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ def _do_error_recovery(self):
successful = self.error_recovery(head, error)

if successful:
error.location.context.end_position = head.position
error.location.end_position = head.position
if debug:
a_print("New position is ",
pos_to_line_col(input_str, head.position),
Expand Down
Loading

0 comments on commit f1c63f6

Please sign in to comment.