NAC_Blockchain/cnnl-compiler/src/parser/ast.rs

326 lines
8.1 KiB
Rust
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.

//! CNNL抽象语法树AST定义
use serde::{Deserialize, Serialize};
/// 程序(顶层节点)
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Program {
pub clauses: Vec<Clause>,
/// 测试块test "..." { assert ... }
#[serde(default)]
pub tests: Vec<TestBlock>,
}
/// 宪法条款
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Clause {
/// 条款标识符(全大写)
pub id: String,
/// 条款层级
pub level: ClauseLevel,
/// 条款标题
pub title: String,
/// 条款名称name: 字段,可选)
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
/// 版本号version: 字段,可选)
#[serde(skip_serializing_if = "Option::is_none")]
pub version: Option<String>,
/// 描述description: 字段,可选)
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
/// 依赖的其他条款
pub depends_on: Vec<String>,
/// 参数列表
pub parameters: Vec<Parameter>,
/// 谓词列表
pub predicates: Vec<Predicate>,
/// 义务列表
pub obligations: Vec<Obligation>,
}
/// 条款层级
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum ClauseLevel {
/// 永恒条款(不可修改)
Eternal,
/// 战略条款(需要超级多数修改)
Strategic,
/// 战术条款(普通多数修改)
Tactical,
}
impl std::fmt::Display for ClauseLevel {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
ClauseLevel::Eternal => write!(f, "eternal"),
ClauseLevel::Strategic => write!(f, "strategic"),
ClauseLevel::Tactical => write!(f, "tactical"),
}
}
}
/// 参数
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Parameter {
pub name: String,
/// 参数类型
pub ty: Type,
pub value: Literal,
/// 参数描述(可选)
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
}
/// 谓词
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Predicate {
pub name: String,
pub params: Vec<(String, Type)>,
pub return_type: Type,
/// 函数体AST 表达式)
pub body: Expression,
}
/// 义务
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Obligation {
pub name: String,
pub frequency: ObligationFrequency,
pub enforcer: String,
pub penalty: String,
/// 义务描述(可选)
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
}
/// 义务频率
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ObligationFrequency {
Continuous, // 持续
Periodic, // 周期性
OnDemand, // 按需
}
impl std::fmt::Display for ObligationFrequency {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
ObligationFrequency::Continuous => write!(f, "continuous"),
ObligationFrequency::Periodic => write!(f, "periodic"),
ObligationFrequency::OnDemand => write!(f, "on_demand"),
}
}
}
/// 类型
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum Type {
Bool,
U64,
U32,
U128,
F64,
String,
}
impl std::fmt::Display for Type {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Type::Bool => write!(f, "bool"),
Type::U64 => write!(f, "u64"),
Type::U32 => write!(f, "u32"),
Type::U128 => write!(f, "u128"),
Type::F64 => write!(f, "f64"),
Type::String => write!(f, "string"),
}
}
}
/// 字面量
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Literal {
Bool(bool),
Int(u64),
Float(f64),
String(String),
}
impl std::fmt::Display for Literal {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Literal::Bool(b) => write!(f, "{}", b),
Literal::Int(n) => write!(f, "{}", n),
Literal::Float(n) => write!(f, "{}", n),
Literal::String(s) => write!(f, "\"{}\"", s),
}
}
}
/// 表达式
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Expression {
// 字面量
Literal(Literal),
// 变量引用
Variable(String),
// 二元运算
Binary {
op: BinaryOp,
left: Box<Expression>,
right: Box<Expression>,
},
// 一元运算
Unary {
op: UnaryOp,
operand: Box<Expression>,
},
// 函数调用
Call {
name: String,
args: Vec<Expression>,
},
// if表达式
If {
condition: Box<Expression>,
then_branch: Box<Expression>,
else_branch: Option<Box<Expression>>,
},
// 代码块
Block(Vec<Statement>),
// 原始字符串(解析器无法完整解析时的降级表示)
Raw(String),
}
/// 二元运算符
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum BinaryOp {
// 算术运算
Add,
Sub,
Mul,
Div,
Mod,
// 比较运算
Eq,
Ne,
Lt,
Le,
Gt,
Ge,
// 逻辑运算
And,
Or,
}
impl std::fmt::Display for BinaryOp {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
BinaryOp::Add => write!(f, "+"),
BinaryOp::Sub => write!(f, "-"),
BinaryOp::Mul => write!(f, "*"),
BinaryOp::Div => write!(f, "/"),
BinaryOp::Mod => write!(f, "%"),
BinaryOp::Eq => write!(f, "=="),
BinaryOp::Ne => write!(f, "!="),
BinaryOp::Lt => write!(f, "<"),
BinaryOp::Le => write!(f, "<="),
BinaryOp::Gt => write!(f, ">"),
BinaryOp::Ge => write!(f, ">="),
BinaryOp::And => write!(f, "&&"),
BinaryOp::Or => write!(f, "||"),
}
}
}
/// 一元运算符
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum UnaryOp {
Not,
Neg,
}
impl std::fmt::Display for UnaryOp {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
UnaryOp::Not => write!(f, "!"),
UnaryOp::Neg => write!(f, "-"),
}
}
}
/// 语句
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Statement {
// 表达式语句
Expression(Expression),
// 返回语句
Return(Expression),
// 变量声明
Let {
name: String,
ty: Option<Type>,
value: Expression,
},
}
/// 测试块
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct TestBlock {
pub description: String,
pub assertions: Vec<String>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_clause_creation() {
let clause = Clause {
id: "XTZH_GOLD_COVERAGE".to_string(),
level: ClauseLevel::Eternal,
title: "黄金储备覆盖率底线".to_string(),
name: None,
version: None,
description: None,
depends_on: vec![],
parameters: vec![Parameter {
name: "XTZH_GOLD_COVERAGE_MIN".to_string(),
ty: Type::F64,
value: Literal::Float(1.25),
description: Some("最低黄金覆盖率".to_string()),
}],
predicates: vec![],
obligations: vec![],
};
assert_eq!(clause.id, "XTZH_GOLD_COVERAGE");
assert_eq!(clause.level, ClauseLevel::Eternal);
assert_eq!(clause.parameters.len(), 1);
}
#[test]
fn test_expression_creation() {
let expr = Expression::Binary {
op: BinaryOp::Ge,
left: Box::new(Expression::Variable("coverage".to_string())),
right: Box::new(Expression::Literal(Literal::Float(1.25))),
};
match expr {
Expression::Binary { op, .. } => assert_eq!(op, BinaryOp::Ge),
_ => panic!("Expected Binary expression"),
}
}
}