205 lines
4.0 KiB
Rust
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(),
|
|
}
|
|
}
|
|
}
|