From e3f08ac013cc5013f1b5f3c25bb073a97223c063 Mon Sep 17 00:00:00 2001 From: John Date: Tue, 27 Feb 2024 22:46:36 -0600 Subject: [PATCH] parser: Overhaul the semi-functional Parser::{delimited, separated, repeated} methods into real higher-order functions --- libconlang/src/parser.rs | 170 +++++++++++++++++---------------------- 1 file changed, 72 insertions(+), 98 deletions(-) diff --git a/libconlang/src/parser.rs b/libconlang/src/parser.rs index 7b3f8fb..8a745f6 100644 --- a/libconlang/src/parser.rs +++ b/libconlang/src/parser.rs @@ -234,6 +234,7 @@ pub struct Parser<'t> { loc: Loc, } +/// Basic parser functionality impl<'t> Parser<'t> { pub fn new(lexer: Lexer<'t>) -> Self { Self { loc: Loc::from(&lexer), lexer, next: None } @@ -306,62 +307,63 @@ impl<'t> Parser<'t> { } } -/// Generic parse functions -impl<'t> Parser<'t> { - /// Parses constructions of the form `Open F Close` - fn delimited( - &mut self, - open: Type, - f: F, - close: Type, +// the three matched delimiter pairs +/// Square brackets: `[` `]` +const BRACKETS: (Type, Type) = (Type::LBrack, Type::RBrack); +/// Curly braces: `{` `}` +const CURLIES: (Type, Type) = (Type::LCurly, Type::RCurly); +/// Parentheses: `(` `)` +const PARENS: (Type, Type) = (Type::LParen, Type::RParen); + +/// Parses constructions of the form `delim.0 f delim.1` (i.e. `(` `foobar` `)`) +fn delim<'t, T>( + f: impl Fn(&mut Parser<'t>) -> PResult, + delim: (Type, Type), while_parsing: Parsing, - ) -> PResult - where - F: Fn(&mut Self) -> PResult, - { - self.match_type(open, while_parsing)?; - let out = f(self)?; - self.match_type(close, while_parsing)?; +) -> impl Fn(&mut Parser<'t>) -> PResult { + move |parser| { + parser.match_type(delim.0, while_parsing)?; + let out = f(parser)?; + parser.match_type(delim.1, while_parsing)?; Ok(out) } - /// Parses constructions of the form `(F Separator ~Terminator)*` +} + +/// Parses constructions of the form `(f sep ~until)*` /// - /// where `~Terminator` is a negative lookahead assertion - fn separated( - &mut self, - separator: Type, - f: F, - terminator: Type, +/// where `~until` is a negative lookahead assertion +fn sep<'t, T>( + f: impl Fn(&mut Parser<'t>) -> PResult, + sep: Type, + until: Type, while_parsing: Parsing, - ) -> PResult> - where - F: Fn(&mut Self) -> PResult, - { +) -> impl Fn(&mut Parser<'t>) -> PResult> { + move |parser| { let mut args = vec![]; - while terminator != self.peek_type(while_parsing)? { - args.push(f(self)?); - if separator != self.peek_type(while_parsing)? { + while until != parser.peek_type(while_parsing)? { + args.push(f(parser)?); + if sep != parser.peek_type(while_parsing)? { break; } - self.consume_peeked(); + parser.consume_peeked(); } Ok(args) } - /// Parses constructions of the form `(F ~Terminator)*` +} + +/// Parses constructions of the form `(f ~until)*` /// - /// where `~Terminator` is a negative lookahead assertion - fn repeated( - &mut self, - f: F, - terminator: Type, +/// where `~until` is a negative lookahead assertion +#[allow(dead_code)] +fn rep<'t, T>( + f: impl Fn(&mut Parser<'t>) -> PResult, + until: Type, while_parsing: Parsing, - ) -> PResult> - where - F: Fn(&mut Self) -> PResult, - { +) -> impl Fn(&mut Parser<'t>) -> PResult> { + move |this| { let mut out = vec![]; - while terminator != self.peek_type(while_parsing)? { - out.push(f(self)?); + while until != this.peek_type(while_parsing)? { + out.push(f(this)?) } Ok(out) } @@ -538,13 +540,10 @@ impl<'t> Parser<'t> { } pub fn modulekind(&mut self) -> PResult { const PARSING: Parsing = Parsing::ModuleKind; + let inline = delim(Self::file, CURLIES, PARSING); + match self.peek_type(PARSING)? { - Type::LCurly => Ok(ModuleKind::Inline(self.delimited( - Type::LCurly, - Self::file, - Type::RCurly, - PARSING, - )?)), + Type::LCurly => Ok(ModuleKind::Inline(inline(self)?)), Type::Semi => { self.consume_peeked(); Ok(ModuleKind::Outline) @@ -578,12 +577,11 @@ impl<'t> Parser<'t> { } pub fn parse_params(&mut self) -> PResult> { const PARSING: Parsing = Parsing::Function; - self.delimited( - Type::LParen, - |this| this.separated(Type::Comma, Self::parse_param, Type::RParen, PARSING), - Type::RParen, + delim( + sep(Self::parse_param, Type::Comma, PARENS.1, PARSING), + PARENS, PARSING, - ) + )(self) } pub fn parse_param(&mut self) -> PResult { Ok(Param { @@ -614,22 +612,19 @@ impl<'t> Parser<'t> { pub fn structkind_tuple(&mut self) -> PResult { const PARSING: Parsing = Parsing::StructKind; - Ok(StructKind::Tuple(self.delimited( - Type::LParen, - |s| s.separated(Type::Comma, Self::ty, Type::RParen, PARSING), - Type::RParen, + Ok(StructKind::Tuple(delim( + sep(Self::ty, Type::Comma, PARENS.1, PARSING), + PARENS, PARSING, - )?)) + )(self)?)) } pub fn structkind_struct(&mut self) -> PResult { const PARSING: Parsing = Parsing::StructKind; - - Ok(StructKind::Struct(self.delimited( - Type::LCurly, - |s| s.separated(Type::Comma, Self::struct_member, Type::RCurly, PARSING), - Type::RCurly, + Ok(StructKind::Struct(delim( + sep(Self::struct_member, Type::Comma, CURLIES.1, PARSING), + CURLIES, PARSING, - )?)) + )(self)?)) } pub fn struct_member(&mut self) -> PResult { const PARSING: Parsing = Parsing::StructMember; @@ -694,12 +689,11 @@ impl<'t> Parser<'t> { pub fn tytuple(&mut self) -> PResult { const PARSING: Parsing = Parsing::TyTuple; Ok(TyTuple { - types: self.delimited( - Type::LParen, - |s| s.separated(Type::Comma, Self::ty, Type::RParen, PARSING), - Type::RParen, + types: delim( + sep(Self::ty, Type::Comma, PARENS.1, PARSING), + PARENS, PARSING, - )?, + )(self)?, }) } /// [TyRef] = (`&`|`&&`)* [Path] @@ -777,21 +771,12 @@ impl<'t> Parser<'t> { /// /// See also: [Parser::stmt] pub fn stmtkind(&mut self) -> PResult { - match self.peek_type(Parsing::StmtKind)? { - Type::Semi => Ok(StmtKind::Empty), - Type::Keyword(Keyword::Let) => self.stmtkind_local(), - item_like!() => self.stmtkind_item(), - _ => self.stmtkind_expr(), - } - } - pub fn stmtkind_local(&mut self) -> PResult { - Ok(StmtKind::Local(self.parse_let()?)) - } - pub fn stmtkind_item(&mut self) -> PResult { - Ok(StmtKind::Item(Box::new(self.item()?))) - } - pub fn stmtkind_expr(&mut self) -> PResult { - Ok(StmtKind::Expr(self.expr()?.into())) + Ok(match self.peek_type(Parsing::StmtKind)? { + Type::Semi => StmtKind::Empty, + Type::Keyword(Keyword::Let) => self.parse_let()?.into(), + item_like!() => self.item()?.into(), + _ => self.expr()?.into(), + }) } pub fn parse_let(&mut self) -> PResult { @@ -928,9 +913,7 @@ impl<'t> Parser<'t> { let mut indices = vec![]; while Ok(Type::LBrack) == self.peek_type(PARSING) { - self.consume_peeked(); - indices.push(self.tuple()?.into()); - self.match_type(Type::RBrack, PARSING)?; + indices.push(delim(Self::tuple, BRACKETS, PARSING)(self)?.into()); } Ok(Index { head: head.into(), indices }.into()) } @@ -988,7 +971,7 @@ impl<'t> Parser<'t> { values: { self.consume_peeked(); let mut out = vec![first]; - out.extend(self.separated(Type::Comma, Self::expr, Type::RBrack, PARSING)?); + out.extend(sep(Self::expr, Type::Comma, END, PARSING)(self)?); out }, } @@ -1093,16 +1076,7 @@ impl<'t> Parser<'t> { /// [Block] = `{` [Stmt]* `}` pub fn block(&mut self) -> PResult { const PARSING: Parsing = Parsing::Block; - const START: Type = Type::LCurly; - const END: Type = Type::RCurly; - Ok(Block { - stmts: self.delimited( - START, - |this| this.repeated(Self::stmt, END, PARSING), - END, - PARSING, - )?, - }) + Ok(Block { stmts: delim(rep(Self::stmt, CURLIES.1, PARSING), CURLIES, PARSING)(self)? }) } } /// ## Control flow subexpressions