use super::*;
use crate::error::{
Error,
ErrorKind::{self, *},
PResult, Parsing,
};
use cl_ast::*;
use cl_lexer::Lexer;
mod prec;
#[derive(Debug)]
pub struct Parser<'t> {
lexer: Lexer<'t>,
next: Option<Token>,
loc: Loc,
}
impl<'t> Parser<'t> {
pub fn new(lexer: Lexer<'t>) -> Self {
Self { loc: Loc::from(&lexer), lexer, next: None }
}
pub fn loc(&self) -> Loc {
self.loc
}
#[inline]
pub fn parse<P: Parse<'t>>(&mut self) -> PResult<P> {
P::parse(self)
}
pub fn error(&self, reason: ErrorKind, while_parsing: Parsing) -> Error {
Error { reason, while_parsing, loc: self.loc }
}
fn consume_from_lexer(&mut self, while_parsing: Parsing) -> PResult<Token> {
loop {
let tok = self
.lexer
.scan()
.map_err(|e| self.error(e.into(), while_parsing))?;
match tok.ty {
TokenKind::Comment | TokenKind::Invalid => continue,
_ => break Ok(tok),
}
}
}
pub fn peek(&mut self, while_parsing: Parsing) -> PResult<&Token> {
if self.next.is_none() {
self.next = Some(self.consume_from_lexer(while_parsing)?);
}
self.next.as_ref().ok_or_else(|| unreachable!())
}
pub fn peek_kind(&mut self, while_parsing: Parsing) -> PResult<TokenKind> {
self.peek(while_parsing).map(|t| t.ty)
}
pub fn consume_peeked(&mut self) -> Option<Token> {
self.loc = Loc::from(&self.lexer);
self.next.take()
}
pub fn consume(&mut self, while_parsing: Parsing) -> PResult<Token> {
match self.consume_peeked() {
Some(token) => Ok(token),
None => self.consume_from_lexer(while_parsing),
}
}
pub fn match_type(&mut self, want: TokenKind, while_parsing: Parsing) -> PResult<Token> {
let got = self.peek_kind(while_parsing)?;
if got == want {
Ok(self.consume_peeked().expect("should not fail after peek"))
} else {
Err(self.error(ExpectedToken { want, got }, while_parsing))
}
}
}
const BRACKETS: (TokenKind, TokenKind) = (TokenKind::LBrack, TokenKind::RBrack);
const CURLIES: (TokenKind, TokenKind) = (TokenKind::LCurly, TokenKind::RCurly);
const PARENS: (TokenKind, TokenKind) = (TokenKind::LParen, TokenKind::RParen);
const fn delim<'t, T>(
f: impl Fn(&mut Parser<'t>) -> PResult<T>,
delim: (TokenKind, TokenKind),
while_parsing: 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)
}
}
const fn sep<'t, T>(
f: impl Fn(&mut Parser<'t>) -> PResult<T>,
sep: TokenKind,
until: TokenKind,
while_parsing: Parsing,
) -> impl Fn(&mut Parser<'t>) -> PResult<Vec<T>> {
move |parser| {
let mut args = vec![];
while until != parser.peek_kind(while_parsing)? {
args.push(f(parser)?);
if sep != parser.peek_kind(while_parsing)? {
break;
}
parser.consume_peeked();
}
Ok(args)
}
}
const fn rep<'t, T>(
f: impl Fn(&mut Parser<'t>) -> PResult<T>,
until: TokenKind,
while_parsing: Parsing,
) -> impl Fn(&mut Parser<'t>) -> PResult<Vec<T>> {
move |parser| {
let mut out = vec![];
while until != parser.peek_kind(while_parsing)? {
out.push(f(parser)?)
}
Ok(out)
}
}
macro item_like() {
TokenKind::Hash
| TokenKind::Pub
| TokenKind::Type
| TokenKind::Const
| TokenKind::Static
| TokenKind::Mod
| TokenKind::Fn
| TokenKind::Struct
| TokenKind::Enum
| TokenKind::Impl
| TokenKind::Use
}
macro literal_like() {
TokenKind::True | TokenKind::False | TokenKind::Literal
}
macro path_like() {
TokenKind::Super
| TokenKind::SelfKw
| TokenKind::SelfTy
| TokenKind::Identifier
| TokenKind::ColonColon
}
pub trait Parse<'t>: Sized {
fn parse(p: &mut Parser<'t>) -> PResult<Self>;
}
impl Parse<'_> for Sym {
fn parse(p: &mut Parser) -> PResult<Sym> {
let tok = p.match_type(TokenKind::Identifier, Parsing::Identifier)?;
match tok.data() {
TokenData::String(ident) => Ok(ident.into()),
_ => panic!("Expected token data for {tok:?}"),
}
}
}
impl Parse<'_> for Mutability {
#[inline]
fn parse(p: &mut Parser) -> PResult<Mutability> {
Ok(match p.match_type(TokenKind::Mut, Parsing::Mutability) {
Ok(_) => Mutability::Mut,
Err(_) => Mutability::Not,
})
}
}
impl Parse<'_> for Visibility {
#[inline]
fn parse(p: &mut Parser) -> PResult<Self> {
Ok(match p.match_type(TokenKind::Pub, Parsing::Visibility) {
Ok(_) => Visibility::Public,
Err(_) => Visibility::Private,
})
}
}
impl Parse<'_> for Literal {
fn parse(p: &mut Parser) -> PResult<Literal> {
let Token { ty, data, .. } = p.consume(Parsing::Literal)?;
match ty {
TokenKind::True => return Ok(Literal::Bool(true)),
TokenKind::False => return Ok(Literal::Bool(false)),
TokenKind::Literal => (),
t => return Err(p.error(Unexpected(t), Parsing::Literal)),
}
Ok(match data {
TokenData::String(v) => Literal::String(v),
TokenData::Character(v) => Literal::Char(v),
TokenData::Integer(v) => Literal::Int(v),
TokenData::Float(v) => Literal::Float(v.to_bits()),
_ => panic!("Expected token data for {ty:?}"),
})
}
}
impl Parse<'_> for File {
fn parse(p: &mut Parser<'_>) -> PResult<Self> {
let mut items = vec![];
while match p.peek_kind(Parsing::File) {
Ok(TokenKind::RCurly) | Err(Error { reason: EndOfInput, .. }) => false,
Ok(_) => true,
Err(e) => Err(e)?,
} {
items.push(Item::parse(p)?)
}
Ok(File { items })
}
}
impl Parse<'_> for Attrs {
fn parse(p: &mut Parser) -> PResult<Attrs> {
if p.match_type(TokenKind::Hash, Parsing::Attrs).is_err() {
return Ok(Attrs { meta: vec![] });
}
let meta = delim(
sep(Meta::parse, TokenKind::Comma, BRACKETS.1, Parsing::Attrs),
BRACKETS,
Parsing::Attrs,
)(p)?;
Ok(Attrs { meta })
}
}
impl Parse<'_> for Meta {
fn parse(p: &mut Parser) -> PResult<Meta> {
Ok(Meta { name: Sym::parse(p)?, kind: MetaKind::parse(p)? })
}
}
impl Parse<'_> for MetaKind {
fn parse(p: &mut Parser) -> PResult<MetaKind> {
const P: Parsing = Parsing::Meta;
let lit_tuple = delim(
sep(Literal::parse, TokenKind::Comma, PARENS.1, P),
PARENS,
P,
);
Ok(match p.peek_kind(P) {
Ok(TokenKind::Eq) => {
p.consume_peeked();
MetaKind::Equals(Literal::parse(p)?)
}
Ok(TokenKind::LParen) => MetaKind::Func(lit_tuple(p)?),
_ => MetaKind::Plain,
})
}
}
impl Parse<'_> for Item {
fn parse(p: &mut Parser<'_>) -> PResult<Self> {
let start = p.loc();
Ok(Item {
attrs: Attrs::parse(p)?,
vis: Visibility::parse(p)?,
kind: ItemKind::parse(p)?,
extents: Span(start, p.loc()),
})
}
}
impl Parse<'_> for ItemKind {
fn parse(p: &mut Parser) -> PResult<Self> {
Ok(match p.peek_kind(Parsing::Item)? {
TokenKind::Type => Alias::parse(p)?.into(),
TokenKind::Const => Const::parse(p)?.into(),
TokenKind::Static => Static::parse(p)?.into(),
TokenKind::Mod => Module::parse(p)?.into(),
TokenKind::Fn => Function::parse(p)?.into(),
TokenKind::Struct => Struct::parse(p)?.into(),
TokenKind::Enum => Enum::parse(p)?.into(),
TokenKind::Impl => Impl::parse(p)?.into(),
TokenKind::Use => Use::parse(p)?.into(),
t => Err(p.error(Unexpected(t), Parsing::Item))?,
})
}
}
impl Parse<'_> for Alias {
fn parse(p: &mut Parser<'_>) -> PResult<Self> {
const P: Parsing = Parsing::Alias;
p.consume_peeked();
let out = Ok(Alias {
to: Sym::parse(p)?,
from: if p.match_type(TokenKind::Eq, P).is_ok() {
Some(Ty::parse(p)?.into())
} else {
None
},
});
p.match_type(TokenKind::Semi, P)?;
out
}
}
impl Parse<'_> for Const {
fn parse(p: &mut Parser) -> PResult<Const> {
const P: Parsing = Parsing::Const;
p.consume_peeked();
let out = Ok(Const {
name: Sym::parse(p)?,
ty: {
p.match_type(TokenKind::Colon, P)?;
Ty::parse(p)?.into()
},
init: {
p.match_type(TokenKind::Eq, P)?;
Expr::parse(p)?.into()
},
});
p.match_type(TokenKind::Semi, P)?;
out
}
}
impl Parse<'_> for Static {
fn parse(p: &mut Parser) -> PResult<Static> {
const P: Parsing = Parsing::Static;
p.consume_peeked();
let out = Ok(Static {
mutable: Mutability::parse(p)?,
name: Sym::parse(p)?,
ty: {
p.match_type(TokenKind::Colon, P)?;
Ty::parse(p)?.into()
},
init: {
p.match_type(TokenKind::Eq, P)?;
Expr::parse(p)?.into()
},
});
p.match_type(TokenKind::Semi, P)?;
out
}
}
impl Parse<'_> for Module {
fn parse(p: &mut Parser<'_>) -> PResult<Self> {
p.consume_peeked();
Ok(Module { name: Sym::parse(p)?, kind: ModuleKind::parse(p)? })
}
}
impl Parse<'_> for ModuleKind {
fn parse(p: &mut Parser) -> PResult<ModuleKind> {
const P: Parsing = Parsing::ModuleKind;
let inline = delim(Parse::parse, CURLIES, P);
match p.peek_kind(P)? {
TokenKind::LCurly => Ok(ModuleKind::Inline(inline(p)?)),
TokenKind::Semi => {
p.consume_peeked();
Ok(ModuleKind::Outline)
}
got => Err(p.error(ExpectedToken { want: TokenKind::Semi, got }, P)),
}
}
}
impl Parse<'_> for Function {
fn parse(p: &mut Parser) -> PResult<Function> {
const P: Parsing = Parsing::Function;
p.consume_peeked();
let name = Sym::parse(p)?;
let (bind, types) = delim(FnSig::parse, PARENS, P)(p)?;
let sign = TyFn {
args: Box::new(match types.len() {
0 => TyKind::Empty,
_ => TyKind::Tuple(TyTuple { types }),
}),
rety: Ok(match p.match_type(TokenKind::Arrow, Parsing::TyFn) {
Ok(_) => Some(Ty::parse(p)?),
Err(_) => None,
})?
.map(Box::new),
};
Ok(Function {
name,
sign,
bind,
body: match p.peek_kind(P)? {
TokenKind::Semi => {
p.consume_peeked();
None
}
_ => Some(Expr::parse(p)?),
},
})
}
}
type FnSig = (Vec<Param>, Vec<TyKind>);
impl Parse<'_> for FnSig {
fn parse(p: &mut Parser) -> PResult<FnSig> {
const P: Parsing = Parsing::Function;
let (mut params, mut types) = (vec![], vec![]);
while Ok(TokenKind::RParen) != p.peek_kind(P) {
let (param, ty) = TypedParam::parse(p)?;
params.push(param);
types.push(ty);
if p.match_type(TokenKind::Comma, P).is_err() {
break;
}
}
Ok((params, types))
}
}
type TypedParam = (Param, TyKind);
impl Parse<'_> for TypedParam {
fn parse(p: &mut Parser) -> PResult<(Param, TyKind)> {
Ok((
Param { mutability: Mutability::parse(p)?, name: Sym::parse(p)? },
{
p.match_type(TokenKind::Colon, Parsing::Param)?;
TyKind::parse(p)?
},
))
}
}
impl Parse<'_> for Struct {
fn parse(p: &mut Parser) -> PResult<Struct> {
p.match_type(TokenKind::Struct, Parsing::Struct)?;
Ok(Struct { name: Sym::parse(p)?, kind: StructKind::parse(p)? })
}
}
impl Parse<'_> for StructKind {
fn parse(p: &mut Parser<'_>) -> PResult<Self> {
const P: Parsing = Parsing::StructKind;
Ok(match p.peek_kind(P)? {
TokenKind::LParen => StructKind::Tuple(delim(
sep(Ty::parse, TokenKind::Comma, PARENS.1, P),
PARENS,
P,
)(p)?),
TokenKind::LCurly => StructKind::Struct(delim(
sep(StructMember::parse, TokenKind::Comma, CURLIES.1, P),
CURLIES,
P,
)(p)?),
TokenKind::Semi => {
p.consume_peeked();
StructKind::Empty
}
got => Err(p.error(ExpectedToken { want: TokenKind::Semi, got }, P))?,
})
}
}
impl Parse<'_> for StructMember {
fn parse(p: &mut Parser) -> PResult<StructMember> {
const P: Parsing = Parsing::StructMember;
Ok(StructMember {
vis: Visibility::parse(p)?,
name: Sym::parse(p)?,
ty: {
p.match_type(TokenKind::Colon, P)?;
Ty::parse(p)?
},
})
}
}
impl Parse<'_> for Enum {
fn parse(p: &mut Parser) -> PResult<Enum> {
p.match_type(TokenKind::Enum, Parsing::Enum)?;
Ok(Enum { name: Sym::parse(p)?, kind: EnumKind::parse(p)? })
}
}
impl Parse<'_> for EnumKind {
fn parse(p: &mut Parser<'_>) -> PResult<EnumKind> {
const P: Parsing = Parsing::EnumKind;
Ok(match p.peek_kind(P)? {
TokenKind::LCurly => EnumKind::Variants(delim(
sep(Variant::parse, TokenKind::Comma, TokenKind::RCurly, P),
CURLIES,
P,
)(p)?),
TokenKind::Semi => {
p.consume_peeked();
EnumKind::NoVariants
}
t => Err(p.error(Unexpected(t), P))?,
})
}
}
impl Parse<'_> for Variant {
fn parse(p: &mut Parser) -> PResult<Variant> {
Ok(Variant { name: Sym::parse(p)?, kind: VariantKind::parse(p)? })
}
}
impl Parse<'_> for VariantKind {
fn parse(p: &mut Parser<'_>) -> PResult<Self> {
const P: Parsing = Parsing::VariantKind;
Ok(match p.peek_kind(P)? {
TokenKind::Eq => {
p.match_type(TokenKind::Eq, P)?;
let tok = p.match_type(TokenKind::Literal, P)?;
VariantKind::CLike(match tok.data() {
TokenData::Integer(i) => *i,
_ => panic!("Expected token data for {tok:?} while parsing {P}"),
})
}
TokenKind::LCurly => VariantKind::Struct(delim(
sep(StructMember::parse, TokenKind::Comma, TokenKind::RCurly, P),
CURLIES,
P,
)(p)?),
TokenKind::LParen => {
let tup = Ty::parse(p)?;
if !matches!(tup.kind, TyKind::Tuple(_) | TyKind::Empty) {
Err(p.error(ErrorKind::ExpectedParsing { want: Parsing::TyTuple }, P))?
}
VariantKind::Tuple(tup)
}
_ => VariantKind::Plain,
})
}
}
impl Parse<'_> for Impl {
fn parse(p: &mut Parser) -> PResult<Impl> {
const P: Parsing = Parsing::Impl;
p.match_type(TokenKind::Impl, P)?;
Ok(Impl { target: ImplKind::parse(p)?, body: delim(File::parse, CURLIES, P)(p)? })
}
}
impl Parse<'_> for ImplKind {
fn parse(p: &mut Parser<'_>) -> PResult<Self> {
const P: Parsing = Parsing::ImplKind;
let target = Ty::parse(p)?;
if p.match_type(TokenKind::For, P).is_err() {
Ok(ImplKind::Type(target))
} else if let TyKind::Path(impl_trait) = target.kind {
Ok(ImplKind::Trait { impl_trait, for_type: Ty::parse(p)?.into() })
} else {
Err(Error {
reason: ExpectedParsing { want: Parsing::Path },
while_parsing: P,
loc: target.extents.head,
})?
}
}
}
impl Parse<'_> for Use {
fn parse(p: &mut Parser) -> PResult<Use> {
const P: Parsing = Parsing::Use;
p.match_type(TokenKind::Use, P)?;
let absolute = p.match_type(TokenKind::ColonColon, P).is_ok();
let tree = UseTree::parse(p)?;
p.match_type(TokenKind::Semi, P)?;
Ok(Use { tree, absolute })
}
}
impl Parse<'_> for UseTree {
fn parse(p: &mut Parser) -> PResult<Self> {
const P: Parsing = Parsing::UseTree;
Ok(match p.peek_kind(P)? {
TokenKind::Star => {
p.consume_peeked();
UseTree::Glob
}
TokenKind::LCurly => UseTree::Tree(delim(
sep(Parse::parse, TokenKind::Comma, CURLIES.1, P),
CURLIES,
P,
)(p)?),
TokenKind::SelfKw | TokenKind::Super | TokenKind::Identifier => {
let name = PathPart::parse(p)?;
if p.match_type(TokenKind::ColonColon, P).is_ok() {
UseTree::Path(name, Box::new(UseTree::parse(p)?))
} else {
let PathPart::Ident(name) = name else {
Err(p.error(ErrorKind::ExpectedParsing { want: Parsing::Identifier }, P))?
};
if p.match_type(TokenKind::As, P).is_ok() {
UseTree::Alias(name, p.parse()?)
} else {
UseTree::Name(name)
}
}
}
t => Err(p.error(Unexpected(t), Parsing::UseTree))?,
})
}
}
impl Parse<'_> for Ty {
fn parse(p: &mut Parser<'_>) -> PResult<Self> {
let start = p.loc();
Ok(Ty { kind: TyKind::parse(p)?, extents: Span(start, p.loc()) })
}
}
impl Parse<'_> for TyKind {
fn parse(p: &mut Parser) -> PResult<TyKind> {
const P: Parsing = Parsing::TyKind;
let out = match p.peek_kind(P)? {
TokenKind::Bang => {
p.consume_peeked();
TyKind::Never
}
TokenKind::Amp | TokenKind::AmpAmp => TyRef::parse(p)?.into(),
TokenKind::LBrack => {
p.match_type(BRACKETS.0, Parsing::TySlice)?;
let ty = TyKind::parse(p)?;
let (out, kind) = match p.match_type(TokenKind::Semi, Parsing::TyArray).is_ok() {
true => {
let literal = p.match_type(TokenKind::Literal, Parsing::TyArray)?;
let &TokenData::Integer(count) = literal.data() else {
Err(p.error(Unexpected(TokenKind::Literal), Parsing::TyArray))?
};
(
TyKind::Array(TyArray { ty: Box::new(ty), count: count as _ }),
Parsing::TyArray,
)
}
false => (
TyKind::Slice(TySlice { ty: Box::new(ty) }),
Parsing::TySlice,
),
};
p.match_type(BRACKETS.1, kind)?;
out
}
TokenKind::LParen => {
let out = TyTuple::parse(p)?;
match out.types.is_empty() {
true => TyKind::Empty,
false => TyKind::Tuple(out),
}
}
TokenKind::Fn => TyFn::parse(p)?.into(),
path_like!() => Path::parse(p)?.into(),
t => Err(p.error(Unexpected(t), P))?,
};
Ok(out)
}
}
impl Parse<'_> for TyTuple {
fn parse(p: &mut Parser) -> PResult<TyTuple> {
const P: Parsing = Parsing::TyTuple;
Ok(TyTuple {
types: delim(sep(TyKind::parse, TokenKind::Comma, PARENS.1, P), PARENS, P)(p)?,
})
}
}
impl Parse<'_> for TyRef {
fn parse(p: &mut Parser) -> PResult<TyRef> {
const P: Parsing = Parsing::TyRef;
let mut count = 0;
loop {
match p.peek_kind(P)? {
TokenKind::Amp => count += 1,
TokenKind::AmpAmp => count += 2,
_ => break,
}
p.consume_peeked();
}
Ok(TyRef { count, mutable: Mutability::parse(p)?, to: Path::parse(p)? })
}
}
impl Parse<'_> for TyFn {
fn parse(p: &mut Parser) -> PResult<TyFn> {
const P: Parsing = Parsing::TyFn;
p.match_type(TokenKind::Fn, P)?;
let args = delim(sep(TyKind::parse, TokenKind::Comma, PARENS.1, P), PARENS, P)(p)?;
Ok(TyFn {
args: Box::new(match args {
t if t.is_empty() => TyKind::Empty,
types => TyKind::Tuple(TyTuple { types }),
}),
rety: match p.match_type(TokenKind::Arrow, Parsing::TyFn) {
Ok(_) => Some(Ty::parse(p)?),
Err(_) => None,
}
.map(Into::into),
})
}
}
impl Parse<'_> for Path {
fn parse(p: &mut Parser) -> PResult<Path> {
const P: Parsing = Parsing::Path;
let absolute = p.match_type(TokenKind::ColonColon, P).is_ok();
let mut parts = vec![];
if absolute {
match PathPart::parse(p) {
Ok(part) => parts.push(part),
Err(_) => return Ok(Path { absolute, parts }),
}
} else {
parts.push(PathPart::parse(p)?)
};
while p.match_type(TokenKind::ColonColon, Parsing::Path).is_ok() {
parts.push(PathPart::parse(p)?)
}
Ok(Path { absolute, parts })
}
}
impl Parse<'_> for PathPart {
fn parse(p: &mut Parser) -> PResult<PathPart> {
const P: Parsing = Parsing::PathPart;
let out = match p.peek_kind(P)? {
TokenKind::Super => PathPart::SuperKw,
TokenKind::SelfKw => PathPart::SelfKw,
TokenKind::SelfTy => PathPart::SelfTy,
TokenKind::Identifier => PathPart::Ident(Sym::parse(p)?),
t => return Err(p.error(Unexpected(t), P)),
};
p.consume_peeked();
Ok(out)
}
}
impl Parse<'_> for Stmt {
fn parse(p: &mut Parser) -> PResult<Stmt> {
let start = p.loc();
Ok(Stmt {
kind: StmtKind::parse(p)?,
semi: match p.match_type(TokenKind::Semi, Parsing::Stmt) {
Ok(_) => Semi::Terminated,
_ => Semi::Unterminated,
},
extents: Span(start, p.loc()),
})
}
}
impl Parse<'_> for StmtKind {
fn parse(p: &mut Parser) -> PResult<StmtKind> {
Ok(match p.peek_kind(Parsing::StmtKind)? {
TokenKind::Semi => StmtKind::Empty,
item_like!() => Item::parse(p)?.into(),
_ => Expr::parse(p)?.into(),
})
}
}
impl Parse<'_> for Expr {
fn parse(p: &mut Parser) -> PResult<Expr> {
let start = p.loc();
Ok(Expr { kind: ExprKind::parse(p)?, extents: Span(start, p.loc()) })
}
}
impl Parse<'_> for ExprKind {
fn parse(p: &mut Parser<'_>) -> PResult<ExprKind> {
prec::exprkind(p, 0)
}
}
impl Parse<'_> for Quote {
fn parse(p: &mut Parser<'_>) -> PResult<Self> {
let quote = delim(
ExprKind::parse,
(TokenKind::Grave, TokenKind::Grave),
Parsing::ExprKind,
)(p)?
.into();
Ok(Quote { quote })
}
}
impl Parse<'_> for Let {
fn parse(p: &mut Parser) -> PResult<Let> {
p.consume_peeked();
Ok(Let {
mutable: Mutability::parse(p)?,
name: Pattern::parse(p)?,
ty: if p.match_type(TokenKind::Colon, Parsing::Let).is_ok() {
Some(Ty::parse(p)?.into())
} else {
None
},
init: if p.match_type(TokenKind::Eq, Parsing::Let).is_ok() {
Some(Expr::parse(p)?.into())
} else {
None
},
})
}
}
impl Parse<'_> for MemberKind {
fn parse(p: &mut Parser) -> PResult<MemberKind> {
const P: Parsing = Parsing::Member;
const DEL: (TokenKind, TokenKind) = PARENS; match p.peek_kind(P)? {
TokenKind::Identifier => {
let name = Sym::parse(p)?;
if p.match_type(DEL.0, P).is_err() {
Ok(MemberKind::Struct(name))
} else {
let exprs = sep(Expr::parse, TokenKind::Comma, DEL.1, P)(p)?;
p.match_type(DEL.1, P)?; Ok(MemberKind::Call(name, Tuple { exprs }))
}
}
TokenKind::Literal => {
let name = Literal::parse(p)?; Ok(MemberKind::Tuple(name))
}
t => Err(p.error(Unexpected(t), P)),
}
}
}
impl Parse<'_> for Fielder {
fn parse(p: &mut Parser) -> PResult<Fielder> {
const P: Parsing = Parsing::Fielder;
Ok(Fielder {
name: Sym::parse(p)?,
init: match p.match_type(TokenKind::Colon, P) {
Ok(_) => Some(Box::new(Expr::parse(p)?)),
Err(_) => None,
},
})
}
}
impl Parse<'_> for AddrOf {
fn parse(p: &mut Parser) -> PResult<AddrOf> {
const P: Parsing = Parsing::AddrOf;
match p.peek_kind(P)? {
TokenKind::Amp => {
p.consume_peeked();
Ok(AddrOf { mutable: Mutability::parse(p)?, expr: ExprKind::parse(p)?.into() })
}
TokenKind::AmpAmp => {
p.consume_peeked();
Ok(AddrOf {
mutable: Mutability::Not,
expr: ExprKind::AddrOf(AddrOf {
mutable: Mutability::parse(p)?,
expr: ExprKind::parse(p)?.into(),
})
.into(),
})
}
got => Err(p.error(ExpectedToken { want: TokenKind::Amp, got }, P)),
}
}
}
impl Parse<'_> for Block {
fn parse(p: &mut Parser) -> PResult<Block> {
const A_BLOCK: Parsing = Parsing::Block;
Ok(Block { stmts: delim(rep(Parse::parse, CURLIES.1, A_BLOCK), CURLIES, A_BLOCK)(p)? })
}
}
impl Parse<'_> for While {
#[rustfmt::skip]
fn parse(p: &mut Parser) -> PResult<While> {
p.match_type(TokenKind::While, Parsing::While)?;
Ok(While {
cond: Expr::parse(p)?.into(),
pass: Block::parse(p)?.into(),
fail: Else::parse(p)?
})
}
}
impl Parse<'_> for If {
#[rustfmt::skip] fn parse(p: &mut Parser) -> PResult<If> {
p.match_type(TokenKind::If, Parsing::If)?;
Ok(If {
cond: Expr::parse(p)?.into(),
pass: Block::parse(p)?.into(),
fail: Else::parse(p)?,
})
}
}
impl Parse<'_> for For {
#[rustfmt::skip]
fn parse(p: &mut Parser) -> PResult<For> {
p.match_type(TokenKind::For, Parsing::For)?;
let bind = Sym::parse(p)?;
p.match_type(TokenKind::In, Parsing::For)?;
Ok(For {
bind,
cond: Expr::parse(p)?.into(),
pass: Block::parse(p)?.into(),
fail: Else::parse(p)?,
})
}
}
impl Parse<'_> for Else {
fn parse(p: &mut Parser) -> PResult<Else> {
match p.peek_kind(Parsing::Else) {
Ok(TokenKind::Else) => {
p.consume_peeked();
Ok(Expr::parse(p)?.into())
}
Ok(_) | Err(Error { reason: EndOfInput, .. }) => Ok(None.into()),
Err(e) => Err(e),
}
}
}
impl Parse<'_> for Break {
fn parse(p: &mut Parser) -> PResult<Break> {
p.match_type(TokenKind::Break, Parsing::Break)?;
Ok(Break { body: ret_body(p, Parsing::Break)? })
}
}
impl Parse<'_> for Return {
fn parse(p: &mut Parser) -> PResult<Return> {
p.match_type(TokenKind::Return, Parsing::Return)?;
Ok(Return { body: ret_body(p, Parsing::Return)? })
}
}
impl Parse<'_> for Pattern {
fn parse(p: &mut Parser<'_>) -> PResult<Self> {
let value = prec::exprkind(p, prec::Precedence::Highest.level())?;
Pattern::try_from(value)
.map_err(|_| p.error(ExpectedParsing { want: Parsing::Pattern }, Parsing::Pattern))
}
}
impl Parse<'_> for Match {
fn parse(p: &mut Parser<'_>) -> PResult<Self> {
p.match_type(TokenKind::Match, Parsing::Match)?;
let scrutinee = Expr::parse(p)?.into();
let arms = delim(
sep(MatchArm::parse, TokenKind::Comma, CURLIES.1, Parsing::Match),
CURLIES,
Parsing::Match,
)(p)?;
Ok(Match { scrutinee, arms })
}
}
impl Parse<'_> for MatchArm {
fn parse(p: &mut Parser<'_>) -> PResult<Self> {
let pat = Pattern::parse(p)?;
p.match_type(TokenKind::FatArrow, Parsing::MatchArm)?;
let expr = Expr::parse(p)?;
Ok(MatchArm(pat, expr))
}
}
fn ret_body(p: &mut Parser, while_parsing: Parsing) -> PResult<Option<Box<Expr>>> {
Ok(match p.peek_kind(while_parsing)? {
TokenKind::Semi => None,
_ => Some(Expr::parse(p)?.into()),
})
}