| @@ -52,29 +52,29 @@ class ParserConf: | |||||
| class Pattern(object): | class Pattern(object): | ||||
| def __init__(self, value, flags=None): | |||||
| def __init__(self, value, flags=()): | |||||
| self.value = value | self.value = value | ||||
| self.flags = flags | |||||
| self.flags = frozenset(flags) | |||||
| def __repr__(self): | def __repr__(self): | ||||
| return repr(self.to_regexp()) | 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): | ||||
| return hash((type(self), self.value)) | |||||
| return hash((type(self), self.value, self.flags)) | |||||
| 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 and self.flags == other.flags | |||||
| if Py36: | if Py36: | ||||
| # Python 3.6 changed syntax for flags in regular expression | # Python 3.6 changed syntax for flags in regular expression | ||||
| def _get_flags(self, value): | def _get_flags(self, value): | ||||
| for f in self.flags or (): | |||||
| for f in self.flags: | |||||
| value = ('(?%s:%s)' % (f, value)) | value = ('(?%s:%s)' % (f, value)) | ||||
| return value | return value | ||||
| else: | else: | ||||
| def _get_flags(self, value): | def _get_flags(self, value): | ||||
| for f in self.flags or (): | |||||
| for f in self.flags: | |||||
| value = ('(?%s)' % f) + value | value = ('(?%s)' % f) + value | ||||
| return value | return value | ||||
| @@ -332,7 +332,7 @@ def _literal_to_pattern(literal): | |||||
| s = s.replace('\\\\', '\\') | s = s.replace('\\\\', '\\') | ||||
| return { 'STRING': PatternStr, | return { 'STRING': PatternStr, | ||||
| 'REGEXP': PatternRE }[literal.type](s, flags or None) | |||||
| 'REGEXP': PatternRE }[literal.type](s, flags) | |||||
| class PrepareLiterals(InlineTransformer): | class PrepareLiterals(InlineTransformer): | ||||
| @@ -368,7 +368,7 @@ class TokenTreeToPattern(Transformer): | |||||
| def expansions(self, exps): | def expansions(self, exps): | ||||
| if len(exps) == 1: | if len(exps) == 1: | ||||
| return exps[0] | return exps[0] | ||||
| assert all(i.flags is None for i in exps) | |||||
| assert all(not i.flags for i in exps) | |||||
| return PatternRE('(?:%s)' % ('|'.join(i.to_regexp() for i in exps))) | return PatternRE('(?:%s)' % ('|'.join(i.to_regexp() for i in exps))) | ||||
| def expr(self, args): | def expr(self, args): | ||||
| @@ -750,13 +750,13 @@ def _make_parser_test(LEXER, PARSER): | |||||
| tree = l.parse('aA') | tree = l.parse('aA') | ||||
| self.assertEqual(tree.children, ['a', 'A']) | self.assertEqual(tree.children, ['a', 'A']) | ||||
| g = """!start: "a"i "a" | |||||
| """ | |||||
| self.assertRaises(GrammarError, _Lark, g) | |||||
| # g = """!start: "a"i "a" | |||||
| # """ | |||||
| # self.assertRaises(GrammarError, _Lark, g) | |||||
| g = """!start: /a/i /a/ | |||||
| """ | |||||
| self.assertRaises(GrammarError, _Lark, g) | |||||
| # g = """!start: /a/i /a/ | |||||
| # """ | |||||
| # self.assertRaises(GrammarError, _Lark, g) | |||||
| g = """start: NAME "," "a" | g = """start: NAME "," "a" | ||||
| NAME: /[a-z_]/i /[a-z0-9_]/i* | NAME: /[a-z_]/i /[a-z0-9_]/i* | ||||