parser: Overhaul the semi-functional Parser::{delimited, separated, repeated} methods into real higher-order functions

This commit is contained in:
John 2024-02-27 22:46:36 -06:00
parent 978f5e40c1
commit e3f08ac013

View File

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