use std::iter::Peekable; use logos::Logos; use crate::{Ast, Kind}; type Error = String; struct Parser<'s> { lex: Peekable>, errors: Vec, } pub(crate) fn parse(s: &str) -> (Vec, Vec) { let lex = Lexer { lex: Kind::lexer(s), } .peekable(); let mut parser = Parser { lex, errors: vec![], }; let mut trees = Vec::new(); while parser.lex.peek().is_some() { if let Some(t) = parser.parse() { trees.push(t); } } (trees, parser.errors) } impl<'s> Parser<'s> { fn parse(&mut self) -> Option> { let Token { kind, span, src } = self.next()?; // match tok { // Token::Lparen => todo!(), // Token::Rparen => { // self.errors.push(format!("Unexpected lparen ")); // self.parse() // } // Token::Symbol => Some(Ast::Leaf(self.lex.str())), // Token::String => todo!(), // Token::Error => todo!(), // } Some(match kind { Kind::Lparen => { let mut bits = Vec::new(); while self.lex.peek()?.kind != Kind::Rparen { bits.push(self.parse()?); } let rp = self.next()?; assert_eq!(rp.kind, Kind::Rparen); Ast::Tree(bits) } Kind::Rparen => { self.errors.push(format!("Unexpected `)` at {:?}", span)); // Keep going from the next token return self.parse(); } Kind::Symbol | Kind::String | Kind::Boolean => Ast::Leaf(src), Kind::Error => unreachable!("Removed by Parser::next"), }) } fn next(&mut self) -> Option> { for tok in &mut self.lex { if tok.kind == crate::Kind::Error { self.errors .push(format!("Bad token at {:?}: `{}`", tok.span, tok.src)) } else { return Some(tok); } } self.errors.push("Unexpected EOF".to_owned()); None } } struct Lexer<'s> { lex: logos::Lexer<'s, crate::Kind>, } impl<'s> Iterator for Lexer<'s> { type Item = Token<'s>; fn next(&mut self) -> Option { self.lex.next().map(|kind| Token { kind, span: self.lex.span(), src: self.lex.slice(), }) } } struct Token<'s> { kind: Kind, span: logos::Span, src: &'s str, }