From b21fe8b5e30b1b7fef17cc2a3cc7f1c20dee6993 Mon Sep 17 00:00:00 2001 From: Chris Mounce Date: Sun, 11 May 2025 02:10:00 -0700 Subject: [PATCH] Tighten label name parsing This includes some custom syntax I'm pretty sure about, such as namespaces and local labels. --- src/labels/labels.rs | 63 ++++++++++++++++++++++++++++++++++++------- src/preprocess/peg.rs | 1 + 2 files changed, 55 insertions(+), 9 deletions(-) diff --git a/src/labels/labels.rs b/src/labels/labels.rs index 2a010f3..e99c98e 100644 --- a/src/labels/labels.rs +++ b/src/labels/labels.rs @@ -7,7 +7,7 @@ use crate::{ pub fn print_labels(b: &Stat) { let mut parser = Parser::new(&b.code); - if !parse_program().parse(&mut parser) { + if !program.parse(&mut parser) { eprintln!("Couldn't parse stat's code: {:?}", b.code); return; } @@ -19,23 +19,68 @@ pub fn print_labels(b: &Stat) { } } -fn parse_program() -> impl Rule { - (Opt((parse_line, star!(("\n", parse_line)))), EOF) +fn program() -> impl Rule { + (Opt((line, star!(("\n", line)))), EOF) } -fn parse_line() -> impl Rule { - Alt((parse_label_line, parse_any_line)) +fn line() -> impl Rule { + Alt((label_line, any_line)) } -fn parse_any_line() -> impl Rule { +fn any_line() -> impl Rule { (star!(Not("\n"), Dot), eol) } -fn parse_label_line() -> impl Rule { - let allowed = Alt(('A'..='Z', 'a'..='z', '0'..='9', "_", "@", "~")); - (":", Tag("label", plus!(allowed)), eol) +fn label_line() -> impl Rule { + (":", Tag("label", label_name), eol) +} + +fn label_name() -> impl Rule { + let namespace = (plus!(word_char), "~"); + ( + Opt(namespace), + star!(word_char), + Opt((".", plus!(word_char))), + ) +} + +fn word_char() -> impl Rule { + Alt(('A'..='Z', 'a'..='z', '0'..='9', "_")) } fn eol() -> impl Rule { Alt((And("\n"), EOF)) } + +#[cfg(test)] +mod test { + use crate::preprocess::peg::Ref; + + use super::*; + + fn parse(rule: &T, input: &str) { + let mut p = Parser::new(input); + let rule = (Ref(rule), EOF); + assert!(rule.parse(&mut p)); + } + + fn parse_err(rule: &T, input: &str) { + let mut p = Parser::new(input); + let rule = (Ref(rule), EOF); + assert!(!rule.parse(&mut p)); + } + + #[test] + fn test_label_name() { + parse(&label_name, "foo"); + parse(&label_name, ".loop"); + parse(&label_name, "foo.loop"); + parse(&label_name, "ns~foo"); + parse(&label_name, "ns~.loop"); + + parse_err(&label_name, "foo."); + parse_err(&label_name, "foo.bar.baz"); + parse_err(&label_name, "foo~bar~baz"); + parse_err(&label_name, "~foo"); + } +} diff --git a/src/preprocess/peg.rs b/src/preprocess/peg.rs index ff7f791..f9d6a4d 100644 --- a/src/preprocess/peg.rs +++ b/src/preprocess/peg.rs @@ -182,6 +182,7 @@ macro_rules! impl_rule_for_tuple { }; } +#[derive(Clone)] pub struct Alt(pub T); macro_rules! impl_rule_for_alt {