Skip to content

Commit bcf94ed

Browse files
Merge pull request RustPython#788 from RustPython/syntax-enhancements
Fix syntax for float literals, statements seperated by semicolons and…
2 parents 42bb346 + ab3d004 commit bcf94ed

File tree

9 files changed

+81
-38
lines changed

9 files changed

+81
-38
lines changed

parser/src/ast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub struct Node {
1616
#[derive(Debug, PartialEq)]
1717
pub enum Top {
1818
Program(Program),
19-
Statement(LocatedStatement),
19+
Statement(Vec<LocatedStatement>),
2020
Expression(Expression),
2121
}
2222

parser/src/lexer.rs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,16 +1044,20 @@ where
10441044
return Some(Ok((tok_start, Tok::Comma, tok_end)));
10451045
}
10461046
'.' => {
1047-
let tok_start = self.get_pos();
1048-
self.next_char();
1049-
if let (Some('.'), Some('.')) = (&self.chr0, &self.chr1) {
1050-
self.next_char();
1051-
self.next_char();
1052-
let tok_end = self.get_pos();
1053-
return Some(Ok((tok_start, Tok::Ellipsis, tok_end)));
1047+
if let Some('0'..='9') = self.chr1 {
1048+
return Some(self.lex_number());
10541049
} else {
1055-
let tok_end = self.get_pos();
1056-
return Some(Ok((tok_start, Tok::Dot, tok_end)));
1050+
let tok_start = self.get_pos();
1051+
self.next_char();
1052+
if let (Some('.'), Some('.')) = (&self.chr0, &self.chr1) {
1053+
self.next_char();
1054+
self.next_char();
1055+
let tok_end = self.get_pos();
1056+
return Some(Ok((tok_start, Tok::Ellipsis, tok_end)));
1057+
} else {
1058+
let tok_end = self.get_pos();
1059+
return Some(Ok((tok_start, Tok::Dot, tok_end)));
1060+
}
10571061
}
10581062
}
10591063
'\n' => {

parser/src/parser.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ pub fn parse_program(source: &str) -> Result<ast::Program, ParseError> {
3535
do_lalr_parsing!(source, Program, StartProgram)
3636
}
3737

38-
pub fn parse_statement(source: &str) -> Result<ast::LocatedStatement, ParseError> {
38+
pub fn parse_statement(source: &str) -> Result<Vec<ast::LocatedStatement>, ParseError> {
3939
do_lalr_parsing!(source, Statement, StartStatement)
4040
}
4141

@@ -180,7 +180,7 @@ mod tests {
180180
let parse_ast = parse_statement(&source).unwrap();
181181
assert_eq!(
182182
parse_ast,
183-
ast::LocatedStatement {
183+
vec![ast::LocatedStatement {
184184
location: ast::Location::new(1, 1),
185185
node: ast::Statement::If {
186186
test: ast::Expression::Number {
@@ -229,7 +229,7 @@ mod tests {
229229
}
230230
},]),
231231
}
232-
}
232+
}]
233233
);
234234
}
235235

@@ -239,7 +239,7 @@ mod tests {
239239
let parse_ast = parse_statement(&source);
240240
assert_eq!(
241241
parse_ast,
242-
Ok(ast::LocatedStatement {
242+
Ok(vec![ast::LocatedStatement {
243243
location: ast::Location::new(1, 1),
244244
node: ast::Statement::Expression {
245245
expression: ast::Expression::Lambda {
@@ -271,7 +271,7 @@ mod tests {
271271
})
272272
}
273273
}
274-
})
274+
}])
275275
)
276276
}
277277

@@ -281,7 +281,7 @@ mod tests {
281281

282282
assert_eq!(
283283
parse_statement(&source),
284-
Ok(ast::LocatedStatement {
284+
Ok(vec![ast::LocatedStatement {
285285
location: ast::Location::new(1, 1),
286286
node: ast::Statement::Assign {
287287
targets: vec![ast::Expression::Tuple {
@@ -309,7 +309,7 @@ mod tests {
309309
]
310310
}
311311
}
312-
})
312+
}])
313313
)
314314
}
315315

@@ -320,7 +320,7 @@ mod tests {
320320
);
321321
assert_eq!(
322322
parse_statement(&source),
323-
Ok(ast::LocatedStatement {
323+
Ok(vec![ast::LocatedStatement {
324324
location: ast::Location::new(1, 1),
325325
node: ast::Statement::ClassDef {
326326
name: String::from("Foo"),
@@ -393,7 +393,7 @@ mod tests {
393393
],
394394
decorator_list: vec![],
395395
}
396-
})
396+
}])
397397
)
398398
}
399399

parser/src/python.lalrpop

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,29 +24,32 @@ pub Top: ast::Top = {
2424

2525
Program: ast::Program = {
2626
<lines:FileLine*> => ast::Program {
27-
statements: Vec::from_iter(lines.into_iter().filter_map(|e| e))
27+
statements: Vec::from_iter(lines.into_iter().flatten())
2828
},
2929
};
3030

3131
// A file line either has a declaration, or an empty newline:
32-
FileLine: Option<ast::LocatedStatement> = {
33-
<s:Statement> => Some(s),
34-
"\n" => None,
32+
FileLine: Vec<ast::LocatedStatement> = {
33+
Statement,
34+
"\n" => vec![],
3535
};
3636

3737
Suite: Vec<ast::LocatedStatement> = {
38-
<s:SimpleStatement> => vec![s],
39-
"\n" indent <s:Statement+> dedent => s,
38+
SimpleStatement,
39+
"\n" indent <s:Statement+> dedent => s.into_iter().flatten().collect(),
4040
};
4141

42-
Statement: ast::LocatedStatement = {
42+
Statement: Vec<ast::LocatedStatement> = {
4343
SimpleStatement,
44-
CompoundStatement,
44+
<s:CompoundStatement> => vec![s],
4545
};
4646

47-
SimpleStatement: ast::LocatedStatement = {
48-
<s:SmallStatement> "\n" => s,
49-
<s:SmallStatement> ";" => s,
47+
SimpleStatement: Vec<ast::LocatedStatement> = {
48+
<s1:SmallStatement> <s2:(";" SmallStatement)*> ";"? "\n" => {
49+
let mut statements = vec![s1];
50+
statements.extend(s2.into_iter().map(|e| e.1));
51+
statements
52+
}
5053
};
5154

5255
SmallStatement: ast::LocatedStatement = {
@@ -899,7 +902,14 @@ ArgumentList: (Vec<ast::Expression>, Vec<ast::Keyword>) = {
899902
keywords.push(ast::Keyword { name: n, value: value });
900903
},
901904
None => {
902-
if keywords.len() > 0 {
905+
// Allow starred args after keyword arguments.
906+
let is_starred = if let ast::Expression::Starred { .. } = &value {
907+
true
908+
} else {
909+
false
910+
};
911+
912+
if keywords.len() > 0 && !is_starred {
903913
panic!("positional argument follows keyword argument {:?}", keywords);
904914
};
905915
args.push(value);

tests/snippets/comprehensions.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,8 @@
2222
y = [a+2 for a in x if a % 2]
2323
print(y)
2424
assert y == [3, 5]
25+
26+
z = [(9,), (10,)]
27+
w = [x for x, in z]
28+
assert w == [9, 10]
29+

tests/snippets/floats.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,7 @@
106106
assert_raises(OverflowError, float('-inf').as_integer_ratio)
107107
assert_raises(ValueError, float('nan').as_integer_ratio)
108108

109+
# Test special case for lexer, float starts with a dot:
110+
a = .5
111+
assert a == 0.5
112+

tests/snippets/function_args.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,12 @@ def va2(*args, **kwargs):
4242
x = {'f': 42, 'e': 1337}
4343
y = {'d': 1337}
4444
va(1, 22, 3, 4, **x, **y)
45+
46+
# star arg after keyword args:
47+
def fubar(x, y, obj=None):
48+
assert x == 4
49+
assert y == 5
50+
assert obj == 6
51+
52+
rest = [4, 5]
53+
fubar(obj=6, *rest)

tests/snippets/statements.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
# Test several statement types
3+
4+
# small ones, seperated by ';':
5+
6+
if True:
7+
5;4;
8+
b=4
9+
b;

vm/src/compile.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -129,15 +129,17 @@ impl Compiler {
129129
// Compile statement in eval mode:
130130
fn compile_statement_eval(
131131
&mut self,
132-
statement: &ast::LocatedStatement,
132+
statements: &[ast::LocatedStatement],
133133
) -> Result<(), CompileError> {
134-
if let ast::Statement::Expression { ref expression } = statement.node {
135-
self.compile_expression(expression)?;
136-
self.emit(Instruction::ReturnValue);
137-
Ok(())
138-
} else {
139-
Err(CompileError::ExpectExpr)
134+
for statement in statements {
135+
if let ast::Statement::Expression { ref expression } = statement.node {
136+
self.compile_expression(expression)?;
137+
} else {
138+
return Err(CompileError::ExpectExpr);
139+
}
140140
}
141+
self.emit(Instruction::ReturnValue);
142+
Ok(())
141143
}
142144

143145
fn compile_statements(

0 commit comments

Comments
 (0)