#![allow(dead_code)] use crate::syn::{ast::*, error::*, lexer::Lexer, span::*, token::*}; use std::{convert::TryFrom, mem}; const EXPR_START: &'static [TokenKind] = &[ TokenKind::Ident, TokenKind::Num, TokenKind::Str, TokenKind::Sym, TokenKind::LParen, TokenKind::LBracket, TokenKind::LBrace, // TODO unary tokens ]; const VALUE_EXPR_START: &'static [TokenKind] = &[ TokenKind::Ident, TokenKind::Num, TokenKind::Str, TokenKind::Sym, ]; pub struct Parser<'t> { lexer: Lexer<'t>, curr_token: Option, } impl<'t> Parser<'t> { pub fn new(lexer: Lexer<'t>) -> Result { let mut parser = Parser { lexer, curr_token: None, }; parser.adv_token()?; Ok(parser) } pub fn is_eof(&self) -> bool { self.lexer.is_eof() } pub fn pos(&self) -> Pos { self.span().start } //////////////////////////////////////////////////////////////////////////////// // Parsing functions //////////////////////////////////////////////////////////////////////////////// pub fn next_expr(&mut self) -> Result { self.next_bin_expr() } fn next_bin_expr(&mut self) -> Result { let lhs = self.next_un_expr()?; todo!() } fn next_un_expr(&mut self) -> Result { todo!() } fn next_base_expr(&mut self) -> Result { let token = self.expect_token_where(|t| VALUE_EXPR_START.contains(&t.kind()), "base expression")?; let expr: Expr = match token.kind() { TokenKind::Ident => BaseExpr { kind: BaseExprKind::Ident, span: token.span(), } .into(), TokenKind::Num => BaseExpr { kind: BaseExprKind::Num, span: token.span(), } .into(), TokenKind::Str => BaseExpr { kind: BaseExprKind::Str, span: token.span(), } .into(), TokenKind::Sym => BaseExpr { kind: BaseExprKind::Sym, span: token.span(), } .into(), _ => unreachable!(), }; Ok(expr) } fn next_list(&mut self) -> Result { let start_token = self.expect_token_where(|t| t.kind() == TokenKind::LBracket, "start of list (left bracket)")?; let mut list_items = Vec::new(); while ! matches!(self.curr_token.map(|t| t.kind()), Some(TokenKind::RBrace) | None) { let expr = self.next_expr()?; } let end_token = self.expect_token_where( |t| t.kind() == TokenKind::RBracket, "end of list (right bracket)", )?; let expr = BaseExpr { kind: BaseExprKind::List(list_items), span: start_token.span().union(end_token.span()), }; Ok(expr.into()) } //////////////////////////////////////////////////////////////////////////////// // Token matching functions //////////////////////////////////////////////////////////////////////////////// fn adv_token(&mut self) -> Result> { let next_token = self.lexer.next_token()?; Ok(mem::replace(&mut self.curr_token, next_token)) } fn match_token_where

(&mut self, pred: P) -> Result> where P: Fn(Token) -> bool, { match self.curr_token { Some(curr) if (pred)(curr) => self.adv_token(), _ => Ok(None), } } fn expect_token_where

(&mut self, pred: P, expected: impl ToString) -> Result where P: Fn(Token) -> bool, { self.match_token_where(pred)? .ok_or_else(|| Error::ExpectedGot { expected: expected.to_string(), got: self .curr_token .map(|token| token.kind().to_string()) .unwrap_or_else(|| "EOF".to_string()), pos: self.pos(), }) } } impl<'t> Spanned for Parser<'t> { fn span(&self) -> Span { self.curr_token .as_ref() .map(Spanned::span) .unwrap_or(Span::default()) } } impl<'t> TryFrom> for Parser<'t> { type Error = Error; fn try_from(lexer: Lexer<'t>) -> Result { Parser::new(lexer) } } impl<'t> TryFrom<&'t str> for Parser<'t> { type Error = Error; fn try_from(text: &'t str) -> Result { Parser::new(Lexer::new(text)) } } #[cfg(test)] mod test { use super::*; #[test] fn test_adv_token() { const EXPECTED: &'static [TokenKind] = &[ TokenKind::Num, TokenKind::Ident, TokenKind::Sym, TokenKind::Str, ]; let mut parser = Parser::try_from("1 ident :sym 'string'").unwrap(); for expected in EXPECTED.iter().copied() { let token = parser.adv_token().unwrap(); let kind = token.unwrap().kind(); assert_eq!(kind, expected); } assert!(parser.is_eof()); } #[test] fn test_match_token_where() { let mut parser = Parser::try_from("1 ident :sym 'string'").unwrap(); assert!(matches!( parser.match_token_where(|token| token.kind() == TokenKind::Num), Ok(Some(_)) )); assert!(matches!( parser.match_token_where(|token| token.kind() == TokenKind::Num), Ok(None) )); assert!(matches!( parser.match_token_where(|token| token.kind() == TokenKind::Ident), Ok(Some(_)) )); assert!(matches!( parser.match_token_where(|token| token.kind() == TokenKind::Ident), Ok(None) )); assert!(matches!( parser.match_token_where(|token| token.kind() == TokenKind::Sym), Ok(Some(_)) )); assert!(matches!( parser.match_token_where(|token| token.kind() == TokenKind::Sym), Ok(None) )); assert!(matches!( parser.match_token_where(|token| token.kind() == TokenKind::Str), Ok(Some(_)) )); assert!(matches!( parser.match_token_where(|token| token.kind() == TokenKind::Str), Ok(None) )); assert!(parser.is_eof()); } #[test] fn test_base_expr() { let mut parser = Parser::try_from("1").unwrap(); assert!(matches!( parser.next_base_expr(), Ok( Expr::Base( BaseExpr { kind: BaseExprKind::Num, .. } ) ) )); } }