use super::token::Token; use super::tokenizer::tokenize; use super::tokenizer::TokenStream; use super::tokenizer::TokenizerError; use crate::lisp::Expression; use std::iter::Peekable; #[derive(Debug, Clone, PartialEq)] pub enum ParserError { UnexpectedToken(Token), TokenizerError(TokenizerError), UnexpectedEndOfInput, } impl From for ParserError { fn from(value: TokenizerError) -> Self { ParserError::TokenizerError(value) } } fn parse_list(stream: &mut Peekable>) -> Result where I: Iterator, { let mut list = Vec::new(); loop { match stream.peek() { // Return current list or nil Some(Ok(Token::ParClose)) => { stream.next(); if list.len() == 0 { return Ok(Expression::Nil); } else { return Ok(list.into()); } } // Switch to cons-pair parsing Some(Ok(Token::Dot)) => { stream.next(); if list.len() > 1 || list.len() == 0 { return Err(ParserError::UnexpectedToken(Token::Dot)); } else { let second_expr = parse_expression(stream)?; match stream.next() { Some(Ok(Token::ParClose)) => { return Ok(Expression::Cell( Box::new(list[0].to_owned()), Box::new(second_expr), )); } Some(Ok(t)) => { return Err(ParserError::UnexpectedToken(t)); } Some(Err(e)) => { return Err(e.into()); } None => { return Err(ParserError::UnexpectedEndOfInput); } } } } _ => {} } list.push(parse_expression(stream)?); } } fn parse_expression(stream: &mut Peekable>) -> Result where I: Iterator, { match stream.next() { Some(Ok(Token::ParOpen)) => parse_list(stream), Some(Ok(Token::Nil)) => Ok(Expression::Nil), Some(Ok(Token::IntLiteral(n))) => Ok(Expression::Integer(n)), Some(Ok(Token::FloatLiteral(f))) => Ok(Expression::Float(f)), Some(Ok(Token::StringLiteral(s))) => Ok(Expression::String(s)), Some(Ok(Token::True)) => Ok(Expression::True), Some(Ok(Token::Symbol(s))) => Ok(Expression::Symbol(s)), Some(Ok(Token::Quote)) => Ok(Expression::Quote(Box::new(parse_expression(stream)?))), Some(Err(e)) => Err(ParserError::TokenizerError(e)), Some(Ok(x)) => Err(ParserError::UnexpectedToken(x)), None => Err(ParserError::UnexpectedEndOfInput), } } pub struct ExpressionStream> { token_stream: Peekable>, } impl> ExpressionStream { pub fn from_token_stream(token_stream: TokenStream) -> Self { ExpressionStream { token_stream: token_stream.peekable(), } } pub fn from_char_stream(char_stream: I) -> Self { ExpressionStream { token_stream: tokenize(char_stream).peekable(), } } } impl> Iterator for ExpressionStream { type Item = Result; fn next(&mut self) -> Option { if self.token_stream.peek() == None { return None; } Some(parse_expression(&mut self.token_stream)) } } #[test] fn test_parser() { let input = "(1 2 3) (4 5 6) (1 . 2) (1 . (2 . (3))) \"test\" '(a b c true nil)"; let ts = tokenize(input.chars()); let es = ExpressionStream::from_token_stream(ts); let exprs = es.collect::, ParserError>>(); assert_eq!( exprs, Ok(vec![ vec![ Expression::Integer(1), Expression::Integer(2), Expression::Integer(3), ] .into(), vec![ Expression::Integer(4), Expression::Integer(5), Expression::Integer(6), ] .into(), Expression::Cell( Box::new(Expression::Integer(1)), Box::new(Expression::Integer(2)), ), vec![ Expression::Integer(1), Expression::Integer(2), Expression::Integer(3), ] .into(), Expression::String("test".to_string()), Expression::Quote(Box::new( vec![ Expression::Symbol("a".to_string()), Expression::Symbol("b".to_string()), Expression::Symbol("c".to_string()), Expression::True, Expression::Nil, ] .into() )), ]) ); }