fix(ast): 解析器支持括号内行首运算符跨行续接
and/or 与 binop/比较链循环此前在检查运算符前不跳 Nl: A and B 换行后再 and C(ThreadingTest check 多行 and 链)停在 Nl 上 循环退出,上层把续行运算符当非法 token 报 SyntaxError。每轮循环先 _skip_nl 再查运算符(对齐 vast 实现),支持 (a\n + b)、(a < b\n < c) 等行首运算符续行。
This commit is contained in:
1 parent
197a7f3314
commit
e83c06041a
1 file changed
+65
-36
+65
-36
@@ -502,20 +502,23 @@ def _parse_or_test(ps: Parser | t.CPtr) -> AST | t.CPtr:
|
||||
"""or_test: and_test ('or' and_test)*"""
|
||||
left: AST | t.CPtr = _parse_and_test(ps)
|
||||
if left is None: return None
|
||||
# 括号内行首 or((A\n or B)):or 前的 NL 在此跳过,否则 or_test 返回后
|
||||
# 上层 _expect_op(RPar) 遇到 or 报"意外的 token 'or'"
|
||||
# (CallGenMixin.vp L7918 跨模块调用检查根因;ClassGenMixin L1988 等
|
||||
# 括号内换行行首 or 同理,按解析顺序未暴露)。
|
||||
_skip_nl(ps)
|
||||
if _cur_kw(ps) == Keyword.Or:
|
||||
values: list[AST | t.CPtr] | t.CPtr = list[AST | t.CPtr](ps.pool, 8)
|
||||
values.append(left)
|
||||
while _cur_kw(ps) == Keyword.Or:
|
||||
_advance(ps)
|
||||
_skip_nl(ps) # 括号内跨行: a or\n b
|
||||
right: AST | t.CPtr = _parse_and_test(ps)
|
||||
if right is None: break
|
||||
values.append(right)
|
||||
values: list[AST | t.CPtr] | t.CPtr = None
|
||||
while True:
|
||||
# 括号内行首 or((A\n or B))与行尾 or(A or\n B)都支持:
|
||||
# 每轮先 _skip_nl 再检查 or,否则 A or B\n or C 在 B 后停在 Nl 上
|
||||
# 循环退出,上层把续行 or 当非法 token(对齐 and_test / vast 实现)。
|
||||
_skip_nl(ps)
|
||||
if _cur_kw(ps) != Keyword.Or:
|
||||
break
|
||||
if values is None:
|
||||
values = list[AST | t.CPtr](ps.pool, 8)
|
||||
values.append(left)
|
||||
_advance(ps)
|
||||
_skip_nl(ps) # 括号内跨行: a or\n b
|
||||
right: AST | t.CPtr = _parse_and_test(ps)
|
||||
if right is None: break
|
||||
values.append(right)
|
||||
if values is not None:
|
||||
node: AST | t.CPtr = BoolOp(ps.pool, OpKind.Or, values)
|
||||
_set_pos(node, left.lineno, left.col_offset, 0, 0)
|
||||
return node
|
||||
@@ -526,17 +529,24 @@ def _parse_and_test(ps: Parser | t.CPtr) -> AST | t.CPtr:
|
||||
"""and_test: not_test ('and' not_test)*"""
|
||||
left: AST | t.CPtr = _parse_not_test(ps)
|
||||
if left is None: return None
|
||||
# 括号内行首 and((A\n and B)):同 or_test 修复(or 前跳 NL)
|
||||
_skip_nl(ps)
|
||||
if _cur_kw(ps) == Keyword.And:
|
||||
values: list[AST | t.CPtr] | t.CPtr = list[AST | t.CPtr](ps.pool, 8)
|
||||
values.append(left)
|
||||
while _cur_kw(ps) == Keyword.And:
|
||||
_advance(ps)
|
||||
_skip_nl(ps) # 括号内跨行: a and\n b
|
||||
right: AST | t.CPtr = _parse_not_test(ps)
|
||||
if right is None: break
|
||||
values.append(right)
|
||||
values: list[AST | t.CPtr] | t.CPtr = None
|
||||
while True:
|
||||
# 括号内行首 and((A\n and B))与行尾 and(A and\n B)都支持:
|
||||
# 每轮先 _skip_nl 再检查 and,否则 A and B\n and C 在 B 后停在
|
||||
# Nl 上循环退出,上层把续行 and 当非法 token
|
||||
# (ThreadingTest check 多行 and 链解析失败根因)。
|
||||
_skip_nl(ps)
|
||||
if _cur_kw(ps) != Keyword.And:
|
||||
break
|
||||
if values is None:
|
||||
values = list[AST | t.CPtr](ps.pool, 8)
|
||||
values.append(left)
|
||||
_advance(ps)
|
||||
_skip_nl(ps) # 括号内跨行: a and\n b
|
||||
right: AST | t.CPtr = _parse_not_test(ps)
|
||||
if right is None: break
|
||||
values.append(right)
|
||||
if values is not None:
|
||||
node: AST | t.CPtr = BoolOp(ps.pool, OpKind.And, values)
|
||||
_set_pos(node, left.lineno, left.col_offset, 0, 0)
|
||||
return node
|
||||
@@ -565,6 +575,7 @@ def _parse_comparison(ps: Parser | t.CPtr) -> AST | t.CPtr:
|
||||
left: AST | t.CPtr = _parse_bitor(ps)
|
||||
if left is None: return None
|
||||
|
||||
_skip_nl(ps) # 括号内行首比较运算符: (a\n < b)
|
||||
op_id: t.CInt = _match_comp_op(ps)
|
||||
if op_id == OpKind.NoneOp:
|
||||
return left
|
||||
@@ -580,6 +591,7 @@ def _parse_comparison(ps: Parser | t.CPtr) -> AST | t.CPtr:
|
||||
_set_pos(first_cmp, left.lineno, left.col_offset, 0, 0)
|
||||
|
||||
# Check chained comparison
|
||||
_skip_nl(ps) # 括号内行首链式比较: (a < b\n < c)
|
||||
next_op: t.CInt = _match_comp_op(ps)
|
||||
if next_op == OpKind.NoneOp:
|
||||
return first_cmp
|
||||
@@ -600,6 +612,7 @@ def _parse_comparison(ps: Parser | t.CPtr) -> AST | t.CPtr:
|
||||
_set_pos(cmp, cur_left.lineno, cur_left.col_offset, 0, 0)
|
||||
values.append(cmp)
|
||||
cur_left = cur_right
|
||||
_skip_nl(ps) # 括号内行首链式比较: (a < b\n < c)
|
||||
next_op = _match_comp_op(ps)
|
||||
node: AST | t.CPtr = BoolOp(ps.pool, OpKind.And, values)
|
||||
_set_pos(node, left.lineno, left.col_offset, 0, 0)
|
||||
@@ -650,9 +663,12 @@ def _advance_comp_op(ps: Parser | t.CPtr):
|
||||
def _parse_bitor(ps: Parser | t.CPtr) -> AST | t.CPtr:
|
||||
left: AST | t.CPtr = _parse_bitxor(ps)
|
||||
if left is None: return None
|
||||
while _match_op(ps, TokOp.VBar):
|
||||
while True:
|
||||
_skip_nl(ps) # 括号内行首 '|': (a\n | b)
|
||||
if _match_op(ps, TokOp.VBar) == 0:
|
||||
break
|
||||
_advance(ps)
|
||||
_skip_nl(ps)
|
||||
_skip_nl(ps) # 括号内跨行: a |\n b
|
||||
right: AST | t.CPtr = _parse_bitxor(ps)
|
||||
node: AST | t.CPtr = BinOp(ps.pool, left, OpKind.BitOr, right)
|
||||
_set_pos(node, left.lineno, left.col_offset, 0, 0)
|
||||
@@ -663,9 +679,12 @@ def _parse_bitor(ps: Parser | t.CPtr) -> AST | t.CPtr:
|
||||
def _parse_bitxor(ps: Parser | t.CPtr) -> AST | t.CPtr:
|
||||
left: AST | t.CPtr = _parse_bitand(ps)
|
||||
if left is None: return None
|
||||
while _match_op(ps, TokOp.Caret):
|
||||
while True:
|
||||
_skip_nl(ps) # 括号内行首 '^': (a\n ^ b)
|
||||
if _match_op(ps, TokOp.Caret) == 0:
|
||||
break
|
||||
_advance(ps)
|
||||
_skip_nl(ps)
|
||||
_skip_nl(ps) # 括号内跨行: a ^\n b
|
||||
right: AST | t.CPtr = _parse_bitand(ps)
|
||||
node: AST | t.CPtr = BinOp(ps.pool, left, OpKind.BitXor, right)
|
||||
_set_pos(node, left.lineno, left.col_offset, 0, 0)
|
||||
@@ -676,9 +695,12 @@ def _parse_bitxor(ps: Parser | t.CPtr) -> AST | t.CPtr:
|
||||
def _parse_bitand(ps: Parser | t.CPtr) -> AST | t.CPtr:
|
||||
left: AST | t.CPtr = _parse_shift(ps)
|
||||
if left is None: return None
|
||||
while _match_op(ps, TokOp.Amp):
|
||||
while True:
|
||||
_skip_nl(ps) # 括号内行首 '&': (a\n & b)
|
||||
if _match_op(ps, TokOp.Amp) == 0:
|
||||
break
|
||||
_advance(ps)
|
||||
_skip_nl(ps)
|
||||
_skip_nl(ps) # 括号内跨行: a &\n b
|
||||
right: AST | t.CPtr = _parse_shift(ps)
|
||||
node: AST | t.CPtr = BinOp(ps.pool, left, OpKind.BitAnd, right)
|
||||
_set_pos(node, left.lineno, left.col_offset, 0, 0)
|
||||
@@ -689,10 +711,13 @@ def _parse_bitand(ps: Parser | t.CPtr) -> AST | t.CPtr:
|
||||
def _parse_shift(ps: Parser | t.CPtr) -> AST | t.CPtr:
|
||||
left: AST | t.CPtr = _parse_arith(ps)
|
||||
if left is None: return None
|
||||
while _match_op(ps, TokOp.LtLt) or _match_op(ps, TokOp.GtGt):
|
||||
while True:
|
||||
_skip_nl(ps) # 括号内行首 '<<'/'>>': (a\n << b)
|
||||
if _match_op(ps, TokOp.LtLt) == 0 and _match_op(ps, TokOp.GtGt) == 0:
|
||||
break
|
||||
op_token: t.CInt = _cur_op(ps)
|
||||
_advance(ps)
|
||||
_skip_nl(ps)
|
||||
_skip_nl(ps) # 括号内跨行: a <<\n b
|
||||
right: AST | t.CPtr = _parse_arith(ps)
|
||||
ast_op: t.CInt = OpKind.LShift
|
||||
if op_token == TokOp.GtGt:
|
||||
@@ -706,10 +731,13 @@ def _parse_shift(ps: Parser | t.CPtr) -> AST | t.CPtr:
|
||||
def _parse_arith(ps: Parser | t.CPtr) -> AST | t.CPtr:
|
||||
left: AST | t.CPtr = _parse_term(ps)
|
||||
if left is None: return None
|
||||
while _match_op(ps, TokOp.Plus) or _match_op(ps, TokOp.Minus):
|
||||
while True:
|
||||
_skip_nl(ps) # 括号内行首 '+'/'-': (a\n + b)
|
||||
if _match_op(ps, TokOp.Plus) == 0 and _match_op(ps, TokOp.Minus) == 0:
|
||||
break
|
||||
op_token: t.CInt = _cur_op(ps)
|
||||
_advance(ps)
|
||||
_skip_nl(ps)
|
||||
_skip_nl(ps) # 括号内跨行: a +\n b
|
||||
right: AST | t.CPtr = _parse_term(ps)
|
||||
ast_op: t.CInt = OpKind.Add
|
||||
if op_token == TokOp.Minus:
|
||||
@@ -724,6 +752,7 @@ def _parse_term(ps: Parser | t.CPtr) -> AST | t.CPtr:
|
||||
left: AST | t.CPtr = _parse_factor(ps)
|
||||
if left is None: return None
|
||||
while True:
|
||||
_skip_nl(ps) # 括号内行首 '*'/'/'/'//'/'%'/'@': (a\n * b)
|
||||
op_token: t.CInt = 0
|
||||
if _match_op(ps, TokOp.Star): op_token = TokOp.Star
|
||||
elif _match_op(ps, TokOp.Slash): op_token = TokOp.Slash
|
||||
@@ -732,7 +761,7 @@ def _parse_term(ps: Parser | t.CPtr) -> AST | t.CPtr:
|
||||
elif _match_op(ps, TokOp.At): op_token = TokOp.At
|
||||
if op_token == 0: break
|
||||
_advance(ps)
|
||||
_skip_nl(ps)
|
||||
_skip_nl(ps) # 括号内跨行: a *\n b
|
||||
right: AST | t.CPtr = _parse_factor(ps)
|
||||
ast_op: t.CInt = _binop_from_op(op_token)
|
||||
node: AST | t.CPtr = BinOp(ps.pool, left, ast_op, right)
|
||||
|
||||
Reference in new issue
Block a user