Skip to content

Commit 190fc41

Browse files
committed
Add support for expressions like 'a <= b < c' + fixes in the printer.
1 parent b7e6918 commit 190fc41

File tree

3 files changed

+58
-12
lines changed

3 files changed

+58
-12
lines changed

src/ast.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,8 +240,12 @@ pub enum Expression {
240240
Attribute(Box<Expression>, Name),
241241
/// Unary operator
242242
Uop(Uop, Box<Expression>),
243-
/// Binary operator
243+
/// Binary operator. A simplified version of `MultiBop`, when the
244+
/// expressivity of MultiBop is not needed.
244245
Bop(Bop, Box<Expression>, Box<Expression>),
246+
/// Binary operator... but may be applied on more than one expr
247+
/// (eg. `a <= b < c`)
248+
MultiBop(Box<Expression>, Vec<(Bop, Expression)>),
245249
/// 1 if 2 else 3
246250
Ternary(Box<Expression>, Box<Expression>, Box<Expression>),
247251
Yield(Vec<Expression>),

src/expressions.rs

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -111,11 +111,19 @@ macro_rules! bop {
111111
delimited!(spaces!(), $tag!($($args)*), spaces!()),
112112
$child
113113
),
114-
first,
115-
|acc, (op, f)| Box::new(Expression::Bop(op, acc, f))
116-
) >> (
117-
r
118-
)
114+
(first, Vec::new()),
115+
|(first, mut acc):(_,Vec<_>), (op, f):(_,Box<_>)| { acc.push((op, *f)); (first, acc) }
116+
) >> ({
117+
let (first, rest) = r;
118+
match rest.len() {
119+
0 => first,
120+
1 => {
121+
let (op, ref rhs) = rest[0];
122+
Box::new(Expression::Bop(op, first, Box::new(rhs.clone())))
123+
}
124+
_ => Box::new(Expression::MultiBop(first, rest))
125+
}
126+
})
119127
)
120128
);
121129
}
@@ -1674,4 +1682,20 @@ mod tests {
16741682
))
16751683
)));
16761684
}
1685+
1686+
#[test]
1687+
fn test_multibop() {
1688+
let test = ExpressionParser::<NewlinesAreNotSpaces>::test;
1689+
1690+
assert_parse_eq(test(make_strspan("a <= b < c")), Ok((make_strspan(""),
1691+
Box::new(Expression::MultiBop(
1692+
Box::new(Expression::Name("a".to_string())),
1693+
vec![
1694+
(Bop::Leq, Expression::Name("b".to_string())),
1695+
(Bop::Lt, Expression::Name("c".to_string())),
1696+
]
1697+
))
1698+
)));
1699+
}
1700+
16771701
}

src/visitors/printer.rs

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ fn format_compound_statement(indent: usize, stmt: &CompoundStatement) -> String
218218
}
219219
if finally_block.len() > 0 {
220220
push_indent(indent, &mut s);
221-
s.push_str("finally_block:\n");
221+
s.push_str("finally:\n");
222222
s.push_str(&format_block(indent+4, finally_block));
223223
}
224224
s
@@ -364,9 +364,11 @@ fn format_typed_params(param: &TypedArgsList) -> String {
364364
StarParams::No => (),
365365
StarParams::Anonymous => s.push_str("*, "),
366366
StarParams::Named((ref name, None)) => {
367+
s.push_str("*");
367368
s.push_str(name);
368369
},
369370
StarParams::Named((ref name, Some(ref typed))) => {
371+
s.push_str("*");
370372
s.push_str(name);
371373
s.push_str(":");
372374
s.push_str(&format_expr(typed));
@@ -561,6 +563,20 @@ fn format_expr(e: &Expression) -> String {
561563
};
562564
format!("{}{}{}", f(e1), op, f(e2))
563565
},
566+
Expression::MultiBop(ref first, ref rest) => {
567+
let mut s = String::new();
568+
s.push_str("(");
569+
s.push_str(&format_expr(first));
570+
s.push_str(")");
571+
for (op, e) in rest {
572+
s.push_str(" ");
573+
s.push_str(&op.to_string());
574+
s.push_str(" (");
575+
s.push_str(&format_expr(e));
576+
s.push_str(")");
577+
}
578+
s
579+
},
564580
Expression::Ternary(e1, e2, e3) =>
565581
format!("({}) if ({}) else ({})", format_expr(e1), format_expr(e2), format_expr(e3)),
566582
Expression::Star(ref e) =>
@@ -598,13 +614,15 @@ fn format_import(imp: &Import) -> String {
598614
}
599615
s.push_str(&format_dotted_name(path));
600616
s.push_str(" import ");
601-
for (name, as_name) in names {
602-
s.push_str(name);
617+
s.push_str(&comma_join(names.iter().map(|(name, as_name)| {
618+
let mut s2 = String::new();
619+
s2.push_str(name);
603620
if let Some(as_name) = as_name {
604-
s.push_str(" as ");
605-
s.push_str(as_name);
621+
s2.push_str(" as ");
622+
s2.push_str(as_name);
606623
}
607-
}
624+
s2
625+
})));
608626
},
609627
Import::Import { ref names } => {
610628
s.push_str("import ");

0 commit comments

Comments
 (0)