syntax: Merge ALL definitions into Bind, and allow type variable introducers at every Bind
This commit is contained in:
84
src/ast.rs
84
src/ast.rs
@@ -114,30 +114,26 @@ pub enum PatOp {
|
|||||||
Alt,
|
Alt,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A record-type definition
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
||||||
pub struct Typedef(pub TypedefKind, pub Pat);
|
|
||||||
|
|
||||||
/// The type of type being defined
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
||||||
pub enum TypedefKind {
|
|
||||||
Struct,
|
|
||||||
Enum,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A pattern binding
|
/// A pattern binding
|
||||||
/// ```ignore
|
/// ```ignore
|
||||||
/// let Pat (= Expr (else Expr)?)?
|
/// let Pat (= Expr (else Expr)?)?
|
||||||
/// const Pat (= Expr (else Expr)?)?
|
/// const Pat (= Expr (else Expr)?)?
|
||||||
/// static Pat (= Expr (else Expr)?)?
|
/// static Pat (= Expr (else Expr)?)?
|
||||||
/// type Pat (= Expr)?
|
/// type Pat (= Expr)?
|
||||||
|
/// struct Pat
|
||||||
|
/// enum Pat
|
||||||
/// fn Pat Expr
|
/// fn Pat Expr
|
||||||
/// mod Pat Expr
|
/// mod Pat Expr
|
||||||
/// impl Pat Expr
|
/// impl Pat Expr
|
||||||
/// Pat => Expr // in match
|
/// Pat => Expr // in match
|
||||||
/// ``````
|
/// ```
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct Bind<A: Annotation = Span>(pub BindKind, pub Pat, pub Vec<Anno<Expr<A>, A>>);
|
pub struct Bind<A: Annotation = Span>(
|
||||||
|
pub BindKind,
|
||||||
|
pub Vec<FqPath>,
|
||||||
|
pub Pat,
|
||||||
|
pub Vec<Anno<Expr<A>, A>>,
|
||||||
|
);
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum BindKind {
|
pub enum BindKind {
|
||||||
@@ -149,6 +145,10 @@ pub enum BindKind {
|
|||||||
Static,
|
Static,
|
||||||
/// A type-alias binding
|
/// A type-alias binding
|
||||||
Type,
|
Type,
|
||||||
|
/// A struct definition
|
||||||
|
Struct,
|
||||||
|
/// An enum definition
|
||||||
|
Enum,
|
||||||
/// A `fn Pat Expr` binding
|
/// A `fn Pat Expr` binding
|
||||||
Fn,
|
Fn,
|
||||||
/// A `mod Pat Expr` binding
|
/// A `mod Pat Expr` binding
|
||||||
@@ -176,6 +176,8 @@ pub struct MakeArm<A: Annotation = Span>(pub String, pub Option<Anno<Expr<A>, A>
|
|||||||
/// Expressions: The beating heart of Dough
|
/// Expressions: The beating heart of Dough
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum Expr<A: Annotation = Span> {
|
pub enum Expr<A: Annotation = Span> {
|
||||||
|
/// Omitted by semicolon insertion-elision rules
|
||||||
|
Omitted,
|
||||||
/// An identifier
|
/// An identifier
|
||||||
Id(FqPath),
|
Id(FqPath),
|
||||||
/// An escaped token for macro binding
|
/// An escaped token for macro binding
|
||||||
@@ -187,8 +189,6 @@ pub enum Expr<A: Annotation = Span> {
|
|||||||
/// `(let | const | static) Pat::NoTopAlt (= expr (else expr)?)?` |
|
/// `(let | const | static) Pat::NoTopAlt (= expr (else expr)?)?` |
|
||||||
/// `(fn | mod | impl) Pat::Fn Expr`
|
/// `(fn | mod | impl) Pat::Fn Expr`
|
||||||
Bind(Box<Bind<A>>),
|
Bind(Box<Bind<A>>),
|
||||||
/// (struct | enum | type) Pat::NoTopAlt
|
|
||||||
Struct(Box<Typedef>),
|
|
||||||
/// Expr { (Ident (: Expr)?),* }
|
/// Expr { (Ident (: Expr)?),* }
|
||||||
Make(Box<Make<A>>),
|
Make(Box<Make<A>>),
|
||||||
/// Op Expr | Expr Op | Expr (Op Expr)+ | Op Expr Expr else Expr
|
/// Op Expr | Expr Op | Expr (Op Expr)+ | Op Expr Expr else Expr
|
||||||
@@ -219,6 +219,7 @@ pub enum Op {
|
|||||||
While, // while Expr Expr (else Expr)?
|
While, // while Expr Expr (else Expr)?
|
||||||
Break, // break Expr
|
Break, // break Expr
|
||||||
Return, // return Expr
|
Return, // return Expr
|
||||||
|
Continue, // continue
|
||||||
|
|
||||||
Dot, // Expr . Expr
|
Dot, // Expr . Expr
|
||||||
|
|
||||||
@@ -356,18 +357,31 @@ impl Display for Use {
|
|||||||
|
|
||||||
impl<A: Annotation> Display for Bind<A> {
|
impl<A: Annotation> Display for Bind<A> {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
let Self(op, pat, exprs) = self;
|
let Self(op, gens, pat, exprs) = self;
|
||||||
|
op.fmt(f)?;
|
||||||
|
if !gens.is_empty() {
|
||||||
|
f.delimit("<", "> ").list(gens, ", ")?;
|
||||||
|
}
|
||||||
|
|
||||||
match op {
|
match op {
|
||||||
BindKind::Match => f.delimit(fmt!("{pat} => "), "").list(exprs, ",!? "),
|
BindKind::Match => f.delimit(fmt!("{pat} => "), "").list(exprs, ",!? "),
|
||||||
BindKind::Fn | BindKind::Mod | BindKind::Impl => {
|
BindKind::Fn | BindKind::Mod | BindKind::Impl => {
|
||||||
f.delimit(fmt!("{op}{pat} "), "").list(exprs, ",!? ")
|
f.delimit(fmt!("{pat} "), "").list(exprs, ",!? ")
|
||||||
}
|
}
|
||||||
|
BindKind::Struct | BindKind::Enum => match pat {
|
||||||
|
Pat::NamedStruct(name, bind) => match bind.as_ref() {
|
||||||
|
Pat::Op(PatOp::Tuple, parts) => f
|
||||||
|
.delimit_indented(fmt!("{name} {{"), "}")
|
||||||
|
.list_wrap("\n", parts, ",\n", ",\n"),
|
||||||
|
other => write!(f, "{name} {{ {other} }}"),
|
||||||
|
},
|
||||||
|
_ => pat.fmt(f),
|
||||||
|
},
|
||||||
_ => match exprs.as_slice() {
|
_ => match exprs.as_slice() {
|
||||||
[] => write!(f, "{op}{pat}"),
|
[] => write!(f, "{pat}"),
|
||||||
[value] => write!(f, "{op}{pat} = {value}"),
|
[value] => write!(f, "{pat} = {value}"),
|
||||||
[value, fail] => write!(f, "{op} {pat} = {value} else {fail}"),
|
[value, fail] => write!(f, "{pat} = {value} else {fail}"),
|
||||||
other => f.delimit(fmt!("{op}{pat} ("), ")").list(other, ", "),
|
other => f.delimit(fmt!("{pat} ("), ")").list(other, ", "),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -380,10 +394,12 @@ impl Display for BindKind {
|
|||||||
Self::Const => "const ",
|
Self::Const => "const ",
|
||||||
Self::Static => "static ",
|
Self::Static => "static ",
|
||||||
Self::Type => "type ",
|
Self::Type => "type ",
|
||||||
|
Self::Struct => "struct ",
|
||||||
|
Self::Enum => "enum ",
|
||||||
Self::Fn => "fn ",
|
Self::Fn => "fn ",
|
||||||
Self::Mod => "mod ",
|
Self::Mod => "mod ",
|
||||||
Self::Impl => "impl ",
|
Self::Impl => "impl ",
|
||||||
Self::Match => "| ",
|
Self::Match => "",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -395,34 +411,15 @@ impl<A: Annotation> Display for Make<A> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Typedef {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
let Self(kind, pat) = self;
|
|
||||||
f.write_str(match kind {
|
|
||||||
TypedefKind::Struct => "struct ",
|
|
||||||
TypedefKind::Enum => "enum ",
|
|
||||||
})?;
|
|
||||||
match pat {
|
|
||||||
Pat::NamedStruct(name, bind) => match bind.as_ref() {
|
|
||||||
Pat::Op(PatOp::Tuple, parts) => f
|
|
||||||
.delimit_indented(fmt!("{name} {{"), "}")
|
|
||||||
.list_wrap("\n", parts, ",\n", ",\n"),
|
|
||||||
other => write!(f, "{name} {{ {other} }}"),
|
|
||||||
},
|
|
||||||
_ => pat.fmt(f),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<A: Annotation> Display for Expr<A> {
|
impl<A: Annotation> Display for Expr<A> {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
Self::Omitted => "/* omitted */".fmt(f),
|
||||||
Self::Id(id) => id.fmt(f),
|
Self::Id(id) => id.fmt(f),
|
||||||
Self::MetId(id) => write!(f, "`{id}"),
|
Self::MetId(id) => write!(f, "`{id}"),
|
||||||
Self::Lit(literal) => literal.fmt(f),
|
Self::Lit(literal) => literal.fmt(f),
|
||||||
Self::Use(v) => write!(f, "use {v}"),
|
Self::Use(v) => write!(f, "use {v}"),
|
||||||
Self::Bind(v) => v.fmt(f),
|
Self::Bind(v) => v.fmt(f),
|
||||||
Self::Struct(v) => v.fmt(f),
|
|
||||||
Self::Make(v) => v.fmt(f),
|
Self::Make(v) => v.fmt(f),
|
||||||
|
|
||||||
Self::Op(op @ (Op::If | Op::While), exprs) => match exprs.as_slice() {
|
Self::Op(op @ (Op::If | Op::While), exprs) => match exprs.as_slice() {
|
||||||
@@ -446,7 +443,7 @@ impl<A: Annotation> Display for Expr<A> {
|
|||||||
Self::Op(Op::Tuple, exprs) => f.delimit("(", ")").list(exprs, ", "),
|
Self::Op(Op::Tuple, exprs) => f.delimit("(", ")").list(exprs, ", "),
|
||||||
Self::Op(Op::Group, exprs) => f.list(exprs, ", "),
|
Self::Op(Op::Group, exprs) => f.list(exprs, ", "),
|
||||||
Self::Op(Op::Meta, exprs) => match exprs.as_slice() {
|
Self::Op(Op::Meta, exprs) => match exprs.as_slice() {
|
||||||
[meta, expr @ ..] => f.delimit(fmt!("#[{meta}] "), "").list(expr, ","),
|
[meta, expr @ ..] => f.delimit(fmt!("#[{meta}]\n"), "").list(expr, ","),
|
||||||
[] => write!(f, "#[]"),
|
[] => write!(f, "#[]"),
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -492,6 +489,7 @@ impl Display for Op {
|
|||||||
Op::While => "while ",
|
Op::While => "while ",
|
||||||
Op::Break => "break ",
|
Op::Break => "break ",
|
||||||
Op::Return => "return ",
|
Op::Return => "return ",
|
||||||
|
Op::Continue => "continue",
|
||||||
Op::Dot => ".",
|
Op::Dot => ".",
|
||||||
Op::RangeEx => "..",
|
Op::RangeEx => "..",
|
||||||
Op::RangeIn => "..=",
|
Op::RangeIn => "..=",
|
||||||
|
|||||||
@@ -80,14 +80,15 @@ impl<M: Match<A> + Annotation, A: Annotation> Match<A> for Anno<M, A> {
|
|||||||
|
|
||||||
impl<A: Annotation> Match<A> for Bind<A> {
|
impl<A: Annotation> Match<A> for Bind<A> {
|
||||||
fn recurse(sub: &mut Subst<A>, pat: &Self, expr: &Self) -> bool {
|
fn recurse(sub: &mut Subst<A>, pat: &Self, expr: &Self) -> bool {
|
||||||
let (Self(pat_kind, pat_pat, pat_expr), Self(expr_kind, expr_pat, expr_expr)) = (pat, expr);
|
let (Self(pat_kind, _, pat_pat, pat_expr), Self(expr_kind, _, expr_pat, expr_expr)) =
|
||||||
|
(pat, expr);
|
||||||
pat_kind == expr_kind
|
pat_kind == expr_kind
|
||||||
&& Match::recurse(sub, pat_pat, expr_pat)
|
&& Match::recurse(sub, pat_pat, expr_pat)
|
||||||
&& Match::recurse(sub, pat_expr, expr_expr)
|
&& Match::recurse(sub, pat_expr, expr_expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply(&mut self, sub: &Subst<A>) {
|
fn apply(&mut self, sub: &Subst<A>) {
|
||||||
let Self(_, pat, expr) = self;
|
let Self(_, _, pat, expr) = self;
|
||||||
pat.apply(sub);
|
pat.apply(sub);
|
||||||
expr.apply(sub);
|
expr.apply(sub);
|
||||||
}
|
}
|
||||||
@@ -106,21 +107,11 @@ impl<A: Annotation> Match<A> for crate::ast::Make<A> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A: Annotation> Match<A> for Typedef {
|
|
||||||
fn recurse(sub: &mut Subst<A>, pat: &Self, expr: &Self) -> bool {
|
|
||||||
let (Self(pat_kind, pat_pat), Self(expr_kind, expr_pat)) = (pat, expr);
|
|
||||||
pat_kind == expr_kind && Match::recurse(sub, pat_pat, expr_pat)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn apply(&mut self, sub: &Subst<A>) {
|
|
||||||
let Self(_, pat) = self;
|
|
||||||
pat.apply(sub);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<A: Annotation> Match<A> for Expr<A> {
|
impl<A: Annotation> Match<A> for Expr<A> {
|
||||||
fn recurse(sub: &mut Subst<A>, pat: &Self, expr: &Self) -> bool {
|
fn recurse(sub: &mut Subst<A>, pat: &Self, expr: &Self) -> bool {
|
||||||
match (pat, expr) {
|
match (pat, expr) {
|
||||||
|
(Expr::Omitted, Expr::Omitted) => true,
|
||||||
|
(Expr::Omitted, _) => false,
|
||||||
(Expr::MetId(name), _) if name == "_" => true,
|
(Expr::MetId(name), _) if name == "_" => true,
|
||||||
(Expr::MetId(name), _) => sub.add_expr(name.clone(), expr),
|
(Expr::MetId(name), _) => sub.add_expr(name.clone(), expr),
|
||||||
(Expr::Id(pat), Expr::Id(expr)) => pat == expr,
|
(Expr::Id(pat), Expr::Id(expr)) => pat == expr,
|
||||||
@@ -131,8 +122,6 @@ impl<A: Annotation> Match<A> for Expr<A> {
|
|||||||
(Expr::Use(_), _) => false,
|
(Expr::Use(_), _) => false,
|
||||||
(Expr::Bind(pat), Expr::Bind(expr)) => Match::recurse(sub, pat, expr),
|
(Expr::Bind(pat), Expr::Bind(expr)) => Match::recurse(sub, pat, expr),
|
||||||
(Expr::Bind(..), _) => false,
|
(Expr::Bind(..), _) => false,
|
||||||
(Expr::Struct(pat), Expr::Struct(expr)) => Match::recurse(sub, pat, expr),
|
|
||||||
(Expr::Struct(_), _) => false,
|
|
||||||
(Expr::Make(pat), Expr::Make(expr)) => Match::recurse(sub, pat, expr),
|
(Expr::Make(pat), Expr::Make(expr)) => Match::recurse(sub, pat, expr),
|
||||||
(Expr::Make(..), _) => false,
|
(Expr::Make(..), _) => false,
|
||||||
(Expr::Op(pat_op, pat_exprs), Expr::Op(expr_op, expr_exprs)) => {
|
(Expr::Op(pat_op, pat_exprs), Expr::Op(expr_op, expr_exprs)) => {
|
||||||
@@ -149,9 +138,8 @@ impl<A: Annotation> Match<A> for Expr<A> {
|
|||||||
*self = expr.clone()
|
*self = expr.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::Id(_) | Expr::Lit(_) | Expr::Use(_) => {}
|
Expr::Omitted | Expr::Id(_) | Expr::Lit(_) | Expr::Use(_) => {}
|
||||||
Expr::Bind(expr) => expr.apply(sub),
|
Expr::Bind(expr) => expr.apply(sub),
|
||||||
Expr::Struct(expr) => expr.apply(sub),
|
|
||||||
Expr::Make(expr) => expr.apply(sub),
|
Expr::Make(expr) => expr.apply(sub),
|
||||||
Expr::Op(op, exprs) => {
|
Expr::Op(op, exprs) => {
|
||||||
op.apply(sub);
|
op.apply(sub);
|
||||||
|
|||||||
108
src/parser.rs
108
src/parser.rs
@@ -535,19 +535,12 @@ pub enum Ps {
|
|||||||
Mid, // MetaIdentifier
|
Mid, // MetaIdentifier
|
||||||
Lit, // Literal
|
Lit, // Literal
|
||||||
Use, // use Use
|
Use, // use Use
|
||||||
Let, // let Pat = Expr (else Expr)?
|
Def, // any definition (let, const, static, struct, enum, fn, ...)
|
||||||
Const, // const Pat = Expr
|
|
||||||
Static, // static Pat = Expr
|
|
||||||
Type, // type Pat = Expr
|
|
||||||
Typedef, // struct { Pat } | struct ( Pat )
|
|
||||||
For, // for Pat in Expr Expr else Expr
|
For, // for Pat in Expr Expr else Expr
|
||||||
Fn, // fn ( Pat,* ) Expr
|
|
||||||
Lambda0, // || Expr
|
Lambda0, // || Expr
|
||||||
Lambda, // | Pat,* | Expr
|
Lambda, // | Pat,* | Expr
|
||||||
DoubleRef, // && Expr
|
DoubleRef, // && Expr
|
||||||
Make, // Expr{ Expr,* }
|
Make, // Expr{ Expr,* }
|
||||||
Mod, // mod Pat Expr
|
|
||||||
Impl, // impl Pat Expr
|
|
||||||
ImplicitDo, // An implicit semicolon
|
ImplicitDo, // An implicit semicolon
|
||||||
ExplicitDo, // An explicit leading semicolon
|
ExplicitDo, // An explicit leading semicolon
|
||||||
End, // Produces an empty value.
|
End, // Produces an empty value.
|
||||||
@@ -568,16 +561,19 @@ fn from_prefix(token: &Token) -> PResult<(Ps, Prec)> {
|
|||||||
|
|
||||||
TKind::Pub => (Ps::Op(Op::Pub), Prec::Body),
|
TKind::Pub => (Ps::Op(Op::Pub), Prec::Body),
|
||||||
TKind::For => (Ps::For, Prec::Body),
|
TKind::For => (Ps::For, Prec::Body),
|
||||||
TKind::Fn => (Ps::Fn, Prec::Body),
|
|
||||||
TKind::Match => (Ps::Op(Op::Match), Prec::Body),
|
TKind::Match => (Ps::Op(Op::Match), Prec::Body),
|
||||||
TKind::Macro => (Ps::Op(Op::Macro), Prec::Assign),
|
TKind::Macro => (Ps::Op(Op::Macro), Prec::Assign),
|
||||||
TKind::Mod => (Ps::Mod, Prec::Body),
|
|
||||||
TKind::Impl => (Ps::Impl, Prec::Body),
|
TKind::Fn
|
||||||
TKind::Let => (Ps::Let, Prec::Tuple),
|
| TKind::Mod
|
||||||
TKind::Const => (Ps::Const, Prec::Body),
|
| TKind::Impl
|
||||||
TKind::Static => (Ps::Static, Prec::Body),
|
| TKind::Let
|
||||||
TKind::Type => (Ps::Type, Prec::Body),
|
| TKind::Const
|
||||||
TKind::Struct | TKind::Enum => (Ps::Typedef, Prec::Body),
|
| TKind::Static
|
||||||
|
| TKind::Type
|
||||||
|
| TKind::Struct
|
||||||
|
| TKind::Enum => (Ps::Def, Prec::Body),
|
||||||
|
|
||||||
TKind::Loop => (Ps::Op(Op::Loop), Prec::Body),
|
TKind::Loop => (Ps::Op(Op::Loop), Prec::Body),
|
||||||
TKind::If => (Ps::Op(Op::If), Prec::Body),
|
TKind::If => (Ps::Op(Op::If), Prec::Body),
|
||||||
TKind::While => (Ps::Op(Op::While), Prec::Body),
|
TKind::While => (Ps::Op(Op::While), Prec::Body),
|
||||||
@@ -658,56 +654,66 @@ fn from_infix(token: &Token) -> PResult<(Ps, Prec)> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'t> Parse<'t> for Typedef {
|
impl<'t> Parse<'t> for BindKind {
|
||||||
type Prec = ();
|
type Prec = ();
|
||||||
|
|
||||||
fn parse(p: &mut Parser<'t>, _level: Self::Prec) -> PResult<Self> {
|
fn parse(p: &mut Parser<'t>, _level: Self::Prec) -> PResult<Self> {
|
||||||
let tok = p.next()?;
|
let bk = match p.peek()?.kind {
|
||||||
match tok.kind {
|
TKind::Let => BindKind::Let,
|
||||||
TKind::Enum => Ok(Self(TypedefKind::Enum, p.parse(PPrec::Tuple)?)),
|
TKind::Const => BindKind::Const,
|
||||||
TKind::Struct => Ok(Self(TypedefKind::Struct, p.parse(PPrec::Tuple)?)),
|
TKind::Static => BindKind::Static,
|
||||||
_ => Err(ParseError::NotType(tok.kind, tok.span)),
|
TKind::Type => BindKind::Type,
|
||||||
}
|
TKind::Struct => BindKind::Struct,
|
||||||
|
TKind::Enum => BindKind::Enum,
|
||||||
|
TKind::Fn => BindKind::Fn,
|
||||||
|
TKind::Mod => BindKind::Mod,
|
||||||
|
TKind::Impl => BindKind::Impl,
|
||||||
|
TKind::Bar => BindKind::Match,
|
||||||
|
// no consume!
|
||||||
|
_ => return Ok(BindKind::Match),
|
||||||
|
};
|
||||||
|
p.consume();
|
||||||
|
Ok(bk)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'t> Parse<'t> for Bind {
|
impl<'t> Parse<'t> for Bind {
|
||||||
type Prec = BindKind;
|
type Prec = ();
|
||||||
|
|
||||||
|
fn parse(p: &mut Parser<'t>, _level: Self::Prec) -> PResult<Self> {
|
||||||
|
let level = p.parse(())?;
|
||||||
|
let generics = match p.next_if(TKind::Lt)? {
|
||||||
|
Ok(_) => p.list(vec![], (), TKind::Comma, TKind::Gt)?,
|
||||||
|
Err(_) => vec![],
|
||||||
|
};
|
||||||
|
|
||||||
fn parse(p: &mut Parser<'t>, level: Self::Prec) -> PResult<Self> {
|
|
||||||
match level {
|
match level {
|
||||||
BindKind::Match => {
|
BindKind::Match => {
|
||||||
// |? Pat => Expr
|
// |? Pat => Expr
|
||||||
p.next_if(TKind::Bar)?.ok(); // and discard
|
|
||||||
Ok(Self(
|
Ok(Self(
|
||||||
level,
|
level,
|
||||||
|
generics,
|
||||||
p.parse(PPrec::Alt)?,
|
p.parse(PPrec::Alt)?,
|
||||||
vec![p.expect(TKind::FatArrow)?.parse(Prec::Body.next())?],
|
vec![p.expect(TKind::FatArrow)?.parse(Prec::Body.next())?],
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
BindKind::Mod | BindKind::Impl => Ok(Self(
|
BindKind::Mod | BindKind::Impl => Ok(Self(
|
||||||
level,
|
level,
|
||||||
p.consume().parse(PPrec::Max)?,
|
generics,
|
||||||
|
p.parse(PPrec::Max)?,
|
||||||
vec![p.parse(Prec::Body.next())?],
|
vec![p.parse(Prec::Body.next())?],
|
||||||
)),
|
)),
|
||||||
BindKind::Fn => {
|
BindKind::Fn => Ok(Self(
|
||||||
if p.consume().next_if(TKind::Lt)?.is_ok() {
|
|
||||||
let _gty: Vec<FqPath> = p.list(vec![], (), TKind::Comma, TKind::Gt)?;
|
|
||||||
}
|
|
||||||
Ok(Self(
|
|
||||||
level,
|
level,
|
||||||
|
generics,
|
||||||
p.parse(PPrec::Fn)?,
|
p.parse(PPrec::Fn)?,
|
||||||
vec![p.parse(Prec::Body.next())?],
|
vec![p.parse(Prec::Body.next())?],
|
||||||
))
|
)),
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
if p.consume().next_if(TKind::Lt)?.is_ok() {
|
|
||||||
let _gty: Vec<FqPath> = p.list(vec![], (), TKind::Comma, TKind::Gt)?;
|
|
||||||
}
|
|
||||||
// let Pat
|
// let Pat
|
||||||
let pat = p.parse(PPrec::Tuple)?;
|
let pat = p.parse(PPrec::Tuple)?;
|
||||||
if p.next_if(TKind::Eq).allow_eof()?.is_none_or(|v| v.is_err()) {
|
if p.next_if(TKind::Eq).allow_eof()?.is_none_or(|v| v.is_err()) {
|
||||||
return Ok(Self(level, pat, vec![]));
|
return Ok(Self(level, generics, pat, vec![]));
|
||||||
}
|
}
|
||||||
|
|
||||||
// = Expr
|
// = Expr
|
||||||
@@ -716,11 +722,16 @@ impl<'t> Parse<'t> for Bind {
|
|||||||
.allow_eof()?
|
.allow_eof()?
|
||||||
.is_none_or(|v| v.is_err())
|
.is_none_or(|v| v.is_err())
|
||||||
{
|
{
|
||||||
return Ok(Self(level, pat, vec![body]));
|
return Ok(Self(level, generics, pat, vec![body]));
|
||||||
}
|
}
|
||||||
|
|
||||||
// else Expr
|
// else Expr
|
||||||
Ok(Self(level, pat, vec![body, p.parse(Prec::Body.next())?]))
|
Ok(Self(
|
||||||
|
level,
|
||||||
|
generics,
|
||||||
|
pat,
|
||||||
|
vec![body, p.parse(Prec::Body.next())?],
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -760,21 +771,14 @@ impl<'t> Parse<'t> for Expr {
|
|||||||
// "End" is produced when an "empty" expression is syntactically required.
|
// "End" is produced when an "empty" expression is syntactically required.
|
||||||
// This happens when a semi or closing delimiter begins an expression.
|
// This happens when a semi or closing delimiter begins an expression.
|
||||||
// The token which emitted "End" cannot be consumed, as it is expected elsewhere.
|
// The token which emitted "End" cannot be consumed, as it is expected elsewhere.
|
||||||
Ps::End if level <= prec.next() => Expr::Op(Op::Tuple, vec![]),
|
Ps::End if level <= prec.next() => Expr::Omitted,
|
||||||
Ps::End => Err(ParseError::NotPrefix(kind, span))?,
|
Ps::End => Err(ParseError::NotPrefix(kind, span))?,
|
||||||
|
|
||||||
Ps::Id => Expr::Id(p.parse(())?),
|
Ps::Id => Expr::Id(p.parse(())?),
|
||||||
Ps::Mid => Expr::MetId(p.consume().next()?.lexeme.to_string()),
|
Ps::Mid => Expr::MetId(p.consume().next()?.lexeme.to_string()),
|
||||||
Ps::Lit => Expr::Lit(p.parse(())?),
|
Ps::Lit => Expr::Lit(p.parse(())?),
|
||||||
Ps::Use => Expr::Use(p.consume().parse(())?),
|
Ps::Use => Expr::Use(p.consume().parse(())?),
|
||||||
Ps::Typedef => Expr::Struct(p.parse(())?),
|
Ps::Def => Expr::Bind(p.parse(())?),
|
||||||
Ps::Let => Expr::Bind(p.parse(BindKind::Let)?),
|
|
||||||
Ps::Const => Expr::Bind(p.parse(BindKind::Const)?),
|
|
||||||
Ps::Static => Expr::Bind(p.parse(BindKind::Static)?),
|
|
||||||
Ps::Type => Expr::Bind(p.parse(BindKind::Type)?),
|
|
||||||
Ps::Mod => Expr::Bind(p.parse(BindKind::Mod)?),
|
|
||||||
Ps::Impl => Expr::Bind(p.parse(BindKind::Impl)?),
|
|
||||||
Ps::Fn => Expr::Bind(p.parse(BindKind::Fn)?),
|
|
||||||
Ps::Lambda | Ps::Lambda0 => {
|
Ps::Lambda | Ps::Lambda0 => {
|
||||||
p.consume();
|
p.consume();
|
||||||
|
|
||||||
@@ -789,6 +793,7 @@ impl<'t> Parse<'t> for Expr {
|
|||||||
|
|
||||||
Expr::Bind(Box::new(Bind(
|
Expr::Bind(Box::new(Bind(
|
||||||
BindKind::Fn,
|
BindKind::Fn,
|
||||||
|
vec![],
|
||||||
Pat::Op(PatOp::Fn, vec![args, rety]),
|
Pat::Op(PatOp::Fn, vec![args, rety]),
|
||||||
vec![p.parse(Prec::Body.next())?],
|
vec![p.parse(Prec::Body.next())?],
|
||||||
)))
|
)))
|
||||||
@@ -928,7 +933,7 @@ fn parse_match<'t>(p: &mut Parser<'t>) -> PResult<Expr> {
|
|||||||
|
|
||||||
let arms = p
|
let arms = p
|
||||||
.expect(TKind::LCurly)?
|
.expect(TKind::LCurly)?
|
||||||
.list(vec![], BindKind::Match, TKind::Comma, TKind::RCurly)?
|
.list(vec![], (), TKind::Comma, TKind::RCurly)?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|Anno(arm, span)| Anno(Expr::Bind(Box::new(arm)), span));
|
.map(|Anno(arm, span)| Anno(Expr::Bind(Box::new(arm)), span));
|
||||||
|
|
||||||
@@ -978,6 +983,7 @@ fn parse_for<'t>(p: &mut Parser<'t>, _level: ()) -> PResult<Expr> {
|
|||||||
.anno(cspan),
|
.anno(cspan),
|
||||||
Expr::Bind(Box::new(Bind(
|
Expr::Bind(Box::new(Bind(
|
||||||
BindKind::Match,
|
BindKind::Match,
|
||||||
|
vec![],
|
||||||
Pat::Name("#iter".into()),
|
Pat::Name("#iter".into()),
|
||||||
vec![
|
vec![
|
||||||
Expr::Op(
|
Expr::Op(
|
||||||
@@ -1000,12 +1006,14 @@ fn parse_for<'t>(p: &mut Parser<'t>, _level: ()) -> PResult<Expr> {
|
|||||||
.anno(cspan),
|
.anno(cspan),
|
||||||
Expr::Bind(Box::new(Bind(
|
Expr::Bind(Box::new(Bind(
|
||||||
BindKind::Match,
|
BindKind::Match,
|
||||||
|
vec![],
|
||||||
Pat::Name("None".into()),
|
Pat::Name("None".into()),
|
||||||
vec![Expr::Op(Op::Break, vec![fail]).anno(fspan)],
|
vec![Expr::Op(Op::Break, vec![fail]).anno(fspan)],
|
||||||
)))
|
)))
|
||||||
.anno(fspan),
|
.anno(fspan),
|
||||||
Expr::Bind(Box::new(Bind(
|
Expr::Bind(Box::new(Bind(
|
||||||
BindKind::Match,
|
BindKind::Match,
|
||||||
|
vec![],
|
||||||
Pat::NamedTuple(
|
Pat::NamedTuple(
|
||||||
"Some".into(),
|
"Some".into(),
|
||||||
Box::new(Pat::Op(PatOp::Tuple, vec![pat])),
|
Box::new(Pat::Op(PatOp::Tuple, vec![pat])),
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ impl std::fmt::Debug for Span {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[expect(non_snake_case)]
|
||||||
/// Stores the start and end byte position
|
/// Stores the start and end byte position
|
||||||
pub fn Span(head: u32, tail: u32) -> Span {
|
pub fn Span(head: u32, tail: u32) -> Span {
|
||||||
Span { head, tail }
|
Span { head, tail }
|
||||||
|
|||||||
Reference in New Issue
Block a user