diff --git a/parser/src/parser/ast.rs b/parser/src/parser/ast.rs index 8644c785..7df1c569 100644 --- a/parser/src/parser/ast.rs +++ b/parser/src/parser/ast.rs @@ -322,10 +322,20 @@ impl GetNode for Expression { } // https://docs.python.org/3/reference/expressions.html#atom-identifiers -#[derive(Debug, Clone)] +#[derive(Clone)] pub struct Name { pub node: Node, pub id: String, + pub parenthesized: bool, +} + +impl fmt::Debug for Name { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Name") + .field("node", &self.node) + .field("id", &self.id) + .finish() + } } #[derive(Clone, Debug, PartialEq)] diff --git a/parser/src/parser/parser.rs b/parser/src/parser/parser.rs index 6e8d083c..ed789bfd 100644 --- a/parser/src/parser/parser.rs +++ b/parser/src/parser/parser.rs @@ -971,6 +971,7 @@ impl<'a> Parser<'a> { let mut expr = Ok(Expression::Name(Box::new(Name { node: self.finish_node(node), id, + parenthesized: false, }))); self.expect(Kind::Identifier); while self.eat(Kind::Dot) { @@ -1268,13 +1269,17 @@ impl<'a> Parser<'a> { } else { None }; + let simple = if let Expression::Name(name) = &lhs { + !name.parenthesized + } else { + false + }; Ok(Statement::AnnAssignStatement(Box::new(AnnAssign { node: self.finish_node(start), target: lhs, annotation, value, - // TODO: implement simple - simple: true, + simple, }))) } @@ -1597,6 +1602,7 @@ impl<'a> Parser<'a> { target: Expression::Name(Box::new(Name { node: identifier_node, id: identifier, + parenthesized: false, })), value, }))); @@ -1604,6 +1610,7 @@ impl<'a> Parser<'a> { return Ok(Expression::Name(Box::new(Name { node: identifier_node, id: identifier, + parenthesized: false, }))); } @@ -1775,6 +1782,7 @@ impl<'a> Parser<'a> { return Ok(Expression::Name(Box::new(Name { node: identifier_node, id: identifier, + parenthesized: false, }))); } }, @@ -2482,6 +2490,7 @@ impl<'a> Parser<'a> { Expression::Name(Box::new(Name { node: self.finish_node(start), id: val, + parenthesized: false, })) } Kind::Integer => { @@ -2654,6 +2663,7 @@ impl<'a> Parser<'a> { Expression::Name(Box::new(Name { node: self.finish_node(start), id: val, + parenthesized: false, })) } Kind::Integer => { @@ -2844,6 +2854,7 @@ impl<'a> Parser<'a> { Ok(Expression::Name(Box::new(Name { node: self.finish_node(node), id: value, + parenthesized: false, }))) } @@ -2927,7 +2938,16 @@ impl<'a> Parser<'a> { seen_comma = true; } if elements.len() == 1 && !seen_comma { - return Ok(elements.pop().unwrap()); + let expr = elements.pop().unwrap(); + if let Expression::Name(name) = expr { + return Ok(Expression::Name(Box::new(Name { + node: name.node, + id: name.id, + parenthesized: true, + }))); + } else { + return Ok(expr); + } } Ok(Expression::Tuple(Box::new(Tuple { node: self.finish_node(node), diff --git a/parser/test_data/inputs/annotated_assignment.py b/parser/test_data/inputs/annotated_assignment.py index 860f3ca7..38165994 100644 --- a/parser/test_data/inputs/annotated_assignment.py +++ b/parser/test_data/inputs/annotated_assignment.py @@ -13,3 +13,8 @@ g: tuple[int, int] = 1, 2 +(h): int = 1 + +( + i +): int = 1 diff --git a/parser/test_data/output/enderpy_python_parser__lexer__tests__snapshot_test_lexer_and_errors@annotated_assignment.py.snap b/parser/test_data/output/enderpy_python_parser__lexer__tests__snapshot_test_lexer_and_errors@annotated_assignment.py.snap index f7349b45..bd890150 100644 --- a/parser/test_data/output/enderpy_python_parser__lexer__tests__snapshot_test_lexer_and_errors@annotated_assignment.py.snap +++ b/parser/test_data/output/enderpy_python_parser__lexer__tests__snapshot_test_lexer_and_errors@annotated_assignment.py.snap @@ -1,6 +1,6 @@ --- source: parser/src/lexer/mod.rs -description: "a: int = 1\n\nb: tuple[int, int] = 1, 2\n\nc: tuple[str, int] = \"1\", 2, \n\nd: tuple[int, int] = b\n\ne: tuple[int, int]\n\nf: tuple[int, int] = e\n\ng: tuple[int,\n int] = 1, 2\n\n" +description: "a: int = 1\n\nb: tuple[int, int] = 1, 2\n\nc: tuple[str, int] = \"1\", 2, \n\nd: tuple[int, int] = b\n\ne: tuple[int, int]\n\nf: tuple[int, int] = e\n\ng: tuple[int,\n int] = 1, 2\n\n(h): int = 1\n\n(\n i\n): int = 1\n" input_file: parser/test_data/inputs/annotated_assignment.py --- 0,1: Identifier (Str("a")) @@ -88,3 +88,22 @@ input_file: parser/test_data/inputs/annotated_assignment.py 171,172: Integer (Number("2")) 172,173: NewLine (None) 173,174: NewLine (None) +174,175: ( (None) +175,176: Identifier (Str("h")) +176,177: ) (None) +177,178: : (None) +179,182: Identifier (Str("int")) +183,184: = (None) +185,186: Integer (Number("1")) +186,187: NewLine (None) +187,188: NewLine (None) +188,189: ( (None) +189,190: NewLine (None) +194,195: Identifier (Str("i")) +195,196: NewLine (None) +196,197: ) (None) +197,198: : (None) +199,202: Identifier (Str("int")) +203,204: = (None) +205,206: Integer (Number("1")) +206,207: NewLine (None) diff --git a/parser/test_data/output/enderpy_python_parser__parser__parser__tests__annotated_assignment.snap b/parser/test_data/output/enderpy_python_parser__parser__parser__tests__annotated_assignment.snap index 75dd8d56..05212651 100644 --- a/parser/test_data/output/enderpy_python_parser__parser__parser__tests__annotated_assignment.snap +++ b/parser/test_data/output/enderpy_python_parser__parser__parser__tests__annotated_assignment.snap @@ -1,11 +1,11 @@ --- source: parser/src/parser/parser.rs -description: "a: int = 1\n\nb: tuple[int, int] = 1, 2\n\nc: tuple[str, int] = \"1\", 2, \n\nd: tuple[int, int] = b\n\ne: tuple[int, int]\n\nf: tuple[int, int] = e\n\ng: tuple[int,\n int] = 1, 2\n\n" +description: "a: int = 1\n\nb: tuple[int, int] = 1, 2\n\nc: tuple[str, int] = \"1\", 2, \n\nd: tuple[int, int] = b\n\ne: tuple[int, int]\n\nf: tuple[int, int] = e\n\ng: tuple[int,\n int] = 1, 2\n\n(h): int = 1\n\n(\n i\n): int = 1\n" --- Module { node: Node { start: 0, - end: 174, + end: 207, }, body: [ AnnAssignStatement( @@ -537,5 +537,81 @@ Module { simple: true, }, ), + AnnAssignStatement( + AnnAssign { + node: Node { + start: 174, + end: 186, + }, + target: Name( + Name { + node: Node { + start: 175, + end: 176, + }, + id: "h", + }, + ), + annotation: Name( + Name { + node: Node { + start: 179, + end: 182, + }, + id: "int", + }, + ), + value: Some( + Constant( + Constant { + node: Node { + start: 185, + end: 186, + }, + value: 1, + }, + ), + ), + simple: false, + }, + ), + AnnAssignStatement( + AnnAssign { + node: Node { + start: 188, + end: 206, + }, + target: Name( + Name { + node: Node { + start: 194, + end: 196, + }, + id: "i", + }, + ), + annotation: Name( + Name { + node: Node { + start: 199, + end: 202, + }, + id: "int", + }, + ), + value: Some( + Constant( + Constant { + node: Node { + start: 205, + end: 206, + }, + value: 1, + }, + ), + ), + simple: false, + }, + ), ], }