Files
leaf/parser/src/ast.rs
T

226 lines
3.9 KiB
Rust

use arcstr::Substr;
use derive_more::Deref;
use indexmap::IndexMap;
use std::ops::Range;
use std::sync::Arc;
#[derive(Debug, Deref)]
pub struct Ident(pub Substr);
#[derive(Debug, Deref)]
pub struct Import(pub Expr);
#[derive(Debug)]
pub struct Number {
pub text: Substr,
pub r#type: Option<Ident>,
}
#[derive(derive_more::Debug)]
pub enum Expr {
#[debug("uninit")]
Uninit(Substr),
#[debug("Ident({:?})", _0.0)]
Ident(Ident),
#[debug("{_0:?}")]
Number(Number),
String(Substr),
#[debug("{_0:?}")]
Binary(Box<BinaryExpr>),
Index(Box<IndexingExpr>),
Access(Box<AccessExpr>),
Deref(Box<Expr>),
Tuple(Vec<Expr>),
List(Vec<Expr>),
Struct(Box<StructCtor>),
#[debug("{_0:?}")]
Block(Arc<Block>),
#[debug("{_0:?}")]
Func(Arc<Function>),
#[debug("{_0:?}")]
Type(Box<Type>),
#[debug("{_0:?}")]
ConstDecl(Box<ConstDecl>),
#[debug("{_0:?}")]
VarDecl(Box<VarDecl>),
#[debug("{_0:?}")]
For(Box<For>),
#[debug("{_0:?}")]
While(Box<While>),
#[debug("{_0:?}")]
If(Box<If>),
Call {
func: Box<Expr>,
args: Vec<Expr>,
},
}
impl Expr {
pub fn range(&self) -> Range<usize> {
match self {
Self::Ident(e) => e.range(),
Self::Access(e) => e.range(),
Self::Number(e) => e.text.range(),
_ => todo!("{self:?}"),
}
}
}
#[derive(Debug)]
pub struct BinaryExpr {
pub lhs: Expr,
pub op: BinaryOp,
pub rhs: Expr,
}
#[derive(Debug)]
pub struct IndexingExpr {
pub value: Expr,
pub index: Expr,
}
#[derive(Debug)]
pub struct AccessExpr {
pub value: Expr,
pub field: Ident,
}
impl AccessExpr {
pub fn range(&self) -> Range<usize> {
self.value.range().start..self.field.0.range().end
}
}
#[rustfmt::skip]
#[derive(derive_more::Debug)]
pub enum BinaryOp {
#[debug("{_0}")] Add(Substr),
#[debug("{_0}")] Sub(Substr),
#[debug("{_0}")] Mul(Substr),
#[debug("{_0}")] Div(Substr),
#[debug("{_0}")] Mod(Substr),
#[debug("{_0}")] Eq(Substr),
#[debug("{_0}")] Ne(Substr),
#[debug("{_0}")] Lt(Substr),
#[debug("{_0}")] Gt(Substr),
#[debug("{_0}")] Le(Substr),
#[debug("{_0}")] Ge(Substr),
#[debug("{_0}")] Range(Substr),
#[debug("{_0}")] Assign(Substr),
#[debug("{_0}")] Cast(Substr),
}
#[derive(Debug)]
pub enum Type {
Ptr { base: Expr, mutable: Option<Substr> },
Struct(Struct),
}
#[derive(Debug)]
pub struct ConstDecl {
pub names: NamePattern,
pub r#type: Option<Expr>,
pub value: Expr,
}
#[derive(Debug)]
pub struct VarDecl {
pub names: NamePattern,
pub r#type: Option<Expr>,
pub value: Expr,
}
#[derive(Debug)]
pub enum NamePattern {
Single(Ident),
Tuple(Vec<Ident>),
List(Vec<Ident>),
}
impl NamePattern {
pub fn as_slice(&self) -> &[Ident] {
match self {
NamePattern::Single(ident) => std::slice::from_ref(ident),
NamePattern::Tuple(idents) => idents.as_slice(),
NamePattern::List(idents) => idents.as_slice(),
}
}
}
#[derive(Debug)]
pub struct Function {
pub text: Substr,
pub args: Vec<NameValuePair>,
pub ret: Option<Expr>,
pub block: Option<Arc<Block>>,
}
#[derive(Debug)]
pub struct NameValuePair {
pub name: Ident,
pub value: Expr,
}
#[derive(Debug)]
pub struct Struct {
pub fields: Vec<Field>,
}
#[derive(Debug)]
pub struct Field {
pub name: Ident,
pub ty: Expr,
pub public: Option<Substr>,
pub mutable: Option<Substr>,
}
#[derive(Debug)]
pub struct StructCtor {
pub r#type: Option<Expr>,
pub r#values: IndexMap<Substr, NameValuePair>,
pub(crate) range: Range<usize>,
}
impl StructCtor {
pub fn range(&self) -> Range<usize> {
self.range.clone()
}
}
#[derive(Debug)]
pub struct Block(pub Vec<Expr>);
#[derive(Debug)]
pub struct For {
pub names: NamePattern,
pub value: Expr,
pub block: Block,
}
#[derive(Debug)]
pub struct While {
pub cond: Expr,
pub block: Block,
}
#[derive(Debug)]
pub struct If {
pub cond: Expr,
pub block: Block,
pub else_: Option<Box<Else>>,
}
#[derive(Debug)]
pub enum Else {
If(If),
Block(Block),
}
#[derive(Debug)]
pub struct CompilationUnit {
pub imports: Vec<Import>,
pub decls: Vec<ConstDecl>,
}