feat(parser): switch 的 case/default 支持 if 守卫

_parse_switch_case / _parse_switch_default 解析可选 `if <cond>` 并传入 MatchCase.guard(原为直接报错 / 写死 None),与 _parse_match_case 同款写法。
This commit is contained in:
TermiNexus committed 2026-10-03 10:58:53 +08:00
1 parent 7b006c96a0
commit 7f3b3dea1a
1 file changed
+25 -7
+25 -7
View File
@@ -4226,7 +4226,9 @@ def _parse_match(ps: rawptr[Parser]) -> rawptr[AST]:
# ============================================================
def _is_switch_default_kw(ps: rawptr[Parser]) -> int:
"""`default:` 是 switch 套件内的上下文关键字:仅当 `default` 后紧跟 ':' 时命中"""
"""`default` 是 switch 套件内的上下文关键字:命中 `default:` 或
`default if <cond>:`(后者支持 guard,与 `case _ if <cond>` 一致;
guard 由 _parse_switch_default 解析)"""
if _cur_type(ps) != TokenType.Name:
return 0
s: str = _cur_str(ps)
@@ -4237,6 +4239,8 @@ def _is_switch_default_kw(ps: rawptr[Parser]) -> int:
return 0
if nxt.type == TokenType.Op and nxt.op_subtype == TokOp.Colon:
return 1
if nxt.type == TokenType.Name and nxt.kw_subtype == Keyword.If:
return 1
return 0
@@ -4292,11 +4296,14 @@ def _CheckSwitchCasePattern(ps: rawptr[Parser], pat: rawptr[AST]) -> int:
def _parse_switch_case(ps: rawptr[Parser]) -> rawptr[AST]:
"""switch 的 `case <常量|枚举变体> ':' suite`(不支持 guard)
"""switch 的 `case <常量|枚举变体> [if <cond>] ':' suite`(支持 guard)
裸名在 match 里是**捕获模式**(MatchAs),在 switch 里应作**值引用**处理
(对齐 C 的 `case NAME:`),故此处把 `MatchAs(pattern=None, name=X)` 归一为
`MatchValue(Name('X'))`;`_` 仍是通配,保持不变。
guard 与 `_parse_match_case` 同款解析(`case pattern [if guard] ':'`):
`case <值> if <cond>` 的条件约束原样传入 MatchCase.guard。
"""
lineno: int = _cur_lineno(ps)
col: int = _cur_col(ps)
@@ -4313,25 +4320,36 @@ def _parse_switch_case(ps: rawptr[Parser]) -> rawptr[AST]:
if _CheckSwitchCasePattern(ps, pattern) == 0:
_RecordSwitchCaseErr("case 标签不是常量/枚举变体", lineno, col)
ps.error_count += 1
# guard 守卫:`case <值> if <cond> ':'`(与 _parse_match_case 同款写法)
guard: rawptr[AST] = None
if _cur_kw(ps) == Keyword.If:
_RecordSwitchCaseErr("switch 的 case 不支持 if 守卫", _cur_lineno(ps), _cur_col(ps))
ps.error_count += 1
_advance(ps)
guard = _parse_or_test(ps)
_expect_op(ps, TokOp.Colon)
node: rawptr[AST] = MatchCase(ps.pool, pattern, None)
node: rawptr[AST] = MatchCase(ps.pool, pattern, guard)
_parse_suite_into_children(ps, node)
_set_pos(node, lineno, col, 0, 0)
return node
def _parse_switch_default(ps: rawptr[Parser]) -> rawptr[AST]:
"""switch 的 `default ':' suite` —— desugar 为 `case _`(MatchAs 通配)"""
"""switch 的 `default [if <cond>] ':' suite` —— desugar 为 `case [<guard>]`(MatchAs 通配)
`default` 即 switch 拼写的 `case _`;现与 `case _ if <cond>` 一致地支持 guard
(`default if <cond>:`),解析出的 guard 原样传入 MatchCase;无 if 时保持原行为
(guard=None,即唯一无 guard 通配臂)。
"""
lineno: int = _cur_lineno(ps)
col: int = _cur_col(ps)
_advance(ps) # default
guard: rawptr[AST] = None
if _cur_kw(ps) == Keyword.If:
_advance(ps)
guard = _parse_or_test(ps)
_expect_op(ps, TokOp.Colon)
wild: rawptr[AST] = MatchAs(ps.pool, None, None)
_set_pos(wild, lineno, col, 0, 0)
node: rawptr[AST] = MatchCase(ps.pool, wild, None)
node: rawptr[AST] = MatchCase(ps.pool, wild, guard)
_parse_suite_into_children(ps, node)
_set_pos(node, lineno, col, 0, 0)
return node