From 766afad56828818ed0e47ed59afbcb2a7f4f0546 Mon Sep 17 00:00:00 2001 From: amansri-30 Date: Sat, 19 Sep 2026 02:09:06 +0530 Subject: [PATCH] feat: add support for 'a' (ASCII) and 'L' (LOCALE) regex flags Adds support for the 'a' and 'L' regex flags in Lark grammars, as requested in issue #1527. - 'a' flag: Makes \w, \W, \b, \B, \d, \D, \s, \S perform ASCII-only matching instead of full Unicode matching - 'L' flag: Makes \w, \W, \b, \B locale dependent (only works with bytes patterns in Python 3) Changes: - Updated _RE_FLAGS in load_grammar.py to include 'a' and 'L' - Added test_flag_order_with_new_flags to verify 'a' flag works - Added test_token_flags_ascii to verify 'a' flag parses correctly --- lark/load_grammar.py | 2 +- tests/test_lexer.py | 7 +++++++ tests/test_parser.py | 8 ++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/lark/load_grammar.py b/lark/load_grammar.py index b98f166c1..171d03d83 100644 --- a/lark/load_grammar.py +++ b/lark/load_grammar.py @@ -29,7 +29,7 @@ EXT = '.lark' -_RE_FLAGS = 'imslux' +_RE_FLAGS = 'imsluxaL' _EMPTY = Symbol('__empty__') diff --git a/tests/test_lexer.py b/tests/test_lexer.py index b080328a5..e1a3c3e49 100644 --- a/tests/test_lexer.py +++ b/tests/test_lexer.py @@ -27,6 +27,13 @@ def test_flag_order_is_deterministic(self): self.assertEqual([t.pattern.to_regexp() for t in p.terminals], ['(?u:(?s:(?m:(?i:x))))']) + def test_flag_order_with_new_flags(self): + # Test that new flag (a) works and is sorted deterministically + p = Lark('start: A+\nA: /x/ai\n', parser='lalr') + # Flags should be sorted alphabetically: a before i + self.assertEqual([t.pattern.to_regexp() for t in p.terminals], + ['(?i:(?a:x))']) + def test_subset_lex(self): p = Lark(""" start: "a" "b" "c" "d" diff --git a/tests/test_parser.py b/tests/test_parser.py index b12752b07..a7c2f2963 100644 --- a/tests/test_parser.py +++ b/tests/test_parser.py @@ -1808,6 +1808,14 @@ def test_token_flags_verbose_multiline(self): x = g.parse('abcdef') self.assertEqual(x.children, ['abcdef']) + def test_token_flags_ascii(self): + # Test the ASCII flag (a) - makes \w, \d, \s ASCII-only + l = _Lark(r"""!start: /\d/a+ + """) + # Should match ASCII digits + tree = l.parse('123') + self.assertEqual(tree.children, ['1', '2', '3']) + @unittest.skipIf(PARSER == 'cyk', "No empty rules") def test_twice_empty(self): g = """!start: ("A"?)?