updated compiler to support multiple frontends and backends
This commit is contained in:
@@ -0,0 +1,213 @@
|
||||
use core::fmt;
|
||||
|
||||
#[allow(unused)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum CompilerError {
|
||||
UnexpectedToken(String),
|
||||
UnexpectedEndOfInput,
|
||||
UnexpectedCharacter(char),
|
||||
Undefined(Name),
|
||||
InvalidSyntax(String),
|
||||
Generic(String),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct Name {
|
||||
pub name: String,
|
||||
pub namespace: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Program {
|
||||
pub declarations: Vec<Declaration>,
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Declaration {
|
||||
Function {
|
||||
name: String,
|
||||
return_type: TypeId,
|
||||
params: Vec<Variable>,
|
||||
body: Block,
|
||||
},
|
||||
Variable {
|
||||
var: Variable,
|
||||
init: Option<ConstExpr>,
|
||||
is_const: bool,
|
||||
},
|
||||
Dependency(Dependency),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Dependency {
|
||||
pub name: String,
|
||||
pub path: String,
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum TypeId {
|
||||
U8,
|
||||
U16,
|
||||
U32,
|
||||
I8,
|
||||
I16,
|
||||
I32,
|
||||
Char,
|
||||
Void,
|
||||
Ptr(Box<TypeId>),
|
||||
Ref(Box<TypeId>),
|
||||
Array(Box<TypeId>, usize),
|
||||
Struct { name: Name, fields: Vec<Variable> },
|
||||
}
|
||||
|
||||
pub type Block = Vec<Statement>;
|
||||
|
||||
#[allow(unused)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Variable {
|
||||
pub name: String,
|
||||
pub type_id: TypeId,
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Statement {
|
||||
Block(Block),
|
||||
Declaration {
|
||||
var: Variable,
|
||||
value: Option<Expression>,
|
||||
},
|
||||
Assign {
|
||||
varname: String,
|
||||
value: Expression,
|
||||
},
|
||||
PtrWrite {
|
||||
ptr: Expression,
|
||||
value: Expression,
|
||||
},
|
||||
Expression {
|
||||
expr: Expression,
|
||||
},
|
||||
If {
|
||||
condition: Expression,
|
||||
then_stmt: Block,
|
||||
else_stmt: Block,
|
||||
},
|
||||
While {
|
||||
condition: Expression,
|
||||
body: Vec<Statement>,
|
||||
},
|
||||
Loop(Block),
|
||||
Break,
|
||||
Continue,
|
||||
Return(Option<Expression>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ConstExpr {
|
||||
Number(i32),
|
||||
String(String),
|
||||
}
|
||||
|
||||
impl fmt::Display for ConstExpr {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
ConstExpr::Number(n) => write!(f, "{}", n),
|
||||
ConstExpr::String(s) => write!(f, "\"{}\"", s),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Expression {
|
||||
Empty,
|
||||
Binary {
|
||||
op: BinaryOperator,
|
||||
left: Box<Expression>,
|
||||
right: Box<Expression>,
|
||||
},
|
||||
Unary {
|
||||
op: UnaryOperator,
|
||||
operand: Box<Expression>,
|
||||
},
|
||||
Variable {
|
||||
name: Name,
|
||||
expr_type: Option<TypeId>,
|
||||
},
|
||||
Call {
|
||||
name: Name,
|
||||
args: Vec<Expression>,
|
||||
},
|
||||
Number(isize),
|
||||
StringLiteral(String),
|
||||
CharLiteral(char),
|
||||
}
|
||||
|
||||
impl Expression {
|
||||
pub fn is_pure(&self) -> bool {
|
||||
match self {
|
||||
Expression::Number(_) => true,
|
||||
Expression::StringLiteral(_) => true,
|
||||
Expression::CharLiteral(_) => true,
|
||||
Expression::Call { .. } => false,
|
||||
Expression::Binary { left, right, .. } => left.is_pure() && right.is_pure(),
|
||||
Expression::Unary { operand, .. } => operand.is_pure(),
|
||||
Expression::Empty => true,
|
||||
Expression::Variable { .. } => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum BinaryOperator {
|
||||
Add,
|
||||
Sub,
|
||||
Mul,
|
||||
Div,
|
||||
Eq,
|
||||
Ne,
|
||||
Lt,
|
||||
Gt,
|
||||
Le,
|
||||
Ge,
|
||||
}
|
||||
|
||||
impl fmt::Display for BinaryOperator {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
BinaryOperator::Add => write!(f, "+"),
|
||||
BinaryOperator::Sub => write!(f, "-"),
|
||||
BinaryOperator::Mul => write!(f, "*"),
|
||||
BinaryOperator::Div => write!(f, "/"),
|
||||
BinaryOperator::Eq => write!(f, "=="),
|
||||
BinaryOperator::Ne => write!(f, "!="),
|
||||
BinaryOperator::Lt => write!(f, "<"),
|
||||
BinaryOperator::Gt => write!(f, ">"),
|
||||
BinaryOperator::Le => write!(f, "<="),
|
||||
BinaryOperator::Ge => write!(f, ">="),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum UnaryOperator {
|
||||
Plus,
|
||||
Minus,
|
||||
Reference,
|
||||
Dereference,
|
||||
}
|
||||
|
||||
impl fmt::Display for UnaryOperator {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
UnaryOperator::Plus => write!(f, "+"),
|
||||
UnaryOperator::Minus => write!(f, "-"),
|
||||
UnaryOperator::Dereference => write!(f, "*"),
|
||||
UnaryOperator::Reference => write!(f, "&"),
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user