diff --git a/ast/parser.vp b/ast/parser.vp index 33e0650..d38902a 100644 --- a/ast/parser.vp +++ b/ast/parser.vp @@ -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 :`(后者支持 guard,与 `case _ if ` 一致; + 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 ] ':' 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 ` 的条件约束原样传入 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 ':'`(与 _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 ] ':' suite` —— desugar 为 `case []`(MatchAs 通配) + + `default` 即 switch 拼写的 `case _`;现与 `case _ if ` 一致地支持 guard + (`default if :`),解析出的 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