cl-parser: General cleanup and maintenance

- Made infallible rules infallible
- Don't double-check keywords where keywords are required.
  - Of course, this change means rules aren't self-contained
- Rename the `Call` precedence level
- Made member-access operators left-associative
- Removed the useless `Nothing` error type. :(
This commit is contained in:
John 2024-04-18 21:04:16 -05:00
parent f315fb5af7
commit a56ee38b15
2 changed files with 55 additions and 69 deletions

View File

@ -29,8 +29,6 @@ pub enum ErrorKind {
ExpectedParsing { ExpectedParsing {
want: Parsing, want: Parsing,
}, },
/// No rules matched
Nothing,
/// Indicates unfinished code /// Indicates unfinished code
Todo, Todo,
} }
@ -134,13 +132,8 @@ impl Display for ErrorKind {
ErrorKind::UnmatchedCurlyBraces => write!(f, "Unmatched curly braces"), ErrorKind::UnmatchedCurlyBraces => write!(f, "Unmatched curly braces"),
ErrorKind::UnmatchedSquareBrackets => write!(f, "Unmatched square brackets"), ErrorKind::UnmatchedSquareBrackets => write!(f, "Unmatched square brackets"),
ErrorKind::Unexpected(t) => write!(f, "Encountered unexpected token `{t}`"), ErrorKind::Unexpected(t) => write!(f, "Encountered unexpected token `{t}`"),
ErrorKind::ExpectedToken { want: e, got: g } => { ErrorKind::ExpectedToken { want: e, got: g } => write!(f, "Expected `{e}`, got `{g}`"),
write!(f, "Expected `{e}`, got `{g}`") ErrorKind::ExpectedParsing { want } => write!(f, "Expected {want}"),
}
ErrorKind::ExpectedParsing { want } => {
write!(f, "Expected {want}")
}
ErrorKind::Nothing => write!(f, "Nothing found"),
ErrorKind::Todo => write!(f, "TODO:"), ErrorKind::Todo => write!(f, "TODO:"),
} }
} }

View File

@ -136,7 +136,6 @@ const fn sep<'t, T>(
/// Parses constructions of the form `(f ~until)*` /// Parses constructions of the form `(f ~until)*`
/// ///
/// where `~until` is a negative lookahead assertion /// where `~until` is a negative lookahead assertion
#[allow(dead_code)]
const fn rep<'t, T>( const fn rep<'t, T>(
f: impl Fn(&mut Parser<'t>) -> PResult<T>, f: impl Fn(&mut Parser<'t>) -> PResult<T>,
until: Punct, until: Punct,
@ -187,7 +186,7 @@ impl<'t> Parser<'t> {
let start = self.loc(); let start = self.loc();
Ok(Item { Ok(Item {
attrs: self.attributes()?, attrs: self.attributes()?,
vis: self.visibility()?, vis: self.visibility(),
kind: self.itemkind()?, kind: self.itemkind()?,
extents: Span(start, self.loc()), extents: Span(start, self.loc()),
}) })
@ -204,21 +203,20 @@ impl<'t> Parser<'t> {
/// Parses a [Path] /// Parses a [Path]
/// ///
/// See also: [Parser::path_part], [Parser::identifier] /// See also: [Parser::path_part], [Parser::identifier]
///
/// [Path] = `::`? ([PathPart] `::`)* [PathPart]?
pub fn path(&mut self) -> PResult<Path> { pub fn path(&mut self) -> PResult<Path> {
const PARSING: Parsing = Parsing::PathExpr; const PARSING: Parsing = Parsing::PathExpr;
let absolute = matches!( let absolute = self.match_op(Punct::ColonColon, PARSING).is_ok();
self.peek_kind(PARSING)?, let mut parts = vec![];
TokenKind::Punct(Punct::ColonColon)
); while let Ok(path_part) = self.path_part() {
if absolute { parts.push(path_part);
self.consume_peeked(); if self.match_op(Punct::ColonColon, PARSING).is_err() {
break;
}
} }
let mut parts = vec![self.path_part()?];
while let Ok(TokenKind::Punct(Punct::ColonColon)) = self.peek_kind(PARSING) {
self.consume_peeked();
parts.push(self.path_part()?);
}
Ok(Path { absolute, parts }) Ok(Path { absolute, parts })
} }
@ -226,15 +224,11 @@ impl<'t> Parser<'t> {
/// ///
/// See also: [Parser::stmtkind] /// See also: [Parser::stmtkind]
pub fn stmt(&mut self) -> PResult<Stmt> { pub fn stmt(&mut self) -> PResult<Stmt> {
const PARSING: Parsing = Parsing::Stmt;
let start = self.loc(); let start = self.loc();
Ok(Stmt { Ok(Stmt {
kind: self.stmtkind()?, kind: self.stmtkind()?,
semi: match self.peek_kind(PARSING) { semi: match self.match_op(Punct::Semi, Parsing::Stmt) {
Ok(TokenKind::Punct(Punct::Semi)) => { Ok(_) => Semi::Terminated,
self.consume_peeked();
Semi::Terminated
}
_ => Semi::Unterminated, _ => Semi::Unterminated,
}, },
extents: Span(start, self.loc()), extents: Span(start, self.loc()),
@ -260,8 +254,8 @@ impl<'t> Parser<'t> {
sep(Self::meta, Punct::Comma, BRACKETS.1, Parsing::Attrs), sep(Self::meta, Punct::Comma, BRACKETS.1, Parsing::Attrs),
BRACKETS, BRACKETS,
Parsing::Attrs, Parsing::Attrs,
); )(self)?;
Ok(Attrs { meta: meta(self)? }) Ok(Attrs { meta })
} }
/// Parses a single [attribute](Meta) /// Parses a single [attribute](Meta)
pub fn meta(&mut self) -> PResult<Meta> { pub fn meta(&mut self) -> PResult<Meta> {
@ -308,7 +302,7 @@ impl<'t> Parser<'t> {
/// Parses a [`type` alias](Alias) /// Parses a [`type` alias](Alias)
pub fn parse_alias(&mut self) -> PResult<Alias> { pub fn parse_alias(&mut self) -> PResult<Alias> {
const PARSING: Parsing = Parsing::Alias; const PARSING: Parsing = Parsing::Alias;
self.match_type(TokenKind::Type, PARSING)?; self.consume_peeked();
let out = Ok(Alias { let out = Ok(Alias {
to: self.identifier()?, to: self.identifier()?,
@ -325,7 +319,7 @@ impl<'t> Parser<'t> {
/// Parses a [compile-time constant](Const) /// Parses a [compile-time constant](Const)
pub fn parse_const(&mut self) -> PResult<Const> { pub fn parse_const(&mut self) -> PResult<Const> {
const PARSING: Parsing = Parsing::Const; const PARSING: Parsing = Parsing::Const;
self.match_type(TokenKind::Const, PARSING)?; self.consume_peeked();
let out = Ok(Const { let out = Ok(Const {
name: self.identifier()?, name: self.identifier()?,
@ -345,10 +339,10 @@ impl<'t> Parser<'t> {
/// Parses a [`static` item](Static) /// Parses a [`static` item](Static)
pub fn parse_static(&mut self) -> PResult<Static> { pub fn parse_static(&mut self) -> PResult<Static> {
const PARSING: Parsing = Parsing::Static; const PARSING: Parsing = Parsing::Static;
self.match_type(TokenKind::Static, PARSING)?; self.consume_peeked();
let out = Ok(Static { let out = Ok(Static {
mutable: self.mutability()?, mutable: self.mutability(),
name: self.identifier()?, name: self.identifier()?,
ty: { ty: {
self.match_op(Punct::Colon, PARSING)?; self.match_op(Punct::Colon, PARSING)?;
@ -365,8 +359,7 @@ impl<'t> Parser<'t> {
/// Parses a [Module] /// Parses a [Module]
pub fn parse_module(&mut self) -> PResult<Module> { pub fn parse_module(&mut self) -> PResult<Module> {
const PARSING: Parsing = Parsing::Module; self.consume_peeked();
self.match_type(TokenKind::Mod, PARSING)?;
Ok(Module { name: self.identifier()?, kind: self.modulekind()? }) Ok(Module { name: self.identifier()?, kind: self.modulekind()? })
} }
@ -392,7 +385,7 @@ impl<'t> Parser<'t> {
/// Parses a [Function] definition /// Parses a [Function] definition
pub fn parse_function(&mut self) -> PResult<Function> { pub fn parse_function(&mut self) -> PResult<Function> {
const PARSING: Parsing = Parsing::Function; const PARSING: Parsing = Parsing::Function;
self.match_type(TokenKind::Fn, PARSING)?; self.consume_peeked();
let name = self.identifier()?; let name = self.identifier()?;
let (bind, types) = delim(Self::parse_params, PARENS, PARSING)(self)?; let (bind, types) = delim(Self::parse_params, PARENS, PARSING)(self)?;
@ -436,7 +429,7 @@ impl<'t> Parser<'t> {
/// Parses a single function [parameter](Param) /// Parses a single function [parameter](Param)
pub fn parse_param(&mut self) -> PResult<(Param, TyKind)> { pub fn parse_param(&mut self) -> PResult<(Param, TyKind)> {
Ok(( Ok((
Param { mutability: self.mutability()?, name: self.identifier()? }, Param { mutability: self.mutability(), name: self.identifier()? },
{ {
self.match_op(Punct::Colon, Parsing::Param)?; self.match_op(Punct::Colon, Parsing::Param)?;
self.tykind()? self.tykind()?
@ -447,7 +440,7 @@ impl<'t> Parser<'t> {
/// Parses a [`struct` definition](Struct) /// Parses a [`struct` definition](Struct)
pub fn parse_struct(&mut self) -> PResult<Struct> { pub fn parse_struct(&mut self) -> PResult<Struct> {
const PARSING: Parsing = Parsing::Struct; const PARSING: Parsing = Parsing::Struct;
self.match_type(TokenKind::Struct, PARSING)?; self.consume_peeked();
Ok(Struct { Ok(Struct {
name: self.identifier()?, name: self.identifier()?,
@ -492,7 +485,7 @@ impl<'t> Parser<'t> {
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;
Ok(StructMember { Ok(StructMember {
vis: self.visibility()?, vis: self.visibility(),
name: self.identifier()?, name: self.identifier()?,
ty: { ty: {
self.match_op(Punct::Colon, PARSING)?; self.match_op(Punct::Colon, PARSING)?;
@ -504,8 +497,7 @@ impl<'t> Parser<'t> {
/// Parses an [`enum`](Enum) definition /// Parses an [`enum`](Enum) definition
pub fn parse_enum(&mut self) -> PResult<Enum> { pub fn parse_enum(&mut self) -> PResult<Enum> {
const PARSING: Parsing = Parsing::Enum; const PARSING: Parsing = Parsing::Enum;
self.consume_peeked();
self.match_type(TokenKind::Enum, PARSING)?;
Ok(Enum { Ok(Enum {
name: self.identifier()?, name: self.identifier()?,
@ -578,8 +570,7 @@ impl<'t> Parser<'t> {
pub fn parse_impl(&mut self) -> PResult<Impl> { pub fn parse_impl(&mut self) -> PResult<Impl> {
const PARSING: Parsing = Parsing::Impl; const PARSING: Parsing = Parsing::Impl;
self.consume_peeked();
self.match_type(TokenKind::Impl, PARSING)?;
Ok(Impl { Ok(Impl {
target: self.parse_impl_kind()?, target: self.parse_impl_kind()?,
@ -605,19 +596,19 @@ impl<'t> Parser<'t> {
} }
} }
pub fn visibility(&mut self) -> PResult<Visibility> { /// [Visibility] = `pub`?
if let TokenKind::Pub = self.peek_kind(Parsing::Visibility)? { pub fn visibility(&mut self) -> Visibility {
self.consume_peeked(); match self.match_type(TokenKind::Pub, Parsing::Visibility) {
return Ok(Visibility::Public); Ok(_) => Visibility::Public,
}; Err(_) => Visibility::Private,
Ok(Visibility::Private) }
}
/// [Mutability] = `mut`?
pub fn mutability(&mut self) -> Mutability {
match self.match_type(TokenKind::Mut, Parsing::Mutability) {
Ok(_) => Mutability::Mut,
Err(_) => Mutability::Not,
} }
pub fn mutability(&mut self) -> PResult<Mutability> {
if let TokenKind::Mut = self.peek_kind(Parsing::Mutability)? {
self.consume_peeked();
return Ok(Mutability::Mut);
};
Ok(Mutability::Not)
} }
} }
@ -675,7 +666,7 @@ impl<'t> Parser<'t> {
} }
self.consume_peeked(); self.consume_peeked();
} }
Ok(TyRef { count, mutable: self.mutability()?, to: self.path()? }) Ok(TyRef { count, mutable: self.mutability(), to: self.path()? })
} }
/// [TyFn] = `fn` [TyTuple] (-> [Ty])? /// [TyFn] = `fn` [TyTuple] (-> [Ty])?
pub fn tyfn(&mut self) -> PResult<TyFn> { pub fn tyfn(&mut self) -> PResult<TyFn> {
@ -726,6 +717,7 @@ impl<'t> Parser<'t> {
TokenKind::Identifier => PathPart::Ident(self.identifier()?), TokenKind::Identifier => PathPart::Ident(self.identifier()?),
t => return Err(self.error(Unexpected(t), PARSING)), t => return Err(self.error(Unexpected(t), PARSING)),
}; };
// Note: this relies on identifier not peeking
self.consume_peeked(); self.consume_peeked();
Ok(out) Ok(out)
} }
@ -754,9 +746,9 @@ impl<'t> Parser<'t> {
} }
pub fn parse_let(&mut self) -> PResult<Let> { pub fn parse_let(&mut self) -> PResult<Let> {
self.match_type(TokenKind::Let, Parsing::Let)?; self.consume_peeked();
Ok(Let { Ok(Let {
mutable: self.mutability()?, mutable: self.mutability(),
name: self.identifier()?, name: self.identifier()?,
ty: if Ok(TokenKind::Punct(Punct::Colon)) == self.peek_kind(Parsing::Let) { ty: if Ok(TokenKind::Punct(Punct::Colon)) == self.peek_kind(Parsing::Let) {
self.consume_peeked(); self.consume_peeked();
@ -787,7 +779,7 @@ impl<'t> Parser<'t> {
/// See also: [Parser::expr] /// See also: [Parser::expr]
pub fn exprkind(&mut self, power: u8) -> PResult<ExprKind> { pub fn exprkind(&mut self, power: u8) -> PResult<ExprKind> {
let parsing = Parsing::ExprKind; let parsing = Parsing::ExprKind;
// // Prefix expressions
let mut head = match self.peek_kind(Parsing::Unary)? { let mut head = match self.peek_kind(Parsing::Unary)? {
literal_like!() => self.literal()?.into(), literal_like!() => self.literal()?.into(),
path_like!() => self.path()?.into(), path_like!() => self.path()?.into(),
@ -821,12 +813,13 @@ impl<'t> Parser<'t> {
fn from_postfix(op: Punct) -> Option<Precedence> { fn from_postfix(op: Punct) -> Option<Precedence> {
Some(match op { Some(match op {
Punct::LBrack => Precedence::Index, Punct::LBrack => Precedence::Index,
Punct::LParen => Precedence::Postfix, Punct::LParen => Precedence::Call,
_ => None?, _ => None?,
}) })
} }
while let Ok(TokenKind::Punct(op)) = self.peek_kind(parsing) { while let Ok(TokenKind::Punct(op)) = self.peek_kind(parsing) {
// Postfix expressions
if let Some((before, ())) = from_postfix(op).and_then(Precedence::postfix) { if let Some((before, ())) = from_postfix(op).and_then(Precedence::postfix) {
if before < power { if before < power {
break; break;
@ -974,7 +967,7 @@ impl<'t> Parser<'t> {
}; };
self.consume_peeked(); self.consume_peeked();
} }
Ok(AddrOf { count, mutable: self.mutability()?, expr: self.exprkind(0)?.into() }) Ok(AddrOf { count, mutable: self.mutability(), expr: self.exprkind(0)?.into() })
} }
/// [Literal] = [LITERAL](TokenKind::Literal) | `true` | `false` /// [Literal] = [LITERAL](TokenKind::Literal) | `true` | `false`
pub fn literal(&mut self) -> PResult<Literal> { pub fn literal(&mut self) -> PResult<Literal> {
@ -1021,7 +1014,7 @@ impl<'t> Parser<'t> {
/// [While] = `while` [Expr] [Block] [Else]? /// [While] = `while` [Expr] [Block] [Else]?
pub fn parse_while(&mut self) -> PResult<While> { pub fn parse_while(&mut self) -> PResult<While> {
self.match_type(TokenKind::While, Parsing::While)?; self.consume_peeked();
Ok(While { Ok(While {
cond: self.expr()?.into(), cond: self.expr()?.into(),
pass: self.block()?.into(), pass: self.block()?.into(),
@ -1031,7 +1024,7 @@ impl<'t> Parser<'t> {
/// [If] = <code>`if` [Expr] [Block] [Else]?</code> /// [If] = <code>`if` [Expr] [Block] [Else]?</code>
#[rustfmt::skip] // second line is barely not long enough #[rustfmt::skip] // second line is barely not long enough
pub fn parse_if(&mut self) -> PResult<If> { pub fn parse_if(&mut self) -> PResult<If> {
self.match_type(TokenKind::If, Parsing::If)?; self.consume_peeked();
Ok(If { Ok(If {
cond: self.expr()?.into(), cond: self.expr()?.into(),
pass: self.block()?.into(), pass: self.block()?.into(),
@ -1040,7 +1033,7 @@ impl<'t> Parser<'t> {
} }
/// [For]: `for` Pattern (TODO) `in` [Expr] [Block] [Else]? /// [For]: `for` Pattern (TODO) `in` [Expr] [Block] [Else]?
pub fn parse_for(&mut self) -> PResult<For> { pub fn parse_for(&mut self) -> PResult<For> {
self.match_type(TokenKind::For, Parsing::For)?; self.consume_peeked();
let bind = self.identifier()?; let bind = self.identifier()?;
self.match_type(TokenKind::In, Parsing::For)?; self.match_type(TokenKind::In, Parsing::For)?;
Ok(For { Ok(For {
@ -1076,8 +1069,8 @@ pub enum Precedence {
Factor, Factor,
Term, Term,
Unary, Unary,
Postfix,
Member, // left-associative Member, // left-associative
Call,
} }
impl Precedence { impl Precedence {
@ -1095,13 +1088,13 @@ impl Precedence {
let level = self.level(); let level = self.level();
match self { match self {
Self::Unary => None, Self::Unary => None,
Self::Member | Self::Assign => Some((level + 1, level)), Self::Assign => Some((level + 1, level)),
_ => Some((level, level + 1)), _ => Some((level, level + 1)),
} }
} }
pub fn postfix(self) -> Option<(u8, ())> { pub fn postfix(self) -> Option<(u8, ())> {
match self { match self {
Self::Index | Self::Postfix => Some((self.level(), ())), Self::Index | Self::Call => Some((self.level(), ())),
_ => None, _ => None,
} }
} }
@ -1116,7 +1109,7 @@ impl From<BinaryKind> for Precedence {
fn from(value: BinaryKind) -> Self { fn from(value: BinaryKind) -> Self {
use BinaryKind as Op; use BinaryKind as Op;
match value { match value {
Op::Call => Precedence::Postfix, Op::Call => Precedence::Call,
Op::Dot => Precedence::Member, Op::Dot => Precedence::Member,
Op::Mul | Op::Div | Op::Rem => Precedence::Term, Op::Mul | Op::Div | Op::Rem => Precedence::Term,
Op::Add | Op::Sub => Precedence::Factor, Op::Add | Op::Sub => Precedence::Factor,