Add combinator NoCase
This commit is contained in:
+47
-2
@@ -7,6 +7,7 @@ pub struct Parser {
|
|||||||
input: String,
|
input: String,
|
||||||
offset: usize,
|
offset: usize,
|
||||||
captures: Vec<RawCapture>,
|
captures: Vec<RawCapture>,
|
||||||
|
case_sensitive: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parser {
|
impl Parser {
|
||||||
@@ -15,6 +16,7 @@ impl Parser {
|
|||||||
input: input.into(),
|
input: input.into(),
|
||||||
offset: 0,
|
offset: 0,
|
||||||
captures: Vec::new(),
|
captures: Vec::new(),
|
||||||
|
case_sensitive: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,7 +129,12 @@ where
|
|||||||
|
|
||||||
impl Rule for &str {
|
impl Rule for &str {
|
||||||
fn parse(&self, p: &mut Parser) -> bool {
|
fn parse(&self, p: &mut Parser) -> bool {
|
||||||
if p.input[p.offset..].starts_with(self) {
|
let matches = if p.case_sensitive {
|
||||||
|
p.input[p.offset..].starts_with(self)
|
||||||
|
} else {
|
||||||
|
p.input[p.offset..(p.offset + self.len())].eq_ignore_ascii_case(self)
|
||||||
|
};
|
||||||
|
if matches {
|
||||||
p.offset += self.len();
|
p.offset += self.len();
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
@@ -139,7 +146,12 @@ impl Rule for &str {
|
|||||||
impl Rule for RangeInclusive<char> {
|
impl Rule for RangeInclusive<char> {
|
||||||
fn parse(&self, p: &mut Parser) -> bool {
|
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) {
|
let matches = if p.case_sensitive {
|
||||||
|
self.contains(&c)
|
||||||
|
} else {
|
||||||
|
self.contains(&c.to_ascii_uppercase()) || self.contains(&c.to_ascii_lowercase())
|
||||||
|
};
|
||||||
|
if matches {
|
||||||
p.offset += c.len_utf8();
|
p.offset += c.len_utf8();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -218,6 +230,21 @@ impl Rule for Dot {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct NoCase<T>(pub T);
|
||||||
|
|
||||||
|
impl<T> Rule for NoCase<T>
|
||||||
|
where
|
||||||
|
T: Rule,
|
||||||
|
{
|
||||||
|
fn parse(&self, p: &mut Parser) -> bool {
|
||||||
|
let old_value = p.case_sensitive;
|
||||||
|
p.case_sensitive = false;
|
||||||
|
let result = self.0.parse(p);
|
||||||
|
p.case_sensitive = old_value;
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Not<T>(pub T);
|
pub struct Not<T>(pub T);
|
||||||
|
|
||||||
impl<T> Rule for Not<T>
|
impl<T> Rule for Not<T>
|
||||||
@@ -406,6 +433,24 @@ mod test {
|
|||||||
parse(&rule, "foo\nbar");
|
parse(&rule, "foo\nbar");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_combinator_nocase() {
|
||||||
|
let rule = NoCase(("foo-", 'a'..='z', 'A'..='Z'));
|
||||||
|
parse(&rule, "foo-ab");
|
||||||
|
parse(&rule, "fOO-cD");
|
||||||
|
parse(&rule, "Foo-Ef");
|
||||||
|
parse(&rule, "FOO-GH");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_mixed_case() {
|
||||||
|
let rule = ("foo ", NoCase("bar"), " baz");
|
||||||
|
parse(&rule, "foo bar baz");
|
||||||
|
parse(&rule, "foo BAR baz");
|
||||||
|
parse_err(&rule, "FOO bar baz");
|
||||||
|
parse_err(&rule, "foo bar BAZ");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_combinator_not() {
|
fn test_combinator_not() {
|
||||||
let rule = (Not("foo"), star!(Dot));
|
let rule = (Not("foo"), star!(Dot));
|
||||||
|
|||||||
Reference in New Issue
Block a user