From 368b49b1f8a8c85a98081f36f1df650e7bb3eff8 Mon Sep 17 00:00:00 2001 From: Hans-Joachim Krauch Date: Tue, 14 May 2024 11:44:50 -0300 Subject: [PATCH] Add support for empty structs (#167) ### Changelog Add support for empty structs ### Docs None ### Description As per the [IDL spec](https://www.omg.org/spec/IDL/4.1/PDF), structs are allowed to have no members: >``` >::+ "struct" ":" "{" * "}" >| "struct" "{" "}" >``` Our parsing grammar however required a struct to have at least one member. This PR adapts the grammar to allow structs without members. --- packages/omgidl-parser/src/idl.ne | 2 +- packages/omgidl-parser/src/parseIDL.test.ts | 14 ++++++++++ .../omgidl-parser/src/parseIDLToAST.test.ts | 21 +++++++++----- .../src/MessageReader.test.ts | 28 +++++++++++++++++++ 4 files changed, 57 insertions(+), 8 deletions(-) diff --git a/packages/omgidl-parser/src/idl.ne b/packages/omgidl-parser/src/idl.ne index 595d280..646897a 100644 --- a/packages/omgidl-parser/src/idl.ne +++ b/packages/omgidl-parser/src/idl.ne @@ -230,7 +230,7 @@ enumFieldName -> multiAnnotations fieldName {% d => { return extend([annotations, name]); } %} -struct -> "struct" fieldName "{" (member):+ "}" {% d => { +struct -> "struct" fieldName "{" (member):* "}" {% d => { const name = d[1].name; const definitions = d[3].flat(2).filter(def => def !== null); return { diff --git a/packages/omgidl-parser/src/parseIDL.test.ts b/packages/omgidl-parser/src/parseIDL.test.ts index eeeffcb..c587480 100644 --- a/packages/omgidl-parser/src/parseIDL.test.ts +++ b/packages/omgidl-parser/src/parseIDL.test.ts @@ -2619,6 +2619,20 @@ module rosidl_parser { }, ]); }); + it("can parse empty struct", () => { + const msgDef = ` + struct a { + }; + `; + const ast = parseIDL(msgDef); + expect(ast).toEqual([ + { + name: "a", + aggregatedKind: "struct", + definitions: [], + }, + ]); + }); // **************** Not supported in our implementation yet it("cannot compose variable size arrays (no serialization support)", () => { const msgDef = ` diff --git a/packages/omgidl-parser/src/parseIDLToAST.test.ts b/packages/omgidl-parser/src/parseIDLToAST.test.ts index f885b1e..83822a6 100644 --- a/packages/omgidl-parser/src/parseIDLToAST.test.ts +++ b/packages/omgidl-parser/src/parseIDLToAST.test.ts @@ -1798,6 +1798,20 @@ module idl_parser { }, ]); }); + it("can parse empty struct", () => { + const msgDef = ` + struct a { + }; + `; + const ast = parseIDLToAST(msgDef); + expect(ast).toEqual([ + { + name: "a", + declarator: "struct", + definitions: [], + }, + ]); + }); /**************** Not supported by IDL (as far as I can tell) */ it("cannot parse constants that reference other constants", () => { const msgDef = ` @@ -1819,13 +1833,6 @@ module idl_parser { `; expect(() => parseIDLToAST(msgDef)).toThrow(/unexpected , token/i); }); - it("cannot parse empty struct", () => { - const msgDef = ` - struct a { - }; - `; - expect(() => parseIDLToAST(msgDef)).toThrow(/unexpected RCBR token/i); - }); /**************** Syntax Errors */ it("missing bracket at the end will result in end of input error", () => { const msgDef = ` diff --git a/packages/omgidl-serialization/src/MessageReader.test.ts b/packages/omgidl-serialization/src/MessageReader.test.ts index 07ddfc3..a811ec4 100644 --- a/packages/omgidl-serialization/src/MessageReader.test.ts +++ b/packages/omgidl-serialization/src/MessageReader.test.ts @@ -1319,4 +1319,32 @@ module builtin_interfaces { expect(msgout).toEqual(data); }); + it("Reads struct with no members", () => { + const msgDef = ` + struct Message { + }; + `; + const data = {}; + const writer = new CdrWriter({ kind: EncapsulationKind.PL_CDR_LE }); + + const rootDef = "Message"; + const reader = new MessageReader(rootDef, parseIDL(msgDef)); + const msgout = reader.readMessage(writer.data); + expect(msgout).toEqual(data); + }); + it("Reads mutable struct with no members", () => { + const msgDef = ` + @mutable + struct Message { + }; + `; + const data = {}; + const writer = new CdrWriter({ kind: EncapsulationKind.PL_CDR_LE }); + writer.sentinelHeader(); // end of struct + + const rootDef = "Message"; + const reader = new MessageReader(rootDef, parseIDL(msgDef)); + const msgout = reader.readMessage(writer.data); + expect(msgout).toEqual(data); + }); });