sprite-rs/src/parse/ast.rs

205 lines
4.0 KiB
Rust

// Copyright (c) 2022 Marceline Cramer
// SPDX-License-Identifier: GPL-3.0-or-later
use super::lexer::Token;
#[derive(Debug)]
pub struct Ast<'a> {
pub defs: Vec<Definition<'a>>,
}
#[derive(Debug)]
pub enum Definition<'a> {
Struct {
name: &'a str,
members: Vec<StructMember<'a>>,
},
Function {
associated_struct: Option<&'a str>,
implementation: FnImpl<'a>,
},
Interface {
name: &'a str,
functions: Vec<FnDef<'a>>,
},
Impl {
structure: &'a str,
interface: Option<&'a str>,
functions: Vec<FnImpl<'a>>,
},
}
#[derive(Debug)]
pub struct FnImpl<'a> {
pub def: FnDef<'a>,
pub body: BranchBody<'a>,
}
#[derive(Debug)]
pub struct FnDef<'a> {
pub mutable: bool,
pub name: &'a str,
pub signature: FnSig<'a>,
}
#[derive(Debug)]
pub struct StructMember<'a> {
pub type_name: &'a str,
pub name: &'a str,
}
#[derive(Debug)]
pub struct FnSig<'a> {
pub args: Vec<FnArg<'a>>,
pub return_type: Option<&'a str>,
}
#[derive(Debug)]
pub struct FnArg<'a> {
pub type_name: &'a str,
pub name: Option<&'a str>,
}
#[derive(Debug)]
pub struct BranchBody<'a> {
pub statements: Vec<Statement<'a>>,
pub tail_expr: Option<Box<Expr<'a>>>,
}
type ExprPair<'a> = Box<(Expr<'a>, Expr<'a>)>;
#[derive(Debug)]
pub enum Expr<'a> {
BinaryOp(BinaryOp, ExprPair<'a>),
UnaryOp(UnaryOp, Box<Expr<'a>>),
Literal(Literal<'a>),
Local(&'a str),
Member(&'a str, Box<Expr<'a>>),
SelfMember(&'a str),
Group(Box<Expr<'a>>),
FnCall(Box<Expr<'a>>, Vec<Expr<'a>>),
If(IfExpr<'a>),
}
#[derive(Debug)]
pub enum BinaryOp {
Add,
Sub,
Mul,
Div,
Assign,
BoolOr,
BoolAnd,
BitOr,
BitAnd,
BitXor,
Less,
LessEq,
Greater,
GreaterEq,
Eq,
Neq,
}
impl BinaryOp {
pub fn from_token(tok: Token) -> Option<Self> {
use BinaryOp::*;
use Token::*;
match tok {
OpAdd => Some(Add),
OpSub => Some(Sub),
OpMul => Some(Mul),
OpDiv => Some(Div),
OpAssign => Some(Assign),
OpBoolOr => Some(BoolOr),
OpBoolAnd => Some(BoolAnd),
OpBitOr => Some(BitOr),
OpBitAnd => Some(BitAnd),
OpBitXor => Some(BitXor),
OpLess => Some(Less),
OpLessEq => Some(LessEq),
OpGreater => Some(Greater),
OpGreaterEq => Some(GreaterEq),
OpEq => Some(Eq),
OpNeq => Some(Neq),
_ => None,
}
}
}
#[derive(Debug)]
pub enum UnaryOp {
BoolNot,
BitNot,
Negate,
}
impl UnaryOp {
pub fn from_token(tok: Token) -> Option<Self> {
use Token::*;
use UnaryOp::*;
match tok {
OpBoolNot => Some(BoolNot),
OpBitNot => Some(BitNot),
OpSub => Some(Negate),
_ => None,
}
}
}
#[derive(Debug)]
pub enum Literal<'a> {
BinaryInteger(&'a str),
OctalInteger(&'a str),
HexInteger(&'a str),
DecimalInteger(&'a str),
DecimalFloat(&'a str),
String(&'a str),
Boolean(bool),
}
#[derive(Debug)]
pub enum Statement<'a> {
Expr(Expr<'a>),
If(IfStmt<'a>),
While {
test_expr: Expr<'a>,
loop_body: BranchBody<'a>,
},
Let {
var: &'a str,
mutable: bool,
expr: Expr<'a>,
},
}
#[derive(Debug)]
pub struct IfExpr<'a> {
pub test_expr: Box<Expr<'a>>,
pub then_body: BranchBody<'a>,
pub else_body: BranchBody<'a>,
}
#[derive(Debug)]
pub struct IfStmt<'a> {
pub test_expr: Expr<'a>,
pub then_body: BranchBody<'a>,
pub else_body: Option<BranchBody<'a>>,
}
impl<'a> IfStmt<'a> {
pub fn to_expr(self) -> IfExpr<'a> {
let Self {
test_expr,
then_body,
else_body,
} = self;
IfExpr {
test_expr: Box::new(test_expr),
then_body,
else_body: else_body.unwrap(),
}
}
}