// © 2023 John Breaux //! A [`Parsable`] struct (an AST node) can parse tokens from a [stream](TokenStream) into it[`self`](https://doc.rust-lang.org/stable/std/keyword.SelfTy.html) use super::*; /// Parses tokens from [stream](TokenStream) into Self node pub trait Parsable { /// Parses tokens from [TokenStream](TokenStream) into Self nodes fn parse<'text, T>(p: &Parser, stream: &mut T) -> Result where Self: Sized, T: TokenStream<'text>; /// Attempts to parse tokens from [stream](TokenStream) into Self nodes. /// /// Masks failed expectations. fn try_parse<'text, T>(p: &Parser, stream: &mut T) -> Result, ParseError> where Self: Sized, T: TokenStream<'text>, { match Self::parse(p, stream) { Ok(some) => Ok(Some(some)), Err(ParseError::LexError(_)) => Ok(None), Err(e) => Err(e), } } fn parse_and<'text, T, R>( p: &Parser, stream: &mut T, f: fn(p: &Parser, &mut T) -> R, ) -> Result<(Self, R), ParseError> where Self: Sized, T: TokenStream<'text>, { Ok((Self::parse(p, stream)?, f(p, stream))) } /// Attempts to parse tokens from [stream](TokenStream) into Self nodes. /// /// Returns [`Self::default()`](Default::default()) on error fn parse_or_default<'text, T>(p: &Parser, stream: &mut T) -> Self where Self: Sized + Default, T: TokenStream<'text>, { Self::parse(p, stream).unwrap_or_default() } } macro_rules! parsable_str_types { ($($t:ty),*$(,)?) => {$( impl Parsable for $t { fn parse<'text, T>(_p: &Parser, stream: &mut T) -> Result where T: TokenStream<'text> { Ok(stream.expect(Type::String)?.lexeme().trim_matches('"').into()) } } )*}; } use std::{path::PathBuf, rc::Rc}; parsable_str_types![String, Rc, Box, PathBuf]; /// Vectors of arbitrary parsables are cool impl Parsable for Vec

{ fn parse<'text, T>(p: &Parser, stream: &mut T) -> Result where T: TokenStream<'text> { // [dead beef] // [A, B,] // [c d e f] // [ something // else ] stream.require(Type::LBracket)?; stream.allow(Type::Endl); let mut out = vec![]; while let Some(t) = P::try_parse(p, stream)? { out.push(t); stream.allow(Type::Separator); stream.allow(Type::Endl); } stream.require(Type::RBracket)?; Ok(out) } }