lisp-8bit/src/parser.rs
2025-09-08 16:47:18 +02:00

134 lines
4.2 KiB
Rust

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<SExpression>, Box<SExpression>),
Atom(LispAtom),
}
#[derive(Debug, Clone, PartialEq, Eq)]
struct State {
expression: Vec<Token>,
index: usize,
_functions: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum LispAtom {
Integer(isize),
String(String),
Identifier(String),
Keyword(Keyword),
Macro(Macro),
}
impl TryFrom<TokenString> for Vec<SExpression> {
fn try_from(value: TokenString) -> Result<Self, Self::Error> {
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<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
))),
};
expr
}
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
)));
}
state.index += 1;
let expression_1 = 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>) -> 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}"),
},
}
}
}