summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorda-woods <dw-git@d-woods.co.uk>2022-06-18 10:10:02 +0100
committerda-woods <dw-git@d-woods.co.uk>2022-06-18 10:10:02 +0100
commit2277c3345ed81770166a0f457c77e3b01b26f994 (patch)
treeb11e694dcec8f145fc375062839ad0646a3644f1
parent7c9f67910babad0efcf31960db1513ac398cb4b2 (diff)
downloadcython-2277c3345ed81770166a0f457c77e3b01b26f994.tar.gz
Improve pattern identification
Some types of pattern are unambiguous so don't need backtracking
-rw-r--r--Cython/Compiler/Parsing.py46
1 files 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:
@@ -4091,25 +4114,9 @@ def p_closed_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()