From 9d9c76e6936f95b87bedf33da74c589da0edaea8 Mon Sep 17 00:00:00 2001 From: Amaan Qureshi Date: Sun, 12 Jan 2025 03:14:54 -0500 Subject: [PATCH] feat(generate): explicitly disallow non-terminals in non-terminals --- cli/generate/src/build_tables/build_parse_table.rs | 10 ++++++++++ cli/src/main.rs | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/cli/generate/src/build_tables/build_parse_table.rs b/cli/generate/src/build_tables/build_parse_table.rs index 403fa57f..7f5d4e20 100644 --- a/cli/generate/src/build_tables/build_parse_table.rs +++ b/cli/generate/src/build_tables/build_parse_table.rs @@ -72,6 +72,10 @@ pub enum ParseTableBuilderError { Conflict(#[from] ConflictError), #[error("Extra rules must have unambiguous endings. Conflicting rules: {0}")] AmbiguousExtra(#[from] AmbiguousExtraError), + #[error( + "The non-terminal rule `{0}` is used in a non-terminal `extra` rule, which is not allowed." + )] + ImproperNonTerminalExtra(String), } #[derive(Default, Debug, Serialize)] @@ -310,6 +314,12 @@ impl<'a> ParseTableBuilder<'a> { // Add a state for each starting terminal of a non-terminal extra rule. for (terminal, item_set) in non_terminal_extra_item_sets_by_first_terminal { + if terminal.is_non_terminal() { + Err(ParseTableBuilderError::ImproperNonTerminalExtra( + self.symbol_name(&terminal), + ))?; + } + self.non_terminal_extra_states .push((terminal, self.parse_table.states.len())); self.add_parse_state(&Vec::new(), &Vec::new(), item_set); diff --git a/cli/src/main.rs b/cli/src/main.rs index a46b6894..9645f3a3 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -749,7 +749,7 @@ impl Generate { std::process::exit(1); } else { // Removes extra context associated with the error - Err(anyhow!(err.to_string()))?; + Err(anyhow!(err.to_string())).with_context(|| "Error when generating parser")?; } } if self.build {