From 583f84c1c1c31d64556924c4ef9192b6a0cc6fbf Mon Sep 17 00:00:00 2001 From: James Duley Date: Thu, 4 Sep 2025 08:49:19 +1200 Subject: [PATCH] Allow keywords as identifiers This matches the behavior of flatc --- .../src/parser/grammar.lalrpop | 19 +++++++++-- test/files/valid/keyword_identifiers.fbs | 32 +++++++++++++++++++ .../api_files/keyword_identifiers.fbs | 30 +++++++++++++++++ .../api_files/keyword_identifiers.rs | 22 +++++++++++++ 4 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 test/files/valid/keyword_identifiers.fbs create mode 100644 test/rust-test-2021/api_files/keyword_identifiers.fbs create mode 100644 test/rust-test-2021/api_files/keyword_identifiers.rs diff --git a/crates/planus-translation/src/parser/grammar.lalrpop b/crates/planus-translation/src/parser/grammar.lalrpop index a094adda..064a1331 100644 --- a/crates/planus-translation/src/parser/grammar.lalrpop +++ b/crates/planus-translation/src/parser/grammar.lalrpop @@ -289,8 +289,23 @@ Sign: Sign<'input> = { > => Sign { span: sp(l, r), token, is_negative: true, }, } -IdentToken: IdentToken<'input> = - => IdentToken { span: sp(l, r), token_metadata: token.1, ident: token.0 }; +IdentToken: IdentToken<'input> = { + => IdentToken { span: sp(l, r), token_metadata: token.1, ident: token.0 }, + + // allow keywords as identifiers (using the keyword's static string) + => IdentToken { span: sp(l, r), token_metadata, ident: "include" }, + => IdentToken { span: sp(l, r), token_metadata, ident: "native_include" }, + => IdentToken { span: sp(l, r), token_metadata, ident: "namespace" }, + => IdentToken { span: sp(l, r), token_metadata, ident: "attribute" }, + => IdentToken { span: sp(l, r), token_metadata, ident: "table" }, + => IdentToken { span: sp(l, r), token_metadata, ident: "struct" }, + => IdentToken { span: sp(l, r), token_metadata, ident: "enum" }, + => IdentToken { span: sp(l, r), token_metadata, ident: "union" }, + => IdentToken { span: sp(l, r), token_metadata, ident: "root_type" }, + => IdentToken { span: sp(l, r), token_metadata, ident: "rpc_service" }, + => IdentToken { span: sp(l, r), token_metadata, ident: "file_extension" }, + => IdentToken { span: sp(l, r), token_metadata, ident: "file_identifier" }, +}; IntegerLiteral: IntegerLiteral<'input> = => IntegerLiteral { span: sp(l, r), token_metadata: token.1, value: token.0 }; diff --git a/test/files/valid/keyword_identifiers.fbs b/test/files/valid/keyword_identifiers.fbs new file mode 100644 index 00000000..058a3018 --- /dev/null +++ b/test/files/valid/keyword_identifiers.fbs @@ -0,0 +1,32 @@ +table include { + namespace: int; + attribute: int; + table: int; + struct: int; + enum: int; + union: int; + root_type: int; + rpc_service: int; + file_extension: int; + file_identifier: int; +} + +enum native_include: byte { + namespace = 0, + attribute = 1, + table = 2, + struct = 3, + enum = 4, + union = 5, + root_type = 6, + rpc_service = 7, + file_extension = 8, + file_identifier = 9, +} + +table holder { + include: include; + native_include: native_include; +} + +root_type holder; diff --git a/test/rust-test-2021/api_files/keyword_identifiers.fbs b/test/rust-test-2021/api_files/keyword_identifiers.fbs new file mode 100644 index 00000000..e6c3ce13 --- /dev/null +++ b/test/rust-test-2021/api_files/keyword_identifiers.fbs @@ -0,0 +1,30 @@ +// Tests that keywords can be used as identifiers, matching flatc behavior. + +table include { + namespace: int; + attribute: int; + table: int; + struct: int; + enum: int; + union: int; + root_type: int; + rpc_service: int; + file_extension: int; + file_identifier: int; +} + +enum native_include: byte { + namespace = 0, + attribute = 1, + table = 2, + struct = 3, + enum = 4, + union = 5, +} + +table holder { + include: include; + native_include: native_include; +} + +root_type holder; diff --git a/test/rust-test-2021/api_files/keyword_identifiers.rs b/test/rust-test-2021/api_files/keyword_identifiers.rs new file mode 100644 index 00000000..113212aa --- /dev/null +++ b/test/rust-test-2021/api_files/keyword_identifiers.rs @@ -0,0 +1,22 @@ +// Check that keywords used as field names produce the expected Rust identifiers. +// Rust keywords get a trailing _ appended by the code generator. +check_type!(Include => namespace : i32); +check_type!(Include => attribute : i32); +check_type!(Include => table : i32); +check_type!(Include => struct_ : i32); +check_type!(Include => enum_ : i32); +check_type!(Include => union_ : i32); +check_type!(Include => root_type : i32); +check_type!(Include => rpc_service : i32); +check_type!(Include => file_extension : i32); +check_type!(Include => file_identifier : i32); + +// Check that keywords used as enum variants produce the expected Rust identifiers. +check_enum_variants!(NativeInclude: i8 { + Namespace = 0, + Attribute = 1, + Table = 2, + Struct = 3, + Enum = 4, + Union = 5, +});