| @@ -1,5 +1,8 @@ | |||||
| import re | import re | ||||
| import sre_parse | import sre_parse | ||||
| import sys | |||||
| Py36 = (sys.version_info[:2] >= (3, 6)) | |||||
| class GrammarError(Exception): | class GrammarError(Exception): | ||||
| pass | pass | ||||
| @@ -54,7 +57,7 @@ class Pattern(object): | |||||
| self.flags = flags | self.flags = flags | ||||
| def __repr__(self): | def __repr__(self): | ||||
| return repr(self._get_flags() + self.value) | |||||
| return repr(self.to_regexp()) | |||||
| # Pattern Hashing assumes all subclasses have a different priority! | # Pattern Hashing assumes all subclasses have a different priority! | ||||
| def __hash__(self): | def __hash__(self): | ||||
| @@ -62,15 +65,24 @@ class Pattern(object): | |||||
| def __eq__(self, other): | def __eq__(self, other): | ||||
| return type(self) == type(other) and self.value == other.value | return type(self) == type(other) and self.value == other.value | ||||
| def _get_flags(self): | |||||
| if self.flags: | |||||
| assert len(self.flags) == 1 | |||||
| return '(?%s)' % self.flags | |||||
| return '' | |||||
| if Py36: | |||||
| # Python 3.6 changed syntax for flags in regular expression | |||||
| def _get_flags(self, value): | |||||
| if self.flags: | |||||
| assert len(self.flags) == 1 | |||||
| return ('(?%s:%s)' % (self.flags[0], value)) | |||||
| return value | |||||
| else: | |||||
| def _get_flags(self, value): | |||||
| if self.flags: | |||||
| assert len(self.flags) == 1 | |||||
| return ('(?%s)' % self.flags) + value | |||||
| return value | |||||
| class PatternStr(Pattern): | class PatternStr(Pattern): | ||||
| def to_regexp(self): | def to_regexp(self): | ||||
| return self._get_flags() + re.escape(self.value) | |||||
| return self._get_flags(re.escape(self.value)) | |||||
| @property | @property | ||||
| def min_width(self): | def min_width(self): | ||||
| @@ -79,7 +91,7 @@ class PatternStr(Pattern): | |||||
| class PatternRE(Pattern): | class PatternRE(Pattern): | ||||
| def to_regexp(self): | def to_regexp(self): | ||||
| return self._get_flags() + self.value | |||||
| return self._get_flags(self.value) | |||||
| @property | @property | ||||
| def min_width(self): | def min_width(self): | ||||
| @@ -30,12 +30,12 @@ def _read(n, *args): | |||||
| class TestParsers(unittest.TestCase): | class TestParsers(unittest.TestCase): | ||||
| def test_same_ast(self): | def test_same_ast(self): | ||||
| "Tests that Earley and LALR parsers produce equal trees" | "Tests that Earley and LALR parsers produce equal trees" | ||||
| g = Lark("""start: "(" name_list ("," "*" NAME)? ")" | |||||
| g = Lark(r"""start: "(" name_list ("," "*" NAME)? ")" | |||||
| name_list: NAME | name_list "," NAME | name_list: NAME | name_list "," NAME | ||||
| NAME: /\w+/ """, parser='lalr') | NAME: /\w+/ """, parser='lalr') | ||||
| l = g.parse('(a,b,c,*x)') | l = g.parse('(a,b,c,*x)') | ||||
| g = Lark("""start: "(" name_list ("," "*" NAME)? ")" | |||||
| g = Lark(r"""start: "(" name_list ("," "*" NAME)? ")" | |||||
| name_list: NAME | name_list "," NAME | name_list: NAME | name_list "," NAME | ||||
| NAME: /\w/+ """) | NAME: /\w/+ """) | ||||
| l2 = g.parse('(a,b,c,*x)') | l2 = g.parse('(a,b,c,*x)') | ||||
| @@ -507,7 +507,7 @@ def _make_parser_test(LEXER, PARSER): | |||||
| g.parse("a" * (sys.getrecursionlimit() // 4)) | g.parse("a" * (sys.getrecursionlimit() // 4)) | ||||
| def test_token_collision(self): | def test_token_collision(self): | ||||
| g = _Lark("""start: "Hello" NAME | |||||
| g = _Lark(r"""start: "Hello" NAME | |||||
| NAME: /\w/+ | NAME: /\w/+ | ||||
| %ignore " " | %ignore " " | ||||
| """) | """) | ||||
| @@ -517,7 +517,7 @@ def _make_parser_test(LEXER, PARSER): | |||||
| self.assertSequenceEqual(x.children, ['HelloWorld']) | self.assertSequenceEqual(x.children, ['HelloWorld']) | ||||
| def test_token_collision_WS(self): | def test_token_collision_WS(self): | ||||
| g = _Lark("""start: "Hello" NAME | |||||
| g = _Lark(r"""start: "Hello" NAME | |||||
| NAME: /\w/+ | NAME: /\w/+ | ||||
| %import common.WS | %import common.WS | ||||
| %ignore WS | %ignore WS | ||||