fix(vast): 修复 match 类模式与 or 模式解析与 CPython 不一致

- case ClassName.attr(...) 类模式:扫描属性链末尾判断 '(',
  此前只查首 token 后 '(',LLVMType.Ptr(...) 被误解析为
  MatchValue(Call) → TPC 对 renum match 走值模式分支,对枚举
  构造表达式运行时求值生成 ptrtoint SSA,LLVM switch 报
  'case value is not a constant integer'
- case 0 | 1 值模式:字面量/符号不再消费顶层 '|',留给
  _ParsePattern 组 MatchOr(此前 ParseExpr 吞掉 '|' 成 BinOp)
This commit is contained in:
TermiNexus committed 2026-08-17 10:22:29 +08:00
1 parent d7213d2197
commit aa9042173e
1 file changed
+40 -10
+40 -10
View File
@@ -883,8 +883,12 @@ class Parser(ExprParserMixin):
value={'True': True, 'False': False, 'None': None}[tok.Value])
self._FixLoc(node, tok)
return node
# 类模式:Name(...) 或 a.b(...)
if self._Peek(1).Type == OP and self._Peek(1).Value == '(':
# 类模式:Name(...) 或 a.b.c(...)——扫描属性链末尾判断 '('
peek_i: int = 1
while (self._Peek(peek_i).Type == OP and self._Peek(peek_i).Value == '.'
and self._Peek(peek_i + 1).Type == NAME):
peek_i += 2
if self._Peek(peek_i).Type == OP and self._Peek(peek_i).Value == '(':
return self._ParseMatchClass()
# 属性值模式 a.b(无括号)
if self._Peek(1).Type == OP and self._Peek(1).Value == '.':
@@ -900,14 +904,10 @@ class Parser(ExprParserMixin):
# 映射模式 {k: v, **rest}
if tok.Type == OP and tok.Value == '{':
return self._ParseMatchMapping()
# 字面量:数字/字符串/负号
if tok.Type == NUMBER or tok.Type == STRING or tok.Type == FSTRING:
value: N.expr = self.ParseExpr()
node = N.MatchValue(value=value)
self._FixLoc(node, start)
return node
if tok.Type == OP and tok.Value in ('-', '+'):
value = self.ParseExpr()
# 值模式:数字/字符串/f-string/带符号字面量(不消费顶层 '|',留给 _ParsePattern 组 MatchOr)
if tok.Type == NUMBER or tok.Type == STRING or tok.Type == FSTRING or (
tok.Type == OP and tok.Value in ('-', '+')):
value: N.expr = self._ParsePatternValue()
node = N.MatchValue(value=value)
self._FixLoc(node, start)
return node
@@ -921,6 +921,36 @@ class Parser(ExprParserMixin):
return node
raise SyntaxError(f"unexpected pattern token {tok.Type}({tok.Value!r})")
def _ParsePatternValue(self) -> N.expr:
"""解析值模式表达式:带可选 +/- 前缀的字面量。
与 CPython 一致:'|' 是模式或分隔符,这里只解析单个字面量
(数字/字符串/f-string),不消费顶层 '|'。
"""
start: Token = self._Peek()
tok: Token = self._Peek()
if tok.Type == OP and tok.Value in ('-', '+'):
op_tok: Token = self._Next()
inner: N.expr
if self._Peek().Type == NUMBER:
inner = self._ParseNumber()
elif self._Peek().Type in (STRING, FSTRING):
inner = self._ParseStringConcat()
else:
raise SyntaxError(
f"expected literal after '{op_tok.Value}' in pattern at line {op_tok.Line}"
)
node: N.expr
if op_tok.Value == '-':
node = N.UnaryOp(op=N.USub(), operand=inner)
else:
node = N.UnaryOp(op=N.UAdd(), operand=inner)
self._FixLoc(node, start)
return node
if tok.Type == NUMBER:
return self._ParseNumber()
return self._ParseStringConcat()
def _ParseMatchValueAttr(self) -> N.pattern:
"""解析值模式属性访问:a.b.c(无括号)。"""
start: Token = self._Peek()