use crate::token;
use std::hash::Hash;
use std::hash::Hasher;
use std::collections::HashMap;
use std::fmt;
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub enum Node {
Program(Program),
Statement(Statement),
Expression(Expression),
}
impl fmt::Display for Node {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Node::Program(p) => p.fmt(f),
Node::Statement(s) => s.fmt(f),
Node::Expression(e) => e.fmt(f),
}
}
}
#[derive(Clone, Debug, Default, Eq, Hash, PartialEq)]
pub struct Program {
pub statements: Vec<Statement>,
}
impl Program {
pub fn new() -> Self {
Program { statements: vec![] }
}
}
impl fmt::Display for Program {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for stmt in &self.statements {
stmt.fmt(f)?;
}
Ok(())
}
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub enum Statement {
Expression(Expression),
Let(LetStatement),
Return(ReturnStatement),
Block(BlockStatement),
}
impl fmt::Display for Statement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Statement::Expression(stmt) => stmt.fmt(f),
Statement::Let(stmt) => stmt.fmt(f),
Statement::Return(stmt) => stmt.fmt(f),
Statement::Block(stmt) => stmt.fmt(f),
}
}
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct LetStatement {
pub name: String,
pub value: Expression,
}
impl fmt::Display for LetStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "let {} = {};", self.name, self.value)
}
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct ReturnStatement {
pub value: Expression,
}
impl fmt::Display for ReturnStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "return {};", self.value)
}
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct BlockStatement {
pub statements: Vec<Statement>,
}
impl fmt::Display for BlockStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for stmt in &self.statements {
stmt.fmt(f)?;
}
Ok(())
}
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub enum Expression {
Identifier(String),
Integer(token::Integer),
Float(token::Float),
Boolean(bool),
String(String),
Array(ArrayLiteral),
Prefix(PrefixExpression),
Infix(InfixExpression),
If(IfExpression),
Function(FunctionLiteral),
Call(CallExpression),
Index(IndexExpression),
Hash(HashLiteral),
}
impl fmt::Display for Expression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Expression::Identifier(id) => id.fmt(f),
Expression::Integer(int) => int.fmt(f),
Expression::Float(fl) => fl.fmt(f),
Expression::Boolean(b) => b.fmt(f),
Expression::Prefix(p) => p.fmt(f),
Expression::String(s) => write!(f, r#""{}""#, s),
Expression::Array(a) => a.fmt(f),
Expression::Infix(i) => i.fmt(f),
Expression::If(i) => i.fmt(f),
Expression::Function(fl) => fl.fmt(f),
Expression::Call(c) => c.fmt(f),
Expression::Index(i) => i.fmt(f),
Expression::Hash(h) => h.fmt(f),
}
}
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct ArrayLiteral {
pub elements: Vec<Expression>,
}
impl fmt::Display for ArrayLiteral {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"[{}]",
self.elements
.iter()
.map(|e| format!("{}", e))
.collect::<Vec<String>>()
.join(", ")
)
}
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct PrefixExpression {
pub operator: token::Token,
pub right: Box<Expression>,
}
impl fmt::Display for PrefixExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({}{})", self.operator, self.right)
}
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct InfixExpression {
pub left: Box<Expression>,
pub operator: token::Token,
pub right: Box<Expression>,
}
impl fmt::Display for InfixExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({} {} {})", self.left, self.operator, self.right)
}
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct IfExpression {
pub condition: Box<Expression>,
pub consequence: BlockStatement,
pub alternative: Option<BlockStatement>,
}
impl fmt::Display for IfExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "if {} {{ {} }}", self.condition, self.consequence)?;
if let Some(alt) = &self.alternative {
write!(f, " else {{ {} }}", alt)?;
}
Ok(())
}
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct FunctionLiteral {
pub parameters: Vec<String>,
pub body: BlockStatement,
}
impl fmt::Display for FunctionLiteral {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "fn({}) {{ {} }}", self.parameters.join(", "), self.body)
}
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct CallExpression {
pub function: Box<Expression>,
pub arguments: Vec<Expression>,
}
impl fmt::Display for CallExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut args = vec![];
for arg in &self.arguments {
args.push(format!("{}", arg));
}
write!(f, "{}({})", self.function, args.join(", "))
}
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct IndexExpression {
pub left: Box<Expression>,
pub index: Box<Expression>,
}
impl fmt::Display for IndexExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({}[{}])", self.left, self.index)
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct HashLiteral {
pub pairs: HashMap<Expression, Expression>,
}
#[allow(clippy::derive_hash_xor_eq)]
impl Hash for HashLiteral {
fn hash<H: Hasher>(&self, _state: &mut H) {
panic!("HashLiteral cannot be hashed");
}
}
impl fmt::Display for HashLiteral {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut pairs = vec![];
for pair in &self.pairs {
pairs.push(format!(r#"{}: {}"#, pair.0, pair.1));
}
pairs.sort();
write!(f, "{{{}}}", pairs.join(", "))
}
}