Parse nested closure with two consecutive parameter lists properly
This commit is contained in:
parent
d290dec97f
commit
31cf11a157
2 changed files with 52 additions and 6 deletions
|
@ -481,6 +481,12 @@ fn dummy_arg(span: Span) -> Arg {
|
||||||
Arg { ty: P(ty), pat: pat, id: ast::DUMMY_NODE_ID }
|
Arg { ty: P(ty), pat: pat, id: ast::DUMMY_NODE_ID }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
|
enum TokenExpectType {
|
||||||
|
Expect,
|
||||||
|
NoExpect,
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> Parser<'a> {
|
impl<'a> Parser<'a> {
|
||||||
pub fn new(sess: &'a ParseSess,
|
pub fn new(sess: &'a ParseSess,
|
||||||
tokens: TokenStream,
|
tokens: TokenStream,
|
||||||
|
@ -797,6 +803,23 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Expect and consume an `|`. If `||` is seen, replace it with a single
|
||||||
|
/// `|` and continue. If an `|` is not seen, signal an error.
|
||||||
|
fn expect_or(&mut self) -> PResult<'a, ()> {
|
||||||
|
self.expected_tokens.push(TokenType::Token(token::BinOp(token::Or)));
|
||||||
|
match self.token {
|
||||||
|
token::BinOp(token::Or) => {
|
||||||
|
self.bump();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
token::OrOr => {
|
||||||
|
let span = self.span.with_lo(self.span.lo() + BytePos(1));
|
||||||
|
Ok(self.bump_with(token::BinOp(token::Or), span))
|
||||||
|
}
|
||||||
|
_ => self.unexpected()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn expect_no_suffix(&self, sp: Span, kind: &str, suffix: Option<ast::Name>) {
|
pub fn expect_no_suffix(&self, sp: Span, kind: &str, suffix: Option<ast::Name>) {
|
||||||
match suffix {
|
match suffix {
|
||||||
None => {/* everything ok */}
|
None => {/* everything ok */}
|
||||||
|
@ -946,6 +969,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
self.parse_seq_to_before_tokens(kets,
|
self.parse_seq_to_before_tokens(kets,
|
||||||
SeqSep::none(),
|
SeqSep::none(),
|
||||||
|
TokenExpectType::Expect,
|
||||||
|p| Ok(p.parse_token_tree()),
|
|p| Ok(p.parse_token_tree()),
|
||||||
|mut e| handler.cancel(&mut e));
|
|mut e| handler.cancel(&mut e));
|
||||||
}
|
}
|
||||||
|
@ -975,13 +999,14 @@ impl<'a> Parser<'a> {
|
||||||
-> Vec<T>
|
-> Vec<T>
|
||||||
where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>
|
where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>
|
||||||
{
|
{
|
||||||
self.parse_seq_to_before_tokens(&[ket], sep, f, |mut e| e.emit())
|
self.parse_seq_to_before_tokens(&[ket], sep, TokenExpectType::Expect, f, |mut e| e.emit())
|
||||||
}
|
}
|
||||||
|
|
||||||
// `fe` is an error handler.
|
// `fe` is an error handler.
|
||||||
fn parse_seq_to_before_tokens<T, F, Fe>(&mut self,
|
fn parse_seq_to_before_tokens<T, F, Fe>(&mut self,
|
||||||
kets: &[&token::Token],
|
kets: &[&token::Token],
|
||||||
sep: SeqSep,
|
sep: SeqSep,
|
||||||
|
expect: TokenExpectType,
|
||||||
mut f: F,
|
mut f: F,
|
||||||
mut fe: Fe)
|
mut fe: Fe)
|
||||||
-> Vec<T>
|
-> Vec<T>
|
||||||
|
@ -1005,7 +1030,12 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if sep.trailing_sep_allowed && kets.iter().any(|k| self.check(k)) {
|
if sep.trailing_sep_allowed && kets.iter().any(|k| {
|
||||||
|
match expect {
|
||||||
|
TokenExpectType::Expect => self.check(k),
|
||||||
|
TokenExpectType::NoExpect => self.token == **k,
|
||||||
|
}
|
||||||
|
}) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4694,12 +4724,14 @@ impl<'a> Parser<'a> {
|
||||||
Vec::new()
|
Vec::new()
|
||||||
} else {
|
} else {
|
||||||
self.expect(&token::BinOp(token::Or))?;
|
self.expect(&token::BinOp(token::Or))?;
|
||||||
let args = self.parse_seq_to_before_end(
|
let args = self.parse_seq_to_before_tokens(
|
||||||
&token::BinOp(token::Or),
|
&[&token::BinOp(token::Or), &token::OrOr],
|
||||||
SeqSep::trailing_allowed(token::Comma),
|
SeqSep::trailing_allowed(token::Comma),
|
||||||
|p| p.parse_fn_block_arg()
|
TokenExpectType::NoExpect,
|
||||||
|
|p| p.parse_fn_block_arg(),
|
||||||
|
|mut e| e.emit()
|
||||||
);
|
);
|
||||||
self.expect(&token::BinOp(token::Or))?;
|
self.expect_or()?;
|
||||||
args
|
args
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
14
src/test/run-pass/closure-returning-closure.rs
Normal file
14
src/test/run-pass/closure-returning-closure.rs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let f = |_||x, y| x+y;
|
||||||
|
assert_eq!(f(())(1, 2), 3);
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue