Simplify parser and improve performance

This commit is contained in:
Tobie Morgan Hitchcock 2023-04-17 13:09:56 +01:00
parent 50c3554242
commit 8bf5585080
4 changed files with 290 additions and 382 deletions

View file

@ -9,6 +9,7 @@ use derive::Store;
use nom::branch::alt; use nom::branch::alt;
use nom::bytes::complete::tag_no_case; use nom::bytes::complete::tag_no_case;
use nom::combinator::map; use nom::combinator::map;
use nom::sequence::preceded;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt; use std::fmt;
@ -154,27 +155,30 @@ pub fn constant(i: &str) -> IResult<&str, Constant> {
} }
fn constant_math(i: &str) -> IResult<&str, Constant> { fn constant_math(i: &str) -> IResult<&str, Constant> {
preceded(
tag_no_case("math::"),
alt(( alt((
map(tag_no_case("math::E"), |_| Constant::MathE), map(tag_no_case("E"), |_| Constant::MathE),
map(tag_no_case("math::FRAC_1_PI"), |_| Constant::MathFrac1Pi), map(tag_no_case("FRAC_1_PI"), |_| Constant::MathFrac1Pi),
map(tag_no_case("math::FRAC_1_SQRT_2"), |_| Constant::MathFrac1Sqrt2), map(tag_no_case("FRAC_1_SQRT_2"), |_| Constant::MathFrac1Sqrt2),
map(tag_no_case("math::FRAC_2_PI"), |_| Constant::MathFrac2Pi), map(tag_no_case("FRAC_2_PI"), |_| Constant::MathFrac2Pi),
map(tag_no_case("math::FRAC_2_SQRT_PI"), |_| Constant::MathFrac2SqrtPi), map(tag_no_case("FRAC_2_SQRT_PI"), |_| Constant::MathFrac2SqrtPi),
map(tag_no_case("math::FRAC_PI_2"), |_| Constant::MathFracPi2), map(tag_no_case("FRAC_PI_2"), |_| Constant::MathFracPi2),
map(tag_no_case("math::FRAC_PI_3"), |_| Constant::MathFracPi3), map(tag_no_case("FRAC_PI_3"), |_| Constant::MathFracPi3),
map(tag_no_case("math::FRAC_PI_4"), |_| Constant::MathFracPi4), map(tag_no_case("FRAC_PI_4"), |_| Constant::MathFracPi4),
map(tag_no_case("math::FRAC_PI_6"), |_| Constant::MathFracPi6), map(tag_no_case("FRAC_PI_6"), |_| Constant::MathFracPi6),
map(tag_no_case("math::FRAC_PI_8"), |_| Constant::MathFracPi8), map(tag_no_case("FRAC_PI_8"), |_| Constant::MathFracPi8),
map(tag_no_case("math::LN_10"), |_| Constant::MathLn10), map(tag_no_case("LN_10"), |_| Constant::MathLn10),
map(tag_no_case("math::LN_2"), |_| Constant::MathLn2), map(tag_no_case("LN_2"), |_| Constant::MathLn2),
map(tag_no_case("math::LOG10_2"), |_| Constant::MathLog102), map(tag_no_case("LOG10_2"), |_| Constant::MathLog102),
map(tag_no_case("math::LOG10_E"), |_| Constant::MathLog10E), map(tag_no_case("LOG10_E"), |_| Constant::MathLog10E),
map(tag_no_case("math::LOG2_10"), |_| Constant::MathLog210), map(tag_no_case("LOG2_10"), |_| Constant::MathLog210),
map(tag_no_case("math::LOG2_E"), |_| Constant::MathLog2E), map(tag_no_case("LOG2_E"), |_| Constant::MathLog2E),
map(tag_no_case("math::PI"), |_| Constant::MathPi), map(tag_no_case("PI"), |_| Constant::MathPi),
map(tag_no_case("math::SQRT_2"), |_| Constant::MathSqrt2), map(tag_no_case("SQRT_2"), |_| Constant::MathSqrt2),
map(tag_no_case("math::TAU"), |_| Constant::MathTau), map(tag_no_case("TAU"), |_| Constant::MathTau),
))(i) )),
)(i)
} }
#[cfg(test)] #[cfg(test)]

View file

@ -21,6 +21,8 @@ use nom::character::complete::char;
use nom::combinator::recognize; use nom::combinator::recognize;
use nom::multi::separated_list0; use nom::multi::separated_list0;
use nom::multi::separated_list1; use nom::multi::separated_list1;
use nom::sequence::delimited;
use nom::sequence::preceded;
use serde::ser::SerializeTupleVariant; use serde::ser::SerializeTupleVariant;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::cmp::Ordering; use std::cmp::Ordering;
@ -284,7 +286,6 @@ pub fn normal(i: &str) -> IResult<&str, Function> {
pub fn custom(i: &str) -> IResult<&str, Function> { pub fn custom(i: &str) -> IResult<&str, Function> {
let (i, _) = tag("fn::")(i)?; let (i, _) = tag("fn::")(i)?;
let (i, s) = recognize(separated_list1(tag("::"), take_while1(val_char)))(i)?; let (i, s) = recognize(separated_list1(tag("::"), take_while1(val_char)))(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = char('(')(i)?; let (i, _) = char('(')(i)?;
let (i, _) = mightbespace(i)?; let (i, _) = mightbespace(i)?;
let (i, a) = separated_list0(commas, value)(i)?; let (i, a) = separated_list0(commas, value)(i)?;
@ -295,7 +296,6 @@ pub fn custom(i: &str) -> IResult<&str, Function> {
fn script(i: &str) -> IResult<&str, Function> { fn script(i: &str) -> IResult<&str, Function> {
let (i, _) = tag("function")(i)?; let (i, _) = tag("function")(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = tag("(")(i)?; let (i, _) = tag("(")(i)?;
let (i, _) = mightbespace(i)?; let (i, _) = mightbespace(i)?;
let (i, a) = separated_list0(commas, value)(i)?; let (i, a) = separated_list0(commas, value)(i)?;
@ -309,15 +309,8 @@ fn script(i: &str) -> IResult<&str, Function> {
} }
fn cast(i: &str) -> IResult<&str, Function> { fn cast(i: &str) -> IResult<&str, Function> {
let (i, _) = char('<')(i)?; let (i, s) = delimited(
let (i, s) = function_casts(i)?; char('<'),
let (i, _) = char('>')(i)?;
let (i, _) = mightbespace(i)?;
let (i, v) = single(i)?;
Ok((i, Function::Cast(s.to_string(), v)))
}
fn function_casts(i: &str) -> IResult<&str, &str> {
alt(( alt((
tag("bool"), tag("bool"),
tag("datetime"), tag("datetime"),
@ -327,284 +320,260 @@ fn function_casts(i: &str) -> IResult<&str, &str> {
tag("int"), tag("int"),
tag("number"), tag("number"),
tag("string"), tag("string"),
))(i) )),
char('>'),
)(i)?;
let (i, _) = mightbespace(i)?;
let (i, v) = single(i)?;
Ok((i, Function::Cast(s.to_string(), v)))
} }
fn function_names(i: &str) -> IResult<&str, &str> { fn function_names(i: &str) -> IResult<&str, &str> {
alt(( recognize(alt((
function_array, preceded(tag("array::"), function_array),
function_count, preceded(tag("crypto::"), function_crypto),
function_crypto, preceded(tag("duration::"), function_duration),
function_duration, preceded(tag("geo::"), function_geo),
function_geo, preceded(tag("http::"), function_http),
function_http, preceded(tag("is::"), function_is),
function_is, preceded(tag("math::"), function_math),
function_math, preceded(tag("meta::"), function_meta),
function_meta, preceded(tag("parse::"), function_parse),
function_not, preceded(tag("rand::"), function_rand),
function_parse, preceded(tag("session::"), function_session),
function_rand, preceded(tag("string::"), function_string),
function_session, preceded(tag("time::"), function_time),
function_sleep, preceded(tag("type::"), function_type),
function_string, tag("count"),
function_time, tag("not"),
function_type, tag("rand"),
))(i) tag("sleep"),
)))(i)
} }
fn function_array(i: &str) -> IResult<&str, &str> { fn function_array(i: &str) -> IResult<&str, &str> {
alt(( alt((
alt(( alt((
tag("array::add"), tag("add"),
tag("array::all"), tag("all"),
tag("array::any"), tag("any"),
tag("array::append"), tag("append"),
tag("array::combine"), tag("combine"),
tag("array::complement"), tag("complement"),
tag("array::concat"), tag("concat"),
tag("array::difference"), tag("difference"),
tag("array::distinct"), tag("distinct"),
tag("array::flatten"), tag("flatten"),
tag("array::group"), tag("group"),
tag("array::insert"), tag("insert"),
)), )),
alt(( alt((
tag("array::intersect"), tag("intersect"),
tag("array::len"), tag("len"),
tag("array::max"), tag("max"),
tag("array::min"), tag("min"),
tag("array::pop"), tag("pop"),
tag("array::prepend"), tag("prepend"),
tag("array::push"), tag("push"),
tag("array::remove"), tag("remove"),
tag("array::reverse"), tag("reverse"),
tag("array::sort::asc"), tag("sort::asc"),
tag("array::sort::desc"), tag("sort::desc"),
tag("array::sort"), tag("sort"),
tag("array::union"), tag("union"),
)), )),
))(i) ))(i)
} }
fn function_count(i: &str) -> IResult<&str, &str> {
tag("count")(i)
}
fn function_crypto(i: &str) -> IResult<&str, &str> { fn function_crypto(i: &str) -> IResult<&str, &str> {
alt(( alt((
tag("crypto::argon2::compare"), preceded(tag("argon2::"), alt((tag("compare"), tag("generate")))),
tag("crypto::argon2::generate"), preceded(tag("bcrypt::"), alt((tag("compare"), tag("generate")))),
tag("crypto::bcrypt::compare"), preceded(tag("pbkdf2::"), alt((tag("compare"), tag("generate")))),
tag("crypto::bcrypt::generate"), preceded(tag("scrypt::"), alt((tag("compare"), tag("generate")))),
tag("crypto::md5"), tag("md5"),
tag("crypto::pbkdf2::compare"), tag("sha1"),
tag("crypto::pbkdf2::generate"), tag("sha256"),
tag("crypto::scrypt::compare"), tag("sha512"),
tag("crypto::scrypt::generate"),
tag("crypto::sha1"),
tag("crypto::sha256"),
tag("crypto::sha512"),
))(i) ))(i)
} }
fn function_duration(i: &str) -> IResult<&str, &str> { fn function_duration(i: &str) -> IResult<&str, &str> {
alt(( alt((tag("days"), tag("hours"), tag("mins"), tag("secs"), tag("weeks"), tag("years")))(i)
tag("duration::days"),
tag("duration::hours"),
tag("duration::mins"),
tag("duration::secs"),
tag("duration::weeks"),
tag("duration::years"),
))(i)
} }
fn function_geo(i: &str) -> IResult<&str, &str> { fn function_geo(i: &str) -> IResult<&str, &str> {
alt(( alt((
tag("geo::area"), tag("area"),
tag("geo::bearing"), tag("bearing"),
tag("geo::centroid"), tag("centroid"),
tag("geo::distance"), tag("distance"),
tag("geo::hash::decode"), preceded(tag("hash::"), alt((tag("decode"), tag("encode")))),
tag("geo::hash::encode"),
))(i) ))(i)
} }
fn function_http(i: &str) -> IResult<&str, &str> { fn function_http(i: &str) -> IResult<&str, &str> {
alt(( alt((tag("head"), tag("get"), tag("put"), tag("post"), tag("patch"), tag("delete")))(i)
tag("http::head"),
tag("http::get"),
tag("http::put"),
tag("http::post"),
tag("http::patch"),
tag("http::delete"),
))(i)
} }
fn function_is(i: &str) -> IResult<&str, &str> { fn function_is(i: &str) -> IResult<&str, &str> {
alt(( alt((
tag("is::alphanum"), tag("alphanum"),
tag("is::alpha"), tag("alpha"),
tag("is::ascii"), tag("ascii"),
tag("is::datetime"), tag("datetime"),
tag("is::domain"), tag("domain"),
tag("is::email"), tag("email"),
tag("is::hexadecimal"), tag("hexadecimal"),
tag("is::latitude"), tag("latitude"),
tag("is::longitude"), tag("longitude"),
tag("is::numeric"), tag("numeric"),
tag("is::semver"), tag("semver"),
tag("is::url"), tag("url"),
tag("is::uuid"), tag("uuid"),
))(i) ))(i)
} }
fn function_math(i: &str) -> IResult<&str, &str> { fn function_math(i: &str) -> IResult<&str, &str> {
alt(( alt((
alt(( alt((
tag("math::abs"), tag("abs"),
tag("math::bottom"), tag("bottom"),
tag("math::ceil"), tag("ceil"),
tag("math::fixed"), tag("fixed"),
tag("math::floor"), tag("floor"),
tag("math::interquartile"), tag("interquartile"),
tag("max"),
tag("mean"),
tag("median"),
tag("midhinge"),
tag("min"),
tag("mode"),
)), )),
alt(( alt((
tag("math::max"), tag("nearestrank"),
tag("math::mean"), tag("percentile"),
tag("math::median"), tag("pow"),
tag("math::midhinge"), tag("product"),
tag("math::min"), tag("round"),
tag("math::mode"), tag("spread"),
)), tag("sqrt"),
alt(( tag("stddev"),
tag("math::nearestrank"), tag("sum"),
tag("math::percentile"), tag("top"),
tag("math::pow"), tag("trimean"),
tag("math::product"), tag("variance"),
tag("math::round"),
tag("math::spread"),
tag("math::sqrt"),
tag("math::stddev"),
tag("math::sum"),
tag("math::top"),
tag("math::trimean"),
tag("math::variance"),
)), )),
))(i) ))(i)
} }
fn function_meta(i: &str) -> IResult<&str, &str> { fn function_meta(i: &str) -> IResult<&str, &str> {
alt((tag("meta::id"), tag("meta::table"), tag("meta::tb")))(i) alt((tag("id"), tag("table"), tag("tb")))(i)
}
fn function_not(i: &str) -> IResult<&str, &str> {
tag("not")(i)
}
fn function_sleep(i: &str) -> IResult<&str, &str> {
tag("sleep")(i)
} }
fn function_parse(i: &str) -> IResult<&str, &str> { fn function_parse(i: &str) -> IResult<&str, &str> {
alt(( alt((
tag("parse::email::host"), preceded(tag("email::"), alt((tag("host"), tag("user")))),
tag("parse::email::user"), preceded(
tag("parse::url::domain"), tag("url::"),
tag("parse::url::fragment"), alt((
tag("parse::url::host"), tag("domain"),
tag("parse::url::path"), tag("fragment"),
tag("parse::url::port"), tag("host"),
tag("parse::url::query"), tag("path"),
tag("parse::url::scheme"), tag("port"),
tag("query"),
tag("scheme"),
)),
),
))(i) ))(i)
} }
fn function_rand(i: &str) -> IResult<&str, &str> { fn function_rand(i: &str) -> IResult<&str, &str> {
alt(( alt((
tag("rand::bool"), tag("bool"),
tag("rand::enum"), tag("enum"),
tag("rand::float"), tag("float"),
tag("rand::guid"), tag("guid"),
tag("rand::int"), tag("int"),
tag("rand::string"), tag("string"),
tag("rand::time"), tag("time"),
tag("rand::ulid"), tag("ulid"),
tag("rand::uuid::v4"), tag("uuid::v4"),
tag("rand::uuid::v7"), tag("uuid::v7"),
tag("rand::uuid"), tag("uuid"),
tag("rand"),
))(i) ))(i)
} }
fn function_session(i: &str) -> IResult<&str, &str> { fn function_session(i: &str) -> IResult<&str, &str> {
alt(( alt((
tag("session::db"), tag("db"),
tag("session::id"), tag("id"),
tag("session::ip"), tag("ip"),
tag("session::ns"), tag("ns"),
tag("session::origin"), tag("origin"),
tag("session::sc"), tag("sc"),
tag("session::sd"), tag("sd"),
tag("session::token"), tag("token"),
))(i) ))(i)
} }
fn function_string(i: &str) -> IResult<&str, &str> { fn function_string(i: &str) -> IResult<&str, &str> {
alt(( alt((
tag("string::concat"), tag("concat"),
tag("string::endsWith"), tag("endsWith"),
tag("string::join"), tag("join"),
tag("string::len"), tag("len"),
tag("string::lowercase"), tag("lowercase"),
tag("string::repeat"), tag("repeat"),
tag("string::replace"), tag("replace"),
tag("string::reverse"), tag("reverse"),
tag("string::slice"), tag("slice"),
tag("string::slug"), tag("slug"),
tag("string::split"), tag("split"),
tag("string::startsWith"), tag("startsWith"),
tag("string::trim"), tag("trim"),
tag("string::uppercase"), tag("uppercase"),
tag("string::words"), tag("words"),
))(i) ))(i)
} }
fn function_time(i: &str) -> IResult<&str, &str> { fn function_time(i: &str) -> IResult<&str, &str> {
alt(( alt((
tag("time::day"), tag("day"),
tag("time::floor"), tag("floor"),
tag("time::format"), tag("format"),
tag("time::group"), tag("group"),
tag("time::hour"), tag("hour"),
tag("time::minute"), tag("minute"),
tag("time::month"), tag("month"),
tag("time::nano"), tag("nano"),
tag("time::now"), tag("now"),
tag("time::round"), tag("round"),
tag("time::second"), tag("second"),
tag("time::timezone"), tag("timezone"),
tag("time::unix"), tag("unix"),
tag("time::wday"), tag("wday"),
tag("time::week"), tag("week"),
tag("time::yday"), tag("yday"),
tag("time::year"), tag("year"),
))(i) ))(i)
} }
fn function_type(i: &str) -> IResult<&str, &str> { fn function_type(i: &str) -> IResult<&str, &str> {
alt(( alt((
tag("type::bool"), tag("bool"),
tag("type::datetime"), tag("datetime"),
tag("type::decimal"), tag("decimal"),
tag("type::duration"), tag("duration"),
tag("type::float"), tag("float"),
tag("type::int"), tag("int"),
tag("type::number"), tag("number"),
tag("type::point"), tag("point"),
tag("type::regex"), tag("regex"),
tag("type::string"), tag("string"),
tag("type::table"), tag("table"),
tag("type::thing"), tag("thing"),
))(i) ))(i)
} }

View file

@ -671,7 +671,7 @@ impl hash::Hash for Geometry {
} }
pub fn geometry(i: &str) -> IResult<&str, Geometry> { pub fn geometry(i: &str) -> IResult<&str, Geometry> {
alt((simple, point, line, polygon, multipoint, multiline, multipolygon, collection))(i) alt((simple, normal))(i)
} }
fn simple(i: &str) -> IResult<&str, Geometry> { fn simple(i: &str) -> IResult<&str, Geometry> {
@ -685,199 +685,140 @@ fn simple(i: &str) -> IResult<&str, Geometry> {
Ok((i, Geometry::Point((x, y).into()))) Ok((i, Geometry::Point((x, y).into())))
} }
fn point(i: &str) -> IResult<&str, Geometry> { fn normal(i: &str) -> IResult<&str, Geometry> {
let (i, _) = char('{')(i)?; let (i, _) = char('{')(i)?;
let (i, _) = mightbespace(i)?; let (i, _) = mightbespace(i)?;
let (i, v) = alt((point, line, polygon, multipoint, multiline, multipolygon, collection))(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = char('}')(i)?;
Ok((i, v))
}
fn point(i: &str) -> IResult<&str, Geometry> {
let (i, v) = alt(( let (i, v) = alt((
|i| { |i| {
let (i, _) = preceded(key_type, point_type)(i)?; let (i, _) = preceded(key_type, point_type)(i)?;
let (i, _) = commas(i)?; let (i, _) = commas(i)?;
let (i, v) = preceded(key_vals, point_vals)(i)?; let (i, v) = preceded(key_vals, point_vals)(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
Ok((i, v)) Ok((i, v))
}, },
|i| { |i| {
let (i, v) = preceded(key_vals, point_vals)(i)?; let (i, v) = preceded(key_vals, point_vals)(i)?;
let (i, _) = commas(i)?; let (i, _) = commas(i)?;
let (i, _) = preceded(key_type, point_type)(i)?; let (i, _) = preceded(key_type, point_type)(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
Ok((i, v)) Ok((i, v))
}, },
))(i)?; ))(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = char('}')(i)?;
Ok((i, v.into())) Ok((i, v.into()))
} }
fn line(i: &str) -> IResult<&str, Geometry> { fn line(i: &str) -> IResult<&str, Geometry> {
let (i, _) = char('{')(i)?;
let (i, _) = mightbespace(i)?;
let (i, v) = alt(( let (i, v) = alt((
|i| { |i| {
let (i, _) = preceded(key_type, line_type)(i)?; let (i, _) = preceded(key_type, line_type)(i)?;
let (i, _) = commas(i)?; let (i, _) = commas(i)?;
let (i, v) = preceded(key_vals, line_vals)(i)?; let (i, v) = preceded(key_vals, line_vals)(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
Ok((i, v)) Ok((i, v))
}, },
|i| { |i| {
let (i, v) = preceded(key_vals, line_vals)(i)?; let (i, v) = preceded(key_vals, line_vals)(i)?;
let (i, _) = commas(i)?; let (i, _) = commas(i)?;
let (i, _) = preceded(key_type, line_type)(i)?; let (i, _) = preceded(key_type, line_type)(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
Ok((i, v)) Ok((i, v))
}, },
))(i)?; ))(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = char('}')(i)?;
Ok((i, v.into())) Ok((i, v.into()))
} }
fn polygon(i: &str) -> IResult<&str, Geometry> { fn polygon(i: &str) -> IResult<&str, Geometry> {
let (i, _) = char('{')(i)?;
let (i, _) = mightbespace(i)?;
let (i, v) = alt(( let (i, v) = alt((
|i| { |i| {
let (i, _) = preceded(key_type, polygon_type)(i)?; let (i, _) = preceded(key_type, polygon_type)(i)?;
let (i, _) = commas(i)?; let (i, _) = commas(i)?;
let (i, v) = preceded(key_vals, polygon_vals)(i)?; let (i, v) = preceded(key_vals, polygon_vals)(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
Ok((i, v)) Ok((i, v))
}, },
|i| { |i| {
let (i, v) = preceded(key_vals, polygon_vals)(i)?; let (i, v) = preceded(key_vals, polygon_vals)(i)?;
let (i, _) = commas(i)?; let (i, _) = commas(i)?;
let (i, _) = preceded(key_type, polygon_type)(i)?; let (i, _) = preceded(key_type, polygon_type)(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
Ok((i, v)) Ok((i, v))
}, },
))(i)?; ))(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = char('}')(i)?;
Ok((i, v.into())) Ok((i, v.into()))
} }
fn multipoint(i: &str) -> IResult<&str, Geometry> { fn multipoint(i: &str) -> IResult<&str, Geometry> {
let (i, _) = char('{')(i)?;
let (i, _) = mightbespace(i)?;
let (i, v) = alt(( let (i, v) = alt((
|i| { |i| {
let (i, _) = preceded(key_type, multipoint_type)(i)?; let (i, _) = preceded(key_type, multipoint_type)(i)?;
let (i, _) = commas(i)?; let (i, _) = commas(i)?;
let (i, v) = preceded(key_vals, multipoint_vals)(i)?; let (i, v) = preceded(key_vals, multipoint_vals)(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
Ok((i, v)) Ok((i, v))
}, },
|i| { |i| {
let (i, v) = preceded(key_vals, multipoint_vals)(i)?; let (i, v) = preceded(key_vals, multipoint_vals)(i)?;
let (i, _) = commas(i)?; let (i, _) = commas(i)?;
let (i, _) = preceded(key_type, multipoint_type)(i)?; let (i, _) = preceded(key_type, multipoint_type)(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
Ok((i, v)) Ok((i, v))
}, },
))(i)?; ))(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = char('}')(i)?;
Ok((i, v.into())) Ok((i, v.into()))
} }
fn multiline(i: &str) -> IResult<&str, Geometry> { fn multiline(i: &str) -> IResult<&str, Geometry> {
let (i, _) = char('{')(i)?;
let (i, _) = mightbespace(i)?;
let (i, v) = alt(( let (i, v) = alt((
|i| { |i| {
let (i, _) = preceded(key_type, multiline_type)(i)?; let (i, _) = preceded(key_type, multiline_type)(i)?;
let (i, _) = commas(i)?; let (i, _) = commas(i)?;
let (i, v) = preceded(key_vals, multiline_vals)(i)?; let (i, v) = preceded(key_vals, multiline_vals)(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
Ok((i, v)) Ok((i, v))
}, },
|i| { |i| {
let (i, v) = preceded(key_vals, multiline_vals)(i)?; let (i, v) = preceded(key_vals, multiline_vals)(i)?;
let (i, _) = commas(i)?; let (i, _) = commas(i)?;
let (i, _) = preceded(key_type, multiline_type)(i)?; let (i, _) = preceded(key_type, multiline_type)(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
Ok((i, v)) Ok((i, v))
}, },
))(i)?; ))(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = char('}')(i)?;
Ok((i, v.into())) Ok((i, v.into()))
} }
fn multipolygon(i: &str) -> IResult<&str, Geometry> { fn multipolygon(i: &str) -> IResult<&str, Geometry> {
let (i, _) = char('{')(i)?;
let (i, _) = mightbespace(i)?;
let (i, v) = alt(( let (i, v) = alt((
|i| { |i| {
let (i, _) = preceded(key_type, multipolygon_type)(i)?; let (i, _) = preceded(key_type, multipolygon_type)(i)?;
let (i, _) = commas(i)?; let (i, _) = commas(i)?;
let (i, v) = preceded(key_vals, multipolygon_vals)(i)?; let (i, v) = preceded(key_vals, multipolygon_vals)(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
Ok((i, v)) Ok((i, v))
}, },
|i| { |i| {
let (i, v) = preceded(key_vals, multipolygon_vals)(i)?; let (i, v) = preceded(key_vals, multipolygon_vals)(i)?;
let (i, _) = commas(i)?; let (i, _) = commas(i)?;
let (i, _) = preceded(key_type, multipolygon_type)(i)?; let (i, _) = preceded(key_type, multipolygon_type)(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
Ok((i, v)) Ok((i, v))
}, },
))(i)?; ))(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = char('}')(i)?;
Ok((i, v.into())) Ok((i, v.into()))
} }
fn collection(i: &str) -> IResult<&str, Geometry> { fn collection(i: &str) -> IResult<&str, Geometry> {
let (i, _) = char('{')(i)?;
let (i, _) = mightbespace(i)?;
let (i, v) = alt(( let (i, v) = alt((
|i| { |i| {
let (i, _) = preceded(key_type, collection_type)(i)?; let (i, _) = preceded(key_type, collection_type)(i)?;
let (i, _) = commas(i)?; let (i, _) = commas(i)?;
let (i, v) = preceded(key_geom, collection_vals)(i)?; let (i, v) = preceded(key_geom, collection_vals)(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
Ok((i, v)) Ok((i, v))
}, },
|i| { |i| {
let (i, v) = preceded(key_geom, collection_vals)(i)?; let (i, v) = preceded(key_geom, collection_vals)(i)?;
let (i, _) = commas(i)?; let (i, _) = commas(i)?;
let (i, _) = preceded(key_type, collection_type)(i)?; let (i, _) = preceded(key_type, collection_type)(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
Ok((i, v)) Ok((i, v))
}, },
))(i)?; ))(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = char('}')(i)?;
Ok((i, v.into())) Ok((i, v.into()))
} }

View file

@ -215,13 +215,7 @@ pub fn multi(i: &str) -> IResult<&str, Idiom> {
Ok((i, Idiom::from(v))) Ok((i, Idiom::from(v)))
}, },
|i| { |i| {
let (i, p) = first(i)?; let (i, p) = alt((first, value))(i)?;
let (i, mut v) = many1(part)(i)?;
v.insert(0, p);
Ok((i, Idiom::from(v)))
},
|i| {
let (i, p) = value(i)?;
let (i, mut v) = many1(part)(i)?; let (i, mut v) = many1(part)(i)?;
v.insert(0, p); v.insert(0, p);
Ok((i, Idiom::from(v))) Ok((i, Idiom::from(v)))