Fix parser bug: icase literals and non-ASCII input
This commit is contained in:
+17
-1
@@ -117,7 +117,7 @@ pub mod backend {
|
|||||||
|
|
||||||
fn literal_i(&mut self, s: &str) -> bool {
|
fn literal_i(&mut self, s: &str) -> bool {
|
||||||
let range = self.offset..(self.offset + s.len());
|
let range = self.offset..(self.offset + s.len());
|
||||||
if range.end <= self.input.len() && self.input[range].eq_ignore_ascii_case(s) {
|
if self.input.is_char_boundary(range.end) && self.input[range].eq_ignore_ascii_case(s) {
|
||||||
self.offset += s.len();
|
self.offset += s.len();
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
@@ -238,6 +238,9 @@ mod tests {
|
|||||||
hex_config = "let " var_name " = 0x" ('a'..'f' / '0'..'9')+;
|
hex_config = "let " var_name " = 0x" ('a'..'f' / '0'..'9')+;
|
||||||
var_name = "foo" / "bar"; // case must match
|
var_name = "foo" / "bar"; // case must match
|
||||||
|
|
||||||
|
@icase
|
||||||
|
may_contain_foo = ("foo" / ANY)+;
|
||||||
|
|
||||||
email_text = (!email ANY / email)*;
|
email_text = (!email ANY / email)*;
|
||||||
email = #Email:(#User:user "@" #Domain:domain);
|
email = #Email:(#User:user "@" #Domain:domain);
|
||||||
user = ('a'..'z'i)+;
|
user = ('a'..'z'i)+;
|
||||||
@@ -316,6 +319,7 @@ mod tests {
|
|||||||
assert!(parse(quoted, r#""\"""#));
|
assert!(parse(quoted, r#""\"""#));
|
||||||
assert!(parse(quoted, r#""foo \"bar\" baz""#));
|
assert!(parse(quoted, r#""foo \"bar\" baz""#));
|
||||||
assert!(parse(quoted, r#""C:\\>""#));
|
assert!(parse(quoted, r#""C:\\>""#));
|
||||||
|
assert!(parse(quoted, r#""ñon-äscii""#));
|
||||||
|
|
||||||
assert!(!parse(quoted, r#""no end"#));
|
assert!(!parse(quoted, r#""no end"#));
|
||||||
assert!(!parse(quoted, r#""foo " bar""#));
|
assert!(!parse(quoted, r#""foo " bar""#));
|
||||||
@@ -346,6 +350,18 @@ mod tests {
|
|||||||
assert!(!parse(long_icase_str, "FOO BAR BA"));
|
assert!(!parse(long_icase_str, "FOO BAR BA"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_icase_literal_multibyte() {
|
||||||
|
// Testing failed matches of a icase literal against multibyte characters,
|
||||||
|
// where the end of the literal doesn't fall on a character boundary.
|
||||||
|
// First, make sure the rule works for ASCII input:
|
||||||
|
assert!(parse(may_contain_foo, "==foo=="));
|
||||||
|
assert!(parse(may_contain_foo, "==bar=="));
|
||||||
|
|
||||||
|
// Then force a comparison where a 3-byte slice would split a multibyte char:
|
||||||
|
assert!(parse(may_contain_foo, "....♥")); // dots force an eventual misalignment
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_captures() {
|
fn test_captures() {
|
||||||
let mut p = ParseState::new("alice@example.com");
|
let mut p = ParseState::new("alice@example.com");
|
||||||
|
|||||||
Reference in New Issue
Block a user