From 773ee191583ba9c3e380295c55a890d07eb6052a Mon Sep 17 00:00:00 2001 From: Chris Mounce Date: Sat, 17 May 2025 16:44:02 -0700 Subject: [PATCH] WIP Progress on parsing labels - Add parsing for motion at start of line - Start parsing if statements - Add first file-based parsing test - Implement Rule for `Box` --- src/labels/labels.rs | 55 +++++++++++++++++-- ...labels__labels__test__label_detection.snap | 9 +++ src/preprocess/peg.rs | 6 ++ tests/labels/find-all.txt | 5 ++ 4 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 src/labels/snapshots/zasm__labels__labels__test__label_detection.snap create mode 100644 tests/labels/find-all.txt diff --git a/src/labels/labels.rs b/src/labels/labels.rs index 19c3a9f..9abfc65 100644 --- a/src/labels/labels.rs +++ b/src/labels/labels.rs @@ -24,11 +24,34 @@ fn program() -> impl Rule { } fn line() -> impl Rule { - Alt((send, label_line, any_line)) + (motion_prefix, Alt((command_line, label_line, any_line))) } -fn send() -> impl Rule { - ("#", w, NoCase("send"), ww, Tag("ref", label_name), w, eol) +fn motion_prefix() -> impl Rule { + star!(Alt(("/", "?")), w, direction) +} + +fn command_line() -> impl Rule { + ("#", w, bare_command) +} + +fn bare_command() -> impl Rule { + Alt((bare_if, bare_send)) +} + +fn bare_if() -> impl Rule { + ( + "if", + w, + condition, + w, + Opt(("then", w)), + Box::new(line) as Box, + ) +} + +fn bare_send() -> impl Rule { + (NoCase("send"), ww, Tag("ref", label_name), w, eol) } fn any_line() -> impl Rule { @@ -160,7 +183,9 @@ fn ww() -> impl Rule { #[cfg(test)] mod test { - use insta::assert_debug_snapshot; + use std::fs; + + use insta::{assert_debug_snapshot, assert_snapshot}; use crate::preprocess::peg::Ref; @@ -225,4 +250,26 @@ mod test { ] "#); } + + #[test] + fn test_label_detection() { + let input = fs::read_to_string("tests/labels/find-all.txt").unwrap(); + let mut parser = Parser::new(&input); + assert!(program.parse(&mut parser)); + + let mut result = String::new(); + let mut last_index = 0; + for group in parser.iter() { + let before = &input[last_index..group.span().start]; + let inner = match group.kind() { + "label" => format!("({})", group.text()), + _ => group.text().into(), + }; + result.push_str(before); + result.push_str(&inner); + last_index = group.span().end; + } + result.push_str(&input[last_index..]); + assert_snapshot!(result); + } } diff --git a/src/labels/snapshots/zasm__labels__labels__test__label_detection.snap b/src/labels/snapshots/zasm__labels__labels__test__label_detection.snap new file mode 100644 index 0000000..745a587 --- /dev/null +++ b/src/labels/snapshots/zasm__labels__labels__test__label_detection.snap @@ -0,0 +1,9 @@ +--- +source: src/labels/labels.rs +expression: result +--- +'Find all the labels and their references +:(foo) +#send foo +#if blocked n #send foo +#if bar foo diff --git a/src/preprocess/peg.rs b/src/preprocess/peg.rs index f9d6a4d..9224885 100644 --- a/src/preprocess/peg.rs +++ b/src/preprocess/peg.rs @@ -106,6 +106,12 @@ pub trait Rule { fn parse(&self, p: &mut Parser) -> bool; } +impl Rule for Box { + fn parse(&self, p: &mut Parser) -> bool { + self.as_ref().parse(p) + } +} + pub struct Ref(pub T); impl Rule for Ref<&T> diff --git a/tests/labels/find-all.txt b/tests/labels/find-all.txt new file mode 100644 index 0000000..e6553c9 --- /dev/null +++ b/tests/labels/find-all.txt @@ -0,0 +1,5 @@ +'Find all the labels and their references +:foo +#send foo +#if blocked n #send foo +#if bar foo