Upgrade dependency Nom to v7

This commit is contained in:
Joakim Soderlund 2024-03-20 17:52:40 +01:00
parent 18ab30684d
commit 217eb6240f
3 changed files with 145 additions and 163 deletions

82
Cargo.lock generated
View file

@ -32,23 +32,11 @@ dependencies = [
"libc",
]
[[package]]
name = "arrayvec"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
[[package]]
name = "autocfg"
version = "1.1.0"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
[[package]]
name = "bitflags"
@ -247,9 +235,9 @@ dependencies = [
[[package]]
name = "itoa"
version = "1.0.10"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "js-sys"
@ -266,19 +254,6 @@ version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "lexical-core"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe"
dependencies = [
"arrayvec",
"bitflags 1.3.2",
"cfg-if",
"ryu",
"static_assertions",
]
[[package]]
name = "libc"
version = "0.2.153"
@ -297,6 +272,12 @@ version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "miniz_oxide"
version = "0.7.2"
@ -312,7 +293,7 @@ version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
dependencies = [
"bitflags 2.5.0",
"bitflags",
"cfg-if",
"cfg_aliases",
"libc",
@ -320,13 +301,12 @@ dependencies = [
[[package]]
name = "nom"
version = "5.1.3"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08959a387a676302eebf4ddbcbc611da04285579f76f88ee0506c63b1a61dd4b"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"lexical-core",
"memchr",
"version_check",
"minimal-lexical",
]
[[package]]
@ -364,9 +344,9 @@ dependencies = [
[[package]]
name = "rayon"
version = "1.9.0"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd"
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
dependencies = [
"either",
"rayon-core",
@ -384,9 +364,9 @@ dependencies = [
[[package]]
name = "regex"
version = "1.10.3"
version = "1.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15"
checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"
dependencies = [
"aho-corasick",
"memchr",
@ -407,9 +387,9 @@ dependencies = [
[[package]]
name = "regex-syntax"
version = "0.8.2"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
[[package]]
name = "rustyline"
@ -417,7 +397,7 @@ version = "14.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7803e8936da37efd9b6d4478277f4b2b9bb5cdb37a113e8d63222e58da647e63"
dependencies = [
"bitflags 2.5.0",
"bitflags",
"cfg-if",
"clipboard-win",
"libc",
@ -464,26 +444,20 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.114"
version = "1.0.115"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0"
checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "syn"
version = "2.0.53"
version = "2.0.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032"
checksum = "002a1b3dbf967edfafc32655d0f377ab0bb7b994aa1d32c8cc7e9b8bf3ebb8f0"
dependencies = [
"proc-macro2",
"quote",
@ -514,12 +488,6 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "wasm-bindgen"
version = "0.2.92"

View file

@ -13,11 +13,11 @@ version = "*"
[dependencies.chrono-english]
version = "*"
[dependencies.nom]
version = "7"
[dependencies.rayon]
version = "*"
[dependencies.regex]
version = "*"
[dependencies.nom]
version = "5"

View file

@ -1,11 +1,28 @@
//! Query parser.
use chrono::prelude::*;
use chrono::DateTime;
use chrono::Utc;
use nom::character::complete::*;
use nom::branch::alt;
use nom::bytes::complete::escaped;
use nom::bytes::complete::tag;
use nom::character::complete::char;
use nom::character::complete::none_of;
use nom::character::complete::one_of;
use nom::character::complete::space0;
use nom::combinator::eof;
use nom::combinator::map;
use nom::combinator::value;
use nom::error::Error as NomError;
use nom::error::ErrorKind as NomErrorKind;
use nom::sequence::*;
use nom::*;
use nom::multi::separated_list1;
use nom::sequence::delimited;
use nom::sequence::preceded;
use nom::sequence::terminated;
use nom::sequence::tuple;
use nom::Err as NomErr;
use nom::Finish;
use nom::IResult;
use fimfareader::archive::Story;
use fimfareader::error::*;
@ -20,6 +37,7 @@ pub enum Source {
DtuFn(Box<dyn Fn(&Story) -> &Option<DateTime<Utc>> + Sync>),
}
#[derive(Clone)]
pub enum Operator {
Exact,
Fuzzy,
@ -28,67 +46,79 @@ pub enum Operator {
}
macro_rules! sfn {
($func:expr) => {
|_| Source::StrFn(Box::new($func))
($tag:expr => $func:expr) => {
preceded(tag($tag), |input| {
Ok((input, Source::StrFn(Box::new($func))))
})
};
}
macro_rules! ifn {
($func:expr) => {
|_| Source::IntFn(Box::new($func))
};
($tag:expr => $func:expr) => {{
preceded(tag($tag), |input| {
Ok((input, Source::IntFn(Box::new($func))))
})
}};
}
macro_rules! dfn {
($func:expr) => {
|_| Source::DtuFn(Box::new($func))
($tag:expr => $func:expr) => {
preceded(tag($tag), |input| {
Ok((input, Source::DtuFn(Box::new($func))))
})
};
}
named!(source<&str, Source>, preceded!(space0, alt!(
tag!("id") => { ifn!(|s| s.id) } |
fn source(input: &str) -> IResult<&str, Source> {
let story = alt((
ifn!("id" => |s| s.id),
sfn!("story" => |s| &s.title),
sfn!("title" => |s| &s.title),
sfn!("description" => |s| &s.description_html),
sfn!("short description" => |s| &s.short_description),
sfn!("url" => |s| &s.url),
dfn!("modified" => |s| &s.date_modified),
dfn!("published" => |s| &s.date_published),
dfn!("updated" => |s| &s.date_updated),
ifn!("chapters" => |s| i64::from(s.num_chapters)),
ifn!("comments" => |s| i64::from(s.num_comments)),
ifn!("dislikes" => |s| i64::from(s.num_dislikes)),
ifn!("likes" => |s| i64::from(s.num_likes)),
ifn!("total views" => |s| i64::from(s.total_num_views)),
ifn!("views" => |s| i64::from(s.num_views)),
ifn!("words" => |s| i64::from(s.num_words)),
));
tag!("story") => { sfn!(|s| &s.title) } |
tag!("title") => { sfn!(|s| &s.title) } |
let author = alt((
sfn!("author" => |s| &s.author.name),
sfn!("author name" => |s| &s.author.name),
ifn!("author id" => |s| s.author.id),
dfn!("author joined" => |s| &s.author.date_joined),
));
tag!("description") => { sfn!(|s| &s.description_html) } |
tag!("short description") => { sfn!(|s| &s.short_description) } |
tag!("url") => { sfn!(|s| &s.url) } |
let archive = alt((
sfn!("path" => |s| &s.archive.path),
sfn!("archive" => |s| &s.archive.path),
sfn!("archive path" => |s| &s.archive.path),
dfn!("entry checked" => |s| &s.archive.date_checked),
dfn!("entry created" => |s| &s.archive.date_created),
dfn!("entry fetched" => |s| &s.archive.date_fetched),
dfn!("entry updated" => |s| &s.archive.date_updated),
));
tag!("modified") => { dfn!(|s| &s.date_modified) } |
tag!("published") => { dfn!(|s| &s.date_published) } |
tag!("updated") => { dfn!(|s| &s.date_updated) } |
preceded(space0, alt((story, author, archive)))(input)
}
tag!("chapters") => { ifn!(|s| i64::from(s.num_chapters)) } |
tag!("comments") => { ifn!(|s| i64::from(s.num_comments)) } |
tag!("dislikes") => { ifn!(|s| i64::from(s.num_dislikes)) } |
tag!("likes") => { ifn!(|s| i64::from(s.num_likes)) } |
tag!("total views") => { ifn!(|s| i64::from(s.total_num_views)) } |
tag!("views") => { ifn!(|s| i64::from(s.num_views)) } |
tag!("words") => { ifn!(|s| i64::from(s.num_words)) } |
fn operator(input: &str) -> IResult<&str, Operator> {
let operator = alt((
value(Operator::Exact, char('=')),
value(Operator::Fuzzy, char(':')),
value(Operator::LessThan, char('<')),
value(Operator::MoreThan, char('>')),
));
tag!("author") => { sfn!(|s| &s.author.name) } |
tag!("author name") => { sfn!(|s| &s.author.name) } |
tag!("author id") => { ifn!(|s| s.author.id) } |
tag!("author joined") => { dfn!(|s| &s.author.date_joined) } |
tag!("path") => { sfn!(|s| &s.archive.path) } |
tag!("archive") => { sfn!(|s| &s.archive.path) } |
tag!("archive path") => { sfn!(|s| &s.archive.path) } |
tag!("entry checked") => { dfn!(|s| &s.archive.date_checked) } |
tag!("entry created") => { dfn!(|s| &s.archive.date_created) } |
tag!("entry fetched") => { dfn!(|s| &s.archive.date_fetched) } |
tag!("entry updated") => { dfn!(|s| &s.archive.date_updated) }
)));
named!(operator<&str, Operator>, preceded!(space0, alt!(
tag!("=") => { |_| Operator::Exact } |
tag!(":") => { |_| Operator::Fuzzy } |
tag!("<") => { |_| Operator::LessThan } |
tag!(">") => { |_| Operator::MoreThan }
)));
preceded(space0, operator)(input)
}
fn unescape(input: &str) -> String {
input
@ -98,47 +128,50 @@ fn unescape(input: &str) -> String {
.replace("\\\\", "\\")
}
named!(value<&str, &str>,
escaped!(none_of!("),|\\"), '\\', one_of!("),|\\"))
);
fn evalue(input: &str) -> IResult<&str, &str> {
escaped(none_of("),|\\"), '\\', one_of("),|\\"))(input)
}
named!(target<&str, String>, preceded!(space0,
map!(value, |value| unescape(value.trim()))
));
fn target(input: &str) -> IResult<&str, String> {
preceded(space0, map(evalue, |value| unescape(value.trim())))(input)
}
fn item(input: &str) -> IResult<&str, Filter> {
let result = tuple((source, operator, target))(input)?;
let (left, (src, op, value)) = result;
let Ok(filter) = optimize(src, op, &value) else {
return Err(Err::Failure((input, NomErrorKind::Permutation)));
let error = NomError::new(input, NomErrorKind::Permutation);
return Err(NomErr::Failure(error));
};
Ok((left, filter))
}
named!(parens<&str, Filter>, alt!(
delimited!(
preceded!(space0, tag!("(")),
preceded!(space0, call!(ofunc)),
preceded!(space0, tag!(")"))
) |
call!(item)
));
fn parens(input: &str) -> IResult<&str, Filter> {
let group = delimited(
preceded(space0, char('(')),
preceded(space0, ofunc),
preceded(space0, char(')')),
);
fn negate(input: &str) -> IResult<&str, Filter> {
let (left, filter) = parens(input)?;
Ok((left, Box::new(move |s| !filter(s))))
alt((group, item))(input)
}
named!(nlist<&str, Filter>, preceded!(space0, alt!(
preceded!(char('!'), call!(negate)) | call!(parens)
)));
fn negate(input: &str) -> IResult<&str, Filter> {
let (input, filter) = parens(input)?;
Ok((input, Box::new(move |s| !filter(s))))
}
named!(alist<&str, Vec<Filter>>, separated_nonempty_list!(
preceded!(space0, char(',')), call!(nlist)
));
fn nlist(input: &str) -> IResult<&str, Filter> {
let negated = preceded(char('!'), negate);
preceded(space0, alt((negated, parens)))(input)
}
fn alist(input: &str) -> IResult<&str, Vec<Filter>> {
let sep = preceded(space0, char(','));
separated_list1(sep, nlist)(input)
}
fn afunc(input: &str) -> IResult<&str, Filter> {
let (left, mut filters) = alist(input)?;
@ -160,9 +193,10 @@ fn afunc(input: &str) -> IResult<&str, Filter> {
Ok((left, filter))
}
named!(olist<&str, Vec<Filter>>, separated_nonempty_list!(
preceded!(space0, char('|')), call!(afunc)
));
fn olist(input: &str) -> IResult<&str, Vec<Filter>> {
let sep = preceded(space0, char('|'));
separated_list1(sep, afunc)(input)
}
fn ofunc(input: &str) -> IResult<&str, Filter> {
let (left, mut filters) = olist(input)?;
@ -184,33 +218,13 @@ fn ofunc(input: &str) -> IResult<&str, Filter> {
Ok((left, filter))
}
fn format_error(query: &str, input: &str, error: NomErrorKind) -> String {
let description = error.description().to_lowercase();
let position = query.len() - input.len();
format!("Invalid {} at {}", description, position)
}
fn translate_error(query: &str, error: Err<(&str, NomErrorKind)>) -> Error {
let message = match error {
Err::Error((i, e)) => format_error(query, i, e),
Err::Failure((i, e)) => format_error(query, i, e),
Err::Incomplete(_) => String::from("Incomplete input"),
};
Error::query(message)
}
fn translate_incomplete(query: &str, input: &str) -> Error {
let position = query.len() - input.len();
Error::query(format!("Incomplete input at {}", position))
fn complete(input: &str) -> IResult<&str, Filter> {
terminated(ofunc, eof)(input.trim())
}
pub fn parse(query: &str) -> Result<Filter> {
match ofunc(query.trim()) {
Ok(("", filter)) => Ok(filter),
Ok((i, _)) => Err(translate_incomplete(query, i)),
Err(e) => Err(translate_error(query, e)),
match complete(query).finish() {
Ok((_, filter)) => Ok(filter),
Err(e) => Err(Error::query(e)),
}
}