diff --git a/ast/parser.vp b/ast/parser.vp index d38902a..40b8db0 100644 --- a/ast/parser.vp +++ b/ast/parser.vp @@ -55,6 +55,8 @@ class Parser: pool: rawptr[memhub.MemManager] # memory pool error_count: int # error count pending_decorators: rawptr[list[rawptr[AST]]] # pending decorators list + # 实参位前导 `*` 的已解析左操作数挂起槽(见 _parse_call / _parse_power)。 + starred_seed: rawptr[AST] # `static` 修饰符(软关键字)挂起标记:语句起始消费 `static`(后随变量声明 # `Name :`)后置 1,由紧随的 `_parse_type_ann` 在类型联合最左插入 t.CStatic # 标记(`static x: int = 0` → `x: t.CStatic | int = 0`),插入后立即清零, @@ -95,6 +97,7 @@ def _parser_init(ps: rawptr[Parser], tokens: rawptr[Token], ps.pool = pool ps.error_count = 0 ps.pending_decorators = None + ps.starred_seed = None ps.pending_static = 0 ps.in_class_body = 0 ps.step_count = 0 @@ -1640,6 +1643,13 @@ def _parse_term(ps: rawptr[Parser]) -> rawptr[AST]: def _parse_factor(ps: rawptr[Parser]) -> rawptr[AST]: """factor: '+' factor | '-' factor | '~' factor | '*' factor | '&' factor | power""" + # 实参位前导 `*` 已由 _parse_call 解析出紧绑定的 Starred 左操作数,直接作为本层 + # 因子返回(必须先于下面的一元判定,否则其后的二元 `+`/`-` 会被误判为一元)。 + # 上层各层随即以该左操作数续接二元运算:`*p + n` ⇒ `(*p) + n`,而非 `*(p + n)`。 + if ps.starred_seed is not None: + seed: rawptr[AST] = ps.starred_seed + ps.starred_seed = None + return seed if (_match_op(ps, TokOp.Plus) or _match_op(ps, TokOp.Minus) or _match_op(ps, TokOp.Tilde) or _match_op(ps, TokOp.Star) or _match_op(ps, TokOp.Amp)): op_token: int = _cur_op(ps) @@ -1755,10 +1765,19 @@ def _parse_call(ps: rawptr[Parser], func: rawptr[AST]) -> rawptr[AST]: elif _match_op(ps, TokOp.Star): _advance(ps) _skip_nls_and_newlines(ps) + # 只按一元因子取下界(保持 `*p[0]` = `*(p[0])` 的 C 结合),再挂到 + # starred_seed 上,交由 _parse_expr 续接其后二元运算:`*p + n` ⇒ + # `(*p) + n`。若整体用 _parse_expr,前导 `*` 会吞掉整条 `p + n` + # 而错解为 `*(p + n)`(zlib append_bytes 的 out 参数不回写根因)。 + seed: rawptr[AST] = _parse_factor(ps) + if seed is None: + ps.error_count += 1 + break + star: rawptr[AST] = Starred(ps.pool, seed, ASTCtx.Load) + _set_pos(star, seed.lineno, seed.col_offset, 0, 0) + ps.starred_seed = star val = _parse_expr(ps) - star: rawptr[AST] = Starred(ps.pool, val, ASTCtx.Load) - _set_pos(star, val.lineno, val.col_offset, 0, 0) - args.append(star) + args.append(val) # keyword = expr elif _cur_type(ps) == TokenType.Name: if ps.cur.next is not None and ps.cur.next.type == TokenType.Op and ps.cur.next.op_subtype == TokOp.Equal: