able-script/ablescript/src/ast.rs

232 lines
4.9 KiB
Rust
Raw Normal View History

//! AbleScript's Abstract Syntax tree
//!
//! Statements are the type which is AST made of, as they
//! express an effect.
//!
//! Expressions are just operations and they cannot be
//! used as statements. Functions in AbleScript are in fact
//! just plain subroutines and they do not return any value,
//! so their calls are statements.
2021-08-07 17:33:28 -05:00
use std::hash::Hash;
2021-06-06 14:09:18 -05:00
use crate::variables::Value;
type Span = std::ops::Range<usize>;
2021-08-07 17:33:28 -05:00
#[derive(Debug, Clone)]
2021-10-04 16:00:18 -05:00
pub struct Ident {
pub ident: String,
pub span: Span,
}
2021-06-06 14:09:18 -05:00
2021-10-04 16:00:18 -05:00
impl Ident {
pub fn new(ident: String, span: Span) -> Self {
Self { ident, span }
}
}
2021-10-04 16:00:18 -05:00
impl PartialEq for Ident {
2021-08-07 17:33:28 -05:00
fn eq(&self, other: &Self) -> bool {
2021-10-04 16:00:18 -05:00
self.ident == other.ident
2021-08-07 17:33:28 -05:00
}
}
2021-10-04 16:00:18 -05:00
impl Hash for Ident {
2021-08-07 17:33:28 -05:00
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
2021-10-04 16:00:18 -05:00
self.ident.hash(state)
2021-08-07 17:33:28 -05:00
}
}
#[derive(Debug, PartialEq, Clone, Hash)]
pub struct Assignable {
pub ident: Ident,
pub kind: AssignableKind,
}
#[derive(Debug, PartialEq, Clone, Hash)]
pub enum AssignableKind {
Variable,
2021-10-13 06:20:23 -05:00
Index { indices: Vec<Expr> },
}
2021-10-21 13:51:24 -05:00
impl Assignable {
pub fn from_expr(expr: Expr) -> Result<Assignable, ()> {
match expr.kind {
ExprKind::Variable(ident) => Ok(Assignable {
ident: Ident::new(ident, expr.span),
kind: AssignableKind::Variable,
}),
ExprKind::Index { expr, index } => Self::from_index(*expr, *index),
_ => Err(()),
}
}
fn from_index(mut buf: Expr, index: Expr) -> Result<Assignable, ()> {
let mut indices = vec![index];
let ident = loop {
match buf.kind {
ExprKind::Variable(ident) => break ident,
ExprKind::Index { expr, index } => {
indices.push(*index);
buf = *expr;
}
_ => return Err(()),
}
};
indices.reverse();
Ok(Assignable {
ident: Ident::new(ident, buf.span),
kind: AssignableKind::Index { indices },
})
}
}
2021-08-07 17:33:28 -05:00
#[derive(Debug, PartialEq, Clone, Hash)]
2021-06-06 14:09:18 -05:00
pub struct Block {
pub block: Vec<Stmt>,
}
/// A syntactic unit expressing an effect.
2021-08-07 17:33:28 -05:00
#[derive(Debug, Clone)]
2021-06-06 14:09:18 -05:00
pub struct Stmt {
pub kind: StmtKind,
pub span: Span,
}
2021-08-07 17:33:28 -05:00
impl PartialEq for Stmt {
fn eq(&self, other: &Self) -> bool {
self.kind == other.kind
}
}
impl Hash for Stmt {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.kind.hash(state)
}
}
#[derive(Debug, PartialEq, Clone, Hash)]
2021-06-06 14:09:18 -05:00
pub enum StmtKind {
// Control flow
If {
cond: Expr,
body: Block,
},
Loop {
body: Block,
},
Break,
HopBack,
Var {
2021-10-04 16:00:18 -05:00
ident: Ident,
2021-06-06 14:09:18 -05:00
init: Option<Expr>,
},
Assign {
assignable: Assignable,
value: Expr,
},
2021-06-06 14:09:18 -05:00
Functio {
2021-10-04 16:00:18 -05:00
ident: Ident,
params: Vec<Ident>,
2021-06-06 14:09:18 -05:00
body: Block,
},
2021-06-11 10:52:47 -05:00
BfFunctio {
2021-10-04 16:00:18 -05:00
ident: Ident,
2021-06-11 10:52:47 -05:00
tape_len: Option<Expr>,
2021-06-11 11:10:11 -05:00
code: Vec<u8>,
2021-06-11 10:52:47 -05:00
},
2021-06-06 14:09:18 -05:00
Call {
expr: Expr,
args: Vec<Expr>,
2021-06-06 14:09:18 -05:00
},
Print(Expr),
Read(Assignable),
2021-10-04 16:00:18 -05:00
Melo(Ident),
2021-06-07 04:07:50 -05:00
Rlyeh,
2021-06-13 20:40:42 -05:00
Rickroll,
2021-06-06 14:09:18 -05:00
}
impl Stmt {
pub fn new(kind: StmtKind, span: Span) -> Self {
Self { kind, span }
}
}
/// Expression is parse unit which do not cause any effect,
/// like math and logical operations or values.
2021-08-07 17:33:28 -05:00
#[derive(Debug, Clone)]
2021-06-06 14:09:18 -05:00
pub struct Expr {
pub kind: ExprKind,
pub span: Span,
2021-06-06 14:09:18 -05:00
}
2021-08-07 17:33:28 -05:00
impl PartialEq for Expr {
fn eq(&self, other: &Self) -> bool {
self.kind == other.kind
}
}
impl Hash for Expr {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.kind.hash(state)
}
}
#[derive(Debug, PartialEq, Clone, Hash)]
2021-06-06 14:09:18 -05:00
pub enum ExprKind {
BinOp {
2021-06-06 14:09:18 -05:00
lhs: Box<Expr>,
rhs: Box<Expr>,
kind: BinOpKind,
},
Not(Box<Expr>),
Literal(Value),
2021-07-27 04:51:05 -05:00
Cart(Vec<(Expr, Expr)>),
Index {
2021-08-28 16:27:35 -05:00
expr: Box<Expr>,
2021-07-27 04:51:05 -05:00
index: Box<Expr>,
},
2022-01-22 13:37:44 -06:00
Len(Box<Expr>),
Variable(String),
2021-06-06 14:09:18 -05:00
}
impl Expr {
pub fn new(kind: ExprKind, span: Span) -> Self {
Self { kind, span }
}
}
2021-08-07 17:33:28 -05:00
#[derive(Debug, PartialEq, Clone, Hash)]
2021-06-06 14:09:18 -05:00
pub enum BinOpKind {
Add,
Subtract,
Multiply,
Divide,
Greater,
Less,
Equal,
NotEqual,
}
2021-06-07 02:17:18 -05:00
impl BinOpKind {
pub fn from_token(t: crate::lexer::Token) -> Result<Self, crate::error::ErrorKind> {
use crate::lexer::Token;
match t {
Token::Plus => Ok(Self::Add),
Token::Minus => Ok(Self::Subtract),
Token::Star => Ok(Self::Multiply),
Token::FwdSlash => Ok(Self::Divide),
Token::GreaterThan => Ok(Self::Greater),
Token::LessThan => Ok(Self::Less),
Token::EqualEqual => Ok(Self::Equal),
Token::NotEqual => Ok(Self::NotEqual),
t => Err(crate::error::ErrorKind::UnexpectedToken(t)),
2021-06-07 02:17:18 -05:00
}
}
}