use std::{collections::HashSet, fmt::Debug, sync::LazyLock}; use super::{util::WHITESPACE_SET, Body, CharCursor, ParserError}; #[derive(Debug)] pub struct Module { functions: Vec, } pub struct Function { pub name: String, pub body: Body, } static NAME_END: LazyLock> = LazyLock::new(|| { let mut set = WHITESPACE_SET.clone(); set.extend(&['(']); set }); impl Module { pub fn parse(cursor: &mut CharCursor) -> Result { let mut functions = Vec::new(); loop { let next = cursor.until(&WHITESPACE_SET); if next.is_empty() { return Ok(Self { functions }); } if next == "fn" { functions.push(Function::parse(cursor)?); } else { return Err(ParserError::at(cursor.pos(), "expected fn".to_string())); } } } } impl Function { pub fn parse(cursor: &mut CharCursor) -> Result { cursor.skip_whitespace(); let name = cursor.until(&NAME_END); if name.is_empty() { return Err(ParserError::at(cursor.pos(), "expected function name".to_string())); } cursor.expect_char('(')?; cursor.expect_char(')')?; let body = Body::parse(cursor)?; Ok(Self { name, body }) } } impl Debug for Function { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_str("fn ")?; f.write_str(&self.name)?; f.write_str("() ")?; self.body.fmt(f)?; Ok(()) } }