Improve regex parsing and allow ‘/‘ characters

This commit is contained in:
Tobie Morgan Hitchcock 2021-05-22 19:13:53 +01:00
parent 1f9cad9431
commit ba60c4437f
2 changed files with 11 additions and 5 deletions

View file

@ -471,6 +471,7 @@ pub fn literal(i: &str) -> IResult<&str, Literal> {
map(array, |v| Literal::Array(v)), map(array, |v| Literal::Array(v)),
map(point, |v| Literal::Point(v)), map(point, |v| Literal::Point(v)),
map(param, |v| Literal::Param(v)), map(param, |v| Literal::Param(v)),
map(regex, |v| Literal::Regex(v)),
map(thing, |v| Literal::Thing(v)), map(thing, |v| Literal::Thing(v)),
map(model, |v| Literal::Model(v)), map(model, |v| Literal::Model(v)),
map(idiom, |v| Literal::Idiom(v)), map(idiom, |v| Literal::Idiom(v)),

View file

@ -1,6 +1,7 @@
use nom::bytes::complete::escaped;
use nom::bytes::complete::is_not; use nom::bytes::complete::is_not;
use nom::bytes::complete::tag; use nom::bytes::complete::tag;
use nom::sequence::delimited; use nom::character::complete::one_of;
use nom::IResult; use nom::IResult;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::cmp::Ordering; use std::cmp::Ordering;
@ -16,6 +17,8 @@ pub struct Regex {
impl<'a> From<&'a str> for Regex { impl<'a> From<&'a str> for Regex {
fn from(r: &str) -> Regex { fn from(r: &str) -> Regex {
let r = r.replace("\\/", "/");
let r = r.as_str();
Regex { Regex {
input: String::from(r), input: String::from(r),
value: match regex::Regex::new(r) { value: match regex::Regex::new(r) {
@ -46,7 +49,9 @@ impl fmt::Display for Regex {
} }
pub fn regex(i: &str) -> IResult<&str, Regex> { pub fn regex(i: &str) -> IResult<&str, Regex> {
let (i, v) = delimited(tag("/"), is_not("/"), tag("/"))(i)?; let (i, _) = tag("/")(i)?;
let (i, v) = escaped(is_not("\\/"), '\\', one_of("/"))(i)?;
let (i, _) = tag("/")(i)?;
Ok((i, Regex::from(v))) Ok((i, Regex::from(v)))
} }
@ -67,11 +72,11 @@ mod tests {
#[test] #[test]
fn regex_complex() { fn regex_complex() {
let sql = "/test.*/"; let sql = r"/test\/[a-z]+\/.*/";
let res = regex(sql); let res = regex(sql);
assert!(res.is_ok()); assert!(res.is_ok());
let out = res.unwrap().1; let out = res.unwrap().1;
assert_eq!("/test.*/", format!("{}", out)); assert_eq!(r"/test/[a-z]+/.*/", format!("{}", out));
assert_eq!(out, Regex::from("test.*")); assert_eq!(out, Regex::from("test/[a-z]+/.*"));
} }
} }