parser: Move parse_for below impl Parse<'t> for Expr, and allow a single semi at EOF
This commit is contained in:
185
src/parser.rs
185
src/parser.rs
@@ -731,93 +731,6 @@ impl<'t> Parse<'t> for MakeArm {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_for<'t>(p: &mut Parser<'t>, _level: ()) -> PResult<Expr> {
|
||||
// for Pat
|
||||
let pat = p.consume().parse(PPrec::Tuple)?;
|
||||
// in Expr
|
||||
let iter: Anno<Expr> = p.expect(TKind::In)?.parse(Prec::Logical.next())?;
|
||||
let cspan = iter.1;
|
||||
// Expr
|
||||
let pass: Anno<Expr> = p.parse(Prec::Body.next())?;
|
||||
let pspan = pass.1;
|
||||
// else Expr?
|
||||
let fail = match p.next_if(TKind::Else).allow_eof()? {
|
||||
Some(Ok(_)) => p.parse(Prec::Body.next())?,
|
||||
_ => Expr::Op(Op::Tuple, vec![]).anno(pspan),
|
||||
};
|
||||
let fspan = fail.1;
|
||||
/*
|
||||
for `pat in `iter `pass else `fail
|
||||
==>
|
||||
match (`iter).into_iter() {
|
||||
#iter => loop match #iter.next() {
|
||||
None => break `fail,
|
||||
Some(`pat) => `pass,
|
||||
},
|
||||
}
|
||||
*/
|
||||
|
||||
Ok(Expr::Op(
|
||||
Op::Match,
|
||||
vec![
|
||||
Expr::Op(
|
||||
Op::Dot,
|
||||
vec![
|
||||
iter,
|
||||
Expr::Op(Op::Call, vec![Expr::Id("into_iter".into()).anno(cspan)]).anno(cspan),
|
||||
],
|
||||
)
|
||||
.anno(cspan),
|
||||
Expr::Bind(Box::new(Bind(
|
||||
BindKind::Match,
|
||||
Pat::Name("#iter".into()),
|
||||
vec![
|
||||
Expr::Op(
|
||||
Op::Loop,
|
||||
vec![
|
||||
Expr::Op(
|
||||
Op::Match,
|
||||
vec![
|
||||
Expr::Op(
|
||||
Op::Dot,
|
||||
vec![
|
||||
Expr::Id("#iter".into()).anno(cspan),
|
||||
Expr::Op(
|
||||
Op::Call,
|
||||
vec![Expr::Id("next".into()).anno(cspan)],
|
||||
)
|
||||
.anno(cspan),
|
||||
],
|
||||
)
|
||||
.anno(cspan),
|
||||
Expr::Bind(Box::new(Bind(
|
||||
BindKind::Match,
|
||||
Pat::Name("None".into()),
|
||||
vec![Expr::Op(Op::Break, vec![fail]).anno(fspan)],
|
||||
)))
|
||||
.anno(fspan),
|
||||
Expr::Bind(Box::new(Bind(
|
||||
BindKind::Match,
|
||||
Pat::NamedTuple(
|
||||
"Some".into(),
|
||||
Box::new(Pat::Op(PatOp::Tuple, vec![pat])),
|
||||
),
|
||||
vec![pass],
|
||||
)))
|
||||
.anno(pspan),
|
||||
],
|
||||
)
|
||||
.anno(pspan),
|
||||
],
|
||||
)
|
||||
.anno(pspan),
|
||||
],
|
||||
)))
|
||||
.anno(pspan),
|
||||
],
|
||||
))
|
||||
}
|
||||
|
||||
impl<'t> Parse<'t> for Expr {
|
||||
type Prec = usize;
|
||||
|
||||
@@ -939,7 +852,14 @@ impl<'t> Parse<'t> for Expr {
|
||||
// As is ImplicitDo (semicolon elision)
|
||||
Ps::ImplicitDo if p.elide_do => head.and_do(span, p.parse(prec.next())?),
|
||||
Ps::ImplicitDo => break,
|
||||
Ps::Op(Op::Do) => head.and_do(span, p.consume().parse(prec.next())?),
|
||||
// Allow `;` at end of file
|
||||
Ps::Op(Op::Do) => head.and_do(
|
||||
span,
|
||||
match p.consume().peek().allow_eof()? {
|
||||
Some(_) => p.parse(prec.next())?,
|
||||
None => Anno(Default::default(), span),
|
||||
},
|
||||
),
|
||||
Ps::Op(Op::Index) => Expr::Op(
|
||||
Op::Index,
|
||||
p.consume()
|
||||
@@ -1008,6 +928,95 @@ fn parse_match<'t>(p: &mut Parser<'t>) -> PResult<Expr> {
|
||||
Ok(expr)
|
||||
}
|
||||
|
||||
fn parse_for<'t>(p: &mut Parser<'t>, _level: ()) -> PResult<Expr> {
|
||||
// for Pat
|
||||
let pat = p.consume().parse(PPrec::Tuple)?;
|
||||
// in Expr
|
||||
let iter: Anno<Expr> = p.expect(TKind::In)?.parse(Prec::Logical.next())?;
|
||||
let cspan = iter.1;
|
||||
// Expr
|
||||
let pass: Anno<Expr> = p.parse(Prec::Body.next())?;
|
||||
let pspan = pass.1;
|
||||
// else Expr?
|
||||
let fail = match p.next_if(TKind::Else).allow_eof()? {
|
||||
Some(Ok(_)) => p.parse(Prec::Body.next())?,
|
||||
_ => Expr::Op(Op::Tuple, vec![]).anno(pspan),
|
||||
};
|
||||
let fspan = fail.1;
|
||||
/*
|
||||
for `pat in `iter `pass else `fail
|
||||
==>
|
||||
match (`iter).into_iter() {
|
||||
#iter => loop match #iter.next() {
|
||||
None => break `fail,
|
||||
Some(`pat) => `pass,
|
||||
},
|
||||
}
|
||||
*/
|
||||
|
||||
// TODO: A better way to do this kind of substitution desugaring
|
||||
// without losing span information!
|
||||
Ok(Expr::Op(
|
||||
Op::Match,
|
||||
vec![
|
||||
Expr::Op(
|
||||
Op::Dot,
|
||||
vec![
|
||||
iter,
|
||||
Expr::Op(Op::Call, vec![Expr::Id("into_iter".into()).anno(cspan)]).anno(cspan),
|
||||
],
|
||||
)
|
||||
.anno(cspan),
|
||||
Expr::Bind(Box::new(Bind(
|
||||
BindKind::Match,
|
||||
Pat::Name("#iter".into()),
|
||||
vec![
|
||||
Expr::Op(
|
||||
Op::Loop,
|
||||
vec![
|
||||
Expr::Op(
|
||||
Op::Match,
|
||||
vec![
|
||||
Expr::Op(
|
||||
Op::Dot,
|
||||
vec![
|
||||
Expr::Id("#iter".into()).anno(cspan),
|
||||
Expr::Op(
|
||||
Op::Call,
|
||||
vec![Expr::Id("next".into()).anno(cspan)],
|
||||
)
|
||||
.anno(cspan),
|
||||
],
|
||||
)
|
||||
.anno(cspan),
|
||||
Expr::Bind(Box::new(Bind(
|
||||
BindKind::Match,
|
||||
Pat::Name("None".into()),
|
||||
vec![Expr::Op(Op::Break, vec![fail]).anno(fspan)],
|
||||
)))
|
||||
.anno(fspan),
|
||||
Expr::Bind(Box::new(Bind(
|
||||
BindKind::Match,
|
||||
Pat::NamedTuple(
|
||||
"Some".into(),
|
||||
Box::new(Pat::Op(PatOp::Tuple, vec![pat])),
|
||||
),
|
||||
vec![pass],
|
||||
)))
|
||||
.anno(pspan),
|
||||
],
|
||||
)
|
||||
.anno(pspan),
|
||||
],
|
||||
)
|
||||
.anno(pspan),
|
||||
],
|
||||
)))
|
||||
.anno(pspan),
|
||||
],
|
||||
))
|
||||
}
|
||||
|
||||
impl<'t, P: Parse<'t> + Annotation> Parse<'t> for Anno<P> {
|
||||
type Prec = P::Prec;
|
||||
fn parse(p: &mut Parser<'t>, level: P::Prec) -> PResult<Self>
|
||||
|
||||
Reference in New Issue
Block a user