From 2277c3345ed81770166a0f457c77e3b01b26f994 Mon Sep 17 00:00:00 2001 From: da-woods Date: Sat, 18 Jun 2022 10:10:02 +0100 Subject: Improve pattern identification Some types of pattern are unambiguous so don't need backtracking --- Cython/Compiler/Parsing.py | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/Cython/Compiler/Parsing.py b/Cython/Compiler/Parsing.py index a08abe66d..1cd67f445 100644 --- a/Cython/Compiler/Parsing.py +++ b/Cython/Compiler/Parsing.py @@ -4073,6 +4073,7 @@ def p_pattern(s): def p_closed_pattern(s): """ + The PEG parser specifies it as | literal_pattern | capture_pattern | wildcard_pattern @@ -4081,7 +4082,29 @@ def p_closed_pattern(s): | sequence_pattern | mapping_pattern | class_pattern + + For the sake avoiding too much backtracking, we know: + * starts with "{" is a sequence_pattern + * starts with "[" is a mapping_pattern + * starts with "(" is a group_pattern or sequence_pattern + * wildcard pattern is just identifier=='_' + The rest are then tried in order with backtracking """ + if s.sy == 'IDENT' and s.systring == '_': + pos = s.position() + s.next() + return MatchCaseNodes.MatchAndAssignPatternNode(pos) + elif s.sy == '{': + return p_mapping_pattern(s) + elif s.sy == '[': + return p_sequence_pattern(s) + elif s.sy == '(': + with tentatively_scan(s) as errors: + result = p_group_pattern(s) + if not errors: + return result + return p_sequence_pattern(s) + with tentatively_scan(s) as errors: result = p_literal_pattern(s) if not errors: @@ -4090,26 +4113,10 @@ def p_closed_pattern(s): result = p_capture_pattern(s) if not errors: return result - with tentatively_scan(s) as errors: - result = p_wildcard_pattern(s) - if not errors: - return result with tentatively_scan(s) as errors: result = p_value_pattern(s) if not errors: return result - with tentatively_scan(s) as errors: - result = p_group_pattern(s) - if not errors: - return result - with tentatively_scan(s) as errors: - result = p_sequence_pattern(s) - if not errors: - return result - with tentatively_scan(s) as errors: - result = p_mapping_pattern(s) - if not errors: - return result return p_class_pattern(s) def p_literal_pattern(s): @@ -4224,13 +4231,6 @@ def p_group_pattern(s): s.expect(")") return pattern -def p_wildcard_pattern(s): - if s.sy != "IDENT" or s.systring != "_": - s.error("Expected '_'") - pos = s.position() - s.next() - return MatchCaseNodes.MatchAndAssignPatternNode(pos) - def p_sequence_pattern(s): opener = s.sy pos = s.position() -- cgit v1.2.1