use std::fmt::Display; use color_eyre::eyre::Error; use crate::lexer::{Keyword, Macro, Token, TokenString, TokenType}; pub static NIL: SExpression = SExpression::Atom(LispAtom::Keyword(Keyword::Nil)); #[derive(Debug, Clone, PartialEq, Eq)] pub enum SExpression { Pair(Box, Box), Atom(LispAtom), } #[derive(Debug, Clone, PartialEq, Eq)] struct State { expression: Vec, index: usize, _functions: Vec, } #[derive(Debug, Clone, PartialEq, Eq)] pub enum LispAtom { Integer(isize), String(String), Identifier(String), Keyword(Keyword), Macro(Macro), } impl TryFrom for Vec { fn try_from(value: TokenString) -> Result { let list = value.tokens; let mut expressions = vec![]; let mut state = State { expression: list, index: 0, _functions: Vec::new(), }; while state.index != state.expression.len() { expressions.push(SExpression::parse_sexpression(&mut state)?); state.index += 1; } Ok(expressions) } type Error = Error; } impl SExpression { fn parse_sexpression(state: &mut State) -> Result { let expr = match &state.expression[state.index].token_type { TokenType::OpenParantheses => Self::parse_expression(state), TokenType::Integer(val) => Ok(Self::Atom(LispAtom::Integer(val.to_owned()))), TokenType::String(val) => Ok(Self::Atom(LispAtom::String(val.to_owned()))), TokenType::Identifier(val) => Ok(Self::Atom(LispAtom::Identifier(val.to_owned()))), TokenType::Keyword(val) => Ok(Self::Atom(LispAtom::Keyword(val.to_owned()))), TokenType::Macro(val) => Ok(Self::Atom(LispAtom::Macro(val.to_owned()))), _other => Err(Error::msg(format!( "Did not expect symbol at row {} col {}", state.expression[state.index].row, state.expression[state.index].col ))), }; dbg!(expr) } fn parse_expression(state: &mut State) -> Result { if state.expression[state.index].token_type != TokenType::OpenParantheses { return Err(Error::msg(format!( "Error: Expected ( at row {} col {}", state.expression[state.index].row, state.expression[state.index].col ))); } state.index += 1; let expression_1 = dbg!(Self::parse_sexpression(state)?); state.index += 1; // Is pair if state.expression[state.index].token_type == TokenType::Dot { state.index += 1; let expression_2 = Self::parse_sexpression(state)?; return Ok(Self::Pair(Box::new(expression_1), Box::new(expression_2))); } else { // Is list let mut elements = vec![expression_1]; while state.expression[state.index].token_type != TokenType::ClosedParantheses { elements.push(Self::parse_sexpression(state)?); state.index += 1; } elements.reverse(); let pair = Self::make_pair_list(elements); return Ok(pair); } } fn make_pair_list(mut expressions: Vec) -> SExpression { if expressions.len() == 1 { return SExpression::Pair(Box::new(expressions[0].clone()), Box::new(NIL.clone())); } return SExpression::Pair( Box::new( expressions .pop() .expect("The length should be more than one"), ), Box::new(Self::make_pair_list(expressions)), ); } } impl Display for SExpression { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Pair(a, b) => write!(f, "({a} . {b})"), Self::Atom(a) => match a { LispAtom::String(a) => write!(f, "\"{a}\""), LispAtom::Integer(a) => write!(f, "{a}"), LispAtom::Keyword(a) => write!(f, "{a}"), LispAtom::Identifier(a) => write!(f, "{a}"), LispAtom::Macro(a) => write!(f, "{a}"), }, } } }