2025-09-08 16:04:31 +02:00
|
|
|
use std::fmt::Display;
|
2024-08-08 21:53:27 +02:00
|
|
|
|
2025-09-08 16:04:31 +02:00
|
|
|
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<SExpression>, Box<SExpression>),
|
|
|
|
Atom(LispAtom),
|
2024-08-08 21:53:27 +02:00
|
|
|
}
|
|
|
|
|
2025-09-08 16:04:31 +02:00
|
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
|
|
struct State {
|
|
|
|
expression: Vec<Token>,
|
|
|
|
index: usize,
|
|
|
|
_functions: Vec<String>,
|
2024-08-08 21:53:27 +02:00
|
|
|
}
|
|
|
|
|
2025-09-08 16:04:31 +02:00
|
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
|
|
pub enum LispAtom {
|
|
|
|
Integer(isize),
|
|
|
|
String(String),
|
2024-08-08 21:53:27 +02:00
|
|
|
Identifier(String),
|
2025-09-08 16:04:31 +02:00
|
|
|
Keyword(Keyword),
|
|
|
|
Macro(Macro),
|
2024-08-08 21:53:27 +02:00
|
|
|
}
|
|
|
|
|
2025-09-08 16:04:31 +02:00
|
|
|
impl TryFrom<TokenString> for Vec<SExpression> {
|
|
|
|
fn try_from(value: TokenString) -> Result<Self, Self::Error> {
|
|
|
|
let list = value.tokens;
|
2024-08-08 21:53:27 +02:00
|
|
|
|
2025-09-08 16:04:31 +02:00
|
|
|
let mut expressions = vec![];
|
2024-08-08 21:53:27 +02:00
|
|
|
|
2025-09-08 16:04:31 +02:00
|
|
|
let mut state = State {
|
|
|
|
expression: list,
|
|
|
|
index: 0,
|
|
|
|
_functions: Vec::new(),
|
|
|
|
};
|
2024-08-08 21:53:27 +02:00
|
|
|
|
2025-09-08 16:04:31 +02:00
|
|
|
while state.index != state.expression.len() {
|
|
|
|
expressions.push(SExpression::parse_sexpression(&mut state)?);
|
|
|
|
state.index += 1;
|
2024-08-08 21:53:27 +02:00
|
|
|
}
|
|
|
|
|
2025-09-08 16:04:31 +02:00
|
|
|
Ok(expressions)
|
2024-08-08 21:53:27 +02:00
|
|
|
}
|
|
|
|
|
2025-09-08 16:04:31 +02:00
|
|
|
type Error = Error;
|
|
|
|
}
|
2024-08-08 21:53:27 +02:00
|
|
|
|
2025-09-08 16:04:31 +02:00
|
|
|
impl SExpression {
|
|
|
|
fn parse_sexpression(state: &mut State) -> Result<Self, Error> {
|
|
|
|
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
|
|
|
|
))),
|
|
|
|
};
|
2024-08-08 21:53:27 +02:00
|
|
|
|
2025-09-08 16:04:31 +02:00
|
|
|
dbg!(expr)
|
2024-08-08 21:53:27 +02:00
|
|
|
}
|
|
|
|
|
2025-09-08 16:04:31 +02:00
|
|
|
fn parse_expression(state: &mut State) -> Result<Self, Error> {
|
|
|
|
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
|
|
|
|
)));
|
2024-08-08 21:53:27 +02:00
|
|
|
}
|
2025-09-08 16:04:31 +02:00
|
|
|
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;
|
|
|
|
}
|
2024-08-08 21:53:27 +02:00
|
|
|
|
2025-09-08 16:04:31 +02:00
|
|
|
elements.reverse();
|
2024-08-08 21:53:27 +02:00
|
|
|
|
2025-09-08 16:04:31 +02:00
|
|
|
let pair = Self::make_pair_list(elements);
|
|
|
|
return Ok(pair);
|
2024-08-08 21:53:27 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-09-08 16:04:31 +02:00
|
|
|
fn make_pair_list(mut expressions: Vec<SExpression>) -> SExpression {
|
|
|
|
if expressions.len() == 1 {
|
|
|
|
return SExpression::Pair(Box::new(expressions[0].clone()), Box::new(NIL.clone()));
|
2024-08-08 21:53:27 +02:00
|
|
|
}
|
|
|
|
|
2025-09-08 16:04:31 +02:00
|
|
|
return SExpression::Pair(
|
|
|
|
Box::new(
|
|
|
|
expressions
|
|
|
|
.pop()
|
|
|
|
.expect("The length should be more than one"),
|
|
|
|
),
|
|
|
|
Box::new(Self::make_pair_list(expressions)),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2024-08-08 21:53:27 +02:00
|
|
|
|
2025-09-08 16:04:31 +02:00
|
|
|
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}"),
|
|
|
|
},
|
|
|
|
}
|
2024-08-08 21:53:27 +02:00
|
|
|
}
|
|
|
|
}
|