use phf::phf_map;
use reblessive::Stk;
use unicase::UniCase;
use super::{ParseResult, Parser};
use crate::sql::{Constant, Expr, Function, FunctionCall};
use crate::syn::error::MessageKind;
use crate::syn::parser::mac::expected;
use crate::syn::parser::{SyntaxError, unexpected};
use crate::syn::token::{Span, t};
pub enum PathKind {
Constant(Constant),
Function,
}
pub(crate) static PATHS: phf::Map<
UniCase<&'static str>,
(PathKind, Option<UniCase<&'static str>>),
> = phf_map! {
UniCase::ascii("api::invoke") => (PathKind::Function, None),
UniCase::ascii("api::timeout") => (PathKind::Function, None),
UniCase::ascii("api::req::body") => (PathKind::Function, None),
UniCase::ascii("api::res::body") => (PathKind::Function, None),
UniCase::ascii("api::res::status") => (PathKind::Function, None),
UniCase::ascii("api::res::header") => (PathKind::Function, None),
UniCase::ascii("api::res::headers") => (PathKind::Function, None),
UniCase::ascii("array::add") => (PathKind::Function, None),
UniCase::ascii("array::all") => (PathKind::Function, None),
UniCase::ascii("array::any") => (PathKind::Function, None),
UniCase::ascii("array::append") => (PathKind::Function, None),
UniCase::ascii("array::at") => (PathKind::Function, None),
UniCase::ascii("array::boolean_and") => (PathKind::Function, None),
UniCase::ascii("array::boolean_not") => (PathKind::Function, None),
UniCase::ascii("array::boolean_or") => (PathKind::Function, None),
UniCase::ascii("array::boolean_xor") => (PathKind::Function, None),
UniCase::ascii("array::clump") => (PathKind::Function, None),
UniCase::ascii("array::combine") => (PathKind::Function, None),
UniCase::ascii("array::complement") => (PathKind::Function, None),
UniCase::ascii("array::concat") => (PathKind::Function, None),
UniCase::ascii("array::difference") => (PathKind::Function, None),
UniCase::ascii("array::distinct") => (PathKind::Function, None),
UniCase::ascii("array::every") => (PathKind::Function, None),
UniCase::ascii("array::fill") => (PathKind::Function, None),
UniCase::ascii("array::filter") => (PathKind::Function, None),
UniCase::ascii("array::filter_index") => (PathKind::Function, None),
UniCase::ascii("array::find") => (PathKind::Function, None),
UniCase::ascii("array::find_index") => (PathKind::Function, None),
UniCase::ascii("array::first") => (PathKind::Function, None),
UniCase::ascii("array::fold") => (PathKind::Function, None),
UniCase::ascii("array::flatten") => (PathKind::Function, None),
UniCase::ascii("array::group") => (PathKind::Function, None),
UniCase::ascii("array::includes") => (PathKind::Function, None),
UniCase::ascii("array::index_of") => (PathKind::Function, None),
UniCase::ascii("array::insert") => (PathKind::Function, None),
UniCase::ascii("array::intersect") => (PathKind::Function, None),
UniCase::ascii("array::is_empty") => (PathKind::Function, None),
UniCase::ascii("array::join") => (PathKind::Function, None),
UniCase::ascii("array::last") => (PathKind::Function, None),
UniCase::ascii("array::len") => (PathKind::Function, None),
UniCase::ascii("array::logical_and") => (PathKind::Function, None),
UniCase::ascii("array::logical_or") => (PathKind::Function, None),
UniCase::ascii("array::logical_xor") => (PathKind::Function, None),
UniCase::ascii("array::map") => (PathKind::Function, None),
UniCase::ascii("array::matches") => (PathKind::Function, None),
UniCase::ascii("array::max") => (PathKind::Function, None),
UniCase::ascii("array::min") => (PathKind::Function, None),
UniCase::ascii("array::pop") => (PathKind::Function, None),
UniCase::ascii("array::prepend") => (PathKind::Function, None),
UniCase::ascii("array::push") => (PathKind::Function, None),
UniCase::ascii("array::range") => (PathKind::Function, None),
UniCase::ascii("array::reduce") => (PathKind::Function, None),
UniCase::ascii("array::remove") => (PathKind::Function, None),
UniCase::ascii("array::repeat") => (PathKind::Function, None),
UniCase::ascii("array::reverse") => (PathKind::Function, None),
UniCase::ascii("array::sequence") => (PathKind::Function, None),
UniCase::ascii("array::shuffle") => (PathKind::Function, None),
UniCase::ascii("array::slice") => (PathKind::Function, None),
UniCase::ascii("array::some") => (PathKind::Function, None),
UniCase::ascii("array::sort") => (PathKind::Function, None),
UniCase::ascii("array::sort_natural") => (PathKind::Function, None),
UniCase::ascii("array::sort_lexical") => (PathKind::Function, None),
UniCase::ascii("array::sort_natural_lexical") => (PathKind::Function, None),
UniCase::ascii("array::swap") => (PathKind::Function, None),
UniCase::ascii("array::transpose") => (PathKind::Function, None),
UniCase::ascii("array::union") => (PathKind::Function, None),
UniCase::ascii("array::windows") => (PathKind::Function, None),
UniCase::ascii("array::sort::asc") => (PathKind::Function, None),
UniCase::ascii("array::sort::desc") => (PathKind::Function, None),
UniCase::ascii("bytes::len") => (PathKind::Function, None),
UniCase::ascii("count") => (PathKind::Function, None),
UniCase::ascii("crypto::blake3") => (PathKind::Function, None),
UniCase::ascii("crypto::joaat") => (PathKind::Function, None),
UniCase::ascii("crypto::md5") => (PathKind::Function, None),
UniCase::ascii("crypto::sha1") => (PathKind::Function, None),
UniCase::ascii("crypto::sha256") => (PathKind::Function, None),
UniCase::ascii("crypto::sha512") => (PathKind::Function, None),
UniCase::ascii("crypto::argon2::compare") => (PathKind::Function, None),
UniCase::ascii("crypto::argon2::generate") => (PathKind::Function, None),
UniCase::ascii("crypto::bcrypt::compare") => (PathKind::Function, None),
UniCase::ascii("crypto::bcrypt::generate") => (PathKind::Function, None),
UniCase::ascii("crypto::pbkdf2::compare") => (PathKind::Function, None),
UniCase::ascii("crypto::pbkdf2::generate") => (PathKind::Function, None),
UniCase::ascii("crypto::scrypt::compare") => (PathKind::Function, None),
UniCase::ascii("crypto::scrypt::generate") => (PathKind::Function, None),
UniCase::ascii("duration::days") => (PathKind::Function, None),
UniCase::ascii("duration::hours") => (PathKind::Function, None),
UniCase::ascii("duration::micros") => (PathKind::Function, None),
UniCase::ascii("duration::millis") => (PathKind::Function, None),
UniCase::ascii("duration::mins") => (PathKind::Function, None),
UniCase::ascii("duration::nanos") => (PathKind::Function, None),
UniCase::ascii("duration::secs") => (PathKind::Function, None),
UniCase::ascii("duration::weeks") => (PathKind::Function, None),
UniCase::ascii("duration::years") => (PathKind::Function, None),
UniCase::ascii("duration::from_days") => (PathKind::Function, Some(UniCase::ascii("duration::from::days"))),
UniCase::ascii("duration::from_hours") => (PathKind::Function, Some(UniCase::ascii("duration::from::hours"))),
UniCase::ascii("duration::from_micros") => (PathKind::Function, Some(UniCase::ascii("duration::from::micros"))),
UniCase::ascii("duration::from_millis") => (PathKind::Function, Some(UniCase::ascii("duration::from::millis"))),
UniCase::ascii("duration::from_mins") => (PathKind::Function, Some(UniCase::ascii("duration::from::mins"))),
UniCase::ascii("duration::from_nanos") => (PathKind::Function, Some(UniCase::ascii("duration::from::nanos"))),
UniCase::ascii("duration::from_secs") => (PathKind::Function, Some(UniCase::ascii("duration::from::secs"))),
UniCase::ascii("duration::from_weeks") => (PathKind::Function, Some(UniCase::ascii("duration::from::weeks"))),
UniCase::ascii("duration::set_year") => (PathKind::Function, None),
UniCase::ascii("duration::set_month") => (PathKind::Function, None),
UniCase::ascii("duration::set_day") => (PathKind::Function, None),
UniCase::ascii("duration::set_hour") => (PathKind::Function, None),
UniCase::ascii("duration::set_minute") => (PathKind::Function, None),
UniCase::ascii("duration::set_second") => (PathKind::Function, None),
UniCase::ascii("duration::set_nanosecond") => (PathKind::Function, None),
UniCase::ascii("encoding::base64::decode") => (PathKind::Function, None),
UniCase::ascii("encoding::base64::encode") => (PathKind::Function, None),
UniCase::ascii("encoding::cbor::decode") => (PathKind::Function, None),
UniCase::ascii("encoding::cbor::encode") => (PathKind::Function, None),
UniCase::ascii("encoding::json::decode") => (PathKind::Function, None),
UniCase::ascii("encoding::json::encode") => (PathKind::Function, None),
UniCase::ascii("eval::gql") => (PathKind::Function, None),
UniCase::ascii("eval::surql") => (PathKind::Function, None),
UniCase::ascii("file::bucket") => (PathKind::Function, None),
UniCase::ascii("file::key") => (PathKind::Function, None),
UniCase::ascii("file::put") => (PathKind::Function, None),
UniCase::ascii("file::put_if_not_exists") => (PathKind::Function, None),
UniCase::ascii("file::get") => (PathKind::Function, None),
UniCase::ascii("file::head") => (PathKind::Function, None),
UniCase::ascii("file::delete") => (PathKind::Function, None),
UniCase::ascii("file::copy") => (PathKind::Function, None),
UniCase::ascii("file::copy_if_not_exists") => (PathKind::Function, None),
UniCase::ascii("file::rename") => (PathKind::Function, None),
UniCase::ascii("file::rename_if_not_exists") => (PathKind::Function, None),
UniCase::ascii("file::exists") => (PathKind::Function, None),
UniCase::ascii("file::list") => (PathKind::Function, None),
UniCase::ascii("geo::area") => (PathKind::Function, None),
UniCase::ascii("geo::bearing") => (PathKind::Function, None),
UniCase::ascii("geo::centroid") => (PathKind::Function, None),
UniCase::ascii("geo::distance") => (PathKind::Function, None),
UniCase::ascii("geo::hash::decode") => (PathKind::Function, None),
UniCase::ascii("geo::hash::encode") => (PathKind::Function, None),
UniCase::ascii("geo::is_valid") => (PathKind::Function, None),
UniCase::ascii("http::head") => (PathKind::Function, None),
UniCase::ascii("http::get") => (PathKind::Function, None),
UniCase::ascii("http::put") => (PathKind::Function, None),
UniCase::ascii("http::post") => (PathKind::Function, None),
UniCase::ascii("http::patch") => (PathKind::Function, None),
UniCase::ascii("http::delete") => (PathKind::Function, None),
UniCase::ascii("math::abs") => (PathKind::Function, None),
UniCase::ascii("math::acos") => (PathKind::Function, None),
UniCase::ascii("math::acot") => (PathKind::Function, None),
UniCase::ascii("math::asin") => (PathKind::Function, None),
UniCase::ascii("math::atan") => (PathKind::Function, None),
UniCase::ascii("math::bottom") => (PathKind::Function, None),
UniCase::ascii("math::ceil") => (PathKind::Function, None),
UniCase::ascii("math::clamp") => (PathKind::Function, None),
UniCase::ascii("math::cos") => (PathKind::Function, None),
UniCase::ascii("math::cot") => (PathKind::Function, None),
UniCase::ascii("math::deg2rad") => (PathKind::Function, None),
UniCase::ascii("math::fixed") => (PathKind::Function, None),
UniCase::ascii("math::floor") => (PathKind::Function, None),
UniCase::ascii("math::interquartile") => (PathKind::Function, None),
UniCase::ascii("math::lerp") => (PathKind::Function, None),
UniCase::ascii("math::lerpangle") => (PathKind::Function, None),
UniCase::ascii("math::ln") => (PathKind::Function, None),
UniCase::ascii("math::log") => (PathKind::Function, None),
UniCase::ascii("math::log10") => (PathKind::Function, None),
UniCase::ascii("math::log2") => (PathKind::Function, None),
UniCase::ascii("math::max") => (PathKind::Function, None),
UniCase::ascii("math::mean") => (PathKind::Function, None),
UniCase::ascii("math::median") => (PathKind::Function, None),
UniCase::ascii("math::midhinge") => (PathKind::Function, None),
UniCase::ascii("math::min") => (PathKind::Function, None),
UniCase::ascii("math::mode") => (PathKind::Function, None),
UniCase::ascii("math::nearestrank") => (PathKind::Function, None),
UniCase::ascii("math::percentile") => (PathKind::Function, None),
UniCase::ascii("math::pow") => (PathKind::Function, None),
UniCase::ascii("math::product") => (PathKind::Function, None),
UniCase::ascii("math::rad2deg") => (PathKind::Function, None),
UniCase::ascii("math::round") => (PathKind::Function, None),
UniCase::ascii("math::sign") => (PathKind::Function, None),
UniCase::ascii("math::sin") => (PathKind::Function, None),
UniCase::ascii("math::spread") => (PathKind::Function, None),
UniCase::ascii("math::sqrt") => (PathKind::Function, None),
UniCase::ascii("math::stddev") => (PathKind::Function, None),
UniCase::ascii("math::sum") => (PathKind::Function, None),
UniCase::ascii("math::tan") => (PathKind::Function, None),
UniCase::ascii("math::top") => (PathKind::Function, None),
UniCase::ascii("math::trimean") => (PathKind::Function, None),
UniCase::ascii("math::variance") => (PathKind::Function, None),
UniCase::ascii("meta::id") => (PathKind::Function, None),
UniCase::ascii("meta::tb") => (PathKind::Function, None),
UniCase::ascii("not") => (PathKind::Function, None),
UniCase::ascii("object::entries") => (PathKind::Function, None),
UniCase::ascii("object::extend") => (PathKind::Function, None),
UniCase::ascii("object::from_entries") => (PathKind::Function, None),
UniCase::ascii("object::is_empty") => (PathKind::Function, None),
UniCase::ascii("object::keys") => (PathKind::Function, None),
UniCase::ascii("object::len") => (PathKind::Function, None),
UniCase::ascii("object::matches") => (PathKind::Function, None),
UniCase::ascii("object::remove") => (PathKind::Function, None),
UniCase::ascii("object::values") => (PathKind::Function, None),
UniCase::ascii("parse::email::host") => (PathKind::Function, None),
UniCase::ascii("parse::email::user") => (PathKind::Function, None),
UniCase::ascii("parse::url::domain") => (PathKind::Function, None),
UniCase::ascii("parse::url::fragment") => (PathKind::Function, None),
UniCase::ascii("parse::url::host") => (PathKind::Function, None),
UniCase::ascii("parse::url::path") => (PathKind::Function, None),
UniCase::ascii("parse::url::port") => (PathKind::Function, None),
UniCase::ascii("parse::url::query") => (PathKind::Function, None),
UniCase::ascii("parse::url::scheme") => (PathKind::Function, None),
UniCase::ascii("rand") => (PathKind::Function, None),
UniCase::ascii("rand::bool") => (PathKind::Function, None),
UniCase::ascii("rand::duration") => (PathKind::Function, None),
UniCase::ascii("rand::enum") => (PathKind::Function, None),
UniCase::ascii("rand::float") => (PathKind::Function, None),
UniCase::ascii("rand::id") => (PathKind::Function, Some(UniCase::ascii("rand::guid"))),
UniCase::ascii("rand::int") => (PathKind::Function, None),
UniCase::ascii("rand::string") => (PathKind::Function, None),
UniCase::ascii("rand::time") => (PathKind::Function, None),
UniCase::ascii("rand::ulid") => (PathKind::Function, None),
UniCase::ascii("rand::uuid::v4") => (PathKind::Function, None),
UniCase::ascii("rand::uuid::v7") => (PathKind::Function, None),
UniCase::ascii("rand::uuid") => (PathKind::Function, None),
UniCase::ascii("record::exists") => (PathKind::Function, None),
UniCase::ascii("record::id") => (PathKind::Function, None),
UniCase::ascii("record::is_edge") => (PathKind::Function, None),
UniCase::ascii("record::table") => (PathKind::Function, None),
UniCase::ascii("record::tb") => (PathKind::Function, None),
UniCase::ascii("search::analyze") => (PathKind::Function, None),
UniCase::ascii("search::linear") => (PathKind::Function, None),
UniCase::ascii("search::rrf") => (PathKind::Function, None),
UniCase::ascii("search::score") => (PathKind::Function, None),
UniCase::ascii("search::highlight") => (PathKind::Function, None),
UniCase::ascii("search::offsets") => (PathKind::Function, None),
UniCase::ascii("set::add") => (PathKind::Function, None),
UniCase::ascii("set::all") => (PathKind::Function, None),
UniCase::ascii("set::any") => (PathKind::Function, None),
UniCase::ascii("set::at") => (PathKind::Function, None),
UniCase::ascii("set::complement") => (PathKind::Function, None),
UniCase::ascii("set::contains") => (PathKind::Function, None),
UniCase::ascii("set::difference") => (PathKind::Function, None),
UniCase::ascii("set::filter") => (PathKind::Function, None),
UniCase::ascii("set::find") => (PathKind::Function, None),
UniCase::ascii("set::first") => (PathKind::Function, None),
UniCase::ascii("set::flatten") => (PathKind::Function, None),
UniCase::ascii("set::fold") => (PathKind::Function, None),
UniCase::ascii("set::intersect") => (PathKind::Function, None),
UniCase::ascii("set::is_empty") => (PathKind::Function, None),
UniCase::ascii("set::join") => (PathKind::Function, None),
UniCase::ascii("set::last") => (PathKind::Function, None),
UniCase::ascii("set::len") => (PathKind::Function, None),
UniCase::ascii("set::map") => (PathKind::Function, None),
UniCase::ascii("set::max") => (PathKind::Function, None),
UniCase::ascii("set::min") => (PathKind::Function, None),
UniCase::ascii("set::reduce") => (PathKind::Function, None),
UniCase::ascii("set::remove") => (PathKind::Function, None),
UniCase::ascii("set::slice") => (PathKind::Function, None),
UniCase::ascii("set::union") => (PathKind::Function, None),
UniCase::ascii("sequence::nextval") => (PathKind::Function, None),
UniCase::ascii("session::ac") => (PathKind::Function, None),
UniCase::ascii("session::db") => (PathKind::Function, None),
UniCase::ascii("session::id") => (PathKind::Function, None),
UniCase::ascii("session::ip") => (PathKind::Function, None),
UniCase::ascii("session::ns") => (PathKind::Function, None),
UniCase::ascii("session::origin") => (PathKind::Function, None),
UniCase::ascii("session::rd") => (PathKind::Function, None),
UniCase::ascii("session::token") => (PathKind::Function, None),
UniCase::ascii("sleep") => (PathKind::Function, None),
UniCase::ascii("string::capitalize") => (PathKind::Function, None),
UniCase::ascii("string::concat") => (PathKind::Function, None),
UniCase::ascii("string::contains") => (PathKind::Function, None),
UniCase::ascii("string::ends_with") => (PathKind::Function, None),
UniCase::ascii("string::join") => (PathKind::Function, None),
UniCase::ascii("string::len") => (PathKind::Function, None),
UniCase::ascii("string::lowercase") => (PathKind::Function, None),
UniCase::ascii("string::repeat") => (PathKind::Function, None),
UniCase::ascii("string::replace") => (PathKind::Function, None),
UniCase::ascii("string::reverse") => (PathKind::Function, None),
UniCase::ascii("string::slice") => (PathKind::Function, None),
UniCase::ascii("string::slug") => (PathKind::Function, None),
UniCase::ascii("string::split") => (PathKind::Function, None),
UniCase::ascii("string::starts_with") => (PathKind::Function, Some(UniCase::ascii("string::startsWith"))),
UniCase::ascii("string::trim") => (PathKind::Function, None),
UniCase::ascii("string::uppercase") => (PathKind::Function, None),
UniCase::ascii("string::words") => (PathKind::Function, None),
UniCase::ascii("string::distance::damerau_levenshtein") => (PathKind::Function, None),
UniCase::ascii("string::distance::hamming") => (PathKind::Function, None),
UniCase::ascii("string::distance::levenshtein") => (PathKind::Function, None),
UniCase::ascii("string::distance::normalized_damerau_levenshtein") => (PathKind::Function, None),
UniCase::ascii("string::distance::normalized_levenshtein") => (PathKind::Function, None),
UniCase::ascii("string::distance::osa") => (PathKind::Function, Some(UniCase::ascii("string::distance::osa_distance"))),
UniCase::ascii("string::html::encode") => (PathKind::Function, None),
UniCase::ascii("string::html::sanitize") => (PathKind::Function, None),
UniCase::ascii("string::is_alphanum") => (PathKind::Function, Some(UniCase::ascii("string::is::alphanum"))),
UniCase::ascii("string::is_alpha") => (PathKind::Function, Some(UniCase::ascii("string::is::alpha"))),
UniCase::ascii("string::is_ascii") => (PathKind::Function, Some(UniCase::ascii("string::is::ascii"))),
UniCase::ascii("string::is_datetime") => (PathKind::Function, Some(UniCase::ascii("string::is::datetime"))),
UniCase::ascii("string::is_domain") => (PathKind::Function, Some(UniCase::ascii("string::is::domain"))),
UniCase::ascii("string::is_email") => (PathKind::Function, Some(UniCase::ascii("string::is::email"))),
UniCase::ascii("string::is_hexadecimal") => (PathKind::Function, Some(UniCase::ascii("string::is::hexadecimal"))),
UniCase::ascii("string::is_ip") => (PathKind::Function, Some(UniCase::ascii("string::is::ip"))),
UniCase::ascii("string::is_ipv4") => (PathKind::Function, Some(UniCase::ascii("string::is::ipv4"))),
UniCase::ascii("string::is_ipv6") => (PathKind::Function, Some(UniCase::ascii("string::is::ipv6"))),
UniCase::ascii("string::is_latitude") => (PathKind::Function, Some(UniCase::ascii("string::is::latitude"))),
UniCase::ascii("string::is_longitude") => (PathKind::Function, Some(UniCase::ascii("string::is::longitude"))),
UniCase::ascii("string::is_numeric") => (PathKind::Function, Some(UniCase::ascii("string::is::numeric"))),
UniCase::ascii("string::is_semver") => (PathKind::Function, Some(UniCase::ascii("string::is::semver"))),
UniCase::ascii("string::is_url") => (PathKind::Function, Some(UniCase::ascii("string::is::url"))),
UniCase::ascii("string::is_ulid") => (PathKind::Function, Some(UniCase::ascii("string::is::ulid"))),
UniCase::ascii("string::is_uuid") => (PathKind::Function, Some(UniCase::ascii("string::is::uuid"))),
UniCase::ascii("string::is_record") => (PathKind::Function, Some(UniCase::ascii("string::is::record"))),
UniCase::ascii("string::semver::compare") => (PathKind::Function, None),
UniCase::ascii("string::semver::major") => (PathKind::Function, None),
UniCase::ascii("string::semver::minor") => (PathKind::Function, None),
UniCase::ascii("string::semver::patch") => (PathKind::Function, None),
UniCase::ascii("string::semver::inc::major") => (PathKind::Function, None),
UniCase::ascii("string::semver::inc::minor") => (PathKind::Function, None),
UniCase::ascii("string::semver::inc::patch") => (PathKind::Function, None),
UniCase::ascii("string::semver::set::major") => (PathKind::Function, None),
UniCase::ascii("string::semver::set::minor") => (PathKind::Function, None),
UniCase::ascii("string::semver::set::patch") => (PathKind::Function, None),
UniCase::ascii("string::similarity::fuzzy") => (PathKind::Function, None),
UniCase::ascii("string::similarity::jaro") => (PathKind::Function, None),
UniCase::ascii("string::similarity::jaro_winkler") => (PathKind::Function, None),
UniCase::ascii("string::similarity::smithwaterman") => (PathKind::Function, None),
UniCase::ascii("string::similarity::sorensen_dice") => (PathKind::Function, None),
UniCase::ascii("string::matches") => (PathKind::Function, None),
UniCase::ascii("time::ceil") => (PathKind::Function, None),
UniCase::ascii("time::day") => (PathKind::Function, None),
UniCase::ascii("time::floor") => (PathKind::Function, None),
UniCase::ascii("time::format") => (PathKind::Function, None),
UniCase::ascii("time::group") => (PathKind::Function, None),
UniCase::ascii("time::hour") => (PathKind::Function, None),
UniCase::ascii("time::max") => (PathKind::Function, None),
UniCase::ascii("time::micros") => (PathKind::Function, None),
UniCase::ascii("time::millis") => (PathKind::Function, None),
UniCase::ascii("time::min") => (PathKind::Function, None),
UniCase::ascii("time::minute") => (PathKind::Function, None),
UniCase::ascii("time::month") => (PathKind::Function, None),
UniCase::ascii("time::nano") => (PathKind::Function, None),
UniCase::ascii("time::now") => (PathKind::Function, None),
UniCase::ascii("time::round") => (PathKind::Function, None),
UniCase::ascii("time::second") => (PathKind::Function, None),
UniCase::ascii("time::timezone") => (PathKind::Function, None),
UniCase::ascii("time::unix") => (PathKind::Function, None),
UniCase::ascii("time::wday") => (PathKind::Function, None),
UniCase::ascii("time::week") => (PathKind::Function, None),
UniCase::ascii("time::yday") => (PathKind::Function, None),
UniCase::ascii("time::year") => (PathKind::Function, None),
UniCase::ascii("time::from_micros") => (PathKind::Function, Some(UniCase::ascii("time::from::micros"))),
UniCase::ascii("time::from_millis") => (PathKind::Function, Some(UniCase::ascii("time::from::millis"))),
UniCase::ascii("time::from_nanos") => (PathKind::Function, Some(UniCase::ascii("time::from::nanos"))),
UniCase::ascii("time::from_secs") => (PathKind::Function, Some(UniCase::ascii("time::from::secs"))),
UniCase::ascii("time::from_ulid") => (PathKind::Function, Some(UniCase::ascii("time::from::ulid"))),
UniCase::ascii("time::from_unix") => (PathKind::Function, Some(UniCase::ascii("time::from::unix"))),
UniCase::ascii("time::from_uuid") => (PathKind::Function, Some(UniCase::ascii("time::from::uuid"))),
UniCase::ascii("time::is_leap_year") => (PathKind::Function, Some(UniCase::ascii("time::is::leap_year"))),
UniCase::ascii("time::set_year") => (PathKind::Function, None),
UniCase::ascii("time::set_month") => (PathKind::Function, None),
UniCase::ascii("time::set_day") => (PathKind::Function, None),
UniCase::ascii("time::set_hour") => (PathKind::Function, None),
UniCase::ascii("time::set_minute") => (PathKind::Function, None),
UniCase::ascii("time::set_second") => (PathKind::Function, None),
UniCase::ascii("time::set_nanosecond") => (PathKind::Function, None),
UniCase::ascii("type::array") => (PathKind::Function, None),
UniCase::ascii("type::bool") => (PathKind::Function, None),
UniCase::ascii("type::bytes") => (PathKind::Function, None),
UniCase::ascii("type::datetime") => (PathKind::Function, None),
UniCase::ascii("type::decimal") => (PathKind::Function, None),
UniCase::ascii("type::duration") => (PathKind::Function, None),
UniCase::ascii("type::field") => (PathKind::Function, None),
UniCase::ascii("type::fields") => (PathKind::Function, None),
UniCase::ascii("type::file") => (PathKind::Function, None),
UniCase::ascii("type::float") => (PathKind::Function, None),
UniCase::ascii("type::geometry") => (PathKind::Function, None),
UniCase::ascii("type::int") => (PathKind::Function, None),
UniCase::ascii("type::number") => (PathKind::Function, None),
UniCase::ascii("type::of") => (PathKind::Function, None),
UniCase::ascii("type::point") => (PathKind::Function, None),
UniCase::ascii("type::range") => (PathKind::Function, None),
UniCase::ascii("type::record") => (PathKind::Function, Some(UniCase::ascii("type::thing"))),
UniCase::ascii("type::set") => (PathKind::Function, None),
UniCase::ascii("type::string") => (PathKind::Function, None),
UniCase::ascii("type::string_lossy") => (PathKind::Function, None),
UniCase::ascii("type::table") => (PathKind::Function, None),
UniCase::ascii("type::uuid") => (PathKind::Function, None),
UniCase::ascii("type::is_array") => (PathKind::Function, Some(UniCase::ascii("type::is::array"))),
UniCase::ascii("type::is_bool") => (PathKind::Function, Some(UniCase::ascii("type::is::bool"))),
UniCase::ascii("type::is_bytes") => (PathKind::Function, Some(UniCase::ascii("type::is::bytes"))),
UniCase::ascii("type::is_collection") => (PathKind::Function, Some(UniCase::ascii("type::is::collection"))),
UniCase::ascii("type::is_datetime") => (PathKind::Function, Some(UniCase::ascii("type::is::datetime"))),
UniCase::ascii("type::is_decimal") => (PathKind::Function, Some(UniCase::ascii("type::is::decimal"))),
UniCase::ascii("type::is_duration") => (PathKind::Function, Some(UniCase::ascii("type::is::duration"))),
UniCase::ascii("type::is_float") => (PathKind::Function, Some(UniCase::ascii("type::is::float"))),
UniCase::ascii("type::is_geometry") => (PathKind::Function, Some(UniCase::ascii("type::is::geometry"))),
UniCase::ascii("type::is_int") => (PathKind::Function, Some(UniCase::ascii("type::is::int"))),
UniCase::ascii("type::is_line") => (PathKind::Function, Some(UniCase::ascii("type::is::line"))),
UniCase::ascii("type::is_multiline") => (PathKind::Function, Some(UniCase::ascii("type::is::multiline"))),
UniCase::ascii("type::is_multipoint") => (PathKind::Function, Some(UniCase::ascii("type::is::multipoint"))),
UniCase::ascii("type::is_multipolygon") => (PathKind::Function, Some(UniCase::ascii("type::is::multipolygon"))),
UniCase::ascii("type::is_none") => (PathKind::Function, Some(UniCase::ascii("type::is::none"))),
UniCase::ascii("type::is_null") => (PathKind::Function, Some(UniCase::ascii("type::is::null"))),
UniCase::ascii("type::is_number") => (PathKind::Function, Some(UniCase::ascii("type::is::number"))),
UniCase::ascii("type::is_object") => (PathKind::Function, Some(UniCase::ascii("type::is::object"))),
UniCase::ascii("type::is_point") => (PathKind::Function, Some(UniCase::ascii("type::is::point"))),
UniCase::ascii("type::is_polygon") => (PathKind::Function, Some(UniCase::ascii("type::is::polygon"))),
UniCase::ascii("type::is_range") => (PathKind::Function, Some(UniCase::ascii("type::is::range"))),
UniCase::ascii("type::is_record") => (PathKind::Function, Some(UniCase::ascii("type::is::record"))),
UniCase::ascii("type::is_set") => (PathKind::Function, None),
UniCase::ascii("type::is_string") => (PathKind::Function, Some(UniCase::ascii("type::is::string"))),
UniCase::ascii("type::is_uuid") => (PathKind::Function, Some(UniCase::ascii("type::is::uuid"))),
UniCase::ascii("value::diff") => (PathKind::Function, None),
UniCase::ascii("value::patch") => (PathKind::Function, None),
UniCase::ascii("value::chain") => (PathKind::Function, None),
UniCase::ascii("value::expect") => (PathKind::Function, None),
UniCase::ascii("vector::add") => (PathKind::Function, None),
UniCase::ascii("vector::angle") => (PathKind::Function, None),
UniCase::ascii("vector::cross") => (PathKind::Function, None),
UniCase::ascii("vector::divide") => (PathKind::Function, None),
UniCase::ascii("vector::dot") => (PathKind::Function, None),
UniCase::ascii("vector::magnitude") => (PathKind::Function, None),
UniCase::ascii("vector::multiply") => (PathKind::Function, None),
UniCase::ascii("vector::normalize") => (PathKind::Function, None),
UniCase::ascii("vector::project") => (PathKind::Function, None),
UniCase::ascii("vector::scale") => (PathKind::Function, None),
UniCase::ascii("vector::subtract") => (PathKind::Function, None),
UniCase::ascii("vector::distance::chebyshev") => (PathKind::Function, None),
UniCase::ascii("vector::distance::euclidean") => (PathKind::Function, None),
UniCase::ascii("vector::distance::hamming") => (PathKind::Function, None),
UniCase::ascii("vector::distance::knn") => (PathKind::Function, None),
UniCase::ascii("vector::distance::mahalanobis") => (PathKind::Function, None),
UniCase::ascii("vector::distance::manhattan") => (PathKind::Function, None),
UniCase::ascii("vector::distance::minkowski") => (PathKind::Function, None),
UniCase::ascii("vector::similarity::cosine") => (PathKind::Function, None),
UniCase::ascii("vector::similarity::jaccard") => (PathKind::Function, None),
UniCase::ascii("vector::similarity::pearson") => (PathKind::Function, None),
UniCase::ascii("vector::similarity::spearman") => (PathKind::Function, None),
UniCase::ascii("math::E") => (PathKind::Constant(Constant::MathE), None),
UniCase::ascii("math::FRAC_1_PI") => (PathKind::Constant(Constant::MathFrac1Pi), None),
UniCase::ascii("math::FRAC_1_SQRT_2") => (PathKind::Constant(Constant::MathFrac1Sqrt2), None),
UniCase::ascii("math::FRAC_2_PI") => (PathKind::Constant(Constant::MathFrac2Pi), None),
UniCase::ascii("math::FRAC_2_SQRT_PI") => (PathKind::Constant(Constant::MathFrac2SqrtPi), None),
UniCase::ascii("math::FRAC_PI_2") => (PathKind::Constant(Constant::MathFracPi2), None),
UniCase::ascii("math::FRAC_PI_3") => (PathKind::Constant(Constant::MathFracPi3), None),
UniCase::ascii("math::FRAC_PI_4") => (PathKind::Constant(Constant::MathFracPi4), None),
UniCase::ascii("math::FRAC_PI_6") => (PathKind::Constant(Constant::MathFracPi6), None),
UniCase::ascii("math::FRAC_PI_8") => (PathKind::Constant(Constant::MathFracPi8), None),
UniCase::ascii("math::INF") => (PathKind::Constant(Constant::MathInfinity), None),
UniCase::ascii("math::INFINITY") => (PathKind::Constant(Constant::MathInfinity), None),
UniCase::ascii("math::LN_10") => (PathKind::Constant(Constant::MathLn10), None),
UniCase::ascii("math::LN_2") => (PathKind::Constant(Constant::MathLn2), None),
UniCase::ascii("math::LOG10_2") => (PathKind::Constant(Constant::MathLog102), None),
UniCase::ascii("math::LOG10_E") => (PathKind::Constant(Constant::MathLog10E), None),
UniCase::ascii("math::LOG2_10") => (PathKind::Constant(Constant::MathLog210), None),
UniCase::ascii("math::LOG2_E") => (PathKind::Constant(Constant::MathLog2E), None),
UniCase::ascii("math::NEG_INF") => (PathKind::Constant(Constant::MathNegInfinity), None),
UniCase::ascii("math::NEG_INFINITY") => (PathKind::Constant(Constant::MathNegInfinity), None),
UniCase::ascii("math::PI") => (PathKind::Constant(Constant::MathPi), None),
UniCase::ascii("math::SQRT_2") => (PathKind::Constant(Constant::MathSqrt2), None),
UniCase::ascii("math::TAU") => (PathKind::Constant(Constant::MathTau), None),
UniCase::ascii("time::EPOCH") => (PathKind::Constant(Constant::TimeEpoch), None),
UniCase::ascii("time::MINIMUM") => (PathKind::Constant(Constant::TimeMin), None),
UniCase::ascii("time::MAXIMUM") => (PathKind::Constant(Constant::TimeMax), None),
UniCase::ascii("duration::MAX") => (PathKind::Constant(Constant::DurationMax), None),
UniCase::ascii("schema::table::exists") => (PathKind::Function, None),
};
const MAX_LEVENSTHEIN_CUT_OFF: u8 = 4;
const MAX_FUNCTION_NAME_LEN: usize = 48;
const LEVENSTHEIN_ARRAY_SIZE: usize = 1 + MAX_FUNCTION_NAME_LEN + MAX_LEVENSTHEIN_CUT_OFF as usize;
fn levenshtein(a: &[u8], b: &[u8], cut_off: u8) -> u8 {
debug_assert!(LEVENSTHEIN_ARRAY_SIZE < u8::MAX as usize);
let mut distance_array = [[0u8; LEVENSTHEIN_ARRAY_SIZE]; 2];
if a.len().abs_diff(b.len()) > cut_off as usize {
return cut_off + 1;
}
assert!(a.len() < LEVENSTHEIN_ARRAY_SIZE);
assert!(b.len() < LEVENSTHEIN_ARRAY_SIZE);
for (i, item) in distance_array[0].iter_mut().enumerate().take(a.len() + 1).skip(1) {
*item = i as u8;
}
for i in 1..=b.len() {
let current = i & 1;
let prev = current ^ 1;
distance_array[current][0] = i as u8;
let mut lowest = i as u8;
for j in 1..=a.len() {
let cost = (a.get(j - 1).map(|x| x.to_ascii_lowercase())
!= b.get(i - 1).map(|x| x.to_ascii_lowercase())) as u8;
let res = (distance_array[prev][j] + 1)
.min(distance_array[current][j - 1] + 1)
.min(distance_array[prev][j - 1] + cost);
distance_array[current][j] = res;
lowest = res.min(lowest)
}
if lowest > cut_off {
return cut_off + 1;
}
}
distance_array[b.len() & 1][a.len()]
}
fn find_suggestion(got: &str) -> Option<&'static str> {
if let Some(surely) = PATHS.into_iter().find_map(|(path, (_, old_path))| match old_path {
Some(s) if s.into_inner() == got => Some(path),
_ => None,
}) {
return Some(surely.into_inner());
}
let mut cut_off = MAX_LEVENSTHEIN_CUT_OFF;
let possibly = PATHS
.keys()
.copied()
.min_by_key(|x| {
let res = levenshtein(got.as_bytes(), x.as_bytes(), cut_off);
cut_off = res.min(cut_off);
res
})
.map(|x| x.into_inner());
if cut_off >= MAX_LEVENSTHEIN_CUT_OFF {
return None;
}
possibly
}
impl Parser<'_> {
pub(super) async fn parse_builtin(&mut self, stk: &mut Stk, start: Span) -> ParseResult<Expr> {
let s = self.unescape_ident_span(start)?;
let mut buffer = s.to_lowercase();
let mut last_span = start;
while self.eat(t!("::")) {
let peek = self.peek();
if !Self::kind_is_identifier(peek.kind) {
unexpected!(self, peek, "an identifier")
}
self.pop_peek();
buffer.push_str("::");
let s = self.unescape_ident_span(peek.span)?;
buffer.reserve(s.len());
for c in s.chars() {
for l in c.to_lowercase() {
buffer.push(l);
}
}
last_span = peek.span;
}
match PATHS.get_entry(&UniCase::ascii(&buffer)) {
Some((_, (PathKind::Constant(x), _))) => Ok(Expr::Constant(x.clone())),
Some((_, (PathKind::Function, _))) => stk
.run(|ctx| self.parse_builtin_function(ctx, buffer))
.await
.map(|x| Expr::FunctionCall(Box::new(x))),
None => {
if let Some(suggest) = find_suggestion(&buffer) {
Err(SyntaxError::new(format_args!(
"Invalid function/constant path, did you maybe mean `{suggest}`"
))
.with_span(start.covers(last_span), MessageKind::Error))
} else {
Err(SyntaxError::new("Invalid function/constant path")
.with_span(start.covers(last_span), MessageKind::Error))
}
}
}
}
pub(super) async fn parse_builtin_function(
&mut self,
stk: &mut Stk,
name: String,
) -> ParseResult<FunctionCall> {
let start = expected!(self, t!("(")).span;
let mut args = Vec::new();
loop {
if self.eat(t!(")")) {
break;
}
let arg = stk.run(|ctx| self.parse_expr_inherit(ctx)).await?;
args.push(arg);
if !self.eat(t!(",")) {
self.expect_closing_delimiter(t!(")"), start)?;
break;
}
}
let receiver = Function::Normal(name);
Ok(FunctionCall {
receiver,
arguments: args,
})
}
}
#[cfg(test)]
mod test {
use super::{MAX_FUNCTION_NAME_LEN, PATHS};
#[test]
fn function_name_constant_up_to_date() {
let max = PATHS.keys().map(|x| x.len()).max().unwrap();
assert_eq!(
MAX_FUNCTION_NAME_LEN, max,
"the constant MAX_FUNCTION_NAME_LEN should be {} but is {}, please update the constant",
max, MAX_FUNCTION_NAME_LEN
);
}
#[test]
fn function_suggestion() {
assert_eq!(super::levenshtein(b" book", b" ook", 5), 1);
assert_eq!(super::find_suggestion("string::start_with"), Some("string::starts_with"));
}
}