use logos::{Logos, SpannedIter}; use crate::{ ast::{IDLModule, Item, ItemInterface, ItemType, UseDecl}, lexer::{Span, Spanned, Token, Ident}, }; use std::{ iter::{Iterator, Peekable, Filter}, ops::Range, }; type Wtf<'a> = Peekable< Filter, Box, Range)) -> bool>>, >; struct TokenIterator<'a> { spanned: Wtf<'a>, } fn token_is_not_comment((ref a, ..): &(Result, Range)) -> bool { !matches!(a, Err(_) | Ok(Token::Comment(..))) } impl<'a> TokenIterator<'a> { pub fn new(src: &'a str) -> Self { let spanned = Token::lexer(src) .spanned() .filter( Box::new(token_is_not_comment) as Box, Range)) -> bool>, ) .peekable(); Self { spanned } } pub fn next(&mut self) -> Option> { let nxt = self .spanned .next() .and_then(|(token, span)| Some(Spanned(token.ok()?, Span(span)))); println!("[NEXT] {:#?}", nxt); nxt } pub fn peek(&mut self) -> Option> { let peek = self .spanned .peek() .and_then(|(token, span)| Some(Spanned(token.as_ref().ok()?, Span(span.clone())))); println!("[PEEK] {:#?}", peek); peek } } pub struct Parser<'a> { tokens: TokenIterator<'a>, } impl<'a> Parser<'a> { pub fn new(src: &'a str) -> Self { Self { tokens: TokenIterator::new(src), } } fn get_real(&mut self, matcher: impl Fn(&Token) -> bool) -> Option> { if matcher(self.tokens.peek()?.0) { self.tokens.next() } else { None } } fn semi(&mut self) -> Option { Some(self.get_real(|token| matches!(token, Token::Semicolon))?.1) } fn ask_ident(&mut self) -> Option> { Some(crate::unwrap_match!( self.get_real(|token| matches!(token, Token::Ident(Ident::Other(_))))?, Spanned(Token::Ident(Ident::Other(ident)), span) => Spanned(ident, span) )) } fn ask_interface(&mut self) -> Option> { let Spanned(_, kSp) = self.get_real(|token| matches!(token, Token::Ident(Ident::Interface)))?; let Spanned(ident, iSp) = self.ask_ident()?; Some(Spanned::new( ItemInterface { name: ident, functions: vec![], }, [kSp, iSp, self.semi()?], )) } fn ask_typealias(&mut self) -> Option> { let Spanned(_, kSp) = self.get_real(|token| matches!(token, Token::Ident(Ident::Type)))?; let Spanned(name, nSp) = self.ask_ident()?; let Spanned(_, eqSp) = self.get_real(|token| matches!(token, Token::Equals))?; let Spanned(referree, rSp) = self.ask_ident()?; Some(Spanned::new( ItemType { name, referree }, [kSp, nSp, eqSp, rSp, self.semi()?], )) } fn ask_item(&mut self) -> Option> { Some(match self.tokens.peek()?.0 { Token::Ident(Ident::Other(_)) => None?, Token::Ident(keyword) => match keyword { Ident::Interface => self.ask_interface()?.map(Item::Interface), Ident::Type => self.ask_typealias()?.map(Item::Type), _ => None?, }, _ => None?, }) } fn ask_use(&mut self) -> Option> { let Spanned(_, kSp) = self.get_real(|token| matches!(token, Token::Ident(Ident::Use)))?; let Spanned(name, nSp) = self.ask_ident()?; Some(Spanned::new( UseDecl { module: name }, [kSp, nSp, self.semi()?], )) } pub fn parse(mut self) -> IDLModule { IDLModule { uses: fill_while(|| self.ask_use()), items: fill_while(|| self.ask_item()), } } } fn fill_while(mut f: impl FnMut() -> Option>) -> Vec { let mut real = vec![]; while let Some(Spanned(t, _)) = f() { real.push(t); } real }