将 ast 英化
This commit is contained in:
1 parent
752f3ddb70
commit
c5570dc8b1
9 files changed
+424
-413
No files matched your search
+29
-21
@@ -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)
|
||||
|
||||
@@ -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):
|
||||
|
||||
+56
-57
@@ -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:
|
||||
|
||||
+29
-29
@@ -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):
|
||||
|
||||
+91
-90
@@ -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)
|
||||
|
||||
@@ -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):
|
||||
|
||||
+132
-129
@@ -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)
|
||||
|
||||
+27
-27
@@ -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):
|
||||
|
||||
+44
-44
@@ -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)
|
||||
|
||||
Reference in new issue
Block a user