diff --git a/src/ast.rs b/src/ast.rs new file mode 100644 index 0000000..6907591 --- /dev/null +++ b/src/ast.rs @@ -0,0 +1,192 @@ +use std::string::ToString; + +pub trait AstNode: ToString {} + +pub trait Expr: AstNode { + fn get_base(&self) -> BaseType; +} + +pub trait Statement: AstNode {} + +#[derive(Copy, Clone)] +pub enum Quantifier { + Const, + Var, +} + +impl ToString for Quantifier { + fn to_string(&self) -> String { + match *self { + Quantifier::Const => "const", + Quantifier::Var => "var", + }.to_string() + } +} + +#[derive(Copy, Clone)] +pub enum BaseType { + Int, + Real, + Never, +} + +impl ToString for BaseType { + fn to_string(&self) -> String { + // TODO: Use typedefs when possible. Might fit better on a high level node + match *self { + BaseType::Int => "integer", + BaseType::Real => "real", + BaseType::Never => panic!("Attempting to get string of never type"), + }.to_string() + } +} + +pub struct Block { + statements: Vec, +} + +impl ToString for Block { + fn to_string(&self) -> String { + let mut s = String::from("{ "); + + for stat in &self.statements { + s.push_str(&stat.to_string()); + s.push(' '); + } + + s.push('}'); + s + } +} + +impl AstNode for Block {} + +impl Statement for Block {} + +pub enum Literal { + Int(i32), + Real(f32), +} + +impl ToString for Literal { + fn to_string(&self) -> String { + match *self { + Literal::Int(x) => x.to_string(), + Literal::Real(x) => x.to_string(), + } + } +} + +impl AstNode for Literal {} + +impl Expr for Literal { + fn get_base(&self) -> BaseType { + match *self { + Literal::Int(_) => BaseType::Int, + Literal::Real(_) => BaseType::Real, + } + } +} + +pub struct Declaration { + variable: Variable, + assn: T, +} + +impl ToString for Declaration { + fn to_string(&self) -> String { + let mut s = String::new(); + + s.push_str(&self.variable.quantifer.to_string()); + s.push(' '); + s.push_str(&self.variable.get_base().to_string()); + s.push(' '); + s.push_str(&self.variable.to_string()); + s.push_str(" = "); + s.push_str(&self.assn.to_string()); + s.push(';'); + + s + } +} + +impl AstNode for Declaration {} + +impl Statement for Declaration {} + +pub struct Variable { + type_: BaseType, + quantifer: Quantifier, + name: String, +} + +impl ToString for Variable { + fn to_string(&self) -> String { + self.name.clone() + } +} + +impl AstNode for Variable {} + +impl Expr for Variable { + fn get_base(&self) -> BaseType { + self.type_ + } +} + +pub enum BinaryOperator +{ + Add(L, R), + Subtract(L, R), + Multiply(L, R), + Divide(L, R), +} + +impl ToString for BinaryOperator { + fn to_string(&self) -> String { + let mut s = String::new(); + + s.push('('); + match self { + BinaryOperator::Add(l, _) => s.push_str(&l.to_string()), + BinaryOperator::Subtract(l, _) => s.push_str(&l.to_string()), + BinaryOperator::Multiply(l, _) => s.push_str(&l.to_string()), + BinaryOperator::Divide(l, _) => s.push_str(&l.to_string()), + } + s.push(')'); + + s.push( + match self { + &BinaryOperator::Add(_, _) => '+', + &BinaryOperator::Subtract(_, _) => '-', + &BinaryOperator::Multiply(_, _) => '*', + &BinaryOperator::Divide(_, _) => '/', + } + ); + + s.push('('); + match self { + BinaryOperator::Add(_, r) => s.push_str(&r.to_string()), + BinaryOperator::Subtract(_, r) => s.push_str(&r.to_string()), + BinaryOperator::Multiply(_, r) => s.push_str(&r.to_string()), + BinaryOperator::Divide(_, r) => s.push_str(&r.to_string()), + } + s.push(')'); + + s + } +} + +impl AstNode for BinaryOperator {} + +impl Expr for BinaryOperator { + fn get_base(&self) -> BaseType { + // TODO: This get_base is clearly wrong + match self { + BinaryOperator::Add(l, _) => l.get_base(), + BinaryOperator::Subtract(l, _) => l.get_base(), + BinaryOperator::Multiply(l, _) => l.get_base(), + BinaryOperator::Divide(l, _) => l.get_base(), + } + } +}