// MoonDatalog —— 抽象语法树(AST)
//
// 语法模型遵循经典 Datalog 并做少量实用扩展:
// - 事实:`parent(alice, bob).`
// - 规则:`ancestor(X, Y) :- parent(X, Y).`
// - 查询:`?- ancestor(X, carol).`
// - 算术比较 / 赋值:`X < Y`、`X = Y + 1`
// - 分层否定:`not friend(X, Y)`
// - 聚合(Soufflé 风格):`N = count : { X }`
///|
/// 源码位置(行 / 列,均从 1 起)。
pub struct Pos {
line : Int
col : Int
} derive(Eq, @debug.Debug)
///|
pub impl Show for Pos with fn to_string(self : Pos) -> String {
"\{self.line}:\{self.col}"
}
///|
/// 算术二元运算符。
pub enum BinOp {
Add
Sub
Mul
Div
Mod
} derive(Eq, @debug.Debug)
///|
/// 比较 / 赋值运算符。
pub enum CmpOp {
Eq
Ne
Lt
Le
Gt
Ge
} derive(Eq, @debug.Debug)
///|
/// 聚合函数。
pub enum AggFunc {
Count
Sum
Min
Max
Avg
} derive(Eq, @debug.Debug)
///|
/// 项(原子参数):常量、变量、一元负号或算术表达式。
pub enum Term {
/// 常量字面量
Const(Value)
/// 变量(`_` 匿名变量在解析时被替换为唯一生成的名字)
Var(String)
/// 一元负号 `-t`
Neg(Term)
/// 算术表达式 `lhs op rhs`
Arith(BinOp, Term, Term)
} derive(Eq, @debug.Debug)
///|
/// 是否为变量名:`_` 或大写字母开头的标识符。
pub fn is_variable_name(s : String) -> Bool {
if s == "_" {
return true
}
let mut first_char : Char? = None
for c in s.iter() {
first_char = Some(c)
break
}
match first_char {
Some(c) => c.is_ascii_uppercase()
None => false
}
}
///|
/// 规则体中的一项。
pub enum BodyItem {
/// 正原子
Pos(Atom)
/// 否定原子 `not p(...)`
Neg(Atom)
/// 比较 / 赋值约束
Cmp(Cmp)
/// 聚合项 `N = func : { ... }`
Agg(Aggregate)
} derive(Eq, @debug.Debug)
///|
/// 谓词原子 `pred(t1, ..., tn)`。
pub struct Atom {
pred : String
args : Array[Term]
pos : Pos
} derive(Eq, @debug.Debug)
///|
/// 比较 / 赋值约束。
pub struct Cmp {
op : CmpOp
lhs : Term
rhs : Term
pos : Pos
} derive(Eq, @debug.Debug)
///|
/// 聚合项:`agg_var = func : { agg_vars... }`。
///
/// 语义与 Soufflé 一致:以规则体中其余变量为分组键,
/// 组内对 `agg_vars` 对应的取值集合计算聚合函数,结果绑定到 `agg_var`。
pub struct Aggregate {
agg_var : String
func : AggFunc
agg_vars : Array[String]
pos : Pos
} derive(Eq, @debug.Debug)
///|
/// 一条规则:`head :- body.`(事实为 `body` 为空)。
pub struct Rule {
head : Atom
body : Array[BodyItem]
pos : Pos
} derive(Eq, @debug.Debug)
///|
/// 一个查询:`?- body.`
pub struct Query {
body : Array[BodyItem]
pos : Pos
} derive(Eq, @debug.Debug)
///|
/// 完整程序:规则(含事实)与查询。
pub struct Program {
rules : Array[Rule]
queries : Array[Query]
} derive(Eq, @debug.Debug)
///|
/// 引擎错误。
pub enum DlError {
/// 词法错误
LexError(Pos, String)
/// 语法错误
ParseError(Pos, String)
/// 语义错误(未定义谓词、元数不符、不安全规则、不可分层否定等)
SemanticError(String)
/// 求值错误(除零、聚合用法非法等)
EvalError(String)
} derive(Eq, @debug.Debug)
///|
pub fn DlError::to_string(self : DlError) -> String {
match self {
LexError(pos, msg) => "词法错误 @ \{pos}: \{msg}"
ParseError(pos, msg) => "语法错误 @ \{pos}: \{msg}"
SemanticError(msg) => "语义错误: \{msg}"
EvalError(msg) => "求值错误: \{msg}"
}
}