diff --git a/compiler/parser/src/parser/file.rs b/compiler/parser/src/parser/file.rs index 1d2685a2ae..1390c114d1 100644 --- a/compiler/parser/src/parser/file.rs +++ b/compiler/parser/src/parser/file.rs @@ -180,23 +180,11 @@ impl ParserContext<'_, N> { fn parse_struct_members(&mut self) -> Result<(Vec, Span)> { let mut members = Vec::new(); - let (mut semi_colons, mut commas) = (false, false); - while !self.check(&Token::RightCurly) { let variable = self.parse_member_variable_declaration()?; - if self.eat(&Token::Semicolon) { - if commas { - self.emit_err(ParserError::mixed_commas_and_semicolons(self.token.span)); - } - semi_colons = true; - } - - if self.eat(&Token::Comma) { - if semi_colons { - self.emit_err(ParserError::mixed_commas_and_semicolons(self.token.span)); - } - commas = true; + if !self.check(&Token::RightCurly) && !self.eat(&Token::Comma) { + self.emit_err(ParserError::comma_expected_after_member(self.token.span)); } members.push(variable); diff --git a/errors/src/errors/parser/parser_errors.rs b/errors/src/errors/parser/parser_errors.rs index 9d5e7716c4..c2d55bea45 100644 --- a/errors/src/errors/parser/parser_errors.rs +++ b/errors/src/errors/parser/parser_errors.rs @@ -73,6 +73,7 @@ create_messages!( } /// For when the parser encountered a mix of commas and semi-colons in struct member variables. + // TODO unused @formatted mixed_commas_and_semicolons { args: (), @@ -341,4 +342,12 @@ create_messages!( msg: format!("Cannot create an external record. Records can only be created in the program that they are defined in."), help: None, } + + /// For when the parser encountered a member declaration not followed by a comma. + @formatted + comma_expected_after_member { + args: (), + msg: "Each member declaration in a struct or record must be followed by a comma (except the last).", + help: None, + } ); diff --git a/tests/expectations/parser/structs/comma_separators_fail.out b/tests/expectations/parser/structs/comma_separators_fail.out new file mode 100644 index 0000000000..9cffb4c3c4 --- /dev/null +++ b/tests/expectations/parser/structs/comma_separators_fail.out @@ -0,0 +1,5 @@ +--- +namespace: Parse +expectation: Fail +outputs: + - "Error [EPAR0370041]: Each member declaration in a struct or record must be followed by a comma (except the last).\n --> test:5:9\n |\n 5 | y: u8\n | ^" diff --git a/tests/expectations/parser/structs/only_comma_separators_fail.out b/tests/expectations/parser/structs/only_comma_separators_fail.out new file mode 100644 index 0000000000..5c435961bd --- /dev/null +++ b/tests/expectations/parser/structs/only_comma_separators_fail.out @@ -0,0 +1,5 @@ +--- +namespace: Parse +expectation: Fail +outputs: + - "Error [EPAR0370041]: Each member declaration in a struct or record must be followed by a comma (except the last).\n --> test:4:14\n |\n 4 | x: u8;\n | ^\nError [EPAR0370009]: unexpected string: expected 'identifier', found ';'\n --> test:4:14\n |\n 4 | x: u8;\n | ^" diff --git a/tests/tests/compiler/bugs/unknown_variable_fail.leo b/tests/tests/compiler/bugs/unknown_variable_fail.leo index ad4c34e782..0abed51013 100644 --- a/tests/tests/compiler/bugs/unknown_variable_fail.leo +++ b/tests/tests/compiler/bugs/unknown_variable_fail.leo @@ -11,7 +11,7 @@ program test.aleo { decimals: u8, circulating_supply: u64, total_supply: u64, - testers: u64 + testers: u64, admin: address, } diff --git a/tests/tests/compiler/console/assert.leo b/tests/tests/compiler/console/assert.leo index 64c739e2e0..04bd32fd1e 100644 --- a/tests/tests/compiler/console/assert.leo +++ b/tests/tests/compiler/console/assert.leo @@ -5,7 +5,7 @@ expectation: Pass program test.aleo { struct Foo { - a: u8; + a: u8, } record Token { diff --git a/tests/tests/compiler/expression/cast_fail.leo b/tests/tests/compiler/expression/cast_fail.leo index 8db06b78d7..f11addb5ed 100644 --- a/tests/tests/compiler/expression/cast_fail.leo +++ b/tests/tests/compiler/expression/cast_fail.leo @@ -8,7 +8,7 @@ program test.aleo { mapping balances: field => field; struct Foo { - data: field; + data: field, } async transition main(a: field) -> Future { diff --git a/tests/tests/compiler/finalize/mapping.leo b/tests/tests/compiler/finalize/mapping.leo index 73efbd22cf..686994a888 100644 --- a/tests/tests/compiler/finalize/mapping.leo +++ b/tests/tests/compiler/finalize/mapping.leo @@ -11,18 +11,18 @@ program test.aleo { mapping balances: address => u128; struct Token { - Owner: address; - balance: u128; + Owner: address, + balance: u128, } mapping tokens: address => Token; struct Bar { - a: u128; + a: u128, } struct Baz { - a: u128; + a: u128, } mapping foo: Bar => Baz; diff --git a/tests/tests/compiler/finalize/shadow_mapping_fail.leo b/tests/tests/compiler/finalize/shadow_mapping_fail.leo index 07e4ab405d..af8543f03c 100644 --- a/tests/tests/compiler/finalize/shadow_mapping_fail.leo +++ b/tests/tests/compiler/finalize/shadow_mapping_fail.leo @@ -21,6 +21,6 @@ program test.aleo { } struct bar { - a: u64; + a: u64, } } diff --git a/tests/tests/compiler/mappings/read_external_mapping.leo b/tests/tests/compiler/mappings/read_external_mapping.leo index 1d5b37d548..1ad09f3b0f 100644 --- a/tests/tests/compiler/mappings/read_external_mapping.leo +++ b/tests/tests/compiler/mappings/read_external_mapping.leo @@ -27,8 +27,8 @@ program relay.aleo { mapping users: address => bool; record message { - owner: address; - data: u8; + owner: address, + data: u8, } async transition send(addr: address, val: u8) -> (message, Future) { diff --git a/tests/tests/compiler/structs/inline_fail.leo b/tests/tests/compiler/structs/inline_fail.leo index 1da57cba5a..20ac36b15a 100644 --- a/tests/tests/compiler/structs/inline_fail.leo +++ b/tests/tests/compiler/structs/inline_fail.leo @@ -5,7 +5,7 @@ expectation: Fail program test.aleo { struct Foo { - x: u32; + x: u32, } function main() { diff --git a/tests/tests/compiler/structs/inline_member_fail.leo b/tests/tests/compiler/structs/inline_member_fail.leo index 8d18b3f53b..a546b75ab4 100644 --- a/tests/tests/compiler/structs/inline_member_fail.leo +++ b/tests/tests/compiler/structs/inline_member_fail.leo @@ -5,7 +5,7 @@ expectation: Fail program test.aleo { struct Foo { - x: u8; + x: u8, } function main() { diff --git a/tests/tests/compiler/structs/member_variable_fail.leo b/tests/tests/compiler/structs/member_variable_fail.leo index 51ed321d8c..e5fd6836c0 100644 --- a/tests/tests/compiler/structs/member_variable_fail.leo +++ b/tests/tests/compiler/structs/member_variable_fail.leo @@ -5,7 +5,7 @@ expectation: Fail program test.aleo { struct Foo { - x: u32; + x: u32, } function main() { diff --git a/tests/tests/compiler/structs/struct_function_namespace_conflict_fail.leo b/tests/tests/compiler/structs/struct_function_namespace_conflict_fail.leo index 2de1da5005..511ef2688d 100644 --- a/tests/tests/compiler/structs/struct_function_namespace_conflict_fail.leo +++ b/tests/tests/compiler/structs/struct_function_namespace_conflict_fail.leo @@ -5,7 +5,7 @@ expectation: Fail program test.aleo { struct Foo { - x: u8; + x: u8, } function Foo() {} diff --git a/tests/tests/parser/structs/comma_separators_fail.leo b/tests/tests/parser/structs/comma_separators_fail.leo new file mode 100644 index 0000000000..98b10a406c --- /dev/null +++ b/tests/tests/parser/structs/comma_separators_fail.leo @@ -0,0 +1,14 @@ +/* +namespace: Parse +expectation: Fail +*/ +program comma_separators.aleo { + struct none { + x: u8 + y: u8 + } + + transition main(public a: u32) -> u32 { + return a; + } +} diff --git a/tests/tests/parser/structs/only_comma_separators_fail.leo b/tests/tests/parser/structs/only_comma_separators_fail.leo new file mode 100644 index 0000000000..fe0f8da542 --- /dev/null +++ b/tests/tests/parser/structs/only_comma_separators_fail.leo @@ -0,0 +1,19 @@ +/* +namespace: Parse +expectation: Fail +*/ +program only_comma_separators.aleo { + struct semicolons { + x: u8; + y: u8 + } + + struct semicolons_with_trailing { + x: u8; + y: u8; + } + + transition main(public a: u32) -> u32 { + return a; + } +}