Skip to content

Commit b3d83c8

Browse files
committed
Fix various issues.
1 parent 801eebf commit b3d83c8

File tree

7 files changed

+116
-49
lines changed

7 files changed

+116
-49
lines changed

src/ast.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ impl fmt::Display for Bop {
162162
Bop::Add => "+",
163163
Bop::Sub => "-",
164164
Bop::Mult => "*",
165-
Bop::Matmult => "]",
165+
Bop::Matmult => "@",
166166
Bop::Mod => "%",
167167
Bop::Floordiv => "//",
168168
Bop::Div => "/",
@@ -264,9 +264,13 @@ pub enum Import {
264264
path: Vec<Name>,
265265
/// For `from x import y, z`, this `vec![(y, None), (vec![z], None)]`.
266266
/// For `from x import y as z`, this `vec![(y, Some(z))]`.
267-
/// For `from x import *`, this is `vec![]`.
268267
names: Vec<(Name, Option<Name>)>
269268
},
269+
/// For `from x import *`, this is `vec![]`.
270+
ImportStarFrom {
271+
leading_dots: usize,
272+
path: Vec<Name>,
273+
},
270274
/// `import x.y as z, foo.bar` is
271275
/// `Import::Import(vec![(vec![x, y], Some(z)), (vec![foo, bar], None)])`.
272276
Import { names: Vec<(Vec<Name>, Option<Name>)> },

src/bytes.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ named_args!(shortbytes(quote: char) <StrSpan, Vec<u8>>,
3939
fold_many0!(
4040
alt!(
4141
call!(escapedchar)
42-
| verify!(none_of!("\\"), |c:char| c != quote) => { |c:char| Some(c as u8) }
42+
| verify!(anychar, |c:char| c != quote) => { |c:char| Some(c as u8) }
4343
),
4444
Vec::new(),
4545
|mut acc:Vec<u8>, c:Option<u8>| { match c { Some(c) => acc.push(c), None => () }; acc }
@@ -50,7 +50,7 @@ named_args!(longbytes(quote: char) <StrSpan, Vec<u8>>,
5050
fold_many0!(
5151
alt!(
5252
call!(escapedchar)
53-
| verify!(tuple!(peek!(take!(3)), none_of!("\\")), |(s,_):(StrSpan,_)| { s.fragment.0.chars().collect::<Vec<char>>() != vec![quote,quote,quote] }) => { |(_,c)| Some(c as u8) }
53+
| verify!(tuple!(peek!(take!(3)), anychar), |(s,_):(StrSpan,_)| { s.fragment.0.chars().collect::<Vec<char>>() != vec![quote,quote,quote] }) => { |(_,c)| Some(c as u8) }
5454
),
5555
Vec::new(),
5656
|mut acc:Vec<u8>, c:Option<u8>| { match c { Some(c) => acc.push(c), None => () }; acc }

src/expressions.rs

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,9 @@ named!(pub test<StrSpan, Box<Expression>>,
4444
| do_parse!(
4545
left: call!(Self::or_test) >>
4646
right: opt!(do_parse!(
47-
spaces!() >>
48-
tag!("if") >>
49-
space_sep!() >>
47+
ws3!(tag!("if")) >>
5048
cond: call!(Self::or_test) >>
51-
space_sep!() >>
52-
tag!("else") >>
53-
space_sep!() >>
49+
ws3!(tag!("else")) >>
5450
right: call!(Self::test) >> (
5551
(cond, right)
5652
)
@@ -239,11 +235,11 @@ named!(atom_expr<StrSpan, Box<Expression>>,
239235
do_parse!(
240236
lhs: call!(Self::atom) >>
241237
trailers: fold_many0!(
242-
alt!(
238+
ws3!(alt!(
243239
delimited!(char!('('), ws4!(call!(ExpressionParser::<NewlinesAreSpaces>::arglist)), char!(')')) => { |args| Trailer::Call(args) }
244240
| delimited!(char!('['), ws4!(separated_list!(char!(','), call!(ExpressionParser::<NewlinesAreSpaces>::subscript))), char!(']')) => { |i| Trailer::Subscript(i) }
245241
| preceded!(ws3!(char!('.')), name) => { |name| Trailer::Attribute(name) }
246-
),
242+
)),
247243
lhs,
248244
|acc, item| Box::new(match item {
249245
Trailer::Call(args) => Expression::Call(acc, args),
@@ -533,10 +529,10 @@ named!(pub arglist<StrSpan, Arglist>,
533529
| preceded!(char!('*'), call!(Self::test)) => { |args: Box<_>| RawArgument::Starargs(*args) }
534530
| do_parse!(
535531
test1: call!(Self::test) >>
536-
next: opt!(alt!(
532+
next: opt!(ws4!(alt!(
537533
preceded!(char!('='), call!(Self::test)) => { |test2: Box<_>| RawArgument::Keyword(*test1.clone(), *test2) } // FIXME: do not clone
538534
| call!(Self::comp_for) => { |v| RawArgument::Positional(Expression::Generator(Box::new(SetItem::Unique(*test1.clone())), v)) } // FIXME: do not clone
539-
)) >> (
535+
))) >> (
540536
match next {
541537
Some(e) => e,
542538
None => RawArgument::Positional(*test1)
@@ -575,11 +571,11 @@ named_args!(comp_for2(acc: Vec<ComprehensionChunk>) <StrSpan, Vec<ComprehensionC
575571
do_parse!(
576572
async: map!(opt!(terminated!(tag!("async"), space_sep!())), |o| o.is_some()) >>
577573
tag!("for") >>
578-
space_sep!() >>
574+
spaces!() >>
579575
item: call!(Self::exprlist) >>
580-
space_sep!() >>
576+
spaces!() >>
581577
tag!("in") >>
582-
space_sep!() >>
578+
spaces!() >>
583579
iterator: map!(call!(Self::or_test), |e| *e) >>
584580
spaces!() >>
585581
r: call!(Self::opt_comp_iter, { let mut acc = acc; acc.push(ComprehensionChunk::For { async, item, iterator }); acc }) >> (
@@ -592,8 +588,9 @@ named_args!(comp_for2(acc: Vec<ComprehensionChunk>) <StrSpan, Vec<ComprehensionC
592588
named_args!(comp_if(acc: Vec<ComprehensionChunk>) <StrSpan, Vec<ComprehensionChunk>>,
593589
do_parse!(
594590
tag!("if") >>
595-
space_sep!() >>
591+
spaces!() >>
596592
cond: map!(call!(Self::test_nocond), |e| *e) >>
593+
spaces!() >>
597594
r: call!(Self::opt_comp_iter, { let mut acc = acc; acc.push(ComprehensionChunk::If { cond }); acc }) >> (
598595
r
599596
)
@@ -1625,6 +1622,29 @@ mod tests {
16251622
)));
16261623
}
16271624

1625+
#[test]
1626+
fn test_listcomp3() {
1627+
let testlist_comp = ExpressionParser::<NewlinesAreNotSpaces>::testlist_comp;
1628+
1629+
assert_parse_eq(testlist_comp(make_strspan("foo for (bar, baz) in qux")), Ok((make_strspan(""),
1630+
TestlistCompReturn::Comp(
1631+
Box::new(SetItem::Unique(Expression::Name("foo".to_string()))),
1632+
vec![
1633+
ComprehensionChunk::For {
1634+
async: false,
1635+
item: vec![
1636+
Expression::TupleLiteral(vec![
1637+
SetItem::Unique(Expression::Name("bar".to_string())),
1638+
SetItem::Unique(Expression::Name("baz".to_string())),
1639+
]),
1640+
],
1641+
iterator: Expression::Name("qux".to_string()),
1642+
},
1643+
],
1644+
)
1645+
)));
1646+
}
1647+
16281648
#[test]
16291649
fn test_setcomp() {
16301650
let atom = ExpressionParser::<NewlinesAreNotSpaces>::atom;

src/functions.rs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ trait IsItTyped {
9898
Self::fpdef,
9999
opt!(
100100
preceded!(
101-
char!('='),
101+
ws4!(char!('=')),
102102
call!(ExpressionParser::<NewlinesAreSpaces>::test)
103103
)
104104
)
@@ -213,7 +213,7 @@ impl<IIT: IsItTyped> ParamlistParser<IIT> {
213213
tag!("*") >>
214214
star_args: opt!(call!(IIT::fpdef)) >>
215215
keyword_args: separated_list!(char!(','), call!(IIT::fpdef_with_default)) >>
216-
star_kwargs: opt!(preceded!(char!(','), opt!(preceded!(tag!("**"), call!(IIT::fpdef))))) >> (
216+
star_kwargs: opt!(ws4!(preceded!(char!(','), opt!(ws4!(preceded!(tag!("**"), call!(IIT::fpdef))))))) >> (
217217
IIT::make_list(Vec::new(), Some(star_args), keyword_args, star_kwargs.unwrap_or(None))
218218
)
219219
)
@@ -314,6 +314,15 @@ mod tests {
314314
})
315315
}
316316
)));
317+
assert_parse_eq(decorator(make_strspan(" @foo.bar(baz)\n"), 2), Ok((make_strspan(""),
318+
Decorator {
319+
name: vec!["foo".to_string(), "bar".to_string()],
320+
args: Some(Arglist {
321+
positional_args: vec![Argument::Normal(Expression::Name("baz".to_string()))],
322+
keyword_args: Vec::new(),
323+
})
324+
}
325+
)));
317326
}
318327

319328
#[test]
@@ -343,6 +352,25 @@ mod tests {
343352
assert!(decorated(make_strspan(" def foo():\n bar"), 1).is_err());
344353
}
345354

355+
#[test]
356+
fn test_decorated_func() {
357+
assert_parse_eq(decorated(make_strspan(" @foo\n def foo():\n bar"), 1), Ok((make_strspan(""),
358+
CompoundStatement::Funcdef(Funcdef {
359+
async: false,
360+
decorators: vec![
361+
Decorator {
362+
name: vec!["foo".to_string()],
363+
args: None
364+
},
365+
],
366+
name: "foo".to_string(),
367+
parameters: TypedArgsList::default(),
368+
return_type: None,
369+
code: vec![Statement::Assignment(vec![Expression::Name("bar".to_string())], vec![])],
370+
})
371+
)));
372+
}
373+
346374
#[test]
347375
fn test_positional() {
348376
assert_parse_eq(ParamlistParser::<Typed>::parse(make_strspan("foo")), Ok((make_strspan(""),

src/statements.rs

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,8 @@ named!(raise_stmt<StrSpan, Statement>,
166166
do_parse!(
167167
tag!("raise") >>
168168
t: opt!(tuple!(
169-
preceded!(space_sep2, call_test!()),
170-
opt!(preceded!(tuple!(space_sep2, tag!("from"), space_sep2), call_test!()))
169+
preceded!(spaces2, call_test!()),
170+
opt!(preceded!(ws2!(tag!("from")), call_test!()))
171171
)) >> (
172172
match t {
173173
Some((exc, Some(from_exc))) => Statement::RaiseExcFrom(*exc, *from_exc),
@@ -250,7 +250,12 @@ named!(import_from<StrSpan, Import>,
250250
| call!(ImportParser::<NewlinesAreNotSpaces>::import_as_names)
251251
) >> ({
252252
let (leading_dots, path) = import_from;
253-
Import::ImportFrom { leading_dots, path, names }
253+
if names.len() > 0 {
254+
Import::ImportFrom { leading_dots, path, names }
255+
}
256+
else {
257+
Import::ImportStarFrom { leading_dots, path }
258+
}
254259
})
255260
)
256261
);
@@ -287,10 +292,10 @@ named!(dotted_as_name<StrSpan, (Vec<Name>, Option<Name>)>,
287292

288293
// import_as_names: import_as_name (',' import_as_name)* [',']
289294
named!(import_as_names<StrSpan, Vec<(Name, Option<Name>)>>,
290-
terminated!(
291-
separated_nonempty_list!(ws2!(char!(',')), call!(Self::import_as_name)),
292-
opt!(tuple!(spaces!(), char!(','), spaces!()))
293-
)
295+
ws3!(terminated!(
296+
separated_nonempty_list!(ws3!(char!(',')), call!(Self::import_as_name)),
297+
opt!(ws3!(char!(',')))
298+
))
294299
);
295300

296301
// dotted_as_names: dotted_as_name (',' dotted_as_name)*
@@ -338,7 +343,7 @@ named_args!(pub block(indent: usize) <StrSpan, Vec<Statement>>,
338343
);
339344
named_args!(cond_and_block(indent: usize) <StrSpan, (Expression, Vec<Statement>)>,
340345
do_parse!(
341-
space_sep >>
346+
spaces >>
342347
cond: call!(ExpressionParser::<NewlinesAreNotSpaces>::test) >>
343348
ws2!(char!(':')) >>
344349
block: call!(block, indent) >> (
@@ -350,19 +355,21 @@ named_args!(cond_and_block(indent: usize) <StrSpan, (Expression, Vec<Statement>)
350355

351356
// compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated | async_stmt
352357
named_args!(compound_stmt(indent: usize) <StrSpan, CompoundStatement>,
353-
switch!(peek!(ws2!(first_word)),
354-
"if" => call!(if_stmt, indent)
355-
| "for" => call!(for_stmt, indent)
356-
| "while" => call!(while_stmt, indent)
357-
| "try" => call!(try_stmt, indent)
358-
| "with" => call!(with_stmt, indent)
359-
| "def" => call!(decorated, indent)
360-
| "class" => call!(decorated, indent)
361-
| "async" => alt!(
358+
switch!(map!(peek!(ws2!(take!(1))), |s| s.fragment.0),
359+
"i" => call!(if_stmt, indent)
360+
| "f" => call!(for_stmt, indent)
361+
| "w" => alt!(
362+
call!(while_stmt, indent)
363+
| call!(with_stmt, indent)
364+
)
365+
| "t" => call!(try_stmt, indent)
366+
| "d" => call!(decorated, indent)
367+
| "c" => call!(decorated, indent)
368+
| "a" => alt!(
362369
call!(decorated, indent) // ASYNC funcdef
363370
| call!(for_stmt, indent)
364371
)
365-
| _ => call!(decorated, indent)
372+
| "@" => call!(decorated, indent)
366373
)
367374
);
368375

@@ -417,12 +424,11 @@ named_args!(for_stmt(indent: usize) <StrSpan, CompoundStatement>,
417424
count!(char!(' '), indent) >>
418425
async: opt!(tuple!(tag!("async"), space_sep2)) >>
419426
tag!("for") >>
420-
space_sep2 >>
427+
spaces >>
421428
item: call!(ExpressionParser::<NewlinesAreNotSpaces>::exprlist) >>
422-
space_sep2 >>
423-
tag!("in") >>
424-
space_sep2 >>
429+
ws2!(tag!("in")) >>
425430
iterator: call!(ExpressionParser::<NewlinesAreNotSpaces>::exprlist) >>
431+
spaces >>
426432
ws2!(char!(':')) >>
427433
for_block: call!(block, indent) >>
428434
else_block: call!(else_block, indent) >> ({
@@ -450,9 +456,10 @@ named_args!(try_stmt(indent: usize) <StrSpan, CompoundStatement>,
450456
newline >>
451457
count!(char!(' '), indent) >>
452458
tag!("except") >>
453-
space_sep2 >>
459+
spaces >>
454460
catch_what: call!(ExpressionParser::<NewlinesAreNotSpaces>::test) >>
455-
catch_as: opt!(preceded!(tuple!(space_sep2, tag!("as"), space_sep2), name)) >>
461+
spaces >>
462+
catch_as: opt!(preceded!(tuple!(tag!("as"), space_sep2), name)) >>
456463
ws2!(char!(':')) >>
457464
block: call!(block, indent) >> (
458465
(*catch_what, catch_as, block)
@@ -498,11 +505,11 @@ named_args!(with_stmt(indent: usize) <StrSpan, CompoundStatement>,
498505
do_parse!(
499506
count!(char!(' '), indent) >>
500507
tag!("with") >>
501-
space_sep2 >>
508+
spaces2 >>
502509
contexts: separated_nonempty_list!(ws2!(char!(',')), do_parse!(
503510
context: call!(ExpressionParser::<NewlinesAreNotSpaces>::expr) >>
504511
as_: opt!(preceded!(
505-
tuple!(space_sep2, tag!("as"), space_sep2),
512+
ws2!(tag!("as")),
506513
call!(ExpressionParser::<NewlinesAreNotSpaces>::expr)
507514
)) >> (
508515
(*context, as_.map(|e| *e))

src/strings.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ named_args!(shortstring(quote: char) <StrSpan, String>,
5757
fold_many0!(
5858
alt!(
5959
call!(escapedchar)
60-
| verify!(none_of!("\\"), |c:char| c != quote) => { |c:char| Some(c) }
60+
| verify!(anychar, |c:char| c != quote) => { |c:char| Some(c) }
6161
),
6262
String::new(),
6363
|mut acc:String, c:Option<char>| { match c { Some(c) => acc.push_str(&c.to_string()), None => () }; acc }
@@ -68,7 +68,7 @@ named_args!(longstring(quote: char) <StrSpan, String>,
6868
fold_many0!(
6969
alt!(
7070
call!(escapedchar)
71-
| verify!(tuple!(peek!(take!(3)), none_of!("\\")), |(s,_):(StrSpan,_)| { s.fragment.0.chars().collect::<Vec<char>>() != vec![quote,quote,quote] }) => { |(_,c)| Some(c) }
71+
| verify!(tuple!(peek!(take!(3)), anychar), |(s,_):(StrSpan,_)| { s.fragment.0.chars().collect::<Vec<char>>() != vec![quote,quote,quote] }) => { |(_,c)| Some(c) }
7272
),
7373
String::new(),
7474
|mut acc:String, c:Option<char>| { match c { Some(c) => acc.push_str(&c.to_string()), None => () }; acc }

src/visitors/printer.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,7 @@ fn format_expr(e: &Expression) -> String {
538538
Expression::Attribute(e, ref n) =>
539539
format!("{}.{}", format_expr(e), n),
540540
Expression::Uop(op, ref e) =>
541-
format!("{}{}", op, format_expr(e)),
541+
format!("{}({})", op, format_expr(e)),
542542
Expression::Bop(op, ref e1, ref e2) => {
543543
let f = |e:&_| match *e {
544544
Expression::Ellipsis | Expression::None | Expression::True |
@@ -615,6 +615,14 @@ fn format_import(imp: &Import) -> String {
615615
s2
616616
})));
617617
},
618+
Import::ImportStarFrom { leading_dots, ref path } => {
619+
s.push_str("from ");
620+
for _ in 0..leading_dots {
621+
s.push_str(".");
622+
}
623+
s.push_str(&format_dotted_name(path));
624+
s.push_str(" import *");
625+
},
618626
Import::Import { ref names } => {
619627
s.push_str("import ");
620628
s.push_str(&comma_join(names.iter().map(|(name, as_name)| {

0 commit comments

Comments
 (0)