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:
1 parent
d7213d2197
commit
aa9042173e
1 file changed
+40
-10
+40
-10
@@ -883,8 +883,12 @@ class Parser(ExprParserMixin):
|
|||||||
value={'True': True, 'False': False, 'None': None}[tok.Value])
|
value={'True': True, 'False': False, 'None': None}[tok.Value])
|
||||||
self._FixLoc(node, tok)
|
self._FixLoc(node, tok)
|
||||||
return node
|
return node
|
||||||
# 类模式:Name(...) 或 a.b(...)
|
# 类模式:Name(...) 或 a.b.c(...)——扫描属性链末尾判断 '('
|
||||||
if self._Peek(1).Type == OP and self._Peek(1).Value == '(':
|
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()
|
return self._ParseMatchClass()
|
||||||
# 属性值模式 a.b(无括号)
|
# 属性值模式 a.b(无括号)
|
||||||
if self._Peek(1).Type == OP and self._Peek(1).Value == '.':
|
if self._Peek(1).Type == OP and self._Peek(1).Value == '.':
|
||||||
@@ -900,14 +904,10 @@ class Parser(ExprParserMixin):
|
|||||||
# 映射模式 {k: v, **rest}
|
# 映射模式 {k: v, **rest}
|
||||||
if tok.Type == OP and tok.Value == '{':
|
if tok.Type == OP and tok.Value == '{':
|
||||||
return self._ParseMatchMapping()
|
return self._ParseMatchMapping()
|
||||||
# 字面量:数字/字符串/负号
|
# 值模式:数字/字符串/f-string/带符号字面量(不消费顶层 '|',留给 _ParsePattern 组 MatchOr)
|
||||||
if tok.Type == NUMBER or tok.Type == STRING or tok.Type == FSTRING:
|
if tok.Type == NUMBER or tok.Type == STRING or tok.Type == FSTRING or (
|
||||||
value: N.expr = self.ParseExpr()
|
tok.Type == OP and tok.Value in ('-', '+')):
|
||||||
node = N.MatchValue(value=value)
|
value: N.expr = self._ParsePatternValue()
|
||||||
self._FixLoc(node, start)
|
|
||||||
return node
|
|
||||||
if tok.Type == OP and tok.Value in ('-', '+'):
|
|
||||||
value = self.ParseExpr()
|
|
||||||
node = N.MatchValue(value=value)
|
node = N.MatchValue(value=value)
|
||||||
self._FixLoc(node, start)
|
self._FixLoc(node, start)
|
||||||
return node
|
return node
|
||||||
@@ -921,6 +921,36 @@ class Parser(ExprParserMixin):
|
|||||||
return node
|
return node
|
||||||
raise SyntaxError(f"unexpected pattern token {tok.Type}({tok.Value!r})")
|
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:
|
def _ParseMatchValueAttr(self) -> N.pattern:
|
||||||
"""解析值模式属性访问:a.b.c(无括号)。"""
|
"""解析值模式属性访问:a.b.c(无括号)。"""
|
||||||
start: Token = self._Peek()
|
start: Token = self._Peek()
|
||||||
|
|||||||
Reference in new issue
Block a user