Revise trait Rule to return bool

This commit is contained in:
2025-05-09 23:16:48 -07:00
parent f3ab9679cc
commit 661a9aa286
+40 -45
View File
@@ -1,7 +1,5 @@
use std::ops::RangeInclusive; use std::ops::RangeInclusive;
use anyhow::{Result, bail};
// TODO: Add offsets // TODO: Add offsets
pub enum Tag { pub enum Tag {
Open(&'static str), Open(&'static str),
@@ -42,7 +40,7 @@ impl Parser {
} }
pub trait Rule { pub trait Rule {
fn parse(&self, p: &mut Parser) -> Result<()>; fn parse(&self, p: &mut Parser) -> bool;
} }
pub struct Ref<T>(pub T); pub struct Ref<T>(pub T);
@@ -51,7 +49,7 @@ impl<T> Rule for Ref<&T>
where where
T: Rule, T: Rule,
{ {
fn parse(&self, p: &mut Parser) -> Result<()> { fn parse(&self, p: &mut Parser) -> bool {
self.0.parse(p) self.0.parse(p)
} }
} }
@@ -61,51 +59,50 @@ where
R: Rule, R: Rule,
F: Fn() -> R, F: Fn() -> R,
{ {
fn parse(&self, p: &mut Parser) -> Result<()> { fn parse(&self, p: &mut Parser) -> bool {
self().parse(p) self().parse(p)
} }
} }
impl Rule for &str { impl Rule for &str {
fn parse(&self, p: &mut Parser) -> Result<()> { fn parse(&self, p: &mut Parser) -> bool {
if p.input[p.offset..].starts_with(self) { if p.input[p.offset..].starts_with(self) {
p.offset += self.len(); p.offset += self.len();
Ok(()) true
} else { } else {
bail!("No match") false
} }
} }
} }
impl Rule for RangeInclusive<char> { impl Rule for RangeInclusive<char> {
fn parse(&self, p: &mut Parser) -> Result<()> { fn parse(&self, p: &mut Parser) -> bool {
if let Some(c) = p.input[p.offset..].chars().next() { if let Some(c) = p.input[p.offset..].chars().next() {
if self.contains(&c) { if self.contains(&c) {
p.offset += c.len_utf8(); p.offset += c.len_utf8();
return Ok(()); return true;
} }
} }
bail!("No match") false
} }
} }
macro_rules! impl_rule_for_tuple { macro_rules! impl_rule_for_tuple {
($($x:ident)+) => { ($($x:ident)+) => {
impl<$($x),+> Rule for ($($x),+,) where $($x: Rule),+, { impl<$($x),+> Rule for ($($x),+,) where $($x: Rule),+, {
fn parse(&self, p: &mut Parser) -> Result<()> { fn parse(&self, p: &mut Parser) -> bool {
let save = p.save(); let save = p.save();
let mut lambda = || { let mut lambda = || {
#[allow(non_snake_case)] #[allow(non_snake_case)]
let ($($x),+,) = self; let ($($x),+,) = self;
$($x.parse(p)?;)+ $(if !$x.parse(p) {return false; })+
Ok(()) true
}; };
match lambda() { if lambda() {
Ok(x) => Ok(x), true
Err(e) => { } else {
p.restore(save); p.restore(save);
Err(e) false
}
} }
} }
} }
@@ -117,17 +114,17 @@ pub struct Alt<T>(pub T);
macro_rules! impl_rule_for_alt { macro_rules! impl_rule_for_alt {
($($x:ident)+) => { ($($x:ident)+) => {
impl<$($x),+> Rule for Alt<($($x),+,)> where $($x: Rule),+ { impl<$($x),+> Rule for Alt<($($x),+,)> where $($x: Rule),+ {
fn parse(&self, p: &mut Parser) -> Result<()> { fn parse(&self, p: &mut Parser) -> bool {
let save = p.save(); let save = p.save();
#[allow(non_snake_case)] #[allow(non_snake_case)]
let ($($x),+,) = &self.0; let ($($x),+,) = &self.0;
$( $(
if $x.parse(p).is_ok() { if $x.parse(p) {
return Ok(()) return true
} }
p.restore(save); p.restore(save);
)+ )+
bail!("No match") false
} }
} }
}; };
@@ -139,23 +136,23 @@ impl<T> Rule for And<T>
where where
T: Rule, T: Rule,
{ {
fn parse(&self, p: &mut Parser) -> Result<()> { fn parse(&self, p: &mut Parser) -> bool {
let save = p.save(); let save = p.save();
self.0.parse(p)?; let result = self.0.parse(p);
p.restore(save); p.restore(save);
Ok(()) result
} }
} }
pub struct Dot; pub struct Dot;
impl Rule for Dot { impl Rule for Dot {
fn parse(&self, p: &mut Parser) -> Result<()> { fn parse(&self, p: &mut Parser) -> bool {
if let Some(c) = p.input[p.offset..].chars().next() { if let Some(c) = p.input[p.offset..].chars().next() {
p.offset += c.len_utf8(); p.offset += c.len_utf8();
Ok(()) true
} else { } else {
bail!("No match") false
} }
} }
} }
@@ -166,13 +163,14 @@ impl<T> Rule for Not<T>
where where
T: Rule, T: Rule,
{ {
fn parse(&self, p: &mut Parser) -> Result<()> { fn parse(&self, p: &mut Parser) -> bool {
let save = p.save(); let save = p.save();
if self.0.parse(p).is_ok() { if self.0.parse(p) {
p.restore(save); p.restore(save);
bail!("No match"); false
} else {
true
} }
Ok(())
} }
} }
@@ -182,9 +180,9 @@ impl<T> Rule for Opt<T>
where where
T: Rule, T: Rule,
{ {
fn parse(&self, p: &mut Parser) -> Result<()> { fn parse(&self, p: &mut Parser) -> bool {
let _ = self.0.parse(p); let _ = self.0.parse(p);
Ok(()) true
} }
} }
@@ -194,9 +192,9 @@ impl<T> Rule for Star<T>
where where
T: Rule, T: Rule,
{ {
fn parse(&self, p: &mut Parser) -> Result<()> { fn parse(&self, p: &mut Parser) -> bool {
while self.0.parse(p).is_ok() {} while self.0.parse(p) {}
Ok(()) true
} }
} }
@@ -212,11 +210,8 @@ macro_rules! star {
pub struct EOF; pub struct EOF;
impl Rule for EOF { impl Rule for EOF {
fn parse(&self, p: &mut Parser) -> Result<()> { fn parse(&self, p: &mut Parser) -> bool {
if p.offset < p.input.len() { p.offset >= p.input.len()
bail!("No match");
}
Ok(())
} }
} }
@@ -237,13 +232,13 @@ mod test {
fn parse<T: Rule>(rule: &T, input: &str) { fn parse<T: Rule>(rule: &T, input: &str) {
let mut p = Parser::new(input); let mut p = Parser::new(input);
let rule = (Ref(rule), EOF); let rule = (Ref(rule), EOF);
assert!(rule.parse(&mut p).is_ok()); assert!(rule.parse(&mut p));
} }
fn parse_err<T: Rule>(rule: &T, input: &str) { fn parse_err<T: Rule>(rule: &T, input: &str) {
let mut p = Parser::new(input); let mut p = Parser::new(input);
let rule = (Ref(rule), EOF); let rule = (Ref(rule), EOF);
assert!(rule.parse(&mut p).is_err()); assert!(!rule.parse(&mut p));
} }
#[test] #[test]