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:
1 parent
7b006c96a0
commit
7f3b3dea1a
1 file changed
+25
-7
+25
-7
@@ -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
|
||||
|
||||
Reference in new issue
Block a user