From b685e4e657b935fdfd0a672869c92ea457f368da Mon Sep 17 00:00:00 2001 From: Chris Mounce Date: Sun, 11 May 2025 01:04:39 -0700 Subject: [PATCH] Add combinator Plus --- src/labels/labels.rs | 5 +++-- src/preprocess/peg.rs | 33 ++++++++++++++++++++++++++++----- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/labels/labels.rs b/src/labels/labels.rs index cb5156a..2a010f3 100644 --- a/src/labels/labels.rs +++ b/src/labels/labels.rs @@ -1,5 +1,6 @@ use crate::{ - preprocess::peg::{Alt, And, Dot, EOF, Not, Opt, Parser, Rule, Star, Tag}, + plus, + preprocess::peg::{Alt, And, Dot, EOF, Not, Opt, Parser, Rule, Tag}, star, world::Stat, }; @@ -32,7 +33,7 @@ fn parse_any_line() -> impl Rule { fn parse_label_line() -> impl Rule { let allowed = Alt(('A'..='Z', 'a'..='z', '0'..='9', "_", "@", "~")); - (":", Tag("label", star!(allowed)), eol) + (":", Tag("label", plus!(allowed)), eol) } fn eol() -> impl Rule { diff --git a/src/preprocess/peg.rs b/src/preprocess/peg.rs index 7ef6bf0..a366f97 100644 --- a/src/preprocess/peg.rs +++ b/src/preprocess/peg.rs @@ -247,6 +247,30 @@ where } } +pub struct Plus(pub T); + +impl Rule for Plus +where + T: Rule, +{ + fn parse(&self, p: &mut Parser) -> bool { + if !self.0.parse(p) { + return false; + } + while self.0.parse(p) {} + true + } +} + +#[macro_export] +macro_rules! plus { + ($($item:expr),+ $(,)?) => { + crate::preprocess::peg::Plus(( + $($item),+, + )) + }; +} + pub struct Star(pub T); impl Rule for Star @@ -262,7 +286,7 @@ where #[macro_export] macro_rules! star { ($($item:expr),+ $(,)?) => { - Star(( + crate::preprocess::peg::Star(( $($item),+, )) }; @@ -334,8 +358,7 @@ mod test { #[test] fn test_char_range() { - let num = '0'..='9'; - let rule = (Ref(&num), star!(Ref(&num))); + let rule = plus!('0'..='9'); parse(&rule, "0"); parse(&rule, "123"); parse(&rule, "9"); @@ -410,7 +433,7 @@ mod test { #[test] fn test_captures() { - let num = Tag("num", ('0'..='9', star!('0'..='9'))); + let num = Tag("num", plus!('0'..='9')); let rule = star!(Alt((num, Dot))); let mut p = Parser::new("I have 123 gems and 45 torches."); assert!(rule.parse(&mut p)); @@ -432,7 +455,7 @@ mod test { #[test] fn test_nested_captures() { let letter = || 'a'..='z'; - let user = Tag("user", (letter, star!(letter))); + let user = Tag("user", plus!(letter)); let domain = Tag("domain", (letter, star!(Opt("."), letter))); let email = Tag("email", (user, "@", domain)); let rule = star!(Alt((email, Dot)));