parser: Overhaul the semi-functional Parser::{delimited, separated, repeated} methods into real higher-order functions
This commit is contained in:
parent
978f5e40c1
commit
e3f08ac013
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user