From f15a56d9bcc9712bca842f182e160df1942aea98 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 6 Jul 2022 10:17:21 +0000 Subject: [PATCH 1/1] Implement a proper command parser... ... that grabs things from the front instead of splitting at spaces and colons and hoping for the best --- ui_test/src/comments.rs | 63 ++++++++++++++++++----------------- ui_test/src/comments/tests.rs | 2 +- 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/ui_test/src/comments.rs b/ui_test/src/comments.rs index dd6ca9581ab..fa46b549700 100644 --- a/ui_test/src/comments.rs +++ b/ui_test/src/comments.rs @@ -98,14 +98,7 @@ fn parse_checked_line( line: &str, ) -> Result<()> { if let Some((_, command)) = line.split_once("//@") { - let command = command.trim(); - if let Some((command, args)) = command.split_once(':') { - self.parse_command_with_args(command, args, l) - } else if let Some((command, _comments)) = command.split_once(' ') { - self.parse_command(command) - } else { - self.parse_command(command) - } + self.parse_command(command.trim(), l) } else if let Some((_, pattern)) = line.split_once("//~") { self.parse_pattern(pattern, fallthrough_to, l) } else if let Some((_, pattern)) = line.split_once("//[") { @@ -189,7 +182,22 @@ pub(crate) fn parse(path: &Path, content: &str) -> Result { Ok(this) } - fn parse_command_with_args(&mut self, command: &str, args: &str, l: usize) -> Result<()> { + fn parse_command(&mut self, command: &str, l: usize) -> Result<()> { + // Commands are letters or dashes, grab everything until the first character that is neither of those. + let (command, args) = match command.chars().position(|c: char| !c.is_alphabetic() && c != '-') { + None => (command, ""), + Some(i) => { + let (command, args) = command.split_at(i); + let mut args = args.chars(); + let next = args.next().expect("the `position` above guarantees that there is at least one char"); + let args = match next { + ':' | ' ' => args.as_str(), + _ => bail!("expected space or `:`, got `{next}`"), + }; + (command, args) + } + }; + match command { "revisions" => { ensure!(self.revisions.is_none(), "cannot specifiy revisions twice"); @@ -222,30 +230,25 @@ fn parse_command_with_args(&mut self, command: &str, args: &str, l: usize) -> Re ); self.error_pattern = Some((args.trim().to_string(), l)); } - // Maybe the user just left a comment explaining a command without arguments - _ => self.parse_command(command)?, - } - Ok(()) - } - - fn parse_command(&mut self, command: &str) -> Result<()> { - if let Some(s) = command.strip_prefix("ignore-") { - self.ignore.push(Condition::parse(s)); - return Ok(()); - } - - if let Some(s) = command.strip_prefix("only-") { - self.only.push(Condition::parse(s)); - return Ok(()); - } + "stderr-per-bitwidth" => { + ensure!(!self.stderr_per_bitwidth, "cannot specifiy stderr-per-bitwidth twice"); + self.stderr_per_bitwidth = true; + } + command => { + if let Some(s) = command.strip_prefix("ignore-") { + self.ignore.push(Condition::parse(s)); + return Ok(()); + } - if command.starts_with("stderr-per-bitwidth") { - ensure!(!self.stderr_per_bitwidth, "cannot specifiy stderr-per-bitwidth twice"); - self.stderr_per_bitwidth = true; - return Ok(()); + if let Some(s) = command.strip_prefix("only-") { + self.only.push(Condition::parse(s)); + return Ok(()); + } + bail!("unknown command {command}"); + } } - bail!("unknown command {command}"); + Ok(()) } fn parse_pattern( diff --git a/ui_test/src/comments/tests.rs b/ui_test/src/comments/tests.rs index cdd81aa9905..15a0aae247b 100644 --- a/ui_test/src/comments/tests.rs +++ b/ui_test/src/comments/tests.rs @@ -44,7 +44,7 @@ fn parse_slash_slash_at() -> Result<()> { fn parse_slash_slash_at_fail() -> Result<()> { init(); let s = r" -//@ error-pattern foomp +//@ error-patttern foomp use std::mem; "; -- 2.44.0