feat(ast): 支持 export/extern 变量声明语法糖
export NAME: T [= v] → NAME: T | t.CExport [= v](裸名导出,不加模块 SHA1 头) extern NAME: T → NAME: T | t.State(仅声明 + 裸名);extern 带初始值响亮失败 新增 _is_export_extern_var lookahead(第三 token 为 : 判变量,(: / [ 判函数不影响 export def)与 _parse_export_extern_var
This commit is contained in:
1 parent
46cd4b4ebf
commit
f854f7e99a
1 file changed
+112
+112
@@ -251,6 +251,40 @@ def _is_typedef(ps: rawptr[Parser]) -> int:
|
|||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
def _is_export_extern_var(ps: rawptr[Parser]) -> int:
|
||||||
|
"""`export NAME :` / `extern NAME :` 变量声明的软关键字判定(1=是,0=否)。
|
||||||
|
|
||||||
|
`export` / `extern` 既可用于**函数**声明(`export def f()` / `export f()` /
|
||||||
|
`extern def f()`,见 `_is_funcdef_kw`),也可用于**变量**声明
|
||||||
|
(`export gdt: [7]gdt_entry = []`;`extern a: int`)。二者由第三个 token 区分:
|
||||||
|
函数是 `(`(参数表)或 `[`(泛型),变量是 `:`(类型注解)。
|
||||||
|
|
||||||
|
- `export name(` / `extern def f(`(函数)⇒ 本判据不命中,函数语义逐字不变;
|
||||||
|
- `export = 5` / `export(x)` / `export.attr`(把 export 当标识符)⇒ 不命中;
|
||||||
|
- `export NAME:` 后缺类型等非法形态在 `_parse_export_extern_var` 内
|
||||||
|
`_record_parse_err` **响亮失败**(非静默)。
|
||||||
|
"""
|
||||||
|
kw: int = _cur_kw(ps)
|
||||||
|
if kw != Keyword.Export and kw != Keyword.Extern:
|
||||||
|
return 0
|
||||||
|
nxt: rawptr[Token] = ps.cur.next
|
||||||
|
if nxt is None:
|
||||||
|
return 0
|
||||||
|
if nxt.type != TokenType.Name:
|
||||||
|
return 0
|
||||||
|
# 名字必须是**非关键字**标识符(排除 `export def f()` 之类把关键字当名字的形态)
|
||||||
|
if nxt.kw_subtype != Keyword.NotKeyword:
|
||||||
|
return 0
|
||||||
|
nxt2: rawptr[Token] = nxt.next
|
||||||
|
if nxt2 is None:
|
||||||
|
return 0
|
||||||
|
if nxt2.type != TokenType.Op:
|
||||||
|
return 0
|
||||||
|
if nxt2.op_subtype != TokOp.Colon:
|
||||||
|
return 0
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
def _is_match_stmt(ps: rawptr[Parser]) -> int:
|
def _is_match_stmt(ps: rawptr[Parser]) -> int:
|
||||||
"""match 是软关键字(CPython 3.10+):lookahead 判断是否为 match 语句
|
"""match 是软关键字(CPython 3.10+):lookahead 判断是否为 match 语句
|
||||||
|
|
||||||
@@ -2760,6 +2794,15 @@ def _parse_statement_into(ps: rawptr[Parser], parent: rawptr[AST]):
|
|||||||
if td_stmt is not None:
|
if td_stmt is not None:
|
||||||
parent.append(td_stmt)
|
parent.append(td_stmt)
|
||||||
return
|
return
|
||||||
|
# export / extern 变量声明(软关键字):`export NAME: T [= v]` /
|
||||||
|
# `extern NAME: T`(**不带**初始值)→ 带存储类标记的模块级 AnnAssign
|
||||||
|
# (见 _parse_export_extern_var)。函数形态(`export NAME(` /
|
||||||
|
# `extern def NAME(`)被 lookahead 排除,语义逐字不变。
|
||||||
|
if _is_export_extern_var(ps) != 0:
|
||||||
|
ee_stmt: rawptr[AST] = _parse_export_extern_var(ps)
|
||||||
|
if ee_stmt is not None:
|
||||||
|
parent.append(ee_stmt)
|
||||||
|
return
|
||||||
# virtual / novirtual 修饰符(软关键字):只在"语句起始 + 紧跟 class/def"
|
# virtual / novirtual 修饰符(软关键字):只在"语句起始 + 紧跟 class/def"
|
||||||
# 时生效;合成既有装饰器 @t.CVTable / @t.NoVTable 后照常走 class/def 解析
|
# 时生效;合成既有装饰器 @t.CVTable / @t.NoVTable 后照常走 class/def 解析
|
||||||
# (见 _ParseVirtualModified)。放在 class/def 分派之前:修饰符必须先被消费,
|
# (见 _ParseVirtualModified)。放在 class/def 分派之前:修饰符必须先被消费,
|
||||||
@@ -3813,6 +3856,75 @@ def _parse_typedef(ps: rawptr[Parser]) -> rawptr[AST]:
|
|||||||
return node
|
return node
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_export_extern_var(ps: rawptr[Parser]) -> rawptr[AST]:
|
||||||
|
"""`export NAME: T [= v]` / `extern NAME: T` → 带存储类标记的模块级 AnnAssign。
|
||||||
|
|
||||||
|
- **export**:注解改写为 `T | t.CExport`,与 `export def` **同一标记、同一消费
|
||||||
|
路径**(定义端裸名,不加模块 SHA1 头——内联汇编 / C 符号对接必需)。
|
||||||
|
允许带初始值;`export tss_buf: [104]uint8`(无初始值)生成零初始化全局定义。
|
||||||
|
- **extern**:注解改写为 `T | t.State`(= t.CExtern | t.CExport:仅声明 + 裸名),
|
||||||
|
与 `extern def` 同口径。**不允许初始值**(符号定义在外部),
|
||||||
|
`extern a: int = 1` → `_record_parse_err` **响亮失败**(非静默)。
|
||||||
|
|
||||||
|
行号/列号取自 `export`/`extern` 关键字位置,报错回显定位到真实源码行;
|
||||||
|
语句必须换行/文件尾结束(与 _parse_typedef / _parse_define_const 同口径)。
|
||||||
|
"""
|
||||||
|
lineno: int = _cur_lineno(ps)
|
||||||
|
col: int = _cur_col(ps)
|
||||||
|
is_extern: int = 0
|
||||||
|
if _cur_kw(ps) == Keyword.Extern:
|
||||||
|
is_extern = 1
|
||||||
|
_advance(ps) # export / extern
|
||||||
|
if _cur_type(ps) != TokenType.Name:
|
||||||
|
# 缺变量名(如 `export : int`):响亮失败。
|
||||||
|
_record_parse_err(ps)
|
||||||
|
ps.error_count += 1
|
||||||
|
return None
|
||||||
|
name: str = _cur_str(ps)
|
||||||
|
_advance(ps)
|
||||||
|
if _expect_op(ps, TokOp.Colon) == 0:
|
||||||
|
# 缺 `:`(如 `export x`):响亮失败。
|
||||||
|
return None
|
||||||
|
ann: rawptr[AST] = _parse_type_ann(ps)
|
||||||
|
if ann is None:
|
||||||
|
ps.error_count += 1
|
||||||
|
_record_parse_err(ps)
|
||||||
|
return None
|
||||||
|
# 存储类标记:export → t.CExport(裸名导出);extern → t.State(声明 + 裸名)
|
||||||
|
storage_attr: rawptr[AST] = Attribute(ps.pool,
|
||||||
|
Name(ps.pool, "t", ASTCtx.Load),
|
||||||
|
"State" if is_extern != 0 else "CExport",
|
||||||
|
ASTCtx.Load)
|
||||||
|
annotation: rawptr[AST] = BinOp(ps.pool, ann, OpKind.BitOr, storage_attr)
|
||||||
|
value: rawptr[AST] = None
|
||||||
|
if _match_op(ps, TokOp.Equal):
|
||||||
|
if is_extern != 0:
|
||||||
|
# extern 变量是外部定义:本模块不允许带初始值。
|
||||||
|
_RecordDescriptorErr("extern 变量声明不能带初始值(符号定义在外部)",
|
||||||
|
lineno, col)
|
||||||
|
ps.error_count += 1
|
||||||
|
return None
|
||||||
|
_advance(ps)
|
||||||
|
value = _parse_test(ps)
|
||||||
|
if value is None:
|
||||||
|
ps.error_count += 1
|
||||||
|
_record_parse_err(ps)
|
||||||
|
return None
|
||||||
|
target: rawptr[AST] = Name(ps.pool, name, ASTCtx.Store)
|
||||||
|
_set_pos(target, lineno, col, 0, 0)
|
||||||
|
node: rawptr[AST] = AnnAssign(ps.pool, target, annotation, value,
|
||||||
|
1 if value is not None else 0)
|
||||||
|
_set_pos(node, lineno, col, 0, 0)
|
||||||
|
_skip_nl(ps)
|
||||||
|
if _cur_type(ps) != TokenType.NewLine and _cur_type(ps) != TokenType.EndMarker:
|
||||||
|
_record_parse_err(ps)
|
||||||
|
ps.error_count += 1
|
||||||
|
return None
|
||||||
|
if _cur_type(ps) == TokenType.NewLine:
|
||||||
|
_advance(ps)
|
||||||
|
return node
|
||||||
|
|
||||||
|
|
||||||
def _parse_enumdef(ps: rawptr[Parser]) -> rawptr[AST]:
|
def _parse_enumdef(ps: rawptr[Parser]) -> rawptr[AST]:
|
||||||
"""enum NAME: 语法糖 → 与 `class NAME(t.CEnum):` 逐字段同形的 ClassDef。
|
"""enum NAME: 语法糖 → 与 `class NAME(t.CEnum):` 逐字段同形的 ClassDef。
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user