use std::sync::Arc;
use indexmap::IndexMap;
pub type StmtList = Arc<[Stmt]>;
#[derive(Debug, Clone)]
pub struct Node {
pub title: String,
pub tags: Vec<String>,
pub headers: IndexMap<String, String>,
pub when: Option<Arc<Expr>>,
pub body: StmtList,
}
#[derive(Debug, Clone)]
pub struct IfBranch {
pub cond: Arc<Expr>,
pub body: StmtList,
}
#[derive(Debug, Clone)]
pub enum Stmt {
Line {
speaker: Option<String>,
text: Vec<TextSegment>,
tags: Vec<String>,
},
Set {
name: String,
expr: Arc<Expr>,
},
If {
branches: Vec<IfBranch>,
else_body: StmtList,
},
Jump(String),
Detour(String),
Return,
Stop,
Command {
name: String,
args: Vec<TextSegment>,
tags: Vec<String>,
},
Once {
block_id: String,
cond: Option<Arc<Expr>>,
body: StmtList,
else_body: StmtList,
},
Declare {
name: String,
expr: Arc<Expr>,
default_src: String,
},
Options(Vec<OptionItem>),
LineGroup(Vec<LineVariant>),
}
#[derive(Debug, Clone)]
pub struct OptionItem {
pub id: String,
pub text: Vec<TextSegment>,
pub cond: Option<Arc<Expr>>,
pub once: bool,
pub tags: Vec<String>,
pub body: StmtList,
}
#[derive(Debug, Clone)]
pub struct LineVariant {
pub id: String,
pub speaker: Option<String>,
pub text: Vec<TextSegment>,
pub cond: Option<Arc<Expr>>,
pub once: bool,
pub tags: Vec<String>,
}
#[derive(Debug, Clone)]
pub enum TextSegment {
Literal(String),
Expr(Arc<Expr>),
MarkupOpen {
name: String,
properties: Vec<(String, String)>,
},
MarkupClose {
name: String,
},
MarkupSelfClose {
name: String,
properties: Vec<(String, String)>,
},
}
impl TextSegment {
pub fn literal(s: impl Into<String>) -> Self {
Self::Literal(s.into())
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum Expr {
Number(f64),
Text(String),
Bool(bool),
Var(String),
Call {
name: String,
args: Vec<Self>,
},
Unary {
op: UnOp,
expr: Box<Self>,
},
Binary {
left: Box<Self>,
op: BinOp,
right: Box<Self>,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BinOp {
Add,
Sub,
Mul,
Div,
Rem,
Eq,
Neq,
Lt,
Lte,
Gt,
Gte,
And,
Or,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum UnOp {
Neg,
Not,
}