diff --git a/lib/core/TypeAnnotationResolver.py b/lib/core/TypeAnnotationResolver.py index b2fcec4..44d496b 100644 --- a/lib/core/TypeAnnotationResolver.py +++ b/lib/core/TypeAnnotationResolver.py @@ -131,10 +131,21 @@ class TypeAnnotationResolver: SymbolTable: 符号表字典 """ if isinstance(Node, ast.BinOp) and isinstance(Node.op, ast.BitOr): - Line: int = getattr(Node, 'lineno', 0) or 0 - raise TypeError( - f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行);" - f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字") + def _is_none_literal(n: ast.AST) -> bool: + if isinstance(n, ast.Constant): + return getattr(n, 'value', ...) is None + return isinstance(n, ast.Name) and getattr(n, 'id', '') == 'None' + + _left_none: bool = _is_none_literal(Node.left) + _right_none: bool = _is_none_literal(Node.right) + if _left_none != _right_none: + # `T | None` / `None | T` 等价于 T + Node = Node.right if _left_none else Node.left + else: + Line: int = getattr(Node, 'lineno', 0) or 0 + raise TypeError( + f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行);" + f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字") if isinstance(Node, ast.Constant): Info: CTypeInfo = TypeAnnotationResolver._from_node_constant(Node, SymbolTable) elif isinstance(Node, ast.Name): diff --git a/lib/vast/ExprParser.py b/lib/vast/ExprParser.py index de82adf..9dc42ef 100644 --- a/lib/vast/ExprParser.py +++ b/lib/vast/ExprParser.py @@ -1783,10 +1783,21 @@ class ExprParserMixin(TokenStream): "[vast] 类型注解的修饰词后缺少类型(如 `x: const int`)。") return None if isinstance(expr, N.BinOp) and isinstance(expr.op, N.BitOr): - Line: int = getattr(expr, 'lineno', 0) or 0 - raise TypeError( - f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行);" - f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字") + def _is_none_literal(n: N.AST) -> bool: + if isinstance(n, N.Constant): + return getattr(n, 'value', ...) is None + return isinstance(n, N.Name) and getattr(n, 'id', '') == 'None' + + _left_none: bool = _is_none_literal(expr.left) + _right_none: bool = _is_none_literal(expr.right) + if _left_none != _right_none: + # `T | None` / `None | T` 等价于 T + expr = expr.right if _left_none else expr.left + else: + Line: int = getattr(expr, 'lineno', 0) or 0 + raise TypeError( + f"[vast] 不支持类型联合 'T1 | T2'(第 {Line} 行);" + f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字") if self._AtPtrSuffix(expr): expr = self._ConsumePtrSuffix(expr) tok: Token = self._Peek()