Skip to content

类Python脚本语言语法规范

本文档描述了当前项目实际实现的语法规则,基于项目的词法分析器、语法分析器和AST结构的实际代码。

完整语法规范(BNF表示法)

bnf
// 程序结构
program ::= contract

// 合约定义
contract ::= "Contract" IDENTIFIER ":" NEWLINE INDENT [member]* DEDENT

member ::= function | struct | constructor

// 函数定义
function ::= "def" IDENTIFIER "(" [parameter_list] ")" ["->" return_type] ":" block

constructor ::= "def" "__init__" "(" [parameter_list] ")" ":" block

parameter_list ::= parameter ["," parameter]*
parameter ::= IDENTIFIER ":" TYPE

// 返回类型定义
return_type ::= TYPE | brace_type_list

brace_type_list ::= "{" type_list "}"

type_list ::= TYPE ["," TYPE]*

// 结构体定义
struct ::= "Struct" IDENTIFIER ":" NEWLINE INDENT [field]+ DEDENT
field ::= IDENTIFIER ":" TYPE NEWLINE

// 语句
statement ::= if_statement
           | return_statement  
           | assignment_statement
           | destructure_assignment
           | variable_declaration
           | expression_statement

block ::= NEWLINE INDENT [statement]* DEDENT

if_statement ::= "if" expression ":" block ["else" ":" block]

return_statement ::= "return" expression NEWLINE

assignment_statement ::= (IDENTIFIER | field_access) "=" expression NEWLINE

destructure_assignment ::= "{" identifier_list "}" "=" expression NEWLINE

identifier_list ::= IDENTIFIER ["," IDENTIFIER]*

variable_declaration ::= IDENTIFIER ":" TYPE ["=" expression] NEWLINE

expression_statement ::= expression NEWLINE

// 表达式
expression ::= binary_expression
            | unary_expression
            | primary_expression

binary_expression ::= expression binary_operator expression

unary_expression ::= unary_operator expression

primary_expression ::= IDENTIFIER
                    | literal
                    | function_call
                    | method_call
                    | field_access
                    | Clone_expression
                    | brace_expression
                    | "(" expression ")"

brace_expression ::= "{" [expression_list] "}"

expression_list ::= expression ["," expression]*

function_call ::= IDENTIFIER "(" [argument_list] ")"

method_call ::= expression "." IDENTIFIER "(" [argument_list] ")"

field_access ::= expression "." IDENTIFIER

clone_expression ::= IDENTIFIER "." "Clone" "(" ")"

argument_list ::= expression ["," expression]*

// 字面量
literal ::= NUMBER | HEX | STRING

// 操作符
binary_operator ::= "+" | "-" | "*" | "/" 
                 | "==" | "!=" | "<" | ">" | "<=" | ">="

unary_operator ::= "-" | "+"

// 词法元素
IDENTIFIER ::= [a-zA-Z_][a-zA-Z0-9_]*
NUMBER ::= [0-9]+
HEX ::= "0x"[0-9a-fA-F]+
STRING ::= '"' [^"]* '"'
TYPE ::= IDENTIFIER
NEWLINE ::= '\n'
INDENT ::= 增加缩进级别
DEDENT ::= 减少缩进级别

1. 程序结构

1.1 程序定义

program ::= contract

一个程序由单个合约组成(单合约系统)。

1.2 合约定义

contract ::= "Contract" IDENTIFIER ":" NEWLINE INDENT [member]* DEDENT

member ::= function | struct | constructor

合约以关键字 Contract 开始,后跟合约名称,使用Python风格的缩进结构。

2. 数据结构

2.1 结构体定义

struct ::= "Struct" IDENTIFIER ":" NEWLINE INDENT [field]+ DEDENT

field ::= IDENTIFIER ":" TYPE NEWLINE

结构体定义必须包含至少一个字段,每个字段都必须有类型声明。

示例:

python
Struct Person:
    name: string
    age: int
    publicKey: hex

3. 函数定义

3.1 普通函数

function ::= "def" IDENTIFIER "(" [parameter_list] ")" ["->" TYPE] ":" block

parameter_list ::= parameter ["," parameter]*
parameter ::= IDENTIFIER ":" TYPE

函数参数必须包含类型声明,返回类型是可选的。

示例:

python
def main(sig: string, pubkey: hex) -> bool:
    result = CheckSig(pubkey, sig)
    return result

3.2 构造函数

constructor ::= "def" "__init__" "(" [parameter_list] ")" ":" block

构造函数使用特殊名称 __init__

示例:

python
def __init__(pubKeyH: hex):
    self.pubKeyHash = pubKeyH

4. 语句

4.1 语句类型

statement ::= if_statement
           | return_statement  
           | assignment_statement
           | variable_declaration
           | expression_statement

block ::= NEWLINE INDENT [statement]* DEDENT

4.2 条件语句

if_statement ::= "if" expression ":" block ["else" ":" block]

示例:

python
if check_lock_time(current_time, timeout):
    verify checkSig(sender, senderSig)
else:
    verify checkSig(recipient, recipientSig)

4.3 返回语句

return_statement ::= "return" expression NEWLINE

4.4 赋值语句

assignment_statement ::= (IDENTIFIER | field_access) "=" expression NEWLINE

field_access ::= expression "." IDENTIFIER

示例:

python
x = 10
self.value = result
Sub.x = 0

4.5 变量声明

variable_declaration ::= IDENTIFIER ":" TYPE ["=" expression] NEWLINE

示例:

python
count: int
name: string = "default"
result: bool = CheckSig(pubkey, sig)

5. 表达式

5.1 表达式类型

expression ::= binary_expression
            | unary_expression
            | primary_expression

primary_expression ::= IDENTIFIER
                    | literal
                    | function_call
                    | method_call
                    | field_access
                    | "(" expression ")"

literal ::= NUMBER | HEX | STRING

5.2 函数调用

function_call ::= IDENTIFIER "(" [argument_list] ")"

argument_list ::= expression ["," expression]*

示例:

python
CheckSig(pubkey, sig)
Sha256(data)
EqualVerify(hash1, hash2)

5.3 方法调用和字段访问

method_call ::= expression "." IDENTIFIER "(" [argument_list] ")"

field_access ::= expression "." IDENTIFIER

支持链式调用:

python
obj.field1.field2
obj.method().field
self.pubKeyHash.a

5.4 二元运算

binary_expression ::= expression binary_operator expression

binary_operator ::= "+" | "-" | "*" | "/" 
                 | "==" | "!=" | "<" | ">" | "<=" | ">="

5.5 一元运算

unary_expression ::= unary_operator expression

unary_operator ::= "-" | "+"

6. 词法元素

6.1 关键字

keywords ::= "Contract" | "def" | "Struct" | "if" | "else" | "return"

6.2 标识符和字面量

IDENTIFIER ::= [a-zA-Z_][a-zA-Z0-9_]*
NUMBER ::= [0-9]+
HEX ::= "0x"[0-9a-fA-F]+
STRING ::= '"' [^"]* '"'
TYPE ::= IDENTIFIER  // 类型标识符,如 int, string, hex, bool

6.3 操作符和分隔符

operators ::= "=" | "==" | "!=" | "<" | ">" | "<=" | ">=" 
           | "+" | "-" | "*" | "/" | "->"

delimiters ::= "(" | ")" | "[" | "]" | ":" | "," | "."

6.4 缩进和换行

语言使用Python风格的缩进来表示代码块结构:

  • NEWLINE: 换行符
  • INDENT: 增加缩进级别
  • DEDENT: 减少缩进级别

7. 所有权系统

该语言实现了类似Rust的所有权概念,但仅对数据变量有约束:

7.1 所有权规则

  • 变量消耗: 当局部变量被使用(作为函数参数、赋值给其他变量等)时,原变量的所有权被转移
  • 合约成员变量例外: 合约的成员变量(如 self.field)在编译时会被直接替换到代码中,因此不受所有权约束,可以多次使用而无需 Clone
  • 克隆操作: 对于局部变量,使用 Clone() 函数可以创建变量的副本,避免所有权转移
  • 字段访问: 访问结构体实例的字段会消耗该字段的所有权,如需多次访问需要先克隆;但合约成员变量不受此限制
  • 特殊内置函数: SetAlt()SetMain() 函数不会消耗变量的所有权

7.2 克隆语法

clone_expression ::= IDENTIFIER "." "Clone" "(" ")"

示例:

python
original_value: int = 42
cloned_value: int = original_value.Clone()
# original_value 仍然可用

7.3 内置函数

语言提供以下内置函数:

  • Clone(): 创建变量的副本,语法为 variable.Clone()
  • SetAlt(variable): 将变量移动到副栈,不消耗变量所有权
  • SetMain(variable): 将变量从副栈移动到主栈,不消耗变量所有权
  • 其他内置函数: 如 CheckSig(), Sha256() 等,遵循普通函数调用语法并消耗参数的所有权

7.4 所有权系统示例

局部变量的所有权转移:

python
data: hex = "0x1234"
result1: bool = CheckSig(data, signature)  # data 被消耗,不能再次使用
# result2: bool = CheckSig(data, signature2)  # 错误:data 已被消耗

# 需要克隆才能多次使用
data2: hex = "0x5678"
cloned_data: hex = data2.Clone()
result1: bool = CheckSig(data2, signature1)
result2: bool = CheckSig(cloned_data, signature2)  # 正确:使用克隆的副本

合约成员变量的特殊行为:

python
def main(sig1: string, sig2: string):
    # 合约成员变量可以多次使用,无需 Clone
    result1: bool = CheckSig(self.pubKey, sig1)
    result2: bool = CheckSig(self.pubKey, sig2)  # 正确:self.pubKey 可以重复使用
    return result1 and result2

特殊内置函数:

python
data: hex = "0x1234"
SetAlt(data)    # data 仍然可用,所有权未被消耗
SetMain(data)   # data 仍然可用,所有权未被消耗

8. 大括号语法糖 ({} 语法)

8.1 语法定义

brace_expression ::= "{" [expression_list] "}"
destructure_assignment ::= "{" identifier_list "}" "=" expression NEWLINE

8.2 用途和语义

大括号语法糖 {} 是一个多功能的语法特性,根据上下文有不同的语义:

8.2.1 多返回值解构

用于承接函数的多个返回值:

python
{a, b} = Split(data, 10)  # Split 返回两个值,分别赋给 a 和 b
{x, y, z} = GetCoordinates()  # 承接三个返回值

8.2.2 结构体字面量

用于创建结构体实例:

python
Struct Point:
    x: int
    y: int

# 使用大括号语法糖创建结构体实例
p: Point = {10, 20}  # 等价于 Point(10, 20)

8.2.3 匿名结构

当没有明确的类型承接时,{} 创建匿名结构:

python
# 这种情况下,{a, b} 只是语法糖,实际上 a, b 是独立变量
{a, b} = Split(data, 10)
# 可以直接使用 a 和 b,无需通过结构体访问
result = a + b

8.3 类型推导规则

编译器根据左侧的类型声明来决定 {} 的语义:

  1. 有明确结构体类型:创建该类型的实例

    python
    point: Point = {x, y}  # 创建 Point 实例
  2. 无类型声明:解构为独立变量

    python
    {a, b} = Split(data, 10)  # a, b 是独立变量
  3. 混合使用:既解构又创建结构体

    python
    {x, y}: Point = GetPoint()  # 解构并创建 Point 实例

8.4 使用示例

8.4.1 多返回值函数

python
def split_data(data: hex, pos: int) -> {hex, hex}:
    # 函数实现返回两个值
    return {left_part, right_part}

# 使用解构赋值
{left, right} = split_data("0x123456", 3)

8.4.2 结构体构造

python
Struct Person:
    name: string
    age: int

# 使用大括号语法糖
person2: Person = {"Bob", 30}

8.4.3 复杂场景

python
Struct Result:
    success: bool
    data: hex

def process_and_split(input: hex) -> (bool, hex, hex):
    # 处理并返回三个值
    return success, left, right

# 混合使用:部分解构,部分构造
{success, left, right} = process_and_split(input_data)
result: Result = {success, left}  # 使用部分结果构造结构体

9. 语法特点

  1. 强制类型声明: 所有函数参数、结构体字段和变量声明都必须包含类型
  2. Python风格缩进: 使用缩进而非大括号来表示代码块
  3. 单合约系统: 每个程序只能包含一个合约
  4. 链式调用支持: 支持 obj.field.method() 形式的链式调用
  5. 构造函数: 使用 __init__ 作为构造函数名称
  6. 字段访问: 支持 self.fieldStructName.field 形式的字段访问
  7. 所有权系统: 变量具有消耗性,支持克隆操作
  8. 大括号语法糖: 支持多返回值解构和结构体字面量语法

9. 类型系统

当前支持的基本类型:

  • int: 整数类型
  • string: 字符串类型
  • hex: 十六进制数据类型
  • bool: 布尔类型
  • 用户定义的结构体类型

10. 注意事项

  1. 所有语句必须以换行符结束
  2. 代码块必须正确缩进
  3. 函数参数和结构体字段的类型声明是强制的
  4. 支持嵌套的字段访问和方法调用
  5. 赋值操作支持简单变量和字段访问作为左值

基于 MIT 许可发布