Skip to content

Commit

Permalink
Optional line numbers in expecting and allow flags in front of regex
Browse files Browse the repository at this point in the history
  • Loading branch information
joente committed Jul 23, 2022
1 parent 880ae53 commit 8598540
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 4 deletions.
2 changes: 1 addition & 1 deletion pyleri/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,4 @@
__author__ = 'Jeroen van der Heijden'
__maintainer__ = 'Jeroen van der Heijden'
__email__ = '[email protected]'
__version__ = '1.3.4'
__version__ = '1.4.0'
19 changes: 18 additions & 1 deletion pyleri/regex.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,31 @@
import re
from .elements import NamedElement, c_export, go_export, java_export

_RE_FLAGS = re.compile(
r'^('
r'(\(\?i\))|'
r'(\(\?m\))|'
r'(\(\?s\))|'
r'(\(\?A\))|'
r'(\(\?x\))|'
r'(\(\?X\))|'
r'(\(\?U\))|'
r'(\(\?:\))'
r')(.)')


class Regex(NamedElement):

__slots__ = ('_compiled',)

def __init__(self, pattern, flags=0):
if not pattern.startswith('^'):
pattern = '^' + pattern
m = _RE_FLAGS.match(pattern)
if not m:
pattern = '^' + pattern
elif m.group(2) != '^':
pos = m.end() - 1
pattern = pattern[:pos] + '^' + pattern[pos:]
assert flags == 0 or flags == re.IGNORECASE, \
'Only re.IGNORECASE is currently accepted as flag'
self._compiled = re.compile(pattern, flags=flags)
Expand Down
10 changes: 8 additions & 2 deletions pyleri/result.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,16 @@ def __init__(self, is_valid, pos):
self.expecting = None
self.tree = None

def as_str(self, translate=None):
def as_str(self, translate=None, line_number=False):
if self.is_valid:
return 'parsed successfully'
res = ['error at position {}'.format(self.pos)]
if line_number:
string = self.tree._string
lnr = string.count('\n', 0, self.pos) + 1
pos = self.pos - string.rfind('\n', 0, self.pos)
res = ['error at line {}, col {}'.format(lnr, pos)]
else:
res = ['error at position {}'.format(self.pos)]
arr = []
for elem in (self.expecting):
expectstr = translate(elem) if translate else None
Expand Down
12 changes: 12 additions & 0 deletions test/test_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,18 @@ def test_list_all_options(self):
'error at position 0, expecting: hi'
)

self.assertEqual(
grammar.parse('').as_str(line_number=True),
'error at line 1, col 1, expecting: hi'
)

self.assertEqual(
grammar.parse("""
hi-hi-hi-hi-hi
""").as_str(line_number=True),
'error at line 2, col 26, expecting: end_of_statement'
)


if __name__ == '__main__':
unittest.main()
9 changes: 9 additions & 0 deletions test/test_regex.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ def test_regex(self):
if elem is regex else None),
'error at position 0, expecting: single_quoted_string'
)
self.assertTrue(grammar.parse("'hi'").is_valid)

def test_flags_regex(self):
regex = Regex(r'(?s)//.*?(\r?\n|$)')
grammar = create_grammar(regex)

self.assertTrue(grammar.parse("""
//test
""").is_valid)


if __name__ == '__main__':
Expand Down

0 comments on commit 8598540

Please sign in to comment.