use std::fmt; use std::fmt::Formatter; #[derive(Debug, PartialEq, Clone)] pub struct Program { pub stmts: Vec, } impl fmt::Display for Program { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { for stmt in &self.stmts { write!(f, "{}", stmt)?; } Ok(()) } } #[derive(Debug, PartialEq, Clone)] pub struct BlockStatement { pub stmts: Vec, } impl fmt::Display for BlockStatement { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{{"); for stmt in &self.stmts { write!(f, "{}", stmt)?; } write!(f, "}}"); Ok(()) } } #[derive(Debug, PartialEq, Clone)] pub enum Prefix { Minus, Bang } impl fmt::Display for Prefix { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { Prefix::Minus => write!(f, "-"), Prefix::Bang => write!(f, "!"), } } } #[derive(Debug, PartialEq, Clone)] pub enum Infix { Eq, NotEq, Lt, Gt, Plus, Minus, Asterisk, Slash, LBracket, } impl fmt::Display for Infix { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { Infix::Eq => write!(f, "=="), Infix::NotEq => write!(f, "!="), Infix::Lt => write!(f, "<"), Infix::Gt => write!(f, ">"), Infix::Plus => write!(f, "+"), Infix::Minus => write!(f, "-"), Infix::Asterisk => write!(f, "*"), Infix::Slash => write!(f, "/"), Infix::LBracket => write!(f, "["), } } } #[derive(Debug, PartialEq, Clone)] pub enum Expression { Identifier(String), IntegerLiteral(i64), String(String), Boolean(bool), Prefix(Prefix, Box), Infix(Infix, Box, Box), If(Box, Box, Option>), FunctionLiteral(Vec, Box), DictionaryLiteral(Vec<(Expression, Expression)>), ArrayLiteral(Vec), Index(Box, Box), Call(Box, Vec), } impl fmt::Display for Expression { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { Expression::Identifier(s) => write!(f, "{}", s), Expression::IntegerLiteral(i) => write!(f, "{}", i), Expression::String(s) => write!(f, "\"{}\"", s), Expression::Boolean(b) => write!(f, "{}", b), Expression::Prefix(p, exp) => write!(f, "({}{})", p, exp), Expression::Infix(op, left, right) => write!(f, "({} {} {})", left, op, right), Expression::If(exp, true_blk, Some(false_blk)) => write!(f,"if ({}) {} else {}", exp, true_blk, false_blk), Expression::If(exp, true_blk, None) => write!(f,"if ({}) {}", exp, true_blk), Expression::DictionaryLiteral(key_values) => { let mut str = String::new(); str.push_str("{"); for (k, v) in key_values{ str.push_str(format!("{}:{},", k, v).as_str()); } if str.ends_with(',') { str.pop(); } str.push_str("}"); write!(f, "{}", str) }, Expression::ArrayLiteral(members) => write!(f, "[{}]", members.iter().map(|a| a.to_string()).collect::>().join(",")), Expression::Index(arr, idx) => write!(f, "{}[{}]", arr.to_string(), idx.to_string()), Expression::FunctionLiteral(params, block) => write!(f, "fn({}){}", params.join(","), block), Expression::Call(exp, params) => write!(f, "{}({})", exp, params.iter().map(|a| a.to_string()).collect::>().join(",")), } } } #[derive(Debug, PartialEq, Clone)] pub enum Statement { Let(String, Box), Return(Option>), Expression(Box), } impl fmt::Display for Statement { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { Statement::Let(s, exp) => write!(f, "let {} = {};", s, exp), Statement::Return(None) => write!(f, "return;"), Statement::Return(Some(val)) => write!(f, "return {};", val), Statement::Expression(exp) => write!(f, "{};", exp), } } }