parent
42725789a0
commit
407a4c3381
2 changed files with 101 additions and 44 deletions
|
@ -24,17 +24,7 @@ pub fn comment(i: &str) -> IResult<&str, ()> {
|
||||||
Ok((i, ()))
|
Ok((i, ()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn blank(i: &str) -> IResult<&str, ()> {
|
pub fn block(i: &str) -> IResult<&str, ()> {
|
||||||
let (i, _) = multispace0(i)?;
|
|
||||||
Ok((i, ()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn space(i: &str) -> IResult<&str, ()> {
|
|
||||||
let (i, _) = multispace1(i)?;
|
|
||||||
Ok((i, ()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn block(i: &str) -> IResult<&str, ()> {
|
|
||||||
let (i, _) = multispace0(i)?;
|
let (i, _) = multispace0(i)?;
|
||||||
let (i, _) = char('/')(i)?;
|
let (i, _) = char('/')(i)?;
|
||||||
let (i, _) = char('*')(i)?;
|
let (i, _) = char('*')(i)?;
|
||||||
|
@ -45,7 +35,7 @@ fn block(i: &str) -> IResult<&str, ()> {
|
||||||
Ok((i, ()))
|
Ok((i, ()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn slash(i: &str) -> IResult<&str, ()> {
|
pub fn slash(i: &str) -> IResult<&str, ()> {
|
||||||
let (i, _) = multispace0(i)?;
|
let (i, _) = multispace0(i)?;
|
||||||
let (i, _) = char('/')(i)?;
|
let (i, _) = char('/')(i)?;
|
||||||
let (i, _) = char('/')(i)?;
|
let (i, _) = char('/')(i)?;
|
||||||
|
@ -53,7 +43,7 @@ fn slash(i: &str) -> IResult<&str, ()> {
|
||||||
Ok((i, ()))
|
Ok((i, ()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dash(i: &str) -> IResult<&str, ()> {
|
pub fn dash(i: &str) -> IResult<&str, ()> {
|
||||||
let (i, _) = multispace0(i)?;
|
let (i, _) = multispace0(i)?;
|
||||||
let (i, _) = char('-')(i)?;
|
let (i, _) = char('-')(i)?;
|
||||||
let (i, _) = char('-')(i)?;
|
let (i, _) = char('-')(i)?;
|
||||||
|
@ -61,9 +51,19 @@ fn dash(i: &str) -> IResult<&str, ()> {
|
||||||
Ok((i, ()))
|
Ok((i, ()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hash(i: &str) -> IResult<&str, ()> {
|
pub fn hash(i: &str) -> IResult<&str, ()> {
|
||||||
let (i, _) = multispace0(i)?;
|
let (i, _) = multispace0(i)?;
|
||||||
let (i, _) = char('#')(i)?;
|
let (i, _) = char('#')(i)?;
|
||||||
let (i, _) = not_line_ending(i)?;
|
let (i, _) = not_line_ending(i)?;
|
||||||
Ok((i, ()))
|
Ok((i, ()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn blank(i: &str) -> IResult<&str, ()> {
|
||||||
|
let (i, _) = multispace0(i)?;
|
||||||
|
Ok((i, ()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn space(i: &str) -> IResult<&str, ()> {
|
||||||
|
let (i, _) = multispace1(i)?;
|
||||||
|
Ok((i, ()))
|
||||||
|
}
|
||||||
|
|
|
@ -1,27 +1,31 @@
|
||||||
|
use crate::sql::comment::{block, slash};
|
||||||
use crate::sql::error::IResult;
|
use crate::sql::error::IResult;
|
||||||
use nom::branch::alt;
|
use nom::branch::alt;
|
||||||
use nom::bytes::complete::escaped;
|
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::character::complete::one_of;
|
use nom::character::complete::char;
|
||||||
|
use nom::character::complete::multispace0;
|
||||||
use nom::combinator::recognize;
|
use nom::combinator::recognize;
|
||||||
|
use nom::multi::many0;
|
||||||
use nom::multi::many1;
|
use nom::multi::many1;
|
||||||
|
use nom::sequence::delimited;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt::{self, Display, Formatter};
|
use std::fmt::{self, Display, Formatter};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
const SINGLE: &str = r#"'"#;
|
const SINGLE: char = '\'';
|
||||||
const SINGLE_ESC: &str = r#"\'"#;
|
const SINGLE_ESC: &str = r#"\'"#;
|
||||||
|
|
||||||
const DOUBLE: &str = r#"""#;
|
const DOUBLE: char = '"';
|
||||||
const DOUBLE_ESC: &str = r#"\""#;
|
const DOUBLE_ESC: &str = r#"\""#;
|
||||||
|
|
||||||
const BACKTICK: &str = r#"`"#;
|
const BACKTICK: char = '`';
|
||||||
const BACKTICK_ESC: &str = r#"\`"#;
|
const BACKTICK_ESC: &str = r#"\`"#;
|
||||||
|
|
||||||
const OBJECT_BEG: &str = "{";
|
const OBJECT_BEG: char = '{';
|
||||||
const OBJECT_END: &str = "}";
|
const OBJECT_END: char = '}';
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Hash)]
|
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Hash)]
|
||||||
pub struct Script(pub String);
|
pub struct Script(pub String);
|
||||||
|
@ -52,44 +56,67 @@ impl Display for Script {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn script(i: &str) -> IResult<&str, Script> {
|
pub fn script(i: &str) -> IResult<&str, Script> {
|
||||||
let (i, v) = recognize(script_raw)(i)?;
|
let (i, v) = script_raw(i)?;
|
||||||
Ok((i, Script(String::from(v))))
|
Ok((i, Script(String::from(v))))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_raw(i: &str) -> IResult<&str, &str> {
|
fn script_raw(i: &str) -> IResult<&str, &str> {
|
||||||
recognize(many1(alt((char_any, char_object, string_single, string_double, string_backtick))))(i)
|
recognize(many0(alt((
|
||||||
|
script_comment,
|
||||||
|
script_object,
|
||||||
|
script_string,
|
||||||
|
script_maths,
|
||||||
|
script_other,
|
||||||
|
))))(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn char_any(i: &str) -> IResult<&str, &str> {
|
fn script_maths(i: &str) -> IResult<&str, &str> {
|
||||||
is_not("{}'`\"")(i)
|
recognize(tag("/"))(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn char_object(i: &str) -> IResult<&str, &str> {
|
fn script_other(i: &str) -> IResult<&str, &str> {
|
||||||
let (i, _) = tag(OBJECT_BEG)(i)?;
|
recognize(many1(is_not("/{}`'\"")))(i)
|
||||||
let (i, v) = script_raw(i)?;
|
|
||||||
let (i, _) = tag(OBJECT_END)(i)?;
|
|
||||||
Ok((i, v))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn string_single(i: &str) -> IResult<&str, &str> {
|
fn script_comment(i: &str) -> IResult<&str, &str> {
|
||||||
let (i, _) = tag(SINGLE)(i)?;
|
recognize(delimited(multispace0, many1(alt((block, slash))), multispace0))(i)
|
||||||
let (i, v) = alt((escaped(is_not(SINGLE_ESC), '\\', one_of(SINGLE)), tag("")))(i)?;
|
|
||||||
let (i, _) = tag(SINGLE)(i)?;
|
|
||||||
Ok((i, v))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn string_double(i: &str) -> IResult<&str, &str> {
|
fn script_object(i: &str) -> IResult<&str, &str> {
|
||||||
let (i, _) = tag(DOUBLE)(i)?;
|
recognize(delimited(char(OBJECT_BEG), script_raw, char(OBJECT_END)))(i)
|
||||||
let (i, v) = alt((escaped(is_not(DOUBLE_ESC), '\\', one_of(DOUBLE)), tag("")))(i)?;
|
|
||||||
let (i, _) = tag(DOUBLE)(i)?;
|
|
||||||
Ok((i, v))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn string_backtick(i: &str) -> IResult<&str, &str> {
|
fn script_string(i: &str) -> IResult<&str, &str> {
|
||||||
let (i, _) = tag(BACKTICK)(i)?;
|
recognize(alt((
|
||||||
let (i, v) = alt((escaped(is_not(BACKTICK_ESC), '\\', one_of(BACKTICK)), tag("")))(i)?;
|
|i| {
|
||||||
let (i, _) = tag(BACKTICK)(i)?;
|
let (i, _) = char(SINGLE)(i)?;
|
||||||
Ok((i, v))
|
let (i, _) = char(SINGLE)(i)?;
|
||||||
|
Ok((i, ""))
|
||||||
|
},
|
||||||
|
|i| {
|
||||||
|
let (i, _) = char(DOUBLE)(i)?;
|
||||||
|
let (i, _) = char(DOUBLE)(i)?;
|
||||||
|
Ok((i, ""))
|
||||||
|
},
|
||||||
|
|i| {
|
||||||
|
let (i, _) = char(SINGLE)(i)?;
|
||||||
|
let (i, v) = escaped(is_not(SINGLE_ESC), '\\', char(SINGLE))(i)?;
|
||||||
|
let (i, _) = char(SINGLE)(i)?;
|
||||||
|
Ok((i, v))
|
||||||
|
},
|
||||||
|
|i| {
|
||||||
|
let (i, _) = char(DOUBLE)(i)?;
|
||||||
|
let (i, v) = escaped(is_not(DOUBLE_ESC), '\\', char(DOUBLE))(i)?;
|
||||||
|
let (i, _) = char(DOUBLE)(i)?;
|
||||||
|
Ok((i, v))
|
||||||
|
},
|
||||||
|
|i| {
|
||||||
|
let (i, _) = char(BACKTICK)(i)?;
|
||||||
|
let (i, v) = escaped(is_not(BACKTICK_ESC), '\\', char(BACKTICK))(i)?;
|
||||||
|
let (i, _) = char(BACKTICK)(i)?;
|
||||||
|
Ok((i, v))
|
||||||
|
},
|
||||||
|
)))(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -150,4 +177,34 @@ mod tests {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn script_advanced() {
|
||||||
|
let sql = r#"
|
||||||
|
// {
|
||||||
|
// }
|
||||||
|
// {}
|
||||||
|
// { }
|
||||||
|
/* { */
|
||||||
|
/* } */
|
||||||
|
/* {} */
|
||||||
|
/* { } */
|
||||||
|
/* {{{ $ }} */
|
||||||
|
/* /* /* /* */
|
||||||
|
let x = {};
|
||||||
|
let x = { };
|
||||||
|
let x = '{';
|
||||||
|
let x = "{";
|
||||||
|
let x = '}';
|
||||||
|
let x = "}";
|
||||||
|
let x = '} } { {';
|
||||||
|
let x = 3 / 4 * 2;
|
||||||
|
let x = /* something */ 45 + 2;
|
||||||
|
"#;
|
||||||
|
let res = script(sql);
|
||||||
|
assert!(res.is_ok());
|
||||||
|
let out = res.unwrap().1;
|
||||||
|
assert_eq!(sql, format!("{}", out));
|
||||||
|
assert_eq!(out, Script::from(sql));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue