From 3c6450e20ae093791637237a35a62b1fa47b94f0 Mon Sep 17 00:00:00 2001 From: Andrew Cowie Date: Fri, 17 Apr 2026 10:28:56 +1000 Subject: [PATCH] Fix parsing of dependent sub-substeps --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/parsing/checks/parser.rs | 3 +++ src/parsing/parser.rs | 48 ++++++++++++++++++++++++++++++++++-- tests/samples/Demolition.tq | 23 +++++++++++++++++ 5 files changed, 74 insertions(+), 4 deletions(-) create mode 100644 tests/samples/Demolition.tq diff --git a/Cargo.lock b/Cargo.lock index 8515a1c6..e854bdb5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -472,7 +472,7 @@ dependencies = [ [[package]] name = "technique" -version = "0.5.4" +version = "0.5.5" dependencies = [ "clap", "ignore", diff --git a/Cargo.toml b/Cargo.toml index dafdfa49..dd11b65f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "technique" -version = "0.5.4" +version = "0.5.5" edition = "2021" description = "A domain specific language for procedures." authors = [ "Andrew Cowie" ] diff --git a/src/parsing/checks/parser.rs b/src/parsing/checks/parser.rs index 3baf8d73..775d8ca5 100644 --- a/src/parsing/checks/parser.rs +++ b/src/parsing/checks/parser.rs @@ -500,6 +500,9 @@ fn step_detection() { assert!(is_substep_dependent(" a. Indented substep")); assert!(!is_substep_dependent("2. Substep can't have number")); assert!(!is_substep_dependent(" 1. Even if it is indented")); + assert!(!is_substep_dependent("i. unus is a sub-substep")); + assert!(!is_substep_dependent("v. quinque is a sub-substep")); + assert!(!is_substep_dependent("x. decem is a sub-substep")); // Test parallel substeps (whitespace agnostic) assert!(is_substep_parallel("- Parallel substep")); diff --git a/src/parsing/parser.rs b/src/parsing/parser.rs index f4828130..bd96e717 100644 --- a/src/parsing/parser.rs +++ b/src/parsing/parser.rs @@ -2126,7 +2126,7 @@ impl<'i> Parser<'i> { |line| is_substep_dependent(line), |outer| { let content = outer.source; - let re = regex!(r"^\s*([a-hj-uw-z])\.\s+"); + let re = regex!(r"^\s*([a-hj-uwy])\.\s+"); let cap = re .captures(content) .ok_or(ParsingError::InvalidStep(outer.offset, 0))?; @@ -2194,6 +2194,47 @@ impl<'i> Parser<'i> { ) } + /// Parse a dependent sub-substep (i., ii., iii., iv., etc.) + fn read_subsubstep_dependent(&mut self) -> Result, ParsingError> { + self.take_block_lines( + is_subsubstep_dependent, + |line| is_subsubstep_dependent(line), + |outer| { + let content = outer.source; + let re = regex!(r"^\s*([ivx]+)\.\s+"); + let cap = re + .captures(content) + .ok_or(ParsingError::InvalidStep(outer.offset, 0))?; + + let numeral = cap + .get(1) + .ok_or(ParsingError::Expected( + outer.offset, + 0, + "the ordinal roman numeral indicating a sub-substep", + ))? + .as_str(); + + let l = cap + .get(0) + .unwrap() + .len(); + + outer.advance(l); + + let text = outer.read_descriptive()?; + + let scopes = outer.read_scopes()?; + + Ok(Scope::DependentBlock { + ordinal: numeral, + description: text, + subscopes: scopes, + }) + }, + ) + } + fn read_descriptive(&mut self) -> Result>, ParsingError> { self.take_block_lines( |_| true, @@ -2598,6 +2639,9 @@ impl<'i> Parser<'i> { } else if is_substep_parallel(content) { let block = self.read_substep_parallel()?; scopes.push(block); + } else if is_subsubstep_dependent(content) { + let block = self.read_subsubstep_dependent()?; + scopes.push(block); } else if is_step_dependent(content) { let block = self.read_step_dependent()?; scopes.push(block); @@ -3058,7 +3102,7 @@ fn is_section(content: &str) -> bool { /// used to compose a number below 40 in roman numerals, as those are /// sub-sub-steps. fn is_substep_dependent(content: &str) -> bool { - let re = regex!(r"^\s*[a-hj-uw-z]\.\s+"); + let re = regex!(r"^\s*[a-hj-uwy]\.\s+"); re.is_match(content) } diff --git a/tests/samples/Demolition.tq b/tests/samples/Demolition.tq new file mode 100644 index 00000000..b561821f --- /dev/null +++ b/tests/samples/Demolition.tq @@ -0,0 +1,23 @@ +demolition : + +# Build hyperspace bypass through solar system + +First we need to destroy the planets in the solar system that are in the way +of our hyperspacial express route. We'll leave Pluto alone; it's the cutest +and apparently not a planet. + + 1. Build bypass through solar system + a. Demolish all the planets. Each one should take slightly less than + two Earth minutes to complete. + i. Mercury + ii. Venus + iii. Mostly Harmless + iv. Mars + v. Astroid Belt (already done?) + vi. Jupiter + vii. Saturn + viii. Uranus + ix. Neptune + x. Eris + xi. Haumea + xii. Makemake