From c5570dc8b1dc474a385b4ed1a62a06d2ca892cdf Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Fri, 7 Aug 2026 18:49:53 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=86=20ast=20=E8=8B=B1=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- includes/ast/__init__.vp | 50 ++++---- includes/ast/astaux.vp | 14 +-- includes/ast/base.vp | 113 +++++++++-------- includes/ast/exprs.vp | 58 ++++----- includes/ast/lexer.vp | 181 +++++++++++++-------------- includes/ast/match.vp | 18 +-- includes/ast/parser.vp | 261 ++++++++++++++++++++------------------- includes/ast/stmts.vp | 54 ++++---- includes/ast/tokens.vp | 88 ++++++------- 9 files changed, 424 insertions(+), 413 deletions(-) diff --git a/includes/ast/__init__.vp b/includes/ast/__init__.vp index 6d0a240..610776c 100644 --- a/includes/ast/__init__.vp +++ b/includes/ast/__init__.vp @@ -3,34 +3,34 @@ from stdint import * import memhub import string -# 导入子模块 +# Import submodule from .tokens import ( Token, TokenType, Keyword, TokOp, _init_tables, ) -# 公共部分:基类、枚举、常量、辅助函数、dump +# Common Section: Base Classes, Enums, Constants, Helper Functions, Dump from .base import ( AST, ASTKind, ASTCtx, OpKind, ASTFlag, - # 常量 + # Constants CONST_INT, CONST_FLOAT, CONST_STR, CONST_BOOL, CONST_NONE, CONST_CHAR, FLAG_IS_ASYNC, FLAG_SIMPLE, FLAG_HAS_STAR, - # 辅助函数 + # Helper Functions _init_ast, _copy_str, _set_pos, _inherit_pos, _set_parent_list, _binop_from_op, _augop_from_op, _cmpop_from_op, _emit, _emit_str, _emit_int, _dump_list, dump, _op_name, ) -# 语句节点 +# Statement Nodes: Module, Expression, Interactive, FunctionType from .stmts import ( - # 模块层 + # Module Layer Module, Expression, Interactive, FunctionType, - # 语句 + # Statement FunctionDef, ClassDef, Return, Delete, Assign, AugAssign, AnnAssign, For, While, If, With, Raise, Try, Assert, Global, Nonlocal, Pass, Break, Continue, Expr, Import, ImportFrom, Match, ) -# 表达式节点 +# Expression Nodes: BoolOp, BinOp, UnaryOp, Lambda, IfExp, Dict, Set from .exprs import ( - # 表达式 + # Expression Layer BoolOp, BinOp, UnaryOp, Lambda, IfExp, Dict, Set, ListComp, SetComp, DictComp, GeneratorExp, Await, Yield, YieldFrom, FormattedValue, JoinedStr, @@ -38,12 +38,12 @@ from .exprs import ( List, Tuple, Slice, Call, Compare, OpNode, ) -# 辅助节点 +# Auxiliary Nodes from .astaux import ( ExceptHandler, Arguments, Arg, Keyword, Alias, WithItem, Comprehension, ) -# 模式匹配 +# Pattern Matching from .match import ( MatchCase, MatchValue, MatchSingleton, MatchSequence, MatchMapping, MatchClass, MatchStar, MatchAs, MatchOr, @@ -54,25 +54,25 @@ from .parser import Parser, _parser_init, parse_tokens, new_parser from .parser import _parse_test # ============================================================ -# 全局内存池指针(遵循项目规则:声明 _mbuddy) -# 用户在 main 中初始化:ast._mbuddy = memhub.MemBuddy(arena, size) +# Global Memory Pool Pointer (follows project rules: declare _mbuddy) +# User initializes in main: ast._mbuddy = memhub.MemBuddy(arena, size) # ============================================================ _mbuddy: memhub.MemBuddy | t.CPtr # ============================================================ -# 公共 API: parse +# Common API: parse # ============================================================ def parse(src: str, pool: memhub.MemManager | t.CPtr) -> AST | t.CPtr: - """解析 Python 源代码,返回 AST Module 节点。 + """Parse Python source code, return the AST Module node. - 参数: - src: NUL 结尾的源代码字符串 - pool: memhub.MemManager 实例,用于分配 AST 节点 + Parameters: + src: NUL source code string, terminated with NUL + pool: memhub.MemManager instance, to allocate AST nodes - 返回: - AST Module 节点,失败返回 None + Returns: + AST Module node, or None """ if src is None or pool is None: return None @@ -89,7 +89,15 @@ def parse(src: str, pool: memhub.MemManager | t.CPtr) -> AST | t.CPtr: def parse_expression(src: str, pool: memhub.MemManager | t.CPtr) -> AST | t.CPtr: - """解析单个表达式,返回 Expression 节点""" + """Parse a single expression, return the Expression node. + + Parameters: + src: NUL expression string, terminated with NUL + pool: memhub.MemManager instance, to allocate AST nodes + + Returns: + Expression node, or None + """ if src is None or pool is None: return None _init_tables(pool) diff --git a/includes/ast/astaux.vp b/includes/ast/astaux.vp index 3a4b083..3c51a00 100644 --- a/includes/ast/astaux.vp +++ b/includes/ast/astaux.vp @@ -10,7 +10,7 @@ from .base import ( # ============================================================ -# ExceptHandler 节点 +# ExceptHandler Node # ============================================================ class ExceptHandler(AST): @@ -53,7 +53,7 @@ class ExceptHandler(AST): # ============================================================ -# Arguments 节点 +# Arguments Node # ============================================================ class Arguments(AST): @@ -119,7 +119,7 @@ class Arguments(AST): # ============================================================ -# Arg 节点 +# Arg Node # ============================================================ class Arg(AST): @@ -160,7 +160,7 @@ class Arg(AST): # ============================================================ -# Keyword 节点 +# Keyword Node # ============================================================ class Keyword(AST): @@ -201,7 +201,7 @@ class Keyword(AST): # ============================================================ -# Alias 节点 +# Alias Node # ============================================================ class Alias(AST): @@ -239,7 +239,7 @@ class Alias(AST): # ============================================================ -# WithItem 节点 +# WithItem Node # ============================================================ class WithItem(AST): @@ -283,7 +283,7 @@ class WithItem(AST): # ============================================================ -# Comprehension 节点 +# Comprehension Node # ============================================================ class Comprehension(AST): diff --git a/includes/ast/base.vp b/includes/ast/base.vp index 3301511..eb133a9 100644 --- a/includes/ast/base.vp +++ b/includes/ast/base.vp @@ -7,11 +7,11 @@ from .tokens import TokOp # ============================================================ -# ASTKind - 节点类型枚举(kind() 虚函数返回值) +# ASTKind - Node type enum (kind() virtual function return value) # ============================================================ class ASTKind(t.CEnum): - # 核心 15 节点 + # Core 15 nodes Module: t.State FunctionDef: t.State ClassDef: t.State @@ -27,11 +27,11 @@ class ASTKind(t.CEnum): UnaryOp: t.State Call: t.State Compare: t.State - # 模块层 + # Module Layer Expression: t.State Interactive: t.State FunctionType: t.State - # 语句 + # Statement Delete: t.State AugAssign: t.State AnnAssign: t.State @@ -47,7 +47,7 @@ class ASTKind(t.CEnum): Import: t.State ImportFrom: t.State Match: t.State - # 表达式 + # Expression Layer BoolOp: t.State Lambda: t.State IfExp: t.State @@ -69,7 +69,7 @@ class ASTKind(t.CEnum): Tuple: t.State Slice: t.State NamedExpr: t.State - # 辅助节点 + # Auxiliary Nodes ExceptHandler: t.State Arguments: t.State Arg: t.State @@ -78,7 +78,7 @@ class ASTKind(t.CEnum): WithItem: t.State Comprehension: t.State OpNode: t.State - # 模式匹配 + # Pattern Matching MatchCase: t.State MatchValue: t.State MatchSingleton: t.State @@ -91,7 +91,7 @@ class ASTKind(t.CEnum): # ============================================================ -# ASTCtx - 名称上下文(Load/Store/Del) +# ASTCtx - Name context (Load/Store/Del) # ============================================================ class ASTCtx(t.CEnum): @@ -101,11 +101,11 @@ class ASTCtx(t.CEnum): # ============================================================ -# OpKind - 运算符枚举(BinOp/UnaryOp/Compare 共用) +# OpKind - Operator enum (BinOp/UnaryOp/Compare) # ============================================================ class OpKind(t.CEnum): - # 二元算术/位运算 + # Binary arithmetic operators Add: t.State Sub: t.State Mult: t.State @@ -119,10 +119,10 @@ class OpKind(t.CEnum): BitXor: t.State BitAnd: t.State FloorDiv: t.State - # 布尔运算 + # Boolean operators And: t.State Or: t.State - # 比较运算 + # Comparison operators Eq: t.State Ne: t.State Lt: t.State @@ -133,16 +133,16 @@ class OpKind(t.CEnum): IsNot: t.State In: t.State NotIn: t.State - # 一元运算 + # Unary operators Not: t.State UAdd: t.State USub: t.State Invert: t.State - # 空 + # None NoneOp: t.State -# Constant 子类型标识 +# Constant subtype identifiers CONST_INT: t.CDefine = 1 CONST_FLOAT: t.CDefine = 2 CONST_STR: t.CDefine = 3 @@ -150,14 +150,14 @@ CONST_BOOL: t.CDefine = 4 CONST_NONE: t.CDefine = 5 CONST_CHAR: t.CDefine = 6 -# 标志位 +# Node flags FLAG_IS_ASYNC: t.CDefine = 1 FLAG_SIMPLE: t.CDefine = 2 FLAG_HAS_STAR: t.CDefine = 4 # ============================================================ -# ASTFlag - 节点标志位枚举 +# ASTFlag - Node flags enum # ============================================================ class ASTFlag(t.CEnum): @@ -167,11 +167,11 @@ class ASTFlag(t.CEnum): # ============================================================ -# 辅助函数 +# Helper Functions # ============================================================ def _copy_str(pool: memhub.MemManager | t.CPtr, src: str) -> str: - """从 pool 分配并复制 C 字符串""" + """Allocate and copy a C string from pool.""" if src is None: return None slen: t.CSizeT = string.strlen(src) buf: str = pool.alloc(slen + 1) @@ -199,7 +199,7 @@ def _inherit_pos(node: AST | t.CPtr, ref: AST | t.CPtr): def _init_ast(node: AST | t.CPtr, pool: memhub.MemManager | t.CPtr, lineno: t.CInt, col: t.CInt): - """初始化 AST 基类字段""" + """Initialize AST base fields.""" node.parent = None node.pool = pool node.lineno = lineno @@ -210,7 +210,7 @@ def _init_ast(node: AST | t.CPtr, pool: memhub.MemManager | t.CPtr, def _set_parent_list(lst: list[AST | t.CPtr] | t.CPtr, parent: AST | t.CPtr): - """为 list 中的每个子节点设置 parent 指针""" + """Set list children parent pointers.""" if lst is None: return n: t.CSizeT = lst.__len__() i: t.CSizeT = 0 @@ -223,17 +223,16 @@ def _set_parent_list(lst: list[AST | t.CPtr] | t.CPtr, parent: AST | t.CPtr): def _append_child(lst: list[AST | t.CPtr] | t.CPtr, node: AST | t.CPtr, pool: memhub.MemManager | t.CPtr): - """向 list 追加子节点(模块级函数,避免与 AST.append 方法名冲突)。 + """Append child nodes to a list (module-level function, to avoid conflicts with the AST.append method name). - 在 AST.append 方法中调用此函数,绕过编译器把 list.append 误解析为 - AST.append 虚函数调用的类型推断问题。""" + Call this function within the AST.append method to bypass the compiler mistaking list.append for a virtual function call to AST.append when doing type inference.""" if lst is None or node is None: return lst.append(node) # ============================================================ -# 运算符映射:TokOp -> OpKind +# Operator Mapping: TokOp -> OpKind # ============================================================ def _binop_from_op(op_id: t.CInt) -> t.CInt: @@ -281,12 +280,12 @@ def _cmpop_from_op(op_id: t.CInt) -> t.CInt: # ============================================================ -# dump 辅助函数 +# dump Helper Functions # ============================================================ def _emit(buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT, text: str) -> t.CSizeT: - """追加字面量到 buf+pos,返回新 pos""" + """Append literal to buf+pos.""" if buf is None or pos >= size: return pos cur: t.CChar | t.CPtr = (t.CVoid | t.CPtr)(t.CUInt64T(buf) + pos) @@ -299,7 +298,7 @@ def _emit(buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT, def _emit_str(buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT, text: str) -> t.CSizeT: - """追加字符串值到 buf+pos(用 %s 格式)""" + """Append a string value to buf pos (using %s format)""" if buf is None or pos >= size: return pos cur: t.CChar | t.CPtr = (t.CVoid | t.CPtr)(t.CUInt64T(buf) + pos) @@ -312,7 +311,7 @@ def _emit_str(buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT, def _emit_int(buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT, val: t.CInt64T) -> t.CSizeT: - """追加整数值到 buf+pos""" + """Append an integer value to buf pos (using %lld format).""" if buf is None or pos >= size: return pos cur: t.CChar | t.CPtr = (t.CVoid | t.CPtr)(t.CUInt64T(buf) + pos) @@ -324,7 +323,7 @@ def _emit_int(buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT, def _op_name(op: t.CInt) -> str: - """返回 OpKind 的字符串名称""" + """Return the string name of an OpKind.""" if op == OpKind.Add: return "Add" if op == OpKind.Sub: return "Sub" if op == OpKind.Mult: return "Mult" @@ -359,7 +358,7 @@ def _op_name(op: t.CInt) -> str: def _dump_list(lst: list[AST | t.CPtr] | t.CPtr, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: - """遍历 list[AST | CPtr] 容器,多态 dump 每个元素""" + """Traverse a list[AST | CPtr] container, polymorphically dump each element.""" if lst is None: pos = _emit(buf, size, pos, "[]") return pos @@ -379,7 +378,7 @@ def _dump_list(lst: list[AST | t.CPtr] | t.CPtr, buf: t.CChar | t.CPtr, def _dump_op_list(lst: t.CPtr, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: - """遍历 list[CInt] (OpKind 值),输出 op 名称列表""" + """Traverse a list[CInt] (OpKind values), output a list of op names.""" if lst is None: pos = _emit(buf, size, pos, "[]") return pos @@ -398,23 +397,23 @@ def _dump_op_list(lst: t.CPtr, buf: t.CChar | t.CPtr, # ============================================================ -# AST - 多态基类 -# -# @t.CVTable 启用 vtable,支持 kind()/type_name()/dump()/accept() 虚函数 -# 子节点用 list[AST | CPtr] 容器存储(O(1) 随机访问,比链表高效) -# parent 字段维护父指针(用于向上遍历) +# AST - Polymorphic Base Class + +# @t.CVTable enables vtable, supporting virtual functions like kind()/type_name()/dump()/accept() +# Child nodes are stored in a list[AST | CPtr] container (O(1) random access, more efficient than linked lists) +# The parent field maintains a pointer to the parent (used for upward traversal) # ============================================================ @t.CVTable class AST: - """AST 节点基类。所有具体节点类继承此类。 + """AST node base class. All specific node classes inherit from this. - 字段: - parent: 父节点指针(向上遍历) - pool: 分配器(用于子节点/字符串分配) - lineno/col_offset: 起始位置 - end_lineno/end_col_offset: 结束位置 - children: 子节点列表(body 语句块,通过 append 添加) + Fields: + parent: Pointer to the parent node (for upward traversal) + pool: Allocator (used for allocating child nodes/strings) + lineno/col_offset: Starting position + end_lineno/end_col_offset: Ending position + children: List of child nodes (body block, added via append) """ parent: AST | t.CPtr pool: memhub.MemManager | t.CPtr @@ -425,31 +424,31 @@ class AST: children: list[AST | t.CPtr] | t.CPtr def kind(self) -> t.CInt: - """返回节点类型(ASTKind 值),子类覆盖""" + """Returns the node type (ASTKind value), overridden by subclasses""" return 0 def type_name(self) -> str: - """返回节点类型名,子类覆盖""" + """Return the node type name, subclasses override""" return "AST" def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: - """多态 dump:子类覆盖以自定义格式。返回写入后的 pos""" + """Polymorphic dump: subclasses override to define custom format. Returns the written pos""" return pos def accept(self, visitor: t.CPtr): - """访问者模式入口(待实现):ASTVisitor 在 __visitor.py 定义后, - 子类覆盖此方法分派到 visitor.visit_X(self)。当前为空实现。""" + """Visitor pattern entry point: subclasses override to dispatch to ASTVisitor in the visitor pattern. + Current implementation is empty. override this method to dispatch to visitor.visit_X(self)""" pass def append(self, node: AST | t.CPtr): - """将 node 追加为子节点(添加到 children 列表),设置 parent 指针。 + """Append node to the children list. - 用于 parser 构建语句块:module.append(stmt), if_node.append(stmt) 等。 - 首次调用时懒初始化 children 列表。 + Used for parser to build statement blocks: module.append(stmt), if_node.append(stmt), etc. + The children list is lazily initialized on first call. - 注意:list[AST|CPtr] 当前按值复制存储(编译器限制),所以必须先设置 - node.parent 再 append,这样副本中的 parent 才是正确的。""" + Note: list[AST|CPtr] is currently stored by value (compiler limitation), so you must set + node.parent before appending, so the parent in the copy is correct.""" if self is None or node is None: return if self.children is None: @@ -459,16 +458,16 @@ class AST: # ============================================================ -# 模块级 dump 函数(供 ast.dump(node, buf, size) 调用) +# Module dump function (for ast.dump(node, buf, size)) # ============================================================ def dump(node: AST | t.CPtr, buf: t.CChar | t.CPtr, size: t.CSizeT): - """将 AST 节点序列化到 buf(容量 size)""" + """Serialize AST node to buf (with capacity size)""" if node is None or buf is None or size == 0: return buf[0] = '\0' final_pos: t.CSizeT = node.dump(buf, size, 0) - # NUL 终止,防止 printf 越界 + # NUL-terminate to prevent printf overflow if final_pos < size: buf[final_pos] = '\0' else: diff --git a/includes/ast/exprs.vp b/includes/ast/exprs.vp index 58bae03..bf145fc 100644 --- a/includes/ast/exprs.vp +++ b/includes/ast/exprs.vp @@ -11,7 +11,7 @@ from .base import ( # ============================================================ -# Name 节点 +# Name node # ============================================================ class Name(AST): @@ -54,7 +54,7 @@ class Name(AST): # ============================================================ -# Constant 节点(用 const_kind 标识子类型) +# Constant nodes (subtype marked by const_kind) # ============================================================ class Constant(AST): @@ -107,7 +107,7 @@ class Constant(AST): pos = _emit(buf, size, pos, "(null)") pos = _emit(buf, size, pos, "'") elif self.const_kind == CONST_CHAR: - # 单引号单字符 → 显示为字符 ASCII 值 + # Single character → display as character ASCII value pos = _emit(buf, size, pos, "char(") pos = _emit_int(buf, size, pos, self.int_val) pos = _emit(buf, size, pos, ")") @@ -123,7 +123,7 @@ class Constant(AST): # ============================================================ -# BinOp 节点 +# BinOp Node # ============================================================ class BinOp(AST): @@ -171,7 +171,7 @@ class BinOp(AST): # ============================================================ -# UnaryOp 节点 +# UnaryOp Node # ============================================================ class UnaryOp(AST): @@ -212,7 +212,7 @@ class UnaryOp(AST): # ============================================================ -# Compare 节点 +# Compare Node # ============================================================ class Compare(AST): @@ -262,7 +262,7 @@ class Compare(AST): # ============================================================ -# Call 节点 +# Call Node # ============================================================ class Call(AST): @@ -311,7 +311,7 @@ class Call(AST): # ============================================================ -# BoolOp 节点 +# BoolOp Node # ============================================================ class BoolOp(AST): @@ -352,7 +352,7 @@ class BoolOp(AST): # ============================================================ -# Lambda 节点 +# Lambda Node # ============================================================ class Lambda(AST): @@ -396,7 +396,7 @@ class Lambda(AST): # ============================================================ -# IfExp 节点 +# IfExp Node # ============================================================ class IfExp(AST): @@ -449,7 +449,7 @@ class IfExp(AST): # ============================================================ -# Dict 节点 +# Dict Node # ============================================================ class Dict(AST): @@ -491,7 +491,7 @@ class Dict(AST): # ============================================================ -# Set 节点 +# Set Node # ============================================================ class Set(AST): @@ -526,7 +526,7 @@ class Set(AST): # ============================================================ -# ListComp 节点 +# ListComp Node # ============================================================ class ListComp(AST): @@ -570,7 +570,7 @@ class ListComp(AST): # ============================================================ -# SetComp 节点 +# SetComp Node # ============================================================ class SetComp(AST): @@ -614,7 +614,7 @@ class SetComp(AST): # ============================================================ -# DictComp 节点 +# DictComp Node # ============================================================ class DictComp(AST): @@ -665,7 +665,7 @@ class DictComp(AST): # ============================================================ -# GeneratorExp 节点 +# GeneratorExp Node # ============================================================ class GeneratorExp(AST): @@ -709,7 +709,7 @@ class GeneratorExp(AST): # ============================================================ -# Await 节点 +# Await Node # ============================================================ class Await(AST): @@ -744,7 +744,7 @@ class Await(AST): # ============================================================ -# Yield 节点 +# Yield Node # ============================================================ class Yield(AST): @@ -779,7 +779,7 @@ class Yield(AST): # ============================================================ -# YieldFrom 节点 +# YieldFrom Node # ============================================================ class YieldFrom(AST): @@ -814,7 +814,7 @@ class YieldFrom(AST): # ============================================================ -# FormattedValue 节点 +# FormattedValue Node # ============================================================ class FormattedValue(AST): @@ -864,7 +864,7 @@ class FormattedValue(AST): # ============================================================ -# JoinedStr 节点 +# JoinedStr Node # ============================================================ class JoinedStr(AST): @@ -899,7 +899,7 @@ class JoinedStr(AST): # ============================================================ -# Attribute 节点 +# Attribute Node # ============================================================ class Attribute(AST): @@ -944,7 +944,7 @@ class Attribute(AST): # ============================================================ -# Subscript 节点 +# Subscript Node # ============================================================ class Subscript(AST): @@ -992,7 +992,7 @@ class Subscript(AST): # ============================================================ -# Starred 节点 +# Starred Node # ============================================================ class Starred(AST): @@ -1033,7 +1033,7 @@ class Starred(AST): # ============================================================ -# List 节点 +# List Node # ============================================================ class List(AST): @@ -1072,7 +1072,7 @@ class List(AST): # ============================================================ -# Tuple 节点 +# Tuple Node # ============================================================ class Tuple(AST): @@ -1111,7 +1111,7 @@ class Tuple(AST): # ============================================================ -# Slice 节点 +# Slice Node # ============================================================ class Slice(AST): @@ -1164,7 +1164,7 @@ class Slice(AST): # ============================================================ -# NamedExpr 节点 +# NamedExpr Node # ============================================================ class NamedExpr(AST): @@ -1208,7 +1208,7 @@ class NamedExpr(AST): # ============================================================ -# OpNode 节点 +# OpNode Node # ============================================================ class OpNode(AST): diff --git a/includes/ast/lexer.vp b/includes/ast/lexer.vp index 0bc7170..0cb88f2 100644 --- a/includes/ast/lexer.vp +++ b/includes/ast/lexer.vp @@ -8,27 +8,27 @@ from .tokens import ( ) -# 缩进栈最大深度 +# Maximum Indentation Stack Depth LEXER_MAX_INDENT: t.CDefine = 256 # ============================================================ -# Lexer 状态结构体 +# Lexer State Structure # ============================================================ class Lexer: - src: str # 源代码(NUL 结尾) - pos: t.CSizeT # 当前位置 - len: t.CSizeT # 源代码长度 - lineno: t.CInt # 当前行号(从 1 开始) - col: t.CInt # 当前列号(从 0 开始) - pool: memhub.MemManager | t.CPtr # 内存池 - indent_stack: t.CInt | t.CPtr # 缩进栈(int 数组,从 pool 分配) - indent_top: t.CInt # 栈顶索引(-1 表示空栈) - paren_depth: t.CInt # 括号深度(>0 时不产生 TokenType.NewLine) - tokens_head: Token | t.CPtr # token 链表头 - tokens_tail: Token | t.CPtr # token 链表尾 - at_line_start: t.CInt # 1=行首(需处理缩进) - error_count: t.CInt # 错误计数 + src: str # Source code (NUL-terminated) + pos: t.CSizeT # Current position + len: t.CSizeT # Source code length + lineno: t.CInt # Current line number (1-based) + col: t.CInt # Current column number (0-based) + pool: memhub.MemManager | t.CPtr # Memory pool + indent_stack: t.CInt | t.CPtr # Indent stack (int array, allocated from pool) + indent_top: t.CInt # Stack top (-1 for empty stack) + paren_depth: t.CInt # Paren depth (>0 for no TokenType.NewLine) + tokens_head: Token | t.CPtr # token list head + tokens_tail: Token | t.CPtr # token list tail + at_line_start: t.CInt # 1=line start (need indent) + error_count: t.CInt # Error count def __new__(self, pool: memhub.MemManager | t.CPtr): ptr: Lexer | t.CPtr = pool.alloc(Lexer.__sizeof__()) @@ -38,13 +38,13 @@ class Lexer: def new_lexer(pool: memhub.MemManager | t.CPtr) -> Lexer | t.CPtr: - """从 pool 分配并返回 Lexer(跨模块安全包装)""" + """Allocate from the pool and return a Lexer (cross-module safe wrapper)""" return Lexer(pool) def _lexer_init(lx: Lexer | t.CPtr, src: str, pool: memhub.MemManager | t.CPtr): - """初始化 Lexer""" + """Initialize Lexer""" if lx == None: return lx.src = src lx.pos = 0 @@ -52,12 +52,12 @@ def _lexer_init(lx: Lexer | t.CPtr, src: str, lx.lineno = 1 lx.col = 0 lx.pool = pool - # 分配缩进栈 + # Allocate indentation stack lx.indent_stack = pool.alloc(LEXER_MAX_INDENT * 8) if lx.indent_stack != None: string.memset(lx.indent_stack, 0, LEXER_MAX_INDENT * 8) lx.indent_top = -1 - # 栈底压入 0(基础缩进) + # Push 0 (base indent) if lx.indent_stack != None: lx.indent_stack[0] = 0 lx.indent_top = 0 @@ -70,11 +70,11 @@ def _lexer_init(lx: Lexer | t.CPtr, src: str, # ============================================================ -# 辅助函数 +# Auxiliary Functions # ============================================================ def _peek(lx: Lexer | t.CPtr, offset: t.CSizeT) -> t.CChar: - """查看 pos+offset 处字符,越界返回 '\0'""" + """Peek character at position pos+offset, return '\0' if out of bounds""" p: t.CSizeT = lx.pos + offset if p >= lx.len: return '\0' @@ -88,7 +88,7 @@ def _peek_cur(lx: Lexer | t.CPtr) -> t.CChar: def _advance(lx: Lexer | t.CPtr) -> t.CChar: - """前进一个字符,返回该字符""" + """Advance one character, return the character""" if lx.pos >= lx.len: return '\0' ch: t.CChar = lx.src[lx.pos] @@ -136,7 +136,7 @@ def _is_space(ch: t.CChar) -> t.CInt: def _emit(lx: Lexer | t.CPtr, tok: Token | t.CPtr): - """将 token 追加到链表""" + """Append token to token list""" if tok == None: return if lx.tokens_head == None: lx.tokens_head = tok @@ -156,25 +156,25 @@ def _make_op_token(lx: Lexer | t.CPtr, op_id: t.CInt, length: t.CInt, # ============================================================ -# 缩进处理 +# Indent Handling # ============================================================ def _handle_indent(lx: Lexer | t.CPtr): - """处理行首缩进,生成 TokenType.Indent/TokenType.Dedent。 - 跳过空行和注释行(不产生缩进变化)。""" - # 先跳过空行和注释行 + """Handle line start indent, generate TokenType.Indent/TokenType.Dedent. + Skip empty lines and comment lines.""" + # Skip empty lines and comment lines while lx.pos < lx.len: - # 记住行首位置,用于非空行回退 + # Save line start position for non-empty lines line_start_pos: t.CSizeT = lx.pos line_start_col: t.CInt = lx.col - # 跳过空白(不跨行) + # Skip whitespace, not across lines while lx.pos < lx.len: ch: t.CChar = lx.src[lx.pos] if ch == ' ' or ch == '\t' or ch == '\f' or ch == '\v': lx.pos += 1 lx.col += 1 elif ch == '\r': - # CRLF 行尾符的 \r,跳过(让 \n 触发空行处理) + # CRLF line end \r, skip \n to trigger empty line processing lx.pos += 1 else: break @@ -182,13 +182,13 @@ def _handle_indent(lx: Lexer | t.CPtr): break ch = lx.src[lx.pos] if ch == '\n': - # 空行,跳过 + # Empty line, skip lx.pos += 1 lx.lineno += 1 lx.col = 0 continue if ch == '\r': - # CRLF 空行(\r 后跟 \n),跳过 \r + # CRLF line end \r, skip \n to trigger empty line processing lx.pos += 1 if lx.pos < lx.len and lx.src[lx.pos] == '\n': lx.pos += 1 @@ -196,21 +196,21 @@ def _handle_indent(lx: Lexer | t.CPtr): lx.col = 0 continue if ch == '#': - # 注释行,跳过到行尾 + # Comment line, skip to end of line while lx.pos < lx.len and lx.src[lx.pos] != '\n': lx.pos += 1 continue - # 非空行:回退到行首,让后续缩进计算能读到前导空格 + # Non-empty line: backtrack to line start to allow indent calculation lx.pos = line_start_pos lx.col = line_start_col break if lx.pos >= lx.len: - # 文件末尾,不再处理缩进 + # End of file, no indent to handle lx.at_line_start = 0 return - # 计算当前行缩进 + # Calculate current line indent indent: t.CInt = 0 save_pos: t.CSizeT = lx.pos save_col: t.CInt = lx.col @@ -227,17 +227,17 @@ def _handle_indent(lx: Lexer | t.CPtr): else: break - # 如果行尾(空行),不处理 + # If line end (empty line), skip indent calculation if lx.pos < lx.len: ch = lx.src[lx.pos] if ch == '\n' or ch == '\r' or ch == '#': - # 空行或注释行,回退位置让主循环处理 + # Empty line or comment line, backtrack position to allow loop to handle indent lx.pos = save_pos lx.col = save_col lx.at_line_start = 0 return - # 与缩进栈比较 + # Compare indent with top of indent stack top_indent: t.CInt = lx.indent_stack[lx.indent_top] if indent > top_indent: # TokenType.Indent @@ -257,7 +257,7 @@ def _handle_indent(lx: Lexer | t.CPtr): # ============================================================ -# 标识符/关键字 +# Identifier/Keyword Handling # ============================================================ def _read_name(lx: Lexer | t.CPtr): @@ -277,7 +277,7 @@ def _read_name(lx: Lexer | t.CPtr): token_set_str(lx.pool, tok, lx.src, start, length) tok.end_lineno = lx.lineno tok.end_col_offset = start_col + t.CInt(length) - # 查找关键字 + # Look up keyword if any kw_id: t.CInt = _kw_lookup(tok.str_val) if kw_id: tok.kw_subtype = kw_id @@ -285,7 +285,7 @@ def _read_name(lx: Lexer | t.CPtr): # ============================================================ -# 数字 +# Number Handling # ============================================================ def _read_number(lx: Lexer | t.CPtr): @@ -296,7 +296,7 @@ def _read_number(lx: Lexer | t.CPtr): is_complex: t.CInt = 0 ch0: t.CChar = lx.src[lx.pos] - # 处理 0x/0o/0b 前缀 + # Handle 0x/0o/0b prefix if ch0 == '0' and lx.pos + 1 < lx.len: ch1: t.CChar = lx.src[lx.pos + 1] if ch1 == 'x' or ch1 == 'X': @@ -339,7 +339,7 @@ def _read_number(lx: Lexer | t.CPtr): _emit_number(lx, start, start_lineno, start_col, 0, 0, 0) return - # 十进制整数/浮点 + # Decimal integer/float while lx.pos < lx.len: ch: t.CChar = lx.src[lx.pos] if _is_digit(ch) or ch == '_': @@ -348,7 +348,7 @@ def _read_number(lx: Lexer | t.CPtr): else: break - # 小数部分 + # Decimal part if lx.pos < lx.len and lx.src[lx.pos] == '.': is_float = 1 lx.pos += 1 @@ -361,7 +361,7 @@ def _read_number(lx: Lexer | t.CPtr): else: break - # 指数部分 + # Exponent part if lx.pos < lx.len: ch: t.CChar = lx.src[lx.pos] if ch == 'e' or ch == 'E': @@ -381,7 +381,7 @@ def _read_number(lx: Lexer | t.CPtr): else: break - # 虚数后缀 + # Complex suffix part if lx.pos < lx.len and lx.src[lx.pos] == 'j': is_complex = 1 is_float = 1 @@ -402,7 +402,7 @@ def _emit_number(lx: Lexer | t.CPtr, start: t.CSizeT, tok.is_complex = is_complex tok.end_lineno = lx.lineno tok.end_col_offset = start_col + t.CInt(length) - # 解析数值 + # Parse number if is_float: tok.float_val = string.atof(tok.str_val) else: @@ -411,18 +411,19 @@ def _emit_number(lx: Lexer | t.CPtr, start: t.CSizeT, # ============================================================ -# 字符串 +# String Handling # ============================================================ def _read_string(lx: Lexer | t.CPtr): - """读取字符串字面量。 - 支持前缀: r, b, u, f, rb, br, rf, fr(大小写不敏感) - 支持引号: ', ", ''', """ + """Read string literal. + Supports prefixes: r, b, u, f, rb, br, rf, fr (case insensitive) + Supports quotes: ', ", ''', + Later we need to support string prefixes like i16/i24""" start_lineno: t.CInt = lx.lineno start_col: t.CInt = lx.col prefix_start: t.CSizeT = lx.pos - # 读取前缀(r/b/u/f) + # Read prefix (r/b/u/f) is_raw: t.CInt = 0 is_bytes: t.CInt = 0 is_fstring: t.CInt = 0 @@ -450,13 +451,13 @@ def _read_string(lx: Lexer | t.CPtr): lx.error_count += 1 return - # 确定引号 + # Determine quote type quote: t.CChar = lx.src[lx.pos] if quote != '\'' and quote != '"': lx.error_count += 1 return - # 检查三引号 + # Check triple quote is_triple: t.CInt = 0 if lx.pos + 2 < lx.len: if lx.src[lx.pos] == quote and lx.src[lx.pos + 1] == quote and lx.src[lx.pos + 2] == quote: @@ -470,7 +471,7 @@ def _read_string(lx: Lexer | t.CPtr): lx.pos += 1 lx.col += 1 - # 读取字符串内容 + # Read string content content_buf_start: t.CSizeT = lx.pos while lx.pos < lx.len: ch = lx.src[lx.pos] @@ -500,7 +501,7 @@ def _read_string(lx: Lexer | t.CPtr): if ch == quote: break if ch == '\n': - # 单引号字符串不能跨行(除非续行) + # Single quote string cannot span multiple lines (unless continued) lx.error_count += 1 return if ch == '\\' and not is_raw: @@ -514,7 +515,7 @@ def _read_string(lx: Lexer | t.CPtr): lx.col += 1 content_end: t.CSizeT = lx.pos - # 跳过结束引号 + # Skip the closing quote if is_triple: if lx.pos + 2 < lx.len: lx.pos += 3 @@ -526,16 +527,16 @@ def _read_string(lx: Lexer | t.CPtr): lx.pos += 1 lx.col += 1 - # 创建 token + # Create token tok: Token | t.CPtr = new_token(lx.pool, TokenType.String, start_lineno, start_col) if tok == None: return content_len: t.CSizeT = content_end - content_buf_start - # esc_len: 转义后实际字节数(用于判断单字符) + # esc_len: Actual bytes after escaping (used to check single character) esc_len: t.CSizeT = content_len - # 处理转义序列(非 raw 字符串) + # Handle escape sequences (non-raw strings) if is_raw == 0 and content_len > 0: - # 分配转换缓冲区(最大情况:每个字符都是普通字符,无需扩展) + # Allocate conversion buffer (max case: each char is plain, no extension) conv_buf: str = lx.pool.alloc(content_len + 1) if conv_buf == None: token_set_str(lx.pool, tok, lx.src, content_buf_start, content_len) @@ -570,7 +571,7 @@ def _read_string(lx: Lexer | t.CPtr): elif next_ch == '0': conv_buf[wpos] = '\0' else: - # 未知转义,保留原样(包括 \xNN 等以后再处理) + # Unknown escape sequence, keep original (includes \xNN) conv_buf[wpos] = '\\' wpos += 1 conv_buf[wpos] = next_ch @@ -587,37 +588,37 @@ def _read_string(lx: Lexer | t.CPtr): token_set_str(lx.pool, tok, lx.src, content_buf_start, content_len) tok.end_lineno = lx.lineno tok.end_col_offset = lx.col - # flags 字段复用:bit0=raw, bit1=bytes, bit2=fstring, bit3=triple, bit4=dquote, bit5=单字符候选 + # flags field: bit0=raw, bit1=bytes, bit2=fstring, bit3=triple, bit4=dquote, bit5=single char candidate if is_raw: tok.kw_subtype = tok.kw_subtype | 1 if is_bytes: tok.kw_subtype = tok.kw_subtype | 2 if is_fstring: tok.kw_subtype = tok.kw_subtype | 4 if is_triple: tok.kw_subtype = tok.kw_subtype | 8 - # bit4 (16) = 双引号(0=单引号, 1=双引号) + # bit4 (16) = double quote=single quote if quote == '"': tok.kw_subtype = tok.kw_subtype | 16 - # bit5 (32) = 单字符候选(非三引号、非 fstring、转义后正好 1 字节) - # 用于 CONST_CHAR 判定,避免 '\0' 等含 NUL 字节被 strlen 误判为空字符串 + # bit5 (32) = single-character candidate (not triple quotes, not f-string, exactly 1 byte after escaping) + # Used for CONST_CHAR checks to prevent '0' and other NUL bytes from being mistaken as empty strings by strlen if is_triple == 0 and is_fstring == 0 and esc_len == 1: tok.kw_subtype = tok.kw_subtype | 32 _emit(lx, tok) # ============================================================ -# 运算符 +# Operator Matching # ============================================================ def _read_operator(lx: Lexer | t.CPtr): - """贪婪匹配运算符""" + """Greedy match operator""" start_lineno: t.CInt = lx.lineno start_col: t.CInt = lx.col remaining: t.CSizeT = lx.len - lx.pos - # 遍历运算符表,找最长匹配 + # Traverse operator table, find longest match best_entry: OpEntry | t.CPtr = None best_len: t.CInt = 0 cur: OpEntry | t.CPtr = _op_head while cur != None: if cur.length <= t.CInt(remaining): - # 比较 cur.name 与 src[pos:pos+cur.length] + # Compare cur.name with src[pos:pos+cur.length] match: t.CInt = 1 i: t.CSizeT = 0 while i < t.CSizeT(cur.length): @@ -632,13 +633,13 @@ def _read_operator(lx: Lexer | t.CPtr): cur = cur.next if best_entry == None: - # 未知字符,报错并跳过 + # Unknown character, report error and skip lx.error_count += 1 lx.pos += 1 lx.col += 1 return - # 更新括号深度 + # Update parenthesis depth if best_entry.op_id == TokOp.LPar or best_entry.op_id == TokOp.Lsqb or best_entry.op_id == TokOp.LBrace: lx.paren_depth += 1 elif best_entry.op_id == TokOp.RPar or best_entry.op_id == TokOp.Rsqb or best_entry.op_id == TokOp.RBrace: @@ -655,14 +656,14 @@ def _read_operator(lx: Lexer | t.CPtr): # ============================================================ -# 主词法分析入口 +# Main Lexical Analysis Entry Point # ============================================================ def tokenize(lx: Lexer | t.CPtr) -> Token | t.CPtr: - """执行词法分析,返回 token 链表头""" + """Execute tokenization, return token list head""" if lx == None: return None while lx.pos < lx.len: - # 行首缩进处理 + # Handle line start indent if lx.at_line_start and lx.paren_depth == 0: _handle_indent(lx) if lx.pos >= lx.len: @@ -672,14 +673,14 @@ def tokenize(lx: Lexer | t.CPtr) -> Token | t.CPtr: if ch == '\0': break - # 换行 + # New line if ch == '\n': if lx.paren_depth > 0: - # 括号内,产生 TokenType.Nl + # # In bi brackets, generates TokenType.Nl tok: Token | t.CPtr = new_token(lx.pool, TokenType.Nl, lx.lineno, lx.col) _emit(lx, tok) else: - # 逻辑换行 + # Logical new line tok: Token | t.CPtr = new_token(lx.pool, TokenType.NewLine, lx.lineno, lx.col) _emit(lx, tok) lx.at_line_start = 1 @@ -688,30 +689,30 @@ def tokenize(lx: Lexer | t.CPtr) -> Token | t.CPtr: lx.col = 0 continue - # 反斜线续行 + # Backslash continuation line if ch == '\\' and lx.pos + 1 < lx.len and lx.src[lx.pos + 1] == '\n': lx.pos += 2 lx.lineno += 1 lx.col = 0 continue - # 空白 + # Whitespace if _is_space(ch): lx.pos += 1 lx.col += 1 continue - # 注释 + # Comment if ch == '#': while lx.pos < lx.len and lx.src[lx.pos] != '\n': lx.pos += 1 continue - # 字符串前缀(如 r"...")或字符串 + # String prefixes (like r"...") or strings if ch == '\'' or ch == '"': _read_string(lx) continue - # 字符串前缀字母后跟引号(必须在 _is_alpha 之前检测,否则 f/r/b/u 会被当作 TokenType.Name) + # A string prefix letter followed by a quote (must be checked before _is_alpha, otherwise f/r/b/u will be treated as TokenType.Name) if (ch == 'r' or ch == 'R' or ch == 'b' or ch == 'B' or ch == 'u' or ch == 'U' or ch == 'f' or ch == 'F'): if lx.pos + 1 < lx.len: @@ -719,7 +720,7 @@ def tokenize(lx: Lexer | t.CPtr) -> Token | t.CPtr: if ch1 == '\'' or ch1 == '"': _read_string(lx) continue - # 双前缀如 rb, br, rf, fr + # Double prefixes like rb, br, rf, fr if lx.pos + 2 < lx.len: ch2: t.CChar = lx.src[lx.pos + 2] if ((ch1 == 'r' or ch1 == 'R' or ch1 == 'b' or ch1 == 'B' or @@ -728,26 +729,26 @@ def tokenize(lx: Lexer | t.CPtr) -> Token | t.CPtr: _read_string(lx) continue - # 标识符/关键字 + # Identifier/keyword if _is_alpha(ch): _read_name(lx) continue - # 数字 + # Number if _is_digit(ch): _read_number(lx) continue - # 运算符 + # Operator _read_operator(lx) - # 文件结尾:产生 TokenType.NewLine(如果有内容) + # End of file: generate TokenType.NewLine (if there's content) if lx.tokens_tail != None: if lx.tokens_tail.type != TokenType.NewLine and lx.tokens_tail.type != TokenType.Nl: tok: Token | t.CPtr = new_token(lx.pool, TokenType.NewLine, lx.lineno, lx.col) _emit(lx, tok) - # 产生剩余 TokenType.Dedent + # Generate remaining remaining TokenType.Dedent while lx.indent_top > 0: lx.indent_top -= 1 tok: Token | t.CPtr = new_token(lx.pool, TokenType.Dedent, lx.lineno, 0) diff --git a/includes/ast/match.vp b/includes/ast/match.vp index e3df402..7e78378 100644 --- a/includes/ast/match.vp +++ b/includes/ast/match.vp @@ -10,7 +10,7 @@ from .base import ( # ============================================================ -# MatchCase 节点 +# MatchCase 节点Node # ============================================================ class MatchCase(AST): @@ -52,7 +52,7 @@ class MatchCase(AST): # ============================================================ -# MatchValue 节点 +# MatchValue Node # ============================================================ class MatchValue(AST): @@ -85,7 +85,7 @@ class MatchValue(AST): # ============================================================ -# MatchSingleton 节点 +# MatchSingleton Node # ============================================================ class MatchSingleton(AST): @@ -118,7 +118,7 @@ class MatchSingleton(AST): # ============================================================ -# MatchSequence 节点 +# MatchSequence Node # ============================================================ class MatchSequence(AST): @@ -153,7 +153,7 @@ class MatchSequence(AST): # ============================================================ -# MatchMapping 节点 +# MatchMapping Node # ============================================================ class MatchMapping(AST): @@ -201,7 +201,7 @@ class MatchMapping(AST): # ============================================================ -# MatchClass 节点 +# MatchClass Node # ============================================================ class MatchClass(AST): @@ -258,7 +258,7 @@ class MatchClass(AST): # ============================================================ -# MatchStar 节点 +# MatchStar Node # ============================================================ class MatchStar(AST): @@ -290,7 +290,7 @@ class MatchStar(AST): # ============================================================ -# MatchAs 节点 +# MatchAs Node # ============================================================ class MatchAs(AST): @@ -329,7 +329,7 @@ class MatchAs(AST): # ============================================================ -# MatchOr 节点 +# MatchOr Node # ============================================================ class MatchOr(AST): diff --git a/includes/ast/parser.vp b/includes/ast/parser.vp index 1fc6a7f..a4f09b2 100644 --- a/includes/ast/parser.vp +++ b/includes/ast/parser.vp @@ -34,14 +34,14 @@ from .lexer import Lexer, _lexer_init, tokenize, new_lexer # ============================================================ -# Parser 状态 +# Parser State # ============================================================ class Parser: - tokens: Token | t.CPtr # token 链表头 - cur: Token | t.CPtr # 当前 token - pool: memhub.MemManager | t.CPtr # 内存池 - error_count: t.CInt # 错误计数 - pending_decorators: list[AST | t.CPtr] | t.CPtr # 待处理的装饰器 list + tokens: Token | t.CPtr # token linked list head + cur: Token | t.CPtr # current token + pool: memhub.MemManager | t.CPtr # memory pool + error_count: t.CInt # error count + pending_decorators: list[AST | t.CPtr] | t.CPtr # pending decorators list def __new__(self, pool: memhub.MemManager | t.CPtr): ptr: Parser | t.CPtr = pool.alloc(Parser.__sizeof__()) @@ -51,7 +51,7 @@ class Parser: def new_parser(pool: memhub.MemManager | t.CPtr) -> Parser | t.CPtr: - """从 pool 分配并返回 Parser(跨模块安全包装)""" + """Allocate from the pool and return the Parser (cross-module safe wrapper)""" return Parser(pool) @@ -66,11 +66,11 @@ def _parser_init(ps: Parser | t.CPtr, tokens: Token | t.CPtr, # ============================================================ -# Token 导航辅助 +# Token Navigation Helpers # ============================================================ def _advance(ps: Parser | t.CPtr): - """前进到下一个 token""" + """Advance to the next token""" if ps.cur is None: return if ps.cur.next is not None: ps.cur = ps.cur.next @@ -107,13 +107,13 @@ def _cur_col(ps: Parser | t.CPtr) -> t.CInt: def _skip_nl(ps: Parser | t.CPtr): - """跳过 TokenType.Nl token""" + """Skip TokenType.Nl token""" while ps.cur is not None and ps.cur.type == TokenType.Nl: ps.cur = ps.cur.next def _skip_nls_and_newlines(ps: Parser | t.CPtr): - """跳过 TokenType.Nl 和 TokenType.NewLine(用于续行)""" + """Skip TokenType.Nl and TokenType.NewLine (used for line continuation)""" while ps.cur is not None: if ps.cur.type == TokenType.Nl or ps.cur.type == TokenType.NewLine: ps.cur = ps.cur.next @@ -122,7 +122,7 @@ def _skip_nls_and_newlines(ps: Parser | t.CPtr): def _expect_type(ps: Parser | t.CPtr, ttype: t.CInt) -> t.CInt: - """期望当前 token 是指定类型,是则前进并返回 1,否则返回 0""" + """Expect the current token to be of the specified type, advance and return 1, otherwise return 0""" if _cur_type(ps) == ttype: _advance(ps) return 1 @@ -131,7 +131,7 @@ def _expect_type(ps: Parser | t.CPtr, ttype: t.CInt) -> t.CInt: def _expect_op(ps: Parser | t.CPtr, op_id: t.CInt) -> t.CInt: - """期望当前是某个运算符""" + """Expecting the current one to be some operator""" if _cur_type(ps) == TokenType.Op and _cur_op(ps) == op_id: _advance(ps) return 1 @@ -140,14 +140,14 @@ def _expect_op(ps: Parser | t.CPtr, op_id: t.CInt) -> t.CInt: def _match_op(ps: Parser | t.CPtr, op_id: t.CInt) -> t.CInt: - """检查但不消耗""" + """Check but not consume the current token""" if _cur_type(ps) == TokenType.Op and _cur_op(ps) == op_id: return 1 return 0 def _accept_op(ps: Parser | t.CPtr, op_id: t.CInt) -> t.CInt: - """如果匹配则消耗并返回 1""" + """If match, consume and return 1""" if _match_op(ps, op_id): _advance(ps) return 1 @@ -155,7 +155,7 @@ def _accept_op(ps: Parser | t.CPtr, op_id: t.CInt) -> t.CInt: # ============================================================ -# 常量构造辅助(新 API:Constant 直接接受 lineno/col) +# Constant Construction Helper (New API: Constant directly accepts lineno/col) # ============================================================ def _new_const_int(pool: memhub.MemManager | t.CPtr, val: t.CInt64T, @@ -173,26 +173,26 @@ def _new_const_str(pool: memhub.MemManager | t.CPtr, val: str, is_dquote: t.CInt = 1, is_triple: t.CInt = 0, is_char: t.CInt = 0) -> AST | t.CPtr: - """创建字符串/字符常量节点 + """Create a string/character constant node - is_dquote: 0=单引号, 非0=双引号(默认双引号) - is_triple: 非0=三引号字符串 - is_char: 非0=单字符候选(lexer 已确认转义后正好 1 字节, 含 '\\0') - 语义区分: - - 'x' (单引号单字符, 非三引号) → CONST_CHAR (i8 值) - - "x" (双引号, 含\\0终止符) → CONST_STR (i8* 指针, i8 x 2) - - 'ab' (单引号多字符) → CONST_STR (i8* 指针) - - '''x''' / \"\"\"x\"\"\" (三引号) → CONST_STR (i8* 指针) - - '' / \"\" (空字符串) → CONST_STR (i8* 指针) + is_dquote: 0 = single quote, non-0 = double quote (default double quote) + is_triple: non-0 = triple-quoted string + is_char: non-0 = single-character candidate (lexer has confirmed that after escaping it's exactly 1 byte, including '0') + Semantic distinctions: + - 'x' (single quote, single character, not triple-quoted) → CONST_CHAR (i8 value) + - "x" (double quote, includes 0 terminator) → CONST_STR (i8* pointer, i8 x 2) + - 'ab' (single quotes, multiple characters) → CONST_STR (i8* pointer) + - '''x''' / \"\"\"x\"\"\" (triple quotes) → CONST_STR (i8* pointer) + - '' / "" (empty string) → CONST_STR (i8* pointer) """ - # 单引号、非三引号、lexer 标记的单字符候选 → CONST_CHAR - # 用 is_char 标记而非 strlen(val),因为 '\0' 转义后是 NUL 字节,strlen 会返回 0 + # Single quotes, non-triple quotes, single-character candidates marked by lexer → CONST_CHAR + # Mark with is_char instead of strlen(val), because '0' becomes a NUL byte after escaping, strlen would return 0 if is_dquote == 0 and is_triple == 0 and is_char != 0: - # 单字符 → CONST_CHAR,int_val 存储字符 ASCII 值 - # val[0] 即使是 NUL 也是合法值 0 + # Single quote # Single character → CONST_CHAR, int_val stores the character's ASCII value + # val[0] is a legal value of 0 even if it's NUL ch_val: t.CInt64T = val[0] return Constant(pool, CONST_CHAR, ch_val, 0.0, val, lineno, col) - # 其他情况 → CONST_STR + # Other situations → CONST_STR return Constant(pool, CONST_STR, 0, 0.0, val, lineno, col) @@ -207,11 +207,11 @@ def _new_const_none(pool: memhub.MemManager | t.CPtr, # ============================================================ -# ctx 辅助(递归修正赋值目标的 ctx) +# ctx Helper (Recursive Fixing Store Context) # ============================================================ def _set_ctx(node: AST | t.CPtr, ctx: t.CInt): - """设置节点的 ctx 字段(按 kind 转型后赋值)""" + """Set ctx field of node (based on kind conversion)""" if node is None: return k: t.CInt = node.kind() if k == ASTKind.Name: @@ -235,7 +235,7 @@ def _set_ctx(node: AST | t.CPtr, ctx: t.CInt): def _fix_store_ctx(node: AST | t.CPtr): - """递归修正赋值目标的 ctx 为 Store""" + """Fix ctx of store targets to be Store""" if node is None: return _set_ctx(node, ASTCtx.Store) k: t.CInt = node.kind() @@ -260,7 +260,7 @@ def _fix_store_ctx(node: AST | t.CPtr): # ============================================================ -# 表达式解析 +# Expression Parser # ============================================================ def _parse_expr(ps: Parser | t.CPtr) -> AST | t.CPtr: @@ -371,8 +371,8 @@ def _parse_not_test(ps: Parser | t.CPtr) -> AST | t.CPtr: def _parse_comparison(ps: Parser | t.CPtr) -> AST | t.CPtr: """comparison: bitor_expr (comp_op bitor_expr)* - 单比较设计:a < b → Compare(left=a, op=Lt, right=b) - 链式比较 a < b < c → BoolOp(And, [Compare(a,<,b), Compare(b,<,c)]) + Single comparison design: a < b → Compare(left=a, op=Lt, right=b) + Chained comparison a < b < c → BoolOp(And, [Compare(a,<,b), Compare(b,<,c)]) """ left: AST | t.CPtr = _parse_bitor(ps) if left is None: return None @@ -382,7 +382,7 @@ def _parse_comparison(ps: Parser | t.CPtr) -> AST | t.CPtr: return left _advance_comp_op(ps) right: AST | t.CPtr = _parse_bitor(ps) - # 单比较:构造 ops 和 comparators list + # Single comparison: construct ops and comparators list ops: list[t.CInt] | t.CPtr = list[t.CInt](ps.pool, 8) ops.append(op_id) comparators: list[AST | t.CPtr] | t.CPtr = list[AST | t.CPtr](ps.pool, 8) @@ -390,12 +390,12 @@ def _parse_comparison(ps: Parser | t.CPtr) -> AST | t.CPtr: first_cmp: AST | t.CPtr = Compare(ps.pool, left, ops, comparators) _set_pos(first_cmp, left.lineno, left.col_offset, 0, 0) - # 检查链式比较 + # Check chained comparison next_op: t.CInt = _match_comp_op(ps) if next_op == OpKind.NoneOp: return first_cmp - # 链式:a < b < c → BoolOp(And, [Compare(a,<,b), Compare(b,<,c), ...]) + # Single comparison with chained conditions: a < b < c → BoolOp(And, [Compare(a,<,b), Compare(b,<,c), ...]) values: list[AST | t.CPtr] | t.CPtr = list[AST | t.CPtr](ps.pool, 8) values.append(first_cmp) cur_left: AST | t.CPtr = right @@ -417,7 +417,7 @@ def _parse_comparison(ps: Parser | t.CPtr) -> AST | t.CPtr: def _match_comp_op(ps: Parser | t.CPtr) -> t.CInt: - """检查当前是否是比较运算符,返回 OP_* 或 OpKind.NoneOp""" + """Check if the current one is a comparison operator, return OP_* or OpKind.NoneOp""" if _cur_type(ps) == TokenType.Op: op_id: t.CInt = _cur_op(ps) if op_id == TokOp.EqEq: return OpKind.Eq @@ -439,7 +439,7 @@ def _match_comp_op(ps: Parser | t.CPtr) -> t.CInt: def _advance_comp_op(ps: Parser | t.CPtr): - """消耗比较运算符 token""" + """Consume comparison operator token""" if _cur_type(ps) == TokenType.Op: _advance(ps) return @@ -595,7 +595,7 @@ def _parse_atom_expr(ps: Parser | t.CPtr) -> AST | t.CPtr: return node base: AST | t.CPtr = _parse_atom(ps) if base is None: return None - # trailer 循环 + # trailer loop while True: if _match_op(ps, TokOp.Dot): _advance(ps) @@ -623,11 +623,11 @@ def _parse_atom_expr(ps: Parser | t.CPtr) -> AST | t.CPtr: def _parse_call(ps: Parser | t.CPtr, func: AST | t.CPtr) -> AST | t.CPtr: - """解析函数调用 trailer。args 和 keywords 均为 list。""" + """Parse function call trailer. Both args and keywords are lists.""" lineno: t.CInt = _cur_lineno(ps) col: t.CInt = _cur_col(ps) _advance(ps) # ( - _skip_nls_and_newlines(ps) # 跳过 ( 后的换行 + _skip_nls_and_newlines(ps) # Skip the line break after '(' args: list[AST | t.CPtr] | t.CPtr = list[AST | t.CPtr](ps.pool, 8) keywords: list[AST | t.CPtr] | t.CPtr = list[AST | t.CPtr](ps.pool, 8) @@ -668,11 +668,11 @@ def _parse_call(ps: Parser | t.CPtr, func: AST | t.CPtr) -> AST | t.CPtr: else: val = _parse_expr(ps) args.append(val) - _skip_nls_and_newlines(ps) # 跳过参数后的换行 + _skip_nls_and_newlines(ps) # Skip the line break after the parameter if not _accept_op(ps, TokOp.Comma): break - _skip_nls_and_newlines(ps) # 跳过逗号后的换行 - _skip_nls_and_newlines(ps) # 跳过 ) 前的换行 + _skip_nls_and_newlines(ps) # Skip the line break after the comma + _skip_nls_and_newlines(ps) # Skip the line break before ')' _expect_op(ps, TokOp.RPar) node: AST | t.CPtr = Call(ps.pool, func, args, keywords) _set_pos(node, lineno, col, 0, 0) @@ -680,7 +680,7 @@ def _parse_call(ps: Parser | t.CPtr, func: AST | t.CPtr) -> AST | t.CPtr: def _parse_subscript(ps: Parser | t.CPtr, value: AST | t.CPtr) -> AST | t.CPtr: - """解析下标 trailer""" + """Parse subscript trailer.""" lineno: t.CInt = _cur_lineno(ps) col: t.CInt = _cur_col(ps) _advance(ps) # [ @@ -696,19 +696,19 @@ def _parse_subscript(ps: Parser | t.CPtr, value: AST | t.CPtr) -> AST | t.CPtr: def _parse_slice(ps: Parser | t.CPtr) -> AST | t.CPtr: - """解析 slice:[expr] ':' [expr] [':' [expr]] | expr | expr, expr, ...""" + """Parse slice: [expr] ':' [expr] [':' [expr]] | expr | expr, expr, ...""" lower: AST | t.CPtr = None if not _match_op(ps, TokOp.Colon): lower = _parse_expr(ps) - # 检查是否有逗号(元组语法: a[x, y, ...]) + # Check if there’s a comma (tuple syntax: a[x, y, ...]) if _match_op(ps, TokOp.Comma): elts: list[AST | t.CPtr] | t.CPtr = list[AST | t.CPtr](ps.pool, 8) if lower is not None: elts.append(lower) while _accept_op(ps, TokOp.Comma): if _match_op(ps, TokOp.Rsqb): - break # 尾随逗号 + break # Trailing comma elem: AST | t.CPtr = _parse_expr(ps) if elem is not None: elts.append(elem) @@ -742,7 +742,7 @@ def _parse_slice(ps: Parser | t.CPtr) -> AST | t.CPtr: def _parse_atom(ps: Parser | t.CPtr) -> AST | t.CPtr: - """atom: 最小表达式单元""" + """atom: the smallest unit of expression""" ttype: t.CInt = _cur_type(ps) lineno: t.CInt = _cur_lineno(ps) col: t.CInt = _cur_col(ps) @@ -798,14 +798,14 @@ def _parse_atom(ps: Parser | t.CPtr) -> AST | t.CPtr: def _parse_paren(ps: Parser | t.CPtr) -> AST | t.CPtr: - """括号表达式: () | (expr) | (expr,) | (expr, ...) | (yield)""" + """Parenthesis expressions: () | (expr) | (expr,) | (expr, ...) | (yield)""" lineno: t.CInt = _cur_lineno(ps) col: t.CInt = _cur_col(ps) _advance(ps) # ( - _skip_nl(ps) # 跳过 ( 后的换行(多行元组) + _skip_nl(ps) # Skip the line break after '(' (multi-line tuple) if _match_op(ps, TokOp.RPar): _advance(ps) - # 空元组 + # Empty tuple empty: list[AST | t.CPtr] | t.CPtr = list[AST | t.CPtr](ps.pool, 8) node: AST | t.CPtr = Tuple(ps.pool, empty, ASTCtx.Load) _set_pos(node, lineno, col, 0, 0) @@ -817,7 +817,7 @@ def _parse_paren(ps: Parser | t.CPtr) -> AST | t.CPtr: return y first: AST | t.CPtr = _parse_expr(ps) if _match_op(ps, TokOp.Comma): - # 元组 + # Tuple elts: list[AST | t.CPtr] | t.CPtr = list[AST | t.CPtr](ps.pool, 8) elts.append(first) while _accept_op(ps, TokOp.Comma): @@ -831,18 +831,18 @@ def _parse_paren(ps: Parser | t.CPtr) -> AST | t.CPtr: _set_pos(node, lineno, col, 0, 0) return node _expect_op(ps, TokOp.RPar) - # 检查推导式 + # Check for generator expression if _cur_kw(ps) == Keyword.For: return _parse_comprehension(ps, first, ASTKind.GeneratorExp, lineno, col) return first def _parse_list(ps: Parser | t.CPtr) -> AST | t.CPtr: - """列表: [] | [expr_list] | [expr_list comp_for]""" + """List expressions: [] | [expr_list] | [expr_list comp_for]""" lineno: t.CInt = _cur_lineno(ps) col: t.CInt = _cur_col(ps) _advance(ps) # [ - _skip_nl(ps) # 跳过 [ 后的换行(多行列表) + _skip_nl(ps) # Skip the line break after '[' (multi-line list) if _match_op(ps, TokOp.Rsqb): _advance(ps) empty: list[AST | t.CPtr] | t.CPtr = list[AST | t.CPtr](ps.pool, 8) @@ -869,11 +869,11 @@ def _parse_list(ps: Parser | t.CPtr) -> AST | t.CPtr: def _parse_brace(ps: Parser | t.CPtr) -> AST | t.CPtr: - """花括号: {} | {set_items} | {dict_items} | {comp_for}""" + """Brace expressions: {} | {set_items} | {dict_items} | {comp_for}""" lineno: t.CInt = _cur_lineno(ps) col: t.CInt = _cur_col(ps) _advance(ps) # { - _skip_nl(ps) + _skip_nl(ps) # Skip the line break after '{' (multi-line dict) if _match_op(ps, TokOp.RBrace): _advance(ps) empty_k: list[AST | t.CPtr] | t.CPtr = list[AST | t.CPtr](ps.pool, 8) @@ -929,11 +929,11 @@ def _parse_brace(ps: Parser | t.CPtr) -> AST | t.CPtr: # ============================================================ -# f-string 解析 +# f-string parsing # ============================================================ def _parse_sub_expr(ps: Parser | t.CPtr, src: str) -> AST | t.CPtr: - """创建子 lexer + parser 解析表达式(用于 f-string 内的 {expr})""" + """Create a sub-lexer and parser to parse expressions (used for {expr} inside f-strings)""" pool: memhub.MemManager | t.CPtr = ps.pool lx: Lexer | t.CPtr = new_lexer(pool) if lx is None: return None @@ -948,12 +948,12 @@ def _parse_sub_expr(ps: Parser | t.CPtr, src: str) -> AST | t.CPtr: def _parse_fstring(ps: Parser | t.CPtr, content: str, lineno: t.CInt, col: t.CInt) -> AST | t.CPtr: - """解析 f-string 内容,构建 JoinedStr 或 FormattedValue。""" + """Parse f-string content, building JoinedStr or FormattedValue nodes""" pool: memhub.MemManager | t.CPtr = ps.pool values: list[AST | t.CPtr] | t.CPtr = list[AST | t.CPtr](pool, 8) i: t.CSizeT = 0 content_len: t.CSizeT = string.strlen(content) - # 字面量文本缓冲区 + # Literal text buffer for f-string content lit_buf: str = pool.alloc(content_len + 1) if lit_buf is None: return None lit_pos: t.CSizeT = 0 @@ -961,13 +961,13 @@ def _parse_fstring(ps: Parser | t.CPtr, content: str, while i < content_len: ch: t.CChar = content[i] if ch == '{': - # {{ → 字面量 { + # {{ → Literal { if i + 1 < content_len and content[i + 1] == '{': lit_buf[lit_pos] = '{' lit_pos += 1 i += 2 continue - # 刷新字面量缓冲区 + # Refresh literal buffer if lit_pos > 0: lit_buf[lit_pos] = '\0' lit_node: AST | t.CPtr = _new_const_str(pool, lit_buf, lineno, col) @@ -975,7 +975,7 @@ def _parse_fstring(ps: Parser | t.CPtr, content: str, lit_buf = pool.alloc(content_len + 1) if lit_buf is None: break lit_pos = 0 - # 查找匹配的 },同时跟踪嵌套 {} 和字符串字面量 + # Find matching closing '}' while tracking nested '{}' and string literals inside the f-string j: t.CSizeT = i + 1 depth: t.CInt = 1 conv_pos: t.CSizeT = 0 @@ -1005,7 +1005,7 @@ def _parse_fstring(ps: Parser | t.CPtr, content: str, if depth != 0: ps.error_count += 1 break - # 提取表达式文本 + # Extract expression text expr_end: t.CSizeT = j if conv_pos > 0: expr_end = conv_pos @@ -1020,9 +1020,9 @@ def _parse_fstring(ps: Parser | t.CPtr, content: str, if expr_buf is None: break string.memcpy(expr_buf, content + i + 1, expr_len) expr_buf[expr_len] = '\0' - # 解析表达式 + # Parse expression text expr_node: AST | t.CPtr = _parse_sub_expr(ps, expr_buf) - # 转换符 + # Conversion specifier conversion: t.CInt = -1 if conv_pos > 0: conv_char: t.CChar = content[conv_pos + 1] @@ -1032,7 +1032,7 @@ def _parse_fstring(ps: Parser | t.CPtr, content: str, conversion = 114 elif conv_char == 'a': conversion = 97 - # 格式说明符 + # Format specifier format_spec: AST | t.CPtr = None if fmt_pos > 0: spec_len: t.CSizeT = j - fmt_pos - 1 @@ -1059,16 +1059,16 @@ def _parse_fstring(ps: Parser | t.CPtr, content: str, lit_pos += 1 i += 1 - # 刷新剩余字面量 + # Refresh remaining literal buffer if lit_pos > 0: lit_buf[lit_pos] = '\0' lit_node2: AST | t.CPtr = _new_const_str(pool, lit_buf, lineno, col) values.append(lit_node2) - # 如果没有内容,返回空字符串 + # If no content, return empty string if values.__len__() == 0: return _new_const_str(pool, "", lineno, col) - # 如果只有一个 FormattedValue 且无字面量,返回 FormattedValue + # If only one FormattedValue and no literal, return FormattedValue if values.__len__() == 1: first: AST | t.CPtr = values.get(0) if first.kind() == ASTKind.FormattedValue: @@ -1080,7 +1080,7 @@ def _parse_fstring(ps: Parser | t.CPtr, content: str, def _parse_comprehension(ps: Parser | t.CPtr, elt: AST | t.CPtr, vtype: t.CInt, lineno: t.CInt, col: t.CInt) -> AST | t.CPtr: - """通用推导式:elt comp_for""" + """General comprehension: elt comp_for""" gens: list[AST | t.CPtr] | t.CPtr = _parse_comp_for(ps) node: AST | t.CPtr = None if vtype == ASTKind.ListComp: @@ -1095,7 +1095,7 @@ def _parse_comprehension(ps: Parser | t.CPtr, elt: AST | t.CPtr, def _parse_comp_for(ps: Parser | t.CPtr) -> list[AST | t.CPtr] | t.CPtr: """comp_for: ['async'] 'for' exprlist 'in' or_test [comp_if] (comp_for)* - 返回 generators list。""" + Returns generators list。""" gens: list[AST | t.CPtr] | t.CPtr = list[AST | t.CPtr](ps.pool, 8) while True: is_async: t.CInt = 0 @@ -1113,7 +1113,7 @@ def _parse_comp_for(ps: Parser | t.CPtr) -> list[AST | t.CPtr] | t.CPtr: break _advance(ps) iter_: AST | t.CPtr = _parse_or_test(ps) - # 收集 ifs 到 list + # Collect ifs to list ifs: list[AST | t.CPtr] | t.CPtr = list[AST | t.CPtr](ps.pool, 8) while _cur_kw(ps) == Keyword.If: _advance(ps) @@ -1126,7 +1126,7 @@ def _parse_comp_for(ps: Parser | t.CPtr) -> list[AST | t.CPtr] | t.CPtr: def _parse_target_list(ps: Parser | t.CPtr) -> AST | t.CPtr: - """解析赋值目标列表(用逗号分隔)""" + """Parse assignment target list (comma-separated)""" first: AST | t.CPtr = _parse_target(ps) if _match_op(ps, TokOp.Comma): elts: list[AST | t.CPtr] | t.CPtr = list[AST | t.CPtr](ps.pool, 8) @@ -1143,7 +1143,7 @@ def _parse_target_list(ps: Parser | t.CPtr) -> AST | t.CPtr: def _parse_target(ps: Parser | t.CPtr) -> AST | t.CPtr: - """解析单个赋值目标""" + """Parse assignment target""" if _match_op(ps, TokOp.Star): _advance(ps) inner: AST | t.CPtr = _parse_atom_expr(ps) @@ -1173,7 +1173,7 @@ def _parse_target(ps: Parser | t.CPtr) -> AST | t.CPtr: node = List(ps.pool, elts, ASTCtx.Store) _set_pos(node, first.lineno, first.col_offset, 0, 0) return node - # 普通 atom_expr,但 ctx=Store + # Normal atom_expr, ctx=Store node = _parse_atom_expr(ps) if node is not None: _set_ctx(node, ASTCtx.Store) @@ -1202,8 +1202,8 @@ def _parse_yield(ps: Parser | t.CPtr) -> AST | t.CPtr: def _parse_varargslist(ps: Parser | t.CPtr, is_lambda: t.CInt = 0) -> AST | t.CPtr: - """函数参数列表解析(lambda 和 def 共用) - 新 API:args/defaults/kw_defaults 为 list,vararg/kwarg 为字段。""" + """Parse function parameter list + New API: args/defaults/kw_defaults are lists, vararg/kwarg are fields.""" args: list[AST | t.CPtr] | t.CPtr = list[AST | t.CPtr](ps.pool, 8) vararg: AST | t.CPtr = None kwarg: AST | t.CPtr = None @@ -1214,7 +1214,7 @@ def _parse_varargslist(ps: Parser | t.CPtr, is_lambda: t.CInt = 0) -> AST | t.CP _skip_nl(ps) if _match_op(ps, TokOp.RPar): break - # *args 或 * (kwonly 分隔) + # *args 或 * (kwonly separated) if _match_op(ps, TokOp.Star): _advance(ps) _skip_nl(ps) @@ -1233,14 +1233,14 @@ def _parse_varargslist(ps: Parser | t.CPtr, is_lambda: t.CInt = 0) -> AST | t.CP break _skip_nl(ps) continue - # / 分隔符(posonly 结束)— 新 API 中 posonly/regular 不区分 + # / Delimiter (posonly end)— New API: posonly/regular are not distinguished if _match_op(ps, TokOp.Slash): _advance(ps) if not _accept_op(ps, TokOp.Comma): break _skip_nl(ps) continue - # 普通参数 + # Normal parameter a: AST | t.CPtr = _parse_arg_def(ps, is_lambda) if a is None: break args.append(a) @@ -1273,11 +1273,11 @@ def _parse_arg_def(ps: Parser | t.CPtr, is_lambda: t.CInt = 0) -> AST | t.CPtr: # ============================================================ -# 语句解析(设计:直接 append 到 parent,不返回 list) +# Statement parsing (Design: directly append to parent, do not return a list) # ============================================================ def _parse_suite_into_children(ps: Parser | t.CPtr, parent: AST | t.CPtr): - """解析语句块,直接 append 为 parent 的子节点。 + """Parse statement suite, directly append to parent's children. suite: TokenType.NewLine TokenType.Indent stmt+ TokenType.Dedent | simple_stmt""" _skip_nl(ps) if _cur_type(ps) == TokenType.NewLine: @@ -1290,24 +1290,24 @@ def _parse_suite_into_children(ps: Parser | t.CPtr, parent: AST | t.CPtr): sidx: t.CInt = 0 while _cur_type(ps) != TokenType.Dedent and _cur_type(ps) != TokenType.EndMarker: sidx += 1 - # 装饰器(类体内方法也可以有装饰器) + # Decorator (class body methods can have decorators) if _match_op(ps, TokOp.At): ps.pending_decorators = _parse_decorators(ps) before_cur: Token | t.CPtr = ps.cur _parse_statement_into(ps, parent) - # 防御:若解析未前进 token,强制前进以避免死循环 + # Defensive: if parse did not advance token, force advance to avoid infinite loop if ps.cur is before_cur: ps.error_count += 1 _advance(ps) _skip_nl(ps) _expect_type(ps, TokenType.Dedent) return - # 单行 suite + # Single-line suite _parse_simple_stmt_into(ps, parent) def _parse_statement_into(ps: Parser | t.CPtr, parent: AST | t.CPtr): - """解析一条语句(复合或简单),append 到 parent。""" + """Parse statement (compound or simple), append to the parent.""" ttype: t.CInt = _cur_type(ps) kw: t.CInt = _cur_kw(ps) if ttype == TokenType.Name: @@ -1346,7 +1346,7 @@ def _parse_simple_stmt_into(ps: Parser | t.CPtr, parent: AST | t.CPtr): def _parse_small_stmt(ps: Parser | t.CPtr) -> AST | t.CPtr: - """small_stmt: 各种简单语句""" + """small_stmt: various simple statements""" kw: t.CInt = _cur_kw(ps) if kw == Keyword.Pass: lineno: t.CInt = _cur_lineno(ps) @@ -1387,12 +1387,12 @@ def _parse_small_stmt(ps: Parser | t.CPtr) -> AST | t.CPtr: return _parse_assert(ps) if kw == Keyword.Yield: return _parse_expr_stmt(ps, _parse_yield(ps)) - # 表达式语句 / 赋值 / augassign / annassign + # Expression statement / assignment / augassign / annassign return _parse_expr_stmt(ps, None) def _maybe_tuple(ps: Parser | t.CPtr, first: AST | t.CPtr) -> AST | t.CPtr: - """如果 first 后面有逗号,收集逗号分隔的表达式为 Tuple。""" + """If there is a comma after first, collect the comma-separated expressions into a Tuple.""" if first is None: return None if not _match_op(ps, TokOp.Comma): return first @@ -1420,13 +1420,13 @@ def _maybe_tuple(ps: Parser | t.CPtr, first: AST | t.CPtr) -> AST | t.CPtr: def _parse_testlist(ps: Parser | t.CPtr) -> AST | t.CPtr: - """解析逗号分隔的表达式列表,多于1个则形成 Tuple。""" + """Parse a comma-separated list of expressions, if there’s more than one, form a tuple.""" first: AST | t.CPtr = _parse_expr(ps) return _maybe_tuple(ps, first) def _parse_expr_stmt(ps: Parser | t.CPtr, first: AST | t.CPtr) -> AST | t.CPtr: - """表达式语句,处理赋值/augassign/annassign""" + """Expression statement, handle assignment/augassign/annassign""" if first is None: first = _parse_testlist(ps) else: @@ -1435,7 +1435,7 @@ def _parse_expr_stmt(ps: Parser | t.CPtr, first: AST | t.CPtr) -> AST | t.CPtr: return None lineno: t.CInt = first.lineno col: t.CInt = first.col_offset - # 赋值 + # Assignment if _match_op(ps, TokOp.Equal): targets: list[AST | t.CPtr] | t.CPtr = list[AST | t.CPtr](ps.pool, 8) targets.append(first) @@ -1479,7 +1479,7 @@ def _parse_expr_stmt(ps: Parser | t.CPtr, first: AST | t.CPtr) -> AST | t.CPtr: node3: AST | t.CPtr = AnnAssign(ps.pool, first, annotation, value3, 1) _set_pos(node3, lineno, col, 0, 0) return node3 - # 表达式语句 + # Expression statement node4: AST | t.CPtr = Expr(ps.pool, first) _set_pos(node4, lineno, col, 0, 0) return node4 @@ -1571,7 +1571,7 @@ def _parse_from_import(ps: Parser | t.CPtr) -> AST | t.CPtr: lineno: t.CInt = _cur_lineno(ps) col: t.CInt = _cur_col(ps) _advance(ps) - # 解析 module(可能带点号) + # Parse module (possibly with dots) level: t.CInt = 0 while _match_op(ps, TokOp.Dot): level += 1 @@ -1580,9 +1580,12 @@ def _parse_from_import(ps: Parser | t.CPtr) -> AST | t.CPtr: level += 3 _advance(ps) module_name: str = None - # 关键字(如 import)的 token type 也是 Name,必须通过 kw_subtype 排除, - # 否则 `from . import` 中的 `import` 会被误认为 module_name - if _cur_type(ps) == TokenType.Name and _cur_kw(ps) == Keyword.NotKeyword: + # The token type for keywords (like import) is also Name, so they must be excluded using kw_subtype, + # otherwise the `import` in `from . import` would be mistakenly treated as a module_name. + # Note: only `import` itself should be excluded. Module names can be keywords (like in `from .match import ...`, + # where match is a Viper match statement keyword), requiring NotKeyword would cause + # `from .match import` to fail parsing and the dependency scan would miss that module. + if _cur_type(ps) == TokenType.Name and _cur_kw(ps) != Keyword.Import: module_name = _cur_str(ps) _advance(ps) while _match_op(ps, TokOp.Dot): @@ -1628,7 +1631,7 @@ def _parse_from_import(ps: Parser | t.CPtr) -> AST | t.CPtr: def _parse_alias_list(ps: Parser | t.CPtr) -> list[AST | t.CPtr] | t.CPtr: - """返回 alias list。""" + """Parse alias list.""" names: list[AST | t.CPtr] | t.CPtr = list[AST | t.CPtr](ps.pool, 8) while True: if _cur_type(ps) != TokenType.Name: @@ -1697,7 +1700,7 @@ def _parse_assert(ps: Parser | t.CPtr) -> AST | t.CPtr: # ============================================================ -# 复合语句 +# Compound statements # ============================================================ def _parse_compound(ps: Parser | t.CPtr) -> AST | t.CPtr: @@ -1738,7 +1741,7 @@ def _parse_if(ps: Parser | t.CPtr) -> AST | t.CPtr: _advance(ps) # if test: AST | t.CPtr = _parse_test(ps) _expect_op(ps, TokOp.Colon) - # 先用空 orelse 构造,后面填充 + # First construct with empty orelse, then fill it in later empty: list[AST | t.CPtr] | t.CPtr = list[AST | t.CPtr](ps.pool, 8) node: If | t.CPtr = If(ps.pool, test, empty) _parse_suite_into_children(ps, node) @@ -1779,7 +1782,7 @@ def _parse_if_tail(ps: Parser | t.CPtr) -> list[AST | t.CPtr] | t.CPtr: # ============================================================ -# 复合语句解析(续) +# Parsing Compound Statements (Continued) # ============================================================ def _parse_while(ps: Parser | t.CPtr) -> AST | t.CPtr: @@ -1891,7 +1894,7 @@ def _parse_with(ps: Parser | t.CPtr, is_async: t.CInt) -> AST | t.CPtr: items.append(item) if not _accept_op(ps, TokOp.Comma): break - # 检查是否可以续行(with (...): 形式) + # Check if we can continue with a newline (with (...): form) if _cur_type(ps) == TokenType.NewLine or _cur_type(ps) == TokenType.Nl: break _expect_op(ps, TokOp.Colon) @@ -1951,7 +1954,7 @@ def _parse_classdef(ps: Parser | t.CPtr) -> AST | t.CPtr: return None name: str = _cur_str(ps) _advance(ps) - # 解析类型参数 [T] 或 [T, U](PEP 695 泛型类语法) + # Parse type parameters [T] or [T, U] (PEP 695 generic class syntax) type_params: list[str] | t.CPtr = None if _accept_op(ps, TokOp.Lsqb): type_params = list[str](ps.pool, 8) @@ -1960,7 +1963,7 @@ def _parse_classdef(ps: Parser | t.CPtr) -> AST | t.CPtr: if _cur_type(ps) == TokenType.Name: tp_name: str = _cur_str(ps) _advance(ps) - # 跳过可选的 bound/constraint: [T: bound] 或 [T: (A, B)] + # Skip optional bound/constraint: [T: bound] or [T: (A, B)] if _match_op(ps, TokOp.Colon): _advance(ps) _parse_test(ps) @@ -1976,7 +1979,7 @@ def _parse_classdef(ps: Parser | t.CPtr) -> AST | t.CPtr: if _cur_type(ps) == TokenType.EndMarker: break # base 或 keyword=value if _cur_type(ps) == TokenType.Name: - # 解析为表达式,若后跟 = 则作为 keyword + # Parse as expression, if followed by '=', then as keyword=value e: AST | t.CPtr = _parse_or_test(ps) if _match_op(ps, TokOp.Equal): _advance(ps) @@ -1998,7 +2001,7 @@ def _parse_classdef(ps: Parser | t.CPtr) -> AST | t.CPtr: def _parse_match(ps: Parser | t.CPtr) -> AST | t.CPtr: - """match 语句:match subject ':' NewLine Indent case+ Dedent""" + """match statement: match subject ':' NewLine Indent case+ Dedent""" lineno: t.CInt = _cur_lineno(ps) col: t.CInt = _cur_col(ps) _advance(ps) # match @@ -2006,8 +2009,8 @@ def _parse_match(ps: Parser | t.CPtr) -> AST | t.CPtr: _expect_op(ps, TokOp.Colon) cases: list[AST | t.CPtr] | t.CPtr = list[AST | t.CPtr](ps.pool, 8) node: AST | t.CPtr = Match(ps.pool, subject, cases) - # 解析 body:与 _parse_suite_into_children 相同的 NewLine/Indent/Dedent 模式, - # 但解析 case 子句到 cases 列表而非普通语句到 children + # Parsing body: Same NewLine/Indent/Dedent pattern as _parse_suite_into_children, + # but parses case clauses into a cases list instead of normal statements into children _skip_nl(ps) if _cur_type(ps) == TokenType.NewLine: _advance(ps) @@ -2020,18 +2023,18 @@ def _parse_match(ps: Parser | t.CPtr) -> AST | t.CPtr: if case_node is not None: cases.append(case_node) else: - _advance(ps) # 跳过非 case token,避免死循环 + _advance(ps) # Skip non-case token to avoid infinite loop _expect_type(ps, TokenType.Dedent) _set_pos(node, lineno, col, 0, 0) return node # ============================================================ -# Match pattern 解析 +# Match pattern parsing # ============================================================ def _make_name_ast(pool: memhub.MemManager | t.CPtr, node: Name | t.CPtr) -> AST | t.CPtr: - """将 Name* 转换为 AST*(解决 TransPyC 类型推断问题)""" + # Analysis: "Convert Name* to AST* (Solving the TransPyC Type Inference Problem)" return node @@ -2075,7 +2078,7 @@ def _parse_closed_pattern(ps: Parser | t.CPtr) -> AST | t.CPtr: tok: Token | t.CPtr sval: str - # 数字字面量 pattern + # Number literal pattern if ttype == TokenType.Number: tok = ps.cur _advance(ps) @@ -2087,7 +2090,7 @@ def _parse_closed_pattern(ps: Parser | t.CPtr) -> AST | t.CPtr: _set_pos(node, lineno, col, 0, 0) return node - # 字符串字面量 pattern + # String literal pattern if ttype == TokenType.String: sval = _cur_str(ps) is_dquote_m: t.CInt = ps.cur.kw_subtype & 16 @@ -2097,7 +2100,7 @@ def _parse_closed_pattern(ps: Parser | t.CPtr) -> AST | t.CPtr: _set_pos(node, lineno, col, 0, 0) return node - # 负数字面量 pattern: -1, -1.5 + # Negative number literal pattern: -1, -1.5 if _match_op(ps, TokOp.Minus): _advance(ps) if _cur_type(ps) == TokenType.Number: @@ -2129,14 +2132,14 @@ def _parse_closed_pattern(ps: Parser | t.CPtr) -> AST | t.CPtr: _set_pos(node, lineno, col, 0, 0) return node name_str: str = _cur_str(ps) - # 通配符 _ + # Wildcard pattern: _ if string.strcmp(name_str, "_") == 0: _advance(ps) node = MatchAs(ps.pool, None, None) _set_pos(node, lineno, col, 0, 0) return node _advance(ps) - # 检查 dotted name(value pattern 或 class pattern) + # Check dotted name(value pattern 或 class pattern) if _match_op(ps, TokOp.Dot): name_node: Name | t.CPtr = Name(ps.pool, name_str, ASTCtx.Load) _set_pos(name_node, lineno, col, 0, 0) @@ -2349,7 +2352,7 @@ def _parse_decorators(ps: Parser | t.CPtr) -> list[AST | t.CPtr] | t.CPtr: # ============================================================ -# 模块入口 +# Module entry # ============================================================ def _parse_module_body(ps: Parser | t.CPtr, module_node: AST | t.CPtr): @@ -2358,14 +2361,14 @@ def _parse_module_body(ps: Parser | t.CPtr, module_node: AST | t.CPtr): stmt_idx: t.CInt = 0 while _cur_type(ps) != TokenType.EndMarker: stmt_idx += 1 - # 装饰器 + # Decorator if _match_op(ps, TokOp.At): ps.pending_decorators = _parse_decorators(ps) - # 记录解析前的 token 指针,用于检测未前进的死循环 + # Record current token pointer to check for infinite loop before_cur: Token | t.CPtr = ps.cur _parse_statement_into(ps, module_node) - # 防御:若解析未前进 token(如 _parse_atom 遇到无法识别的 token 返回 None), - # 强制前进以避免主循环死循环;累计 error_count 供调用方诊断 + # Defense: If parsing doesn't advance the token (like when _parse_atom encounters an unrecognized token and returns None), + # force it to move forward to avoid an infinite loop in the main loop; accumulate error_count for the caller to diagnose if ps.cur is before_cur: ps.error_count += 1 _advance(ps) @@ -2374,7 +2377,7 @@ def _parse_module_body(ps: Parser | t.CPtr, module_node: AST | t.CPtr): def parse_tokens(pool: memhub.MemManager | t.CPtr, tokens: Token | t.CPtr) -> AST | t.CPtr: - """从 token 链表解析 AST Module。""" + """Parse an AST Module from a token list.""" if pool is None or tokens is None: return None ps: Parser | t.CPtr = new_parser(pool) diff --git a/includes/ast/stmts.vp b/includes/ast/stmts.vp index 471001e..5c99161 100644 --- a/includes/ast/stmts.vp +++ b/includes/ast/stmts.vp @@ -11,7 +11,7 @@ from .base import ( # ============================================================ -# Module 节点 +# Module Node # ============================================================ @t.CVTable @@ -42,7 +42,7 @@ class Module(AST): # ============================================================ -# Assign 节点 +# Assign Node # ============================================================ class Assign(AST): @@ -84,7 +84,7 @@ class Assign(AST): # ============================================================ -# If 节点 +# If Node # ============================================================ class If(AST): @@ -130,7 +130,7 @@ class If(AST): # ============================================================ -# For 节点 +# For Node # ============================================================ class For(AST): @@ -188,7 +188,7 @@ class For(AST): # ============================================================ -# While 节点 +# While Node # ============================================================ class While(AST): @@ -232,7 +232,7 @@ class While(AST): # ============================================================ -# Return 节点 +# Return Node # ============================================================ class Return(AST): @@ -267,7 +267,7 @@ class Return(AST): # ============================================================ -# Expr 节点(表达式语句) +# Expr Node (expression statement) # ============================================================ class Expr(AST): @@ -302,7 +302,7 @@ class Expr(AST): # ============================================================ -# FunctionDef 节点 +# FunctionDef Node # ============================================================ class FunctionDef(AST): @@ -367,7 +367,7 @@ class FunctionDef(AST): # ============================================================ -# Expression 节点 +# Expression Node # ============================================================ class Expression(AST): @@ -404,7 +404,7 @@ class Expression(AST): # ============================================================ -# Interactive 节点 +# Interactive Node # ============================================================ class Interactive(AST): @@ -441,7 +441,7 @@ class Interactive(AST): # ============================================================ -# FunctionType 节点 +# FunctionType Node # ============================================================ class FunctionType(AST): @@ -484,7 +484,7 @@ class FunctionType(AST): # ============================================================ -# ClassDef 节点 +# ClassDef Node # ============================================================ class ClassDef(AST): @@ -547,7 +547,7 @@ class ClassDef(AST): # ============================================================ -# Delete 节点 +# Delete Node # ============================================================ class Delete(AST): @@ -582,7 +582,7 @@ class Delete(AST): # ============================================================ -# AugAssign 节点 +# AugAssign Node # ============================================================ class AugAssign(AST): @@ -630,7 +630,7 @@ class AugAssign(AST): # ============================================================ -# AnnAssign 节点 +# AnnAssign Node # ============================================================ class AnnAssign(AST): @@ -687,7 +687,7 @@ class AnnAssign(AST): # ============================================================ -# With 节点 +# With Node # ============================================================ class With(AST): @@ -731,7 +731,7 @@ class With(AST): # ============================================================ -# Raise 节点 +# Raise Node # ============================================================ class Raise(AST): @@ -775,7 +775,7 @@ class Raise(AST): # ============================================================ -# Try 节点 +# Try Node # ============================================================ class Try(AST): @@ -827,7 +827,7 @@ class Try(AST): # ============================================================ -# Assert 节点 +# Assert Node # ============================================================ class Assert(AST): @@ -871,7 +871,7 @@ class Assert(AST): # ============================================================ -# Global 节点 +# Global Node # ============================================================ class Global(AST): @@ -906,7 +906,7 @@ class Global(AST): # ============================================================ -# Nonlocal 节点 +# Nonlocal Node # ============================================================ class Nonlocal(AST): @@ -941,7 +941,7 @@ class Nonlocal(AST): # ============================================================ -# Pass 节点 +# Pass Node # ============================================================ class Pass(AST): @@ -969,7 +969,7 @@ class Pass(AST): # ============================================================ -# Break 节点 +# Break Node # ============================================================ class Break(AST): @@ -997,7 +997,7 @@ class Break(AST): # ============================================================ -# Continue 节点 +# Continue Node # ============================================================ class Continue(AST): @@ -1025,7 +1025,7 @@ class Continue(AST): # ============================================================ -# Import 节点 +# Import Node # ============================================================ class Import(AST): @@ -1060,7 +1060,7 @@ class Import(AST): # ============================================================ -# ImportFrom 节点 +# ImportFrom Node # ============================================================ class ImportFrom(AST): @@ -1107,7 +1107,7 @@ class ImportFrom(AST): # ============================================================ -# Match 节点 +# Match Node # ============================================================ class Match(AST): diff --git a/includes/ast/tokens.vp b/includes/ast/tokens.vp index d3a4ea0..c0addb7 100644 --- a/includes/ast/tokens.vp +++ b/includes/ast/tokens.vp @@ -5,8 +5,8 @@ import string # ============================================================ -# Token 类型枚举(参考 CPython Lib/token.py) -# 用 t.CEnum 组织为类型安全枚举;旧名 XXX 保留为兼容别名 +# Token type enumeration (refer to CPython Lib/token.py) +# Organized as a type-safe enum using t.CEnum; old names XXX retained as compatible aliases # ============================================================ class TokenType(t.CEnum): @@ -27,9 +27,9 @@ class TokenType(t.CEnum): # ============================================================ -# 关键字枚举(参考 CPython Lib/keyword.py) -# 用 t.CEnum 组织为类型安全枚举;旧名 KW_XXX 保留为兼容别名 -# NotKeyword(0) 表示非关键字(哨兵,避免 False_=0 与 kw_subtype=0 冲突) +# Keyword enumeration (refer to CPython Lib/keyword.py) +# Organized as a type-safe enum using t.CEnum; old names KW_XXX are kept as compatible aliases +# NotKeyword(0) represents a non-keyword (sentinel to avoid conflict between False_=0 and kw_subtype=0) # ============================================================ class Keyword(t.CEnum): @@ -75,9 +75,9 @@ class Keyword(t.CEnum): # ============================================================ -# 运算符/分隔符枚举 -# 用 t.CEnum 组织为类型安全枚举;旧名 OP_XXX 保留为兼容别名 -# 存储在 token.op_subtype 字段 +# Operator/Separator Enumeration +# Organized as a type-safe enum using t.CEnum; old names OP_XXX retained as compatible aliases +# Stored in the token.op_subtype field # ============================================================ class TokOp(t.CEnum): @@ -128,29 +128,29 @@ class TokOp(t.CEnum): Tilde: t.State # ~ ColonEq: t.State # := Ellipsis: t.State # ... - Bang: t.State # ! (非标准,用于解析容错) + Bang: t.State # !(Non-standard, used for parsing tolerance) # ============================================================ -# Token 结构体 +# Token stucture # ============================================================ class Token: - type: t.CInt # Token 类型(TokenType.EndMarker/TokenType.NewLine/TokenType.Name/...) - op_subtype: t.CInt # 运算符子类型(OP_*),仅 type==TokenType.Op 时有效 - kw_subtype: t.CInt # 关键字子类型(KW_*),仅 type==TokenType.Name 且是关键字时有效 - str_val: str # token 文本(NUL 结尾,从 pool 分配) - int_val: t.CInt64T # 整数值(TokenType.Number 用) - float_val: t.CDouble # 浮点值(TokenType.Number 用) - is_float: t.CInt # 1=浮点数, 0=整数 - is_complex: t.CInt # 1=复数, 0=实数 - lineno: t.CInt # 起始行号 - col_offset: t.CInt # 起始列偏移 - end_lineno: t.CInt # 结束行号 - end_col_offset: t.CInt # 结束列偏移 - next: Token | t.CPtr # 链表下一个 token + type: t.CInt # Token type (TokenType.EndMarker / TokenType.NewLine / TokenType.Name / ...) + op_subtype: t.CInt # Operator subtype (OP_*). Only valid when type == TokenType.Op + kw_subtype: t.CInt # Keyword subtype (KW_*). Only valid when type == TokenType.Name and it is a keyword + str_val: str # Token text (NUL‑terminated, allocated from pool) + int_val: t.CInt64T # Integer value (used by TokenType.Number) + float_val: t.CDouble # Floating‑point value (used by TokenType.Number) + is_float: t.CInt # 1 = floating‑point number, 0 = integer + is_complex: t.CInt # 1 = complex number, 0 = real number + lineno: t.CInt # Starting line number + col_offset: t.CInt # Starting column offset + end_lineno: t.CInt # Ending line number + end_col_offset: t.CInt # Ending column offset + next: Token | t.CPtr # Next token in linked list def __new__(self, pool: memhub.MemManager | t.CPtr): - """从 mpool 分配 Token 结构体内存并零初始化""" + """Allocate zero‑initialized Token struct memory from mpool""" ptr: Token | t.CPtr = pool.alloc(Token.__sizeof__()) if ptr: string.memset(ptr, 0, Token.__sizeof__()) @@ -158,8 +158,8 @@ class Token: # ============================================================ -# 关键字查找表 -# 由于 TransPyC 无 dict 字面量,用链表实现 +# Keyword lookup table +# Since TransPyC has no dict literals, implemented with linked lists # ============================================================ class KwEntry: name: str @@ -173,13 +173,13 @@ class KwEntry: return ptr -# 全局关键字链表头(懒初始化) +# Global keyword linked list head (lazy initialization) _kw_head: KwEntry | t.CPtr = None _kw_pool: memhub.MemManager | t.CPtr = None def _kw_intern(pool: memhub.MemManager | t.CPtr, name: str, kw_id: t.CInt): - """将关键字名注册到链表""" + """Register keyword name in the linked list""" global _kw_head entry: KwEntry | t.CPtr = KwEntry(pool) if entry == None: return @@ -194,7 +194,7 @@ def _kw_intern(pool: memhub.MemManager | t.CPtr, name: str, kw_id: t.CInt): def _kw_lookup(name: str) -> t.CInt: - """查找关键字,返回 kw_id(0 表示非关键字)""" + """Look up keyword name in the linked list, return the kw_id (0 if not keyword)""" cur: KwEntry | t.CPtr = _kw_head while cur != None: if string.strcmp(cur.name, name) == 0: @@ -204,7 +204,7 @@ def _kw_lookup(name: str) -> t.CInt: def _init_keywords(pool: memhub.MemManager | t.CPtr): - """初始化关键字表(仅一次)""" + """Initialize keyword linked list (only once)""" global _kw_head, _kw_pool if _kw_head != None: return _kw_pool = pool @@ -249,12 +249,12 @@ def _init_keywords(pool: memhub.MemManager | t.CPtr): # ============================================================ -# 运算符查找表 -# 由于 TransPyC 无 dict,用数组+线性查找 -# 运算符按长度降序排列,以便贪婪匹配 +# Operator lookup table +# Since TransPyC doesn't have dict, use an array with linear search +# Operators are sorted by descending length for greedy matching # ============================================================ class OpEntry: - name: str # 运算符文本(如 "==", "+=") + name: str # Operator text (e.g. "==", "+=") op_id: t.CInt length: t.CInt next: OpEntry | t.CPtr @@ -285,16 +285,16 @@ def _op_intern(pool: memhub.MemManager | t.CPtr, name: str, op_id: t.CInt): def _init_operators(pool: memhub.MemManager | t.CPtr): - """初始化运算符表(按长度降序注册,便于贪婪匹配)""" + """Initialize the operator table (register in descending length order for easy greedy matching)""" global _op_head if _op_head != None: return - # 3 字符运算符 + # 3-character operators _op_intern(pool, "**=", TokOp.StarEqEq) _op_intern(pool, "//=", TokOp.DSlashEq) _op_intern(pool, ">>=", TokOp.GtGtEq) _op_intern(pool, "<<=", TokOp.LtLtEq) _op_intern(pool, "...", TokOp.Ellipsis) - # 2 字符运算符 + # 2-character operators _op_intern(pool, "->", TokOp.RArrow) _op_intern(pool, "+=", TokOp.PlusEq) _op_intern(pool, "-=", TokOp.MinusEq) @@ -314,7 +314,7 @@ def _init_operators(pool: memhub.MemManager | t.CPtr): _op_intern(pool, "==", TokOp.EqEq) _op_intern(pool, "!=", TokOp.ExclaimEq) _op_intern(pool, ":=", TokOp.ColonEq) - # 1 字符运算符 + # 1-character operators _op_intern(pool, "(", TokOp.LPar) _op_intern(pool, ")", TokOp.RPar) _op_intern(pool, "[", TokOp.Lsqb) @@ -341,18 +341,18 @@ def _init_operators(pool: memhub.MemManager | t.CPtr): def _init_tables(pool: memhub.MemManager | t.CPtr): - """初始化所有查找表(幂等)""" + """Initialize all lookup tables (idempotent)""" _init_keywords(pool) _init_operators(pool) # ============================================================ -# Token 创建辅助函数 +# Token creation helper functions # ============================================================ def new_token(pool: memhub.MemManager | t.CPtr, ttype: t.CInt, lineno: t.CInt, col_offset: t.CInt) -> Token | t.CPtr: - """创建一个空 Token,调用方填充字段""" + """Create a new empty Token and fill in fields later""" tok: Token | t.CPtr = Token(pool) if tok == None: return None tok.type = ttype @@ -365,9 +365,9 @@ def new_token(pool: memhub.MemManager | t.CPtr, ttype: t.CInt, lineno: t.CInt, def token_set_str(pool: memhub.MemManager | t.CPtr, tok: Token | t.CPtr, src: str, start: t.CSizeT, length: t.CSizeT): - """从 src[start:start+length] 复制文本到 token.str_val + """Copy text from src[start:start + length] to token.str_val - 注意:length == 0 时也分配 1 字节存 NUL,让空字符串与 NULL 指针区分开。 + Note: When length == 0, still allocate 1 byte for NUL, so that an empty string is distinguished from a NULL pointer. """ if tok == None: return buf: str = pool.alloc(length + 1) @@ -382,7 +382,7 @@ def token_set_str(pool: memhub.MemManager | t.CPtr, tok: Token | t.CPtr, def token_set_str_literal(pool: memhub.MemManager | t.CPtr, tok: Token | t.CPtr, text: str): - """直接复制一个 C 字符串到 token.str_val""" + """Copy a C string to token.str_val""" if tok == None or text == None: return slen: t.CSizeT = string.strlen(text) buf: str = pool.alloc(slen + 1)