diff options
author | da-woods <dw-git@d-woods.co.uk> | 2022-08-01 18:28:03 +0100 |
---|---|---|
committer | da-woods <dw-git@d-woods.co.uk> | 2022-08-01 18:35:31 +0100 |
commit | 9f35805dc92b820e32d85600dd08ba3aa13ede03 (patch) | |
tree | eb31927fedaee2f07423aa4f4a10aaa96058ba7d | |
parent | 2aac3a01bce5edd6bc519d079f96fe8db4556426 (diff) | |
download | cython-9f35805dc92b820e32d85600dd08ba3aa13ede03.tar.gz |
Factor out shared bits of p_atom and p_literal_pattern
-rw-r--r-- | Cython/Compiler/Parsing.pxd | 2 | ||||
-rw-r--r-- | Cython/Compiler/Parsing.py | 91 |
2 files changed, 46 insertions, 47 deletions
diff --git a/Cython/Compiler/Parsing.pxd b/Cython/Compiler/Parsing.pxd index 1be718581..17fe9f769 100644 --- a/Cython/Compiler/Parsing.pxd +++ b/Cython/Compiler/Parsing.pxd @@ -64,6 +64,8 @@ cdef expect_ellipsis(PyrexScanner s) cdef make_slice_nodes(pos, subscripts) cpdef make_slice_node(pos, start, stop = *, step = *) cdef p_atom(PyrexScanner s) +cdef parse_atom_string(pos, PyrexScanner s): +cdef parse_atom_ident_constants(pos, PyrexScanner s): @cython.locals(value=unicode) cdef p_int_literal(PyrexScanner s) cdef p_name(PyrexScanner s, name) diff --git a/Cython/Compiler/Parsing.py b/Cython/Compiler/Parsing.py index 94efe2c6b..2a6975b0b 100644 --- a/Cython/Compiler/Parsing.py +++ b/Cython/Compiler/Parsing.py @@ -735,36 +735,51 @@ def p_atom(s): s.next() return ExprNodes.ImagNode(pos, value = value) elif sy == 'BEGIN_STRING': - kind, bytes_value, unicode_value = p_cat_string_literal(s) - if kind == 'c': - return ExprNodes.CharNode(pos, value = bytes_value) - elif kind == 'u': - return ExprNodes.UnicodeNode(pos, value = unicode_value, bytes_value = bytes_value) - elif kind == 'b': - return ExprNodes.BytesNode(pos, value = bytes_value) - elif kind == 'f': - return ExprNodes.JoinedStrNode(pos, values = unicode_value) - elif kind == '': - return ExprNodes.StringNode(pos, value = bytes_value, unicode_value = unicode_value) - else: - s.error("invalid string kind '%s'" % kind) + return parse_atom_string(pos, s) elif sy == 'IDENT': - name = s.systring - if name == "None": - result = ExprNodes.NoneNode(pos) - elif name == "True": - result = ExprNodes.BoolNode(pos, value=True) - elif name == "False": - result = ExprNodes.BoolNode(pos, value=False) - elif name == "NULL" and not s.in_python_file: - result = ExprNodes.NullNode(pos) - else: - result = p_name(s, name) + result = parse_atom_ident_constants(pos, s) + if result is None: + result = p_name(s, name = s.systring) s.next() return result else: s.error("Expected an identifier or literal") + +def parse_atom_string(pos, s): + kind, bytes_value, unicode_value = p_cat_string_literal(s) + if kind == 'c': + return ExprNodes.CharNode(pos, value = bytes_value) + elif kind == 'u': + return ExprNodes.UnicodeNode(pos, value = unicode_value, bytes_value = bytes_value) + elif kind == 'b': + return ExprNodes.BytesNode(pos, value = bytes_value) + elif kind == 'f': + return ExprNodes.JoinedStrNode(pos, values = unicode_value) + elif kind == '': + return ExprNodes.StringNode(pos, value = bytes_value, unicode_value = unicode_value) + else: + s.error("invalid string kind '%s'" % kind) + + +def parse_atom_ident_constants(pos, s): + """ + Returns None if it isn't one special-cased named constants. + Does not call s.next() + """ + name = s.systring + result = None + if name == "None": + result = ExprNodes.NoneNode(pos) + elif name == "True": + result = ExprNodes.BoolNode(pos, value=True) + elif name == "False": + result = ExprNodes.BoolNode(pos, value=False) + elif name == "NULL" and not s.in_python_file: + result = ExprNodes.NullNode(pos) + return result + + def p_int_literal(s): pos = s.position() value = s.systring @@ -4210,32 +4225,14 @@ def p_literal_pattern(s): if sy == 'BEGIN_STRING': if next_must_be_a_number: s.error("Expected a number") - kind, bytes_value, unicode_value = p_cat_string_literal(s) - if kind == 'c': - res = ExprNodes.CharNode(pos, value = bytes_value) - elif kind == 'u': - res = ExprNodes.UnicodeNode(pos, value = unicode_value, bytes_value = bytes_value) - elif kind == 'b': - res = ExprNodes.BytesNode(pos, value = bytes_value) - elif kind == 'f': + res = parse_atom_string(pos, s) + if isinstance(res, ExprNodes.JoinedStrNode): res = Nodes.ErrorNode(pos, what = "f-strings are not accepted for pattern matching") - elif kind == '': - res = ExprNodes.StringNode(pos, value = bytes_value, unicode_value = unicode_value) - else: - s.error("invalid string kind '%s'" % kind) return MatchCaseNodes.MatchValuePatternNode(pos, value = res) elif sy == 'IDENT': - name = s.systring - result = None - if name == "None": - result = ExprNodes.NoneNode(pos) - elif name == "True": - result = ExprNodes.BoolNode(pos, value=True) - elif name == "False": - result = ExprNodes.BoolNode(pos, value=False) - elif name == "NULL" and not s.in_python_file: - # Included Null as an exactly matched constant here - result = ExprNodes.NullNode(pos) + # Note that p_atom_ident_constants includes NULL. + # This is a deliberate Cython addition to the pattern matching specification + result = parse_atom_ident_constants(pos, s) if result: s.next() return MatchCaseNodes.MatchValuePatternNode(pos, value = result, is_is_check = True) |