Files
simple-rust-tests/__lang/monkey-rs/src/ast.rs
2022-06-02 00:32:03 +08:00

152 lines
4.5 KiB
Rust

use std::fmt;
use std::fmt::Formatter;
#[derive(Debug, PartialEq, Clone)]
pub struct Program {
pub stmts: Vec<Statement>,
}
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<Statement>,
}
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<Expression>),
Infix(Infix, Box<Expression>, Box<Expression>),
If(Box<Expression>, Box<BlockStatement>, Option<Box<BlockStatement>>),
FunctionLiteral(Vec<String>, Box<BlockStatement>),
DictionaryLiteral(Vec<(Expression, Expression)>),
ArrayLiteral(Vec<Expression>),
Index(Box<Expression>, Box<Expression>),
Call(Box<Expression>, Vec<Expression>),
}
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::<Vec<String>>().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::<Vec<String>>().join(",")),
}
}
}
#[derive(Debug, PartialEq, Clone)]
pub enum Statement {
Let(String, Box<Expression>),
Return(Option<Box<Expression>>),
Expression(Box<Expression>),
}
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),
}
}
}