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,
}
/// 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<T, F>(
&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<T>,
delim: (Type, Type),
while_parsing: Parsing,
) -> PResult<T>
where
F: Fn(&mut Self) -> PResult<T>,
{
self.match_type(open, while_parsing)?;
let out = f(self)?;
self.match_type(close, while_parsing)?;
) -> impl Fn(&mut Parser<'t>) -> PResult<T> {
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<T, F>(
&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<T>,
sep: Type,
until: Type,
while_parsing: Parsing,
) -> PResult<Vec<T>>
where
F: Fn(&mut Self) -> PResult<T>,
{
) -> impl Fn(&mut Parser<'t>) -> PResult<Vec<T>> {
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<T, F>(
&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<T>,
until: Type,
while_parsing: Parsing,
) -> PResult<Vec<T>>
where
F: Fn(&mut Self) -> PResult<T>,
{
) -> impl Fn(&mut Parser<'t>) -> PResult<Vec<T>> {
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<ModuleKind> {
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<Vec<Param>> {
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<Param> {
Ok(Param {
@ -614,22 +612,19 @@ impl<'t> Parser<'t> {
pub fn structkind_tuple(&mut self) -> PResult<StructKind> {
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<StructKind> {
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<StructMember> {
const PARSING: Parsing = Parsing::StructMember;
@ -694,12 +689,11 @@ impl<'t> Parser<'t> {
pub fn tytuple(&mut self) -> PResult<TyTuple> {
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<StmtKind> {
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<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()))
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<Let> {
@ -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<Block> {
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