Files
TransPyC/lib/vast/__init__.py
T
TermiNexus 6350b81307 feat(vast_c): extern/export 完整语义(注解改写+标记)并接入 vast.parse
- ParseExternDef:支持 4 种语法(extern/export [def] A(...) -> T [': pass']),返回注解改写为 <原类型> | t.State(extern)/ <原类型> | t.CExport(export),节点设 Extern=True/Export=True(对齐 vast Parser._ParseExternDef/_ParseExportDef)
- MakeTAttrNode:构造 t.Attr 注解节点(Attribute(Name('t'), attr))
- vast.parse 接入:默认走 vast_c C 加速路径(VAST_USE_C=0 禁用,=strict fail-fast 直接抛),异常回退纯 Python vast
- 差分测试 83/83 全绿(新增 7 个 extern/export 用例);includes/ 与 TransPyV/App 4 个真实 .vp 文件 C 路径与纯 Python 输出一致
2026-08-18 06:59:10 +08:00

87 lines
3.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""vast - Viper/Python 自研语法解析器(ast 替代品)
vast 提供与 CPython 3.12 标准库 ``ast`` 完全一致的 API:
- 节点类:``AST`` 及全部 131 个节点类(Name/Call/BinOp/FunctionDef/...)
- 解析入口:``parse(source, filename, mode, ...)`` 产出 ``Module``
- 辅助函数:``dump`` / ``walk`` / ``iter_child_nodes`` / ``iter_fields`` /
``unparse`` / ``copy_location`` / ``fix_missing_locations`` /
``get_source_segment`` / ``literal_eval``
- 类型标注占位:``expr`` / ``stmt`` / ``operator`` / ``cmpop`` 等
编译器侧替换方式(零修改其余代码)::
import vast as ast
vast 原生支持 Viper 软关键字 fn/fun/func/function(并入解析器),无需
ExpandSoftKeywords 预处理。
"""
from __future__ import annotations
import os as _os
import sys as _sys
from lib.vast.Nodes import AST
from lib.vast.Nodes import _NODE_DEFS
# 将全部节点类提升到包命名空间
for _name in _NODE_DEFS:
globals()[_name] = getattr(_sys.modules['lib.vast.Nodes'], _name)
from lib.vast.Parser import Parse # noqa: E402
from lib.vast.Utils import ( # noqa: E402
iter_fields, iter_child_nodes, walk, dump, copy_location,
fix_missing_locations, get_source_segment, literal_eval,
)
from lib.vast.Unparser import Unparse as unparse # noqa: E402
from lib.vast.Tokenizer import SOFT_KEYWORDS # noqa: E402
def _ParsePure(source: str, mode: str) -> AST:
"""纯 Python vast 解析(vast_c 不可用或回退时使用)。"""
tree: AST = Parse(source)
if mode == 'exec':
return tree
if mode == 'eval':
if len(tree.body) != 1 or not isinstance(tree.body[0], _sys.modules['lib.vast.Nodes'].Expr):
raise SyntaxError('invalid syntax for eval mode')
expr_node: AST = _sys.modules['lib.vast.Nodes'].Expression(
body=tree.body[0].value)
return expr_node
if mode == 'single':
interactive: AST = _sys.modules['lib.vast.Nodes'].Interactive(body=tree.body)
return interactive
raise ValueError(f"invalid mode {mode!r}")
# C 加速解析器(vast_c 扩展):可用则优先,输出与 vast.parse 结构完全一致。
# VAST_USE_C=0 禁用 C 路径;=strict 时 C 路径异常直接抛出(fail-fast)。
_VAST_C_PARSE = None
try:
from lib.vast_c import parse as _VAST_C_PARSE
except Exception:
_VAST_C_PARSE = None
def parse(source: str, filename: str = '<unknown>', mode: str = 'exec', *,
type_comments: bool = False, feature_version: tuple[int, int] | int | None = None) -> AST:
"""解析源码字符串为 AST(与 ast.parse 同签名、同结构)。
优先使用 C 加速解析器 vast_c(输出结构完全一致),异常时回退纯 Python vast;
环境变量 VAST_USE_C:'0' 禁用 C 路径,'strict' 时 C 路径异常直接抛出。
"""
if _VAST_C_PARSE is not None and _os.environ.get('VAST_USE_C', '1') != '0':
try:
return _VAST_C_PARSE(source, mode)
except Exception:
if _os.environ.get('VAST_USE_C') == 'strict':
raise
return _ParsePure(source, mode)
__all__: list[str] = [
'AST', 'parse', 'dump', 'walk', 'iter_fields', 'iter_child_nodes',
'unparse', 'copy_location', 'fix_missing_locations',
'get_source_segment', 'literal_eval', 'SOFT_KEYWORDS',
] + list(_NODE_DEFS.keys())