ast: pub
, mod
, and Ty::Fn parsing
This commit is contained in:
parent
46b17a7eb6
commit
bcabbcd39d
108
src/ast.rs
108
src/ast.rs
@ -46,20 +46,6 @@ pub enum Pat {
|
|||||||
Typed(Box<Pat>, Ty),
|
Typed(Box<Pat>, Ty),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The arms of a make expression
|
|
||||||
/// ```ignore
|
|
||||||
/// Identifier (':' Expr)?
|
|
||||||
/// ```
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
||||||
pub struct MakeArm<A: Annotation = Span>(pub String, pub Option<Anno<Expr<A>, A>>);
|
|
||||||
|
|
||||||
/// The arms of a match expression
|
|
||||||
/// ```ignore
|
|
||||||
/// (Pat |)* Pat? => Expr
|
|
||||||
/// ```
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
||||||
pub struct MatchArm<A: Annotation = Span>(pub Pat, pub Anno<Expr<A>, A>);
|
|
||||||
|
|
||||||
/// In-universe types
|
/// In-universe types
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum Ty {
|
pub enum Ty {
|
||||||
@ -73,26 +59,66 @@ pub enum Ty {
|
|||||||
Slice(Box<Ty>),
|
Slice(Box<Ty>),
|
||||||
/// `[Ty; _]`
|
/// `[Ty; _]`
|
||||||
Array(Box<Ty>, Box<Expr>),
|
Array(Box<Ty>, Box<Expr>),
|
||||||
/// `[Rety, ..Args]`
|
/// `[..Args, Rety]`
|
||||||
Fn(Vec<Ty>),
|
Fn(Vec<Ty>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A `const` binding (which defines its name before executing)
|
/// A `let` binding
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
/// ```ignore
|
||||||
pub struct Const<A: Annotation = Span>(pub Pat, pub Anno<Expr<A>, A>);
|
/// let Pat (= Expr)?
|
||||||
|
/// ``````
|
||||||
/// A function definition `fn Ident? (Pat,*) Expr`
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
||||||
pub struct Fn<A: Annotation = Span>(pub Option<String>, pub Pat, pub Anno<Expr<A>, A>);
|
|
||||||
|
|
||||||
/// A `let` binding: `let Pat (= Expr)?`
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct Let<A: Annotation = Span>(pub Pat, pub Option<Anno<Expr<A>, A>>);
|
pub struct Let<A: Annotation = Span>(pub Pat, pub Option<Anno<Expr<A>, A>>);
|
||||||
|
|
||||||
/// `match Expr { MatchArm,* }``
|
/// A `const` binding (which defines its name before executing)
|
||||||
|
/// ```ignore
|
||||||
|
/// const Pat = Expr
|
||||||
|
/// ```
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct Const<A: Annotation = Span>(pub Pat, pub Anno<Expr<A>, A>);
|
||||||
|
|
||||||
|
/// A function definition
|
||||||
|
/// ```ignore
|
||||||
|
/// fn Ident? (Pat) Expr
|
||||||
|
/// ```
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct Fn<A: Annotation = Span>(pub Option<String>, pub Pat, pub Anno<Expr<A>, A>);
|
||||||
|
|
||||||
|
/// A match expression
|
||||||
|
/// ```ignore
|
||||||
|
/// match Expr { MatchArm,* }
|
||||||
|
/// ```
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct Match<A: Annotation = Span>(pub Anno<Expr<A>, A>, pub Vec<MatchArm<A>>);
|
pub struct Match<A: Annotation = Span>(pub Anno<Expr<A>, A>, pub Vec<MatchArm<A>>);
|
||||||
|
|
||||||
|
/// The "arms" of a match expression
|
||||||
|
/// ```ignore
|
||||||
|
/// Pat => Expr
|
||||||
|
/// ```
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct MatchArm<A: Annotation = Span>(pub Pat, pub Anno<Expr<A>, A>);
|
||||||
|
|
||||||
|
/// A make (constructor) expression
|
||||||
|
/// ```ignore
|
||||||
|
/// Expr { (Ident (: Expr)?),* }
|
||||||
|
/// ```
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct Make<A: Annotation = Span>(pub Box<Anno<Expr<A>, A>>, pub Vec<MakeArm<A>>);
|
||||||
|
|
||||||
|
/// A single "arm" of a make expression
|
||||||
|
/// ```ignore
|
||||||
|
/// Identifier (':' Expr)?
|
||||||
|
/// ```
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct MakeArm<A: Annotation = Span>(pub String, pub Option<Anno<Expr<A>, A>>);
|
||||||
|
|
||||||
|
/// An inline namespace
|
||||||
|
/// ```ignore
|
||||||
|
/// mod Ty Expr
|
||||||
|
/// ```
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct Mod<A: Annotation = Span>(pub Ty, pub 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> {
|
||||||
@ -109,9 +135,11 @@ pub enum Expr<A: Annotation = Span> {
|
|||||||
/// `| Pat<Tuple> | Expr` | `|| Expr` | `fn Ident? (Pat,*) Expr`
|
/// `| Pat<Tuple> | Expr` | `|| Expr` | `fn Ident? (Pat,*) Expr`
|
||||||
Fn(Box<Fn<A>>),
|
Fn(Box<Fn<A>>),
|
||||||
/// Expr { (Ident (: Expr)?),* }
|
/// Expr { (Ident (: Expr)?),* }
|
||||||
Make(Box<Anno<Self, A>>, Vec<MakeArm<A>>),
|
Make(Box<Make<A>>),
|
||||||
/// match Expr { MatchArm,* }
|
/// match Expr { MatchArm,* }
|
||||||
Match(Box<Match<A>>),
|
Match(Box<Match<A>>),
|
||||||
|
/// mod Ty Expr
|
||||||
|
Mod(Box<Mod<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
|
||||||
Op(Op, Vec<Anno<Self, A>>),
|
Op(Op, Vec<Anno<Self, A>>),
|
||||||
}
|
}
|
||||||
@ -149,6 +177,7 @@ pub enum Op {
|
|||||||
Macro, // macro Expr => Expr
|
Macro, // macro Expr => Expr
|
||||||
Block, // { Expr }
|
Block, // { Expr }
|
||||||
Array, // [ Expr,* ]
|
Array, // [ Expr,* ]
|
||||||
|
ArRep, // [ Expr ; Expr ]
|
||||||
Group, // ( Expr ,?)
|
Group, // ( Expr ,?)
|
||||||
Tuple, // Expr (, Expr)*
|
Tuple, // Expr (, Expr)*
|
||||||
|
|
||||||
@ -156,6 +185,7 @@ pub enum Op {
|
|||||||
Index, // Expr [ Expr,* ]
|
Index, // Expr [ Expr,* ]
|
||||||
Call, // Expr ( Expr,* )
|
Call, // Expr ( Expr,* )
|
||||||
|
|
||||||
|
Pub, // pub Expr
|
||||||
Loop, // loop Expr
|
Loop, // loop Expr
|
||||||
If, // if Expr Expr (else Expr)?
|
If, // if Expr Expr (else Expr)?
|
||||||
While, // while Expr Expr (else Expr)?
|
While, // while Expr Expr (else Expr)?
|
||||||
@ -254,6 +284,20 @@ impl<A: Annotation> Display for Match<A> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<A: Annotation> Display for Make<A> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let Self(expr, make_arms) = self;
|
||||||
|
f.delimit(fmt!("({expr} {{"), "})").list(make_arms, ", ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A: Annotation> Display for Mod<A> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let Self(ty, expr) = self;
|
||||||
|
write!(f, "mod {ty} {expr}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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 {
|
||||||
@ -262,10 +306,9 @@ impl<A: Annotation> Display for Expr<A> {
|
|||||||
Self::Lit(literal) => literal.fmt(f),
|
Self::Lit(literal) => literal.fmt(f),
|
||||||
Self::Let(v) => v.fmt(f),
|
Self::Let(v) => v.fmt(f),
|
||||||
Self::Const(v) => v.fmt(f),
|
Self::Const(v) => v.fmt(f),
|
||||||
Self::Make(expr, make_arms) => {
|
Self::Make(v) => v.fmt(f),
|
||||||
f.delimit(fmt!("({expr} {{"), "})").list(make_arms, ", ")
|
|
||||||
}
|
|
||||||
Self::Match(v) => v.fmt(f),
|
Self::Match(v) => v.fmt(f),
|
||||||
|
Self::Mod(v) => v.fmt(f),
|
||||||
Self::Fn(v) => v.fmt(f),
|
Self::Fn(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() {
|
||||||
@ -273,6 +316,7 @@ impl<A: Annotation> Display for Expr<A> {
|
|||||||
other => f.delimit(fmt!("({op}, "), ")").list(other, ", "),
|
other => f.delimit(fmt!("({op}, "), ")").list(other, ", "),
|
||||||
},
|
},
|
||||||
Self::Op(Op::Array, exprs) => f.delimit("[", "]").list(exprs, ", "),
|
Self::Op(Op::Array, exprs) => f.delimit("[", "]").list(exprs, ", "),
|
||||||
|
Self::Op(Op::ArRep, exprs) => f.delimit("[", "]").list(exprs, "; "),
|
||||||
Self::Op(Op::Block, exprs) => f
|
Self::Op(Op::Block, exprs) => f
|
||||||
.delimit_indented("{", "}")
|
.delimit_indented("{", "}")
|
||||||
.list_wrap("\n", exprs, "\n", "\n"),
|
.list_wrap("\n", exprs, "\n", "\n"),
|
||||||
@ -292,7 +336,7 @@ impl<A: Annotation> Display for Expr<A> {
|
|||||||
Self::Op(op @ Op::Macro, exprs) => f.delimit(op, "").list(exprs, " => "),
|
Self::Op(op @ Op::Macro, exprs) => f.delimit(op, "").list(exprs, " => "),
|
||||||
Self::Op(op @ Op::Try, exprs) => f.delimit("(", fmt!("){op}")).list(exprs, ", "),
|
Self::Op(op @ Op::Try, exprs) => f.delimit("(", fmt!("){op}")).list(exprs, ", "),
|
||||||
Self::Op(op, exprs) => match exprs.as_slice() {
|
Self::Op(op, exprs) => match exprs.as_slice() {
|
||||||
[one] => write!(f, "{op}({one})"),
|
[one] => write!(f, "{op}{one}"),
|
||||||
many => f.delimit("(", ")").list(many, op),
|
many => f.delimit("(", ")").list(many, op),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -307,11 +351,13 @@ impl Display for Op {
|
|||||||
Op::Macro => "macro ".fmt(f),
|
Op::Macro => "macro ".fmt(f),
|
||||||
Op::Block => "{}".fmt(f),
|
Op::Block => "{}".fmt(f),
|
||||||
Op::Array => "[]".fmt(f),
|
Op::Array => "[]".fmt(f),
|
||||||
|
Op::ArRep => "[;]".fmt(f),
|
||||||
Op::Group => "()".fmt(f),
|
Op::Group => "()".fmt(f),
|
||||||
Op::Tuple => "()".fmt(f),
|
Op::Tuple => "()".fmt(f),
|
||||||
Op::Try => "?".fmt(f),
|
Op::Try => "?".fmt(f),
|
||||||
Op::Index => "".fmt(f),
|
Op::Index => "".fmt(f),
|
||||||
Op::Call => "".fmt(f),
|
Op::Call => "".fmt(f),
|
||||||
|
Op::Pub => "pub ".fmt(f),
|
||||||
Op::Loop => "loop ".fmt(f),
|
Op::Loop => "loop ".fmt(f),
|
||||||
Op::If => "if ".fmt(f),
|
Op::If => "if ".fmt(f),
|
||||||
Op::While => "while ".fmt(f),
|
Op::While => "while ".fmt(f),
|
||||||
@ -393,7 +439,7 @@ impl Display for Ty {
|
|||||||
Self::Array(ty, n) => write!(f, "[{ty}; {n}]"),
|
Self::Array(ty, n) => write!(f, "[{ty}; {n}]"),
|
||||||
Self::Fn(items) => match items.as_slice() {
|
Self::Fn(items) => match items.as_slice() {
|
||||||
[] => write!(f, "fn ()"),
|
[] => write!(f, "fn ()"),
|
||||||
[rety, args @ ..] => f
|
[args @ .., rety] => f
|
||||||
.delimit(fmt!("fn ("), fmt!(") -> {rety}"))
|
.delimit(fmt!("fn ("), fmt!(") -> {rety}"))
|
||||||
.list(args, ", "),
|
.list(args, ", "),
|
||||||
},
|
},
|
||||||
|
@ -132,6 +132,33 @@ impl<A: Annotation> Match<A> for crate::ast::Match<A> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<A: Annotation> Match<A> for crate::ast::Make<A> {
|
||||||
|
fn recurse(sub: &mut Subst<A>, pat: &Self, expr: &Self) -> bool {
|
||||||
|
let (Make(pat, pat_arms), Make(expr, expr_arms)) = (pat, expr);
|
||||||
|
Match::recurse(sub, pat, expr) && Match::recurse(sub, pat_arms, expr_arms)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply(&mut self, sub: &Subst<A>) {
|
||||||
|
let Make(expr, make_arms) = self;
|
||||||
|
expr.apply(sub);
|
||||||
|
make_arms.apply(sub);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A: Annotation> Match<A> for Mod<A> {
|
||||||
|
fn recurse(sub: &mut Subst<A>, pat: &Self, expr: &Self) -> bool {
|
||||||
|
let (Self(_pat_ty, pat_expr), Self(_expr_ty, expr_expr)) = (pat, expr);
|
||||||
|
// TODO: unify types for ast matching
|
||||||
|
// Match::recurse(sub, pat_ty, expr_ty) &&
|
||||||
|
Match::recurse(sub, pat_expr, expr_expr)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply(&mut self, sub: &Subst<A>) {
|
||||||
|
let Mod(_ty, expr) = self;
|
||||||
|
expr.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) {
|
||||||
@ -145,12 +172,12 @@ impl<A: Annotation> Match<A> for Expr<A> {
|
|||||||
(Expr::Let(..), _) => false,
|
(Expr::Let(..), _) => false,
|
||||||
(Expr::Const(pat), Expr::Const(expr)) => Match::recurse(sub, pat, expr),
|
(Expr::Const(pat), Expr::Const(expr)) => Match::recurse(sub, pat, expr),
|
||||||
(Expr::Const(..), _) => false,
|
(Expr::Const(..), _) => false,
|
||||||
(Expr::Make(pat, pat_arms), Expr::Make(expr, expr_arms)) => {
|
(Expr::Make(pat), Expr::Make(expr)) => Match::recurse(sub, pat, expr),
|
||||||
Match::recurse(sub, pat, expr) && Match::recurse(sub, pat_arms, expr_arms)
|
|
||||||
}
|
|
||||||
(Expr::Make(..), _) => false,
|
(Expr::Make(..), _) => false,
|
||||||
(Expr::Match(pat), Expr::Match(expr)) => Match::recurse(sub, pat, expr),
|
(Expr::Match(pat), Expr::Match(expr)) => Match::recurse(sub, pat, expr),
|
||||||
(Expr::Match(..), _) => false,
|
(Expr::Match(..), _) => false,
|
||||||
|
(Expr::Mod(pat), Expr::Mod(expr)) => Match::recurse(sub, pat, expr),
|
||||||
|
(Expr::Mod(..), _) => false,
|
||||||
(Expr::Fn(pat), Expr::Fn(expr)) => Match::recurse(sub, pat, expr),
|
(Expr::Fn(pat), Expr::Fn(expr)) => Match::recurse(sub, pat, expr),
|
||||||
(Expr::Fn(..), _) => false,
|
(Expr::Fn(..), _) => 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)) => {
|
||||||
@ -168,22 +195,12 @@ impl<A: Annotation> Match<A> for Expr<A> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::Id(_) | Expr::Lit(_) => {}
|
Expr::Id(_) | Expr::Lit(_) => {}
|
||||||
Expr::Let(expr) => {
|
Expr::Let(expr) => expr.apply(sub),
|
||||||
expr.apply(sub);
|
Expr::Const(expr) => expr.apply(sub),
|
||||||
}
|
Expr::Make(expr) => expr.apply(sub),
|
||||||
Expr::Const(expr) => {
|
Expr::Match(expr) => expr.apply(sub),
|
||||||
expr.apply(sub);
|
Expr::Mod(expr) => expr.apply(sub),
|
||||||
}
|
Expr::Fn(expr) => expr.apply(sub),
|
||||||
Expr::Make(expr, make_arms) => {
|
|
||||||
expr.apply(sub);
|
|
||||||
make_arms.apply(sub);
|
|
||||||
}
|
|
||||||
Expr::Match(expr) => {
|
|
||||||
expr.apply(sub);
|
|
||||||
}
|
|
||||||
Expr::Fn(expr) => {
|
|
||||||
expr.apply(sub);
|
|
||||||
}
|
|
||||||
Expr::Op(op, exprs) => {
|
Expr::Op(op, exprs) => {
|
||||||
op.apply(sub);
|
op.apply(sub);
|
||||||
exprs.apply(sub);
|
exprs.apply(sub);
|
||||||
|
@ -232,6 +232,8 @@ impl<'t> Lexer<'t> {
|
|||||||
"loop" => TKind::Loop,
|
"loop" => TKind::Loop,
|
||||||
"macro" => TKind::Macro,
|
"macro" => TKind::Macro,
|
||||||
"match" => TKind::Match,
|
"match" => TKind::Match,
|
||||||
|
"mod" => TKind::Module,
|
||||||
|
"pub" => TKind::Public,
|
||||||
"return" => TKind::Return,
|
"return" => TKind::Return,
|
||||||
"then" => TKind::Do,
|
"then" => TKind::Do,
|
||||||
"true" => TKind::True,
|
"true" => TKind::True,
|
||||||
|
@ -318,6 +318,28 @@ impl<'t> Parse<'t> for Ty {
|
|||||||
tok => Err(ParseError::NotType(tok.kind, tok.span))?,
|
tok => Err(ParseError::NotType(tok.kind, tok.span))?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
TKind::Fn => {
|
||||||
|
p.consume().consume_if(TKind::LParen)?;
|
||||||
|
|
||||||
|
let mut tys = p.list(vec![], (), TKind::Comma, TKind::RParen)?;
|
||||||
|
match p.next_if(TKind::Arrow) {
|
||||||
|
Ok(_) => {
|
||||||
|
tys.push(p.parse(())?);
|
||||||
|
Ty::Fn(tys)
|
||||||
|
}
|
||||||
|
_ => Ty::Tuple(tys),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TKind::LParen => {
|
||||||
|
let mut tys = p.consume().list(vec![], (), TKind::Comma, TKind::RParen)?;
|
||||||
|
match p.next_if(TKind::Arrow) {
|
||||||
|
Ok(_) => {
|
||||||
|
tys.push(p.parse(())?);
|
||||||
|
Ty::Fn(tys)
|
||||||
|
}
|
||||||
|
_ => Ty::Tuple(tys),
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => Err(ParseError::NotType(tok.kind, tok.span))?,
|
_ => Err(ParseError::NotType(tok.kind, tok.span))?,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -399,6 +421,7 @@ pub enum Ps {
|
|||||||
DoubleRef, // && Expr
|
DoubleRef, // && Expr
|
||||||
Make, // Expr{ Expr,* }
|
Make, // Expr{ Expr,* }
|
||||||
Match, // match Expr { MatchArm,* }
|
Match, // match Expr { MatchArm,* }
|
||||||
|
Mod, // mod Ty Expr
|
||||||
End, // Produces an empty value.
|
End, // Produces an empty value.
|
||||||
Op(Op), // A normal [ast::Op]
|
Op(Op), // A normal [ast::Op]
|
||||||
}
|
}
|
||||||
@ -414,9 +437,11 @@ fn from_prefix(token: &Token) -> PResult<(Ps, Prec)> {
|
|||||||
(Ps::Lit, Prec::Max)
|
(Ps::Lit, Prec::Max)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TKind::Public => (Ps::Op(Op::Pub), Prec::Body),
|
||||||
TKind::Fn => (Ps::Fn, Prec::Body),
|
TKind::Fn => (Ps::Fn, Prec::Body),
|
||||||
TKind::Match => (Ps::Match, Prec::Body),
|
TKind::Match => (Ps::Match, Prec::Body),
|
||||||
TKind::Macro => (Ps::Op(Op::Macro), Prec::Assign),
|
TKind::Macro => (Ps::Op(Op::Macro), Prec::Assign),
|
||||||
|
TKind::Module => (Ps::Mod, Prec::Body),
|
||||||
TKind::Let => (Ps::Let, Prec::Tuple),
|
TKind::Let => (Ps::Let, Prec::Tuple),
|
||||||
TKind::Const => (Ps::Const, Prec::Body),
|
TKind::Const => (Ps::Const, Prec::Body),
|
||||||
TKind::Loop => (Ps::Op(Op::Loop), Prec::Body),
|
TKind::Loop => (Ps::Op(Op::Loop), Prec::Body),
|
||||||
@ -427,7 +452,7 @@ fn from_prefix(token: &Token) -> PResult<(Ps, Prec)> {
|
|||||||
|
|
||||||
TKind::LCurly => (Ps::Op(Op::Block), Prec::Min),
|
TKind::LCurly => (Ps::Op(Op::Block), Prec::Min),
|
||||||
TKind::RCurly => (Ps::End, Prec::Do),
|
TKind::RCurly => (Ps::End, Prec::Do),
|
||||||
TKind::LBrack => (Ps::Op(Op::Array), Prec::Min),
|
TKind::LBrack => (Ps::Op(Op::Array), Prec::Tuple),
|
||||||
TKind::RBrack => (Ps::End, Prec::Tuple),
|
TKind::RBrack => (Ps::End, Prec::Tuple),
|
||||||
TKind::LParen => (Ps::Op(Op::Group), Prec::Min),
|
TKind::LParen => (Ps::Op(Op::Group), Prec::Min),
|
||||||
TKind::RParen => (Ps::End, Prec::Tuple),
|
TKind::RParen => (Ps::End, Prec::Tuple),
|
||||||
@ -560,6 +585,13 @@ impl<'t> Parse<'t> for MakeArm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'t> Parse<'t> for Mod {
|
||||||
|
type Prec = ();
|
||||||
|
fn parse(p: &mut Parser<'t>, _level: Self::Prec) -> PResult<Self> {
|
||||||
|
Ok(Mod(p.consume().parse(())?, p.parse(Prec::Body.value())?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'t> Parse<'t> for Expr {
|
impl<'t> Parse<'t> for Expr {
|
||||||
type Prec = usize;
|
type Prec = usize;
|
||||||
|
|
||||||
@ -585,22 +617,13 @@ impl<'t> Parse<'t> for Expr {
|
|||||||
Ps::Lit => Expr::Lit(p.parse(())?),
|
Ps::Lit => Expr::Lit(p.parse(())?),
|
||||||
Ps::Let => Expr::Let(p.parse(())?),
|
Ps::Let => Expr::Let(p.parse(())?),
|
||||||
Ps::Const => Expr::Const(p.parse(())?),
|
Ps::Const => Expr::Const(p.parse(())?),
|
||||||
Ps::Op(Op::Macro) => Expr::Op(
|
|
||||||
Op::Macro,
|
|
||||||
vec![p.consume().parse(prec.next())?, {
|
|
||||||
p.next_if(TKind::FatArrow)?;
|
|
||||||
p.parse(prec.next())?
|
|
||||||
}],
|
|
||||||
),
|
|
||||||
Ps::Match => Expr::Match(p.parse(())?),
|
Ps::Match => Expr::Match(p.parse(())?),
|
||||||
|
Ps::Mod => Expr::Mod(p.parse(())?),
|
||||||
Ps::Op(Op::Block) => Expr::Op(
|
Ps::Op(Op::Block) => Expr::Op(
|
||||||
Op::Block,
|
Op::Block,
|
||||||
p.consume().opt(MIN, TKind::RCurly)?.into_iter().collect(),
|
p.consume().opt(MIN, TKind::RCurly)?.into_iter().collect(),
|
||||||
),
|
),
|
||||||
Ps::Op(Op::Array) => Expr::Op(
|
Ps::Op(Op::Array) => parse_array(p)?,
|
||||||
Op::Array,
|
|
||||||
p.consume().list(vec![], 0, TKind::Comma, TKind::RBrack)?,
|
|
||||||
),
|
|
||||||
Ps::Op(Op::Group) => match p.consume().opt(MIN, TKind::RParen)? {
|
Ps::Op(Op::Group) => match p.consume().opt(MIN, TKind::RParen)? {
|
||||||
Some(value) => Expr::Op(Op::Group, vec![value]),
|
Some(value) => Expr::Op(Op::Group, vec![value]),
|
||||||
None => Expr::Op(Op::Tuple, vec![]),
|
None => Expr::Op(Op::Tuple, vec![]),
|
||||||
@ -629,10 +652,12 @@ impl<'t> Parse<'t> for Expr {
|
|||||||
Ps::Lambda0 => Expr::Fn(Box::new(Fn(None, Pat::Tuple(vec![]), {
|
Ps::Lambda0 => Expr::Fn(Box::new(Fn(None, Pat::Tuple(vec![]), {
|
||||||
p.consume().parse(Prec::Body.next())?
|
p.consume().parse(Prec::Body.next())?
|
||||||
}))),
|
}))),
|
||||||
Ps::DoubleRef => Expr::Op(
|
Ps::DoubleRef => p.consume().parse(prec.next()).map(|Anno(expr, span)| {
|
||||||
|
Expr::Op(
|
||||||
Op::Refer,
|
Op::Refer,
|
||||||
vec![Expr::Op(Op::Refer, vec![p.consume().parse(prec.next())?]).anno(span)],
|
vec![Anno(Expr::Op(Op::Refer, vec![Anno(expr, span)]), span)],
|
||||||
),
|
)
|
||||||
|
})?,
|
||||||
|
|
||||||
Ps::Op(op) => Expr::Op(op, vec![p.consume().parse(prec.next())?]),
|
Ps::Op(op) => Expr::Op(op, vec![p.consume().parse(prec.next())?]),
|
||||||
_ => unimplemented!("prefix {op:?}"),
|
_ => unimplemented!("prefix {op:?}"),
|
||||||
@ -650,10 +675,12 @@ impl<'t> Parse<'t> for Expr {
|
|||||||
head = match op {
|
head = match op {
|
||||||
// Make (structor expressions) are context-sensitive
|
// Make (structor expressions) are context-sensitive
|
||||||
Ps::Make => match &head {
|
Ps::Make => match &head {
|
||||||
Expr::Op(Op::Path, _) | Expr::Id(_) | Expr::MetId(_) => Expr::Make(
|
Expr::Op(Op::Path, _) | Expr::Id(_) | Expr::MetId(_) => {
|
||||||
|
Expr::Make(Box::new(Make(
|
||||||
head.anno(span).into(),
|
head.anno(span).into(),
|
||||||
p.consume().list(vec![], (), TKind::Comma, TKind::RCurly)?,
|
p.consume().list(vec![], (), TKind::Comma, TKind::RCurly)?,
|
||||||
),
|
)))
|
||||||
|
}
|
||||||
_ => break,
|
_ => break,
|
||||||
},
|
},
|
||||||
Ps::Op(Op::Index) => Expr::Op(
|
Ps::Op(Op::Index) => Expr::Op(
|
||||||
@ -686,6 +713,25 @@ impl<'t> Parse<'t> for Expr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parses an array with 0 or more elements, or an array-repetition
|
||||||
|
fn parse_array<'t>(p: &mut Parser<'t>) -> PResult<Expr> {
|
||||||
|
if p.consume().peek()?.kind == TKind::RBrack {
|
||||||
|
p.consume();
|
||||||
|
return Ok(Expr::Op(Op::Array, vec![]));
|
||||||
|
}
|
||||||
|
|
||||||
|
let prec = Prec::Tuple;
|
||||||
|
let item = p.parse(prec.value())?;
|
||||||
|
let repeat = p.opt_if(prec.next(), TKind::Semi)?;
|
||||||
|
p.next_if(TKind::RBrack)?;
|
||||||
|
|
||||||
|
Ok(match (repeat, item) {
|
||||||
|
(Some(repeat), item) => Expr::Op(Op::ArRep, vec![item, repeat]),
|
||||||
|
(None, Anno(Expr::Op(Op::Tuple, items), _)) => Expr::Op(Op::Array, items),
|
||||||
|
(None, item) => Expr::Op(Op::Array, vec![item]),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
impl<'t, P: Parse<'t> + Annotation> Parse<'t> for Anno<P> {
|
impl<'t, P: Parse<'t> + Annotation> Parse<'t> for Anno<P> {
|
||||||
type Prec = P::Prec;
|
type Prec = P::Prec;
|
||||||
fn parse(p: &mut Parser<'t>, level: P::Prec) -> PResult<Self>
|
fn parse(p: &mut Parser<'t>, level: P::Prec) -> PResult<Self>
|
||||||
|
@ -24,6 +24,8 @@ pub enum TKind {
|
|||||||
Loop,
|
Loop,
|
||||||
Macro,
|
Macro,
|
||||||
Match,
|
Match,
|
||||||
|
Module,
|
||||||
|
Public,
|
||||||
Return,
|
Return,
|
||||||
True,
|
True,
|
||||||
While,
|
While,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user