pub type Loc = std::ops::Range<usize>;
pub trait Locate {
fn loc(&self) -> Loc;
}
#[derive(Clone, Debug, PartialEq)]
pub struct None {
pub loc: Loc,
}
impl None {
pub fn new(loc: Loc) -> Self {
Self { loc }
}
}
impl Locate for None {
fn loc(&self) -> Loc {
self.loc.clone()
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Bool<'input> {
pub loc: Loc,
pub value: &'input str,
}
impl<'input> Bool<'input> {
pub fn new(loc: Loc, value: &'input str) -> Self {
Self { loc, value }
}
}
impl<'input> Locate for Bool<'input> {
fn loc(&self) -> Loc {
self.loc.clone()
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum NumKind {
Dec,
Hex,
Bin,
Oct,
Float,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Num<'input> {
pub loc: Loc,
pub kind: NumKind,
pub value: &'input str,
}
impl<'input> Num<'input> {
pub fn dec(loc: Loc, value: &'input str) -> Self {
Self { loc, kind: NumKind::Dec, value }
}
pub fn hex(loc: Loc, value: &'input str) -> Self {
Self { loc, kind: NumKind::Hex, value }
}
pub fn bin(loc: Loc, value: &'input str) -> Self {
Self { loc, kind: NumKind::Bin, value }
}
pub fn oct(loc: Loc, value: &'input str) -> Self {
Self { loc, kind: NumKind::Oct, value }
}
pub fn float(loc: Loc, value: &'input str) -> Self {
Self { loc, kind: NumKind::Float, value }
}
}
impl<'input> Locate for Num<'input> {
fn loc(&self) -> Loc {
self.loc.clone()
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Ident<'input> {
pub loc: Loc,
pub value: &'input str,
}
impl<'input> Ident<'input> {
pub fn new(loc: Loc, value: &'input str) -> Self {
Self { loc, value }
}
}
impl<'input> Locate for Ident<'input> {
fn loc(&self) -> Loc {
self.loc.clone()
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Atom<'input> {
pub loc: Loc,
pub value: &'input str,
}
impl<'input> Atom<'input> {
pub fn new(loc: Loc, value: &'input str) -> Self {
Self { loc, value }
}
}
impl<'input> Locate for Atom<'input> {
fn loc(&self) -> Loc {
self.loc.clone()
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Str<'input> {
pub loc: Loc,
pub value: &'input str,
}
impl<'input> Str<'input> {
pub fn new(loc: Loc, value: &'input str) -> Self {
Self { loc, value }
}
}
impl<'input> Locate for Str<'input> {
fn loc(&self) -> Loc {
self.loc.clone()
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum BinaryOp {
ObjIdx,
StaticIdx,
ExprIdx,
Mul,
Div,
Mod,
Add,
Sub,
Shl,
Shr,
BitAnd,
BitXor,
BitOr,
Eq,
Neq,
Lt,
Gt,
LtEq,
GtEq,
And,
Or,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Binary<'input> {
pub loc: Loc,
pub op: BinaryOp,
pub left: Box<Expr<'input>>,
pub right: Box<Expr<'input>>,
}
impl<'input> Binary<'input> {
pub fn new(loc: Loc, op: BinaryOp, left: Box<Expr<'input>>, right: Box<Expr<'input>>) -> Self {
Self { loc, op, left, right }
}
}
impl<'input> Locate for Binary<'input> {
fn loc(&self) -> Loc {
self.loc.clone()
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Call<'input> {
pub loc: Loc,
pub fun: Box<Expr<'input>>,
pub args: Vec<Expr<'input>>,
}
impl<'input> Call<'input> {
pub fn new(loc: Loc, fun: Box<Expr<'input>>, args: Vec<Expr<'input>>) -> Self {
Self { loc, fun, args }
}
}
impl<'input> Locate for Call<'input> {
fn loc(&self) -> Loc {
self.loc.clone()
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum UnaryOp {
Deref,
Cloned,
Pos,
Neg,
Not,
BitNot,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Unary<'input> {
pub loc: Loc,
pub op: UnaryOp,
pub subject: Box<Expr<'input>>,
}
impl<'input> Unary<'input> {
pub fn new(loc: Loc, op: UnaryOp, subject: Box<Expr<'input>>) -> Self {
Self { loc, op, subject }
}
}
impl<'input> Locate for Unary<'input> {
fn loc(&self) -> Loc {
self.loc.clone()
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum AssignOp {
Assign,
AssignAdd,
AssignSub,
AssignMul,
AssignDiv,
AssignMod,
AssignBitOr,
AssignBitXor,
AssignShl,
AssignShr,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Assign<'input> {
pub loc: Loc,
pub op: AssignOp,
pub left: Box<Expr<'input>>,
pub right: Box<Expr<'input>>,
}
impl<'input> Assign<'input> {
pub fn new(loc: Loc, op: AssignOp, left: Box<Expr<'input>>, right: Box<Expr<'input>>) -> Self {
Self { loc, op, left, right }
}
}
impl<'input> Locate for Assign<'input> {
fn loc(&self) -> Loc {
self.loc.clone()
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Block<'input> {
pub loc: Loc,
pub action: Vec<Expr<'input>>,
}
impl<'input> Block<'input> {
pub fn new(loc: Loc, action: Vec<Expr<'input>>) -> Self {
Self { loc, action }
}
}
impl<'input> Locate for Block<'input> {
fn loc(&self) -> Loc {
self.loc.clone()
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct ElseIf<'input> {
pub loc: Loc,
pub cond: Box<Expr<'input>>,
pub block: Block<'input>,
}
impl<'input> ElseIf<'input> {
pub fn new(loc: Loc, cond: Box<Expr<'input>>, block: Block<'input>) -> Self {
Self { loc, cond, block }
}
}
impl<'input> Locate for ElseIf<'input> {
fn loc(&self) -> Loc {
self.loc.clone()
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Else<'input> {
pub loc: Loc,
pub block: Block<'input>,
}
impl<'input> Else<'input> {
pub fn new(loc: Loc, block: Block<'input>) -> Self {
Self { loc, block }
}
}
impl<'input> Locate for Else<'input> {
fn loc(&self) -> Loc {
self.loc.clone()
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum IfBranch<'input> {
ElseIf(ElseIf<'input>),
Else(Else<'input>),
}
impl<'input> Locate for IfBranch<'input> {
fn loc(&self) -> Loc {
match self {
Self::ElseIf(branch) => branch.loc(),
Self::Else(branch) => branch.loc(),
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct If<'input> {
pub loc: Loc,
pub label: Option<Ident<'input>>,
pub cond: Box<Expr<'input>>,
pub block: Block<'input>,
pub branches: Vec<IfBranch<'input>>,
}
impl<'input> If<'input> {
pub fn new(loc: Loc, label: Option<Ident<'input>>, cond: Box<Expr<'input>>, block: Block<'input>, branches: Vec<IfBranch<'input>>) -> Self {
Self { loc, label, cond, block, branches }
}
}
impl<'input> Locate for If<'input> {
fn loc(&self) -> Loc {
self.loc.clone()
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct InlineFun<'input> {
pub loc: Loc,
pub args: Vec<Ident<'input>>,
pub block: Block<'input>,
}
impl<'input> InlineFun<'input> {
pub fn new(loc: Loc, args: Vec<Ident<'input>>, block: Block<'input>) -> Self {
Self { loc, args, block }
}
}
impl<'input> Locate for InlineFun<'input> {
fn loc(&self) -> Loc {
self.loc.clone()
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Fun<'input> {
pub loc: Loc,
pub publ: bool,
pub name: Ident<'input>,
pub args: Vec<Ident<'input>>,
pub block: Block<'input>,
}
impl<'input> Fun<'input> {
pub fn new(loc: Loc, publ: bool, name: Ident<'input>, args: Vec<Ident<'input>>, block: Block<'input>) -> Self {
Self { loc, publ, name, args, block }
}
}
impl<'input> Locate for Fun<'input> {
fn loc(&self) -> Loc {
self.loc.clone()
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum Expr<'input> {
None(None),
Bool(Bool<'input>),
Num(Num<'input>),
Ident(Ident<'input>),
Atom(Atom<'input>),
Str(Str<'input>),
Binary(Binary<'input>),
Call(Call<'input>),
Unary(Unary<'input>),
Assign(Assign<'input>),
If(If<'input>),
InlineFun(InlineFun<'input>),
Fun(Fun<'input>),
Block(Block<'input>),
}
impl<'input> Expr<'input> {
#[inline]
pub fn none(loc: Loc) -> Self {
Self::None(None::new(loc))
}
#[inline]
pub fn bool(loc: Loc, value: &'input str) -> Self {
Self::Bool(Bool::new(loc, value))
}
#[inline]
pub fn dec(loc: Loc, value: &'input str) -> Self {
Self::Num(Num::dec(loc, value))
}
#[inline]
pub fn hex(loc: Loc, value: &'input str) -> Self {
Self::Num(Num::hex(loc, value))
}
#[inline]
pub fn bin(loc: Loc, value: &'input str) -> Self {
Self::Num(Num::bin(loc, value))
}
#[inline]
pub fn oct(loc: Loc, value: &'input str) -> Self {
Self::Num(Num::oct(loc, value))
}
#[inline]
pub fn float(loc: Loc, value: &'input str) -> Self {
Self::Num(Num::float(loc, value))
}
#[inline]
pub fn ident(loc: Loc, value: &'input str) -> Self {
Self::Ident(Ident::new(loc, value))
}
#[inline]
pub fn atom(loc: Loc, value: &'input str) -> Self {
Self::Ident(Ident::new(loc, value))
}
#[inline]
pub fn str(loc: Loc, value: &'input str) -> Self {
Self::Str(Str::new(loc, value))
}
#[inline]
pub fn binary(loc: Loc, left: Self, op: BinaryOp, right: Self) -> Self {
Self::Binary(Binary::new(loc, op, Box::new(left), Box::new(right)))
}
#[inline]
pub fn call(loc: Loc, fun: Self, args: Vec<Self>) -> Self {
Self::Call(Call::new(loc, Box::new(fun), args))
}
#[inline]
pub fn unary(loc: Loc, op: UnaryOp, subject: Self) -> Self {
Self::Unary(Unary::new(loc, op, Box::new(subject)))
}
#[inline]
pub fn assign(loc: Loc, left: Self, op: AssignOp, right: Self) -> Self {
Self::Assign(Assign::new(loc, op, Box::new(left), Box::new(right)))
}
}
impl<'input> Locate for Expr<'input> {
fn loc(&self) -> Loc {
match self {
Expr::None(expr) => expr.loc(),
Expr::Bool(expr) => expr.loc(),
Expr::Num(expr) => expr.loc(),
Expr::Ident(expr) => expr.loc(),
Expr::Atom(expr) => expr.loc(),
Expr::Str(expr) => expr.loc(),
Expr::Binary(expr) => expr.loc(),
Expr::Call(expr) => expr.loc(),
Expr::Unary(expr) => expr.loc(),
Expr::Assign(expr) => expr.loc(),
Expr::If(expr) => expr.loc(),
Expr::InlineFun(expr) => expr.loc(),
Expr::Fun(expr) => expr.loc(),
Expr::Block(expr) => expr.loc(),
}
}
}