Rust Parser v1

This commit is contained in:
2019-05-23 16:01:12 +02:00
parent 32b35602fb
commit a14f145856
8 changed files with 2379 additions and 0 deletions

816
Cargo.lock generated Normal file
View File

@@ -0,0 +1,816 @@
[[package]]
name = "aho-corasick"
version = "0.6.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "aho-corasick"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "argon2rs"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
"scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "arrayvec"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ascii-canvas"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "atty"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
"termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "autocfg"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "backtrace"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "backtrace-sys"
version = "0.1.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bit-set"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bit-vec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bit-vec"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bitflags"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "blake2-rfc"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
"constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "block-buffer"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "block-padding"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "byte-tools"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "byteorder"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cc"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cfg-if"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cloudabi"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "constant_time_eq"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "diff"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "digest"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "dirs"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "docopt"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)",
"strsim 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "either"
version = "1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ena"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "failure"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"backtrace 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
"failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "failure_derive"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)",
"synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fake-simd"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "fixedbitset"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "generic-array"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "itertools"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "lalrpop"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ascii-canvas 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"bit-set 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"docopt 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lalrpop-util 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
"petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)",
"sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
"term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "lalrpop-util"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "lazy_static"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "log"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "memchr"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "new_debug_unreachable"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "nodrop"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "numtoa"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "opaque-debug"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ordermap"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "parser"
version = "0.1.0"
dependencies = [
"lalrpop 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lalrpop-util 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "petgraph"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "phf_generator"
version = "0.7.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "phf_shared"
version = "0.7.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "precomputed-hash"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "proc-macro2"
version = "0.4.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quote"
version = "0.6.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_chacha"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_core"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rand_hc"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_isaac"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_jitter"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_os"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_pcg"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_xorshift"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rdrand"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "redox_syscall"
version = "0.1.54"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "redox_termios"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "redox_users"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex"
version = "1.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex-syntax"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex-syntax"
version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-demangle"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "scoped_threadpool"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde"
version = "1.0.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_derive"
version = "1.0.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "sha2"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
"digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "siphasher"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "string_cache"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"new_debug_unreachable 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
"precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "string_cache_codegen"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
"phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "string_cache_shared"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "strsim"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "syn"
version = "0.15.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "synstructure"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "term"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "termion"
version = "1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
"numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "thread_local"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "typenum"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ucd-util"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicode-xid"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "utf8-ranges"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5"
"checksum aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e6f484ae0c99fec2e858eb6134949117399f222608d84cadb3f58c1f97c2364c"
"checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392"
"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71"
"checksum ascii-canvas 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff8eb72df928aafb99fe5d37b383f2fe25bd2a765e3e5f7c365916b6f2463a29"
"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799"
"checksum backtrace 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "70af6de4789ac39587f100176ac7f704531e9e534b0f8676f658b3d909ce9a94"
"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6"
"checksum bit-set 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e84c238982c4b1e1ee668d136c510c67a13465279c0cb367ea6baf6310620a80"
"checksum bit-vec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f59bbe95d4e52a6398ec21238d31577f2b28a9d86807f06ca59d191d8440d0bb"
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400"
"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
"checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09"
"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb"
"checksum cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "39f75544d7bbaf57560d2168f28fd649ff9c76153874db88bdbdfd839b1a7e7d"
"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33"
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
"checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a"
"checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c"
"checksum dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901"
"checksum docopt 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f525a586d310c87df72ebcd98009e57f1cc030c8c268305287a476beb653969"
"checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b"
"checksum ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dc01d68e08ca384955a3aeba9217102ca1aa85b6e168639bf27739f1d749d87"
"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2"
"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
"checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33"
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
"checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592"
"checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358"
"checksum lalrpop 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b7f2d14eb07d819e961e5169f61d67de76a7cdbc6778b62192bcfe27c5af019"
"checksum lalrpop-util 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9768f55211206d3c17181108d8facb80bdffc1f1e674a67b1dddb2743529ca19"
"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
"checksum libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)" = "42914d39aad277d9e176efbdad68acb1d5443ab65afe0e0e4f0d49352a950880"
"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39"
"checksum new_debug_unreachable 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f40f005c60db6e03bae699e414c58bf9aa7ea02a2d0b9bfbcf19286cc4c82b30"
"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
"checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
"checksum opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "93f5bb2e8e8dec81642920ccff6b61f1eb94fa3020c5a325c9851ff604152409"
"checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063"
"checksum petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3659d1ee90221741f65dd128d9998311b0e40c5d3c23a62445938214abce4f"
"checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662"
"checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0"
"checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
"checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db"
"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0"
"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
"checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
"checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252"
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
"checksum redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe5204c3a17e97dde73f285d49be585df59ed84b50a872baf416e73b62c3828"
"checksum regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384"
"checksum regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f0a0bcab2fd7d1d7c54fa9eae6f43eddeb9ce2e7352f8518a814a4f65d60c58"
"checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7"
"checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96"
"checksum rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ccc78bfd5acd7bf3e89cffcf899e5cb1a52d6fafa8dec2739ad70c9577a57288"
"checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
"checksum serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)" = "a72e9b96fa45ce22a4bc23da3858dfccfd60acd28a25bcd328a98fdd6bea43fd"
"checksum serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)" = "101b495b109a3e3ca8c4cbe44cf62391527cdfb6ba15821c5ce80bcd5ea23f9f"
"checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d"
"checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac"
"checksum string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423"
"checksum string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eea1eee654ef80933142157fdad9dd8bc43cf7c74e999e369263496f04ff4da"
"checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc"
"checksum strsim 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "032c03039aae92b350aad2e3779c352e104d919cb192ba2fabbd7b831ce4f0f6"
"checksum syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)" = "a1393e4a97a19c01e900df2aec855a29f71cf02c402e2f443b8d2747c25c5dbe"
"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f"
"checksum term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "edd106a334b7657c10b7c540a0106114feadeb4dc314513e97df481d5d966f42"
"checksum termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dde0593aeb8d47accea5392b39350015b5eccb12c0d98044d856983d89548dea"
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"
"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

22
Cargo.toml Normal file
View File

@@ -0,0 +1,22 @@
[package]
name = "parser"
version = "0.1.0"
authors = ["Lionel Sambuc <lionel.sambuc@gmail.com>"]
edition = "2018"
build = "build.rs" # LALRPOP preprocessing
[lib]
name = "parser"
path = "src/lib.rs"
[[bin]]
name = "parser-driver"
path = "src/main.rs"
[dependencies]
lalrpop-util = "0.17.0"
regex = "0.2.1"
[build-dependencies]
lalrpop = "0.17.0"

5
build.rs Normal file
View File

@@ -0,0 +1,5 @@
extern crate lalrpop;
fn main() {
lalrpop::process_root().unwrap();
}

113
src/ast.rs Normal file
View File

@@ -0,0 +1,113 @@
trait Expression {
fn check_type();
fn predict();
fn execute();
}
/**********************************************************************/
/* FORMATTING DATA */
/**********************************************************************/
#[derive(Clone, Debug)]
pub enum Projection {
Nifti(LiteralSelector, Bag),
JSON(JsonValue, Bag),
}
// JSON FORMAT
#[derive(Clone, Debug)]
pub enum JsonValue {
String(String),
JsonNumber(LiteralNumber),
Bool(bool),
Null,
Object(Vec<(String, JsonValue)>),
Array(Vec<JsonValue>),
Selector(LiteralSelector),
Aggregation(Aggregation),
}
#[derive(Clone, Debug)]
pub enum Aggregation {
Count(bool, LiteralSelector),
Sum(LiteralSelector),
Min(LiteralSelector),
Max(LiteralSelector),
}
// NIFTI
#[derive(Clone, Debug)]
struct Transform {
reference: String,
offset: Vec<LiteralNumber>,
rotation: Vec<Vec<LiteralNumber>>,
}
/**********************************************************************/
/* SELECTING / FILTERING DATA */
/**********************************************************************/
#[derive(Clone, Debug)]
pub enum Bag {
Distinct(Box<Bag>),
Filter(Option<Predicate>, Option<Box<Bag>>),
Complement(Box<Bag>),
Intersection(Box<Bag>, Box<Bag>),
Union(Box<Bag>, Box<Bag>),
Bag(Vec<Bag>),
Inside(Shape),
Outside(Shape),
}
/**********************************************************************/
/* BAG OPERATORS */
/**********************************************************************/
#[derive(Clone, Debug)]
pub enum Predicate {
Less(Position, LiteralPosition),
Greater(Position, LiteralPosition),
Equal(Position, LiteralPosition),
Not(Box<Predicate>),
And(Box<Predicate>, Box<Predicate>),
Or(Box<Predicate>, Box<Predicate>),
}
/**********************************************************************/
/* SPATIAL OPERATORS */
/**********************************************************************/
/**********************************************************************/
/* SHAPES */
/**********************************************************************/
#[derive(Clone, Debug)]
pub enum Shape {
Point(LiteralPosition),
HyperRectangle(Vec<LiteralPosition>),
HyperSphere(LiteralPosition, LiteralNumber),
Nifti(),
}
/**********************************************************************/
/* POSITIONS */
/**********************************************************************/
#[derive(Clone, Debug)]
pub enum Position {
StrCmpICase(LiteralSelector, String),
StrCmp(LiteralSelector, String),
Selector(LiteralSelector),
LiteralPosition(LiteralPosition),
}
/**********************************************************************/
/* Literals / TOKENS */
/**********************************************************************/
#[derive(Clone, Debug)]
pub struct Field(pub String, pub Option<usize>);
#[derive(Clone, Debug)]
pub enum LiteralNumber {
Int(i64),
Float(f64),
}
pub type LiteralPosition = Vec<LiteralNumber>;
pub type LiteralSelector = Vec<Field>;

10
src/lib.rs Normal file
View File

@@ -0,0 +1,10 @@
#[macro_use]
extern crate lalrpop_util;
lalrpop_mod!(pub queries); // synthesized by LALRPOP
pub mod ast;
pub use ast::*;
#[cfg(test)]
mod tests;

28
src/main.rs Normal file
View File

@@ -0,0 +1,28 @@
extern crate parser;
use parser::queries;
use std::io;
fn main() {
//let parser = queries::FiltersParser::new();
let parser = queries::QueryParser::new();
loop {
println!("\n> Expression to parse (type `quit` to exit): ");
let mut input = String::new();
match io::stdin().read_line(&mut input) {
Ok(0) => break, // Catch ^D
Ok(1) => continue, // Catch \n
Err(_) => continue,
Ok(_) => (),
}
if input.trim().eq_ignore_ascii_case("quit") {
break;
}
println!("\n> Tree: \n{:?}", parser.parse(input.as_str()));
}
}

441
src/queries.lalrpop Normal file
View File

@@ -0,0 +1,441 @@
use std::str::FromStr;
use crate::ast;
use crate::ast::*;
grammar;
//*********************************************************************/
// FORMATTING DATA */
//*********************************************************************/
pub Query = { Projections? };
Projections: ast::Projection = {
NiftiOperator,
JsonOperator
};
// If selector is not provided, one (1) will be used as the values for
// each position where there is a point in bag_expression.
//
// If it is provided, it MUST resolve to a NUMBER.
NiftiOperator: ast::Projection = {
"nifti" "(" <s:( Selector "," )?> <b:Bags> ")" =>
if let Some((sel, _)) = s {
Projection::Nifti(sel, b)
} else {
Projection::Nifti(Vec::new(), b)
}
};
JsonOperator: ast::Projection = {
"json" "(" <f:JsonValues> "," <b:Bags> ")" =>
Projection::JSON(f, b)
};
//*********************************************************************/
// JSON */
//*********************************************************************/
// Taken and adapted from:
// https://github.com/antlr/grammars-v4/blob/master/json/JSON.g4
//
// Some of the parser / lexer rules are in the imported grammar as well.
JsonValues: ast::JsonValue = {
String => JsonValue::String(<>),
JsonNumber => <>,
JsonObj => <>,
JsonArray => <>,
"true" => JsonValue::Bool(true),
"false" => JsonValue::Bool(false),
"null" => JsonValue::Null,
// Support reference to values from the selected bag.
Selector => JsonValue::Selector(<>),
Aggregations => JsonValue::Aggregation(<>)
};
JsonObj: ast::JsonValue = {
"{" <exp:( JsonPair ( "," JsonPair )* )?> "}" => {
if let Some((elem, list)) = exp {
let mut values: Vec<(String, JsonValue)> = vec![elem];
for v in list {
let (_, pair) = v;
values.push(pair.clone());
}
JsonValue::Object(values)
} else {
JsonValue::Object(Vec::new())
}
}
};
JsonPair: (String, ast::JsonValue) = {
<s:String> ":" <v:JsonValues> => (s, v)
};
JsonArray: ast::JsonValue = {
"[" <exp:( JsonValues ( "," JsonValues )* )?> "]" => {
if let Some((elem, list)) = exp {
let mut values: Vec<JsonValue> = vec![elem];
for v in list.iter() {
let (_, val) = v;
values.push(val.clone());
}
JsonValue::Array(values)
} else {
JsonValue::Array(Vec::new())
}
}
};
// The bag expression is implicit here, as this is te
// second argument to the json operator
Aggregations: ast::Aggregation = {
"count" "(" <d:"distinct"?> <s:Selector> ")" => {
if let Some(_) = d {
Aggregation::Count(true, s)
} else {
Aggregation::Count(false, s)
}
},
"sum" "(" <Selector> ")" =>
Aggregation::Sum(<>),
"min" "(" <Selector> ")" =>
Aggregation::Min(<>),
"max" "(" <Selector> ")" =>
Aggregation::Max(<>),
};
//*********************************************************************/
// SELECTING / FILTERING DATA */
//*********************************************************************/
pub Filters = { Bags };
// All these expressions generate bags.
Bags: ast::Bag = {
// Bag Operators
Distinct,
Filter,
Complement,
Intersection,
Union,
Bag,
// Spatial Operators
Inside,
Outside,
// When used directly here, the inside() operation on the shape is
// implied.
Shapes => Bag::Inside(<>)
};
//*********************************************************************/
// BAG OPERATORS */
//*********************************************************************/
Distinct: ast::Bag = {
"distinct" "(" <Bags> ")" =>
Bag::Distinct(Box::new(<>))
};
// Returns all the points which are NOT part of the bag.
Complement: ast::Bag = {
"complement" "(" <Bags> ")" =>
Bag::Complement(Box::new(<>))
};
// Returns points which are part of both left and right sets.
Intersection: ast::Bag = {
"intersection" "(" <lh:Bags> "," <rh:Bags> ")" =>
Bag::Intersection(Box::new(lh), Box::new(rh))
};
// Returns points which are either part of left or right sets
// (or both).
Union: ast::Bag = {
"union" "(" <lh:Bags> "," <rh:Bags> ")" =>
Bag::Union(Box::new(lh), Box::new(rh))
};
// Filters point so that points part of the resulting bag respect
// the predicate.
Filter: ast::Bag = {
// "filter" "(" <p:Predicates> "," <b:Bags> ")" =>
"filter" "(" <b:Bags> ")" =>
Bag::Filter(None, Some(Box::new(b))),
"filter" "(" <p:Predicates> <b:("," <Bags> )?> ")" => match b {
Some(b) => Bag::Filter(Some(p), Some(Box::new(b))),
None => Bag::Filter(Some(p), None),
}
};
Predicates: ast::Predicate = {
Less,
Greater,
Equal,
Not,
And,
Or
};
Less: ast::Predicate = {
"<" "(" <v:Positions> "," <literal:Position> ")" => {
Predicate::Less(v, literal)
}
};
Greater: ast::Predicate = {
">" "(" <v:Positions> "," <literal:Position> ")" => {
Predicate::Greater(v, literal)
}
};
Equal: ast::Predicate = {
"=" "(" <v:Positions> "," <literal:Position> ")" => {
Predicate::Equal(v, literal)
}
};
Not: ast::Predicate = {
"!" "(" <p:Predicates> ")" =>
Predicate::Not(Box::new(p))
};
And: ast::Predicate = {
"&" "(" <lh:Predicates> "," <rh:Predicates> ")" =>
Predicate::And(Box::new(lh), Box::new(rh))
};
Or: ast::Predicate = {
"|" "(" <lh:Predicates> "," <rh:Predicates> ")" =>
Predicate::Or(Box::new(lh), Box::new(rh))
};
// Arbitrary bag of positions.
Bag: ast::Bag = {
"bag" "{" <elem:Bags> <list:("," Bags )*> "}" => {
let mut bags = vec![elem];
for (_, b) in list {
bags.push(b);
}
Bag::Bag(bags)
}
};
//*********************************************************************/
// SPATIAL OPERATORS */
//*********************************************************************/
// Faces | vertices are included to allow selection on a pure plane or
// boundary.
//
// For example:
// intersection(outside(hyperrectangle{[0,0], [1,1]},
// inside(hyperrectangle{[0,0], [1,1]})
// will be true for any point lying EXACTLY on a face, corner or edge
// of the cube [0,0], [1,1].
// Returns the set of points outside the shape, (face included)
Outside: ast::Bag = {
"outside" "(" <Shapes> ")" =>
Bag::Outside(<>)
};
// Returns the set of points inside the shape, (face included)
Inside: ast::Bag = {
"inside" "(" <Shapes> ")" =>
Bag::Inside(<>)
};
//*********************************************************************/
// SHAPES */
//*********************************************************************/
// Shapes are defined in terms of POSITION, a.k.a a LiteralPosition
// value, which is not a POSITIONS, which might be a filter for example.
Shapes: ast::Shape = {
Point,
HyperRectangle,
HyperSphere,
Nifti
};
// If the hyperrectangle is aligned with the axes, then two points are
// enough, if not we need all the points to be specified.
HyperRectangle: ast::Shape = {
"hyperrectangle" "{"
<l:Position> "," <h:Position>
<list:( "," Position "," Position )*>
"}" => {
let mut pos = vec![l, h];
for (_, lh, _, rh) in list.iter() {
pos.push(lh.clone());
pos.push(rh.clone());
}
Shape::HyperRectangle(pos)
}
};
// A hypersphere is defined by its center and a radius, independantly
// of the number of dimensions of the space.
HyperSphere: ast::Shape = {
"hypersphere" "{" <c:Position> "," <r:PositiveNumber> "}" =>
Shape::HyperSphere(c, r)
};
Point: ast::Shape = {
"point" "{" <Position> "}" =>
Shape::Point(<>)
};
// Define a shape as the non-zero values in a NIfTI object, defined by
// nifti{
// spaceId: string,
// lower_corner: position, // Optional, default to the origin
// rotation: [ position+ ], // Optional, no rotation by default
// bytes: uri(STRING) // uri to the NIfTI object
// }
Nifti: ast::Shape = {
"nifti" "{"
String ","
( Position "," )?
( "[" Position ( "," Position)* "]" "," )?
ByteProvider
"}" => {
Shape::Nifti()
}
};
// FIXME: STRING is assumed to be a well-formed URI, fully specify here?
//
// FIXME: Add a provider for in-line raw-byte stream.
ByteProvider = { "uri" "(" String ")" };
//*********************************************************************/
// POSITIONS */
//*********************************************************************/
// Always returns a vector of numbers, a.k.a a position (a scalar will
// be represented as a vector of one element)
Positions: ast::Position = {
StrCmpICase,
StrCmp,
Selector => Position::Selector(<>),
Position => Position::LiteralPosition(<>)
};
// Compare lexicographically two strings, and returns a `position`:
// [-1] : String is lexicographically before,
// [ 0] : is equal,
// [ 1] : is after.
StrCmp: ast::Position = {
"str_cmp" "(" <s:Selector> "," <v:String> ")" => {
Position::StrCmp(s, v)
}
};
// Same, but case insensitive.
StrCmpICase: ast::Position = {
"str_cmp_ignore_case" "(" <s:Selector> "," <v:String> ")" => {
Position::StrCmpICase(s, v)
}
};
// FIXME: FIELDS are expected to be exisiting in the data model. Root Object is assumed to be the type of the ressource on which the POST call was done.
Selector = {
( <Field> )+
};
Position: ast::LiteralPosition = {
"[" <element:Number> <list:( "," <Number>)*> "]" => {
let mut pos: LiteralPosition = vec![element];
for e in list.iter() {
pos.push(e.clone());
}
pos
}
};
//*********************************************************************/
// TOKENS - STRINGS */
//*********************************************************************/
// Accept field descriptor which
// 1. start with a dot ('.')
// 2. optionnally followed by a field name consisting of a letter or
// underscore, followed by letters, numbers or underscore,
// 3. optionnally followed by brakets enclosing an natural number
// denoting an offset in a list or array.
Field: Field = {
<n:r"[.]([a-zA-Z_][[a-zA-Z_0-9]]*)?([\[](0|[1-9][0-9]*)[\]])?"> => {
if let Some(pos) = n.rfind('[') {
let name = &n[1..pos];
let index = &n[(pos+1)..(n.len()-1)];
let index = usize::from_str(index).unwrap();
Field(String::from(name), Some(index))
} else {
let name = &n[1..];
Field(String::from(name), None)
}
}
};
String: String = {
r#"["]([\\](["\\/bfnrt]|u[0-9a-fA-F]{4})|[^"\\\u0000-\u001F])*["]"# =>
String::from(<>)
};
//*********************************************************************/
// TOKENS - NUMBERS */
//*********************************************************************/
// We define 3 kinds of number, to avoid ambiguities in the rules.
JsonNumber: ast::JsonValue = {
<s:"-"?> <v:Num> => match s {
None => JsonValue::JsonNumber(v),
Some(_) => match v {
LiteralNumber::Int(x) => JsonValue::JsonNumber(LiteralNumber::Int(-x)),
LiteralNumber::Float(x) => JsonValue::JsonNumber(LiteralNumber::Float(-x))
}
}
};
PositiveNumber: ast::LiteralNumber = { "+"? <v:Num> => v };
Number: ast::LiteralNumber = {
"+" <v:Num> => v,
"-" <v:Num> => match v {
LiteralNumber::Int(x) => LiteralNumber::Int(-x),
LiteralNumber::Float(x) => LiteralNumber::Float(-x)
},
<v:Num> => v
};
Num: ast::LiteralNumber = {
r"0([.][0-9]+([eE][+\-]?(0|[1-9][0-9]*))?)?"
=> {
if let Ok(v) = i64::from_str(<>) {
LiteralNumber::Int(v)
} else {
// Either parsing as a float succeed or we pass along
// the error
LiteralNumber::Float(f64::from_str(<>).unwrap())
}
},
r"[1-9][0-9]*([.][0-9]+)?([eE][+\-]?(0|[1-9][0-9]*))?"
=> {
if let Ok(v) = i64::from_str(<>) {
LiteralNumber::Int(v)
} else {
// Either parsing as a float succeed or we pass along
// the error
LiteralNumber::Float(f64::from_str(<>).unwrap())
}
}
};

944
src/tests.rs Normal file
View File

@@ -0,0 +1,944 @@
//use super::ast;
/******************************************************************/
/* FORMATTING DATA */
/******************************************************************/
#[cfg(test)]
mod query {
use crate::queries;
fn query_parser() -> queries::QueryParser {
queries::QueryParser::new()
}
#[test]
fn query() {
let p = query_parser();
let nifti = "nifti(point{[0]})";
// Option is Empty
assert!(p.parse("").is_ok());
// Option is there
assert!(p.parse(nifti).is_ok());
// Too many element
assert!(p.parse(format!("{} {}", nifti, nifti).as_str()).is_err());
}
/* Not useful to test this rule
#[test]
fn projections() {
let p = query_parser();
let nifti = "nifti(point{[0]})";
let json = "json(., point{[0]})";
// Each alternative
assert!(p.parse(nifti).is_ok());
assert!(p.parse(json).is_ok());
}
*/
#[test]
fn nifti_operator() {
let p = query_parser();
// Check allowed forms of the operator
assert!(p.parse("nifti(point{[0]})").is_ok());
assert!(p.parse("nifti(.properties.id, point{[0]})").is_ok());
//FIXME: THIS SHOULD BE ALLOWED
assert!(p.parse("nifti(2, point{[0]})").is_ok());
assert!(p.parse("nifti(2.23, point{[0]})").is_ok());
//FIXME: SYNTAX OK, TYPE NOT
assert!(p.parse("nifti(\"asd\", point{[0]})").is_err());
}
#[test]
fn json_operator() {
let p = query_parser();
assert!(p.parse("json(true, point{[0]})").is_ok());
assert!(p.parse("json(23, point{[0]})").is_ok());
assert!(p.parse("json([23, 24], point{[0]})").is_ok());
assert!(p.parse("json([23, count(.)], point{[0]})").is_ok());
assert!(p.parse("json(true)").is_err());
assert!(p.parse("json(true,)").is_err());
assert!(p.parse("json(, point{[0]})").is_err());
assert!(p.parse("json(point{[0]})").is_err());
assert!(p.parse("json(true, point)").is_err());
}
#[test]
fn json_values() {
let p = query_parser();
assert!(p
.parse(format!("json({}, point{{[0]}})", "true").as_str())
.is_ok());
assert!(p
.parse(format!("json({}, point{{[0]}})", "false").as_str())
.is_ok());
assert!(p
.parse(format!("json({}, point{{[0]}})", "null").as_str())
.is_ok());
// Incorrect capitalisation
assert!(p
.parse(format!("json({}, point{{[0]}})", "True").as_str())
.is_err());
assert!(p
.parse(format!("json({}, point{{[0]}})", "False").as_str())
.is_err());
assert!(p
.parse(format!("json({}, point{{[0]}})", "Null").as_str())
.is_err());
}
#[test]
fn json_obj() {
let p = query_parser();
assert!(p
.parse(format!("json({}, point{{[0]}})", "{}").as_str())
.is_ok());
assert!(p
.parse(format!("json({}, point{{[0]}})", "{\"field\": 0}").as_str())
.is_ok());
assert!(p
.parse(format!("json({}, point{{[0]}})", "{\"field\": 0, \"field1\": 1}").as_str())
.is_ok());
assert!(p
.parse(format!("json({}, point{{[0]}})", "{\"field\": [0, 1]}").as_str())
.is_ok());
assert!(p
.parse(format!("json({}, point{{[0]}})", "{\"field\": {\"field1\": 0}}").as_str())
.is_ok());
assert!(p
.parse(
format!(
"json({}, point{{[0]}})",
"{\"field\": [{\"field1\": 0}, {\"field1\": 1}]}"
)
.as_str()
)
.is_ok());
}
#[test]
fn json_pair() {
let p = query_parser();
assert!(p
.parse(format!("json({}, point{{[0]}})", "{:}").as_str())
.is_err());
assert!(p
.parse(format!("json({}, point{{[0]}})", "{field: 0}").as_str())
.is_err());
assert!(p
.parse(format!("json({}, point{{[0]}})", "{0: 0}").as_str())
.is_err());
assert!(p
.parse(format!("json({}, point{{[0]}})", "{\"0\": }").as_str())
.is_err());
assert!(p
.parse(format!("json({}, point{{[0]}})", "{\"0\": 0 }").as_str())
.is_ok());
assert!(p
.parse(format!("json({}, point{{[0]}})", "{\"field\": 0 }").as_str())
.is_ok());
assert!(p
.parse(format!("json({}, point{{[0]}})", "{\"field\": \"0\" }").as_str())
.is_ok());
}
#[test]
fn json_array() {
let p = query_parser();
assert!(p
.parse(format!("json({}, point{{[0]}})", "[, 0]").as_str())
.is_err());
assert!(p
.parse(format!("json({}, point{{[0]}})", "[]").as_str())
.is_ok());
assert!(p
.parse(format!("json({}, point{{[0]}})", "[0]").as_str())
.is_ok());
assert!(p
.parse(format!("json({}, point{{[0]}})", "[0, 1]").as_str())
.is_ok());
assert!(p
.parse(format!("json({}, point{{[0]}})", "[{\"field\": 0}, {\"field\": 1}]").as_str())
.is_ok());
}
#[test]
fn aggregations() {
let p = query_parser();
//FIXME: ADD STUFF
// count ()
assert!(p
.parse(format!("json({}, point{{[0]}})", "count()").as_str())
.is_err());
assert!(p
.parse(format!("json({}, point{{[0]}})", "count(distinct)").as_str())
.is_err());
assert!(p
.parse(format!("json({}, point{{[0]}})", "count(.)").as_str())
.is_ok());
assert!(p
.parse(format!("json({}, point{{[0]}})", "count(distinct .)").as_str())
.is_ok());
// sum ()
assert!(p
.parse(format!("json({}, point{{[0]}})", "sum()").as_str())
.is_err());
assert!(p
.parse(format!("json({}, point{{[0]}})", "sum(.)").as_str())
.is_ok());
// min ()
assert!(p
.parse(format!("json({}, point{{[0]}})", "min()").as_str())
.is_err());
assert!(p
.parse(format!("json({}, point{{[0]}})", "min(.)").as_str())
.is_ok());
// max ()
assert!(p
.parse(format!("json({}, point{{[0]}})", "max()").as_str())
.is_err());
assert!(p
.parse(format!("json({}, point{{[0]}})", "max(.)").as_str())
.is_ok());
}
#[test]
fn json_numbers() {
let p = query_parser();
// Integers
assert!(p
.parse(format!("json({}, point{{[0]}})", "0").as_str())
.is_ok());
assert!(p
.parse(format!("json({}, point{{[0]}})", "+0").as_str())
.is_err());
assert!(p
.parse(format!("json({}, point{{[0]}})", "-0").as_str())
.is_ok());
assert!(p
.parse(format!("json({}, point{{[0]}})", "1").as_str())
.is_ok());
assert!(p
.parse(format!("json({}, point{{[0]}})", "+1").as_str())
.is_err());
assert!(p
.parse(format!("json({}, point{{[0]}})", "-1").as_str())
.is_ok());
// Floating point values
assert!(p
.parse(format!("json({}, point{{[0]}})", "0.0").as_str())
.is_ok());
assert!(p
.parse(format!("json({}, point{{[0]}})", "+0.0").as_str())
.is_err());
assert!(p
.parse(format!("json({}, point{{[0]}})", "-0.0").as_str())
.is_ok());
assert!(p
.parse(format!("json({}, point{{[0]}})", "0.1").as_str())
.is_ok());
assert!(p
.parse(format!("json({}, point{{[0]}})", "+0.01").as_str())
.is_err());
assert!(p
.parse(format!("json({}, point{{[0]}})", "-0.01").as_str())
.is_ok());
}
}
#[cfg(test)]
mod filters {
use crate::queries;
/******************************************************************/
/* SELECTING / FILTERING DATA */
/******************************************************************/
fn filters_parser() -> queries::FiltersParser {
queries::FiltersParser::new()
}
#[test]
fn filters() {
let p = filters_parser();
assert!(p.parse("").is_err());
assert!(p.parse("point{[0]}").is_ok());
}
/* Not useful to test this rule
#[test]
fn bags() {
let p = filters_parser();
} */
#[test]
fn distinct() {
let p = filters_parser();
assert!(p.parse("distinct()").is_err());
assert!(p.parse("distinct(point{[0]})").is_ok());
}
#[test]
fn complement() {
let p = filters_parser();
assert!(p.parse("complement()").is_err());
assert!(p.parse("complement(point{[0]})").is_ok());
}
#[test]
fn intersection() {
let p = filters_parser();
assert!(p.parse("intersection()").is_err());
assert!(p.parse("intersection(point{[0]})").is_err());
assert!(p
.parse("intersection(point{[0]}, point{[0]}, point{[0]})")
.is_err());
assert!(p.parse("intersection(point{[0]}, point{[0]})").is_ok());
}
#[test]
fn union() {
let p = filters_parser();
assert!(p.parse("union()").is_err());
assert!(p.parse("union(point{[0]})").is_err());
assert!(p
.parse("union(point{[0]}, point{[0]}, point{[0]})")
.is_err());
assert!(p.parse("union(point{[0]}, point{[0]})").is_ok());
}
#[test]
fn filter() {
let p = filters_parser();
assert!(p.parse("filter()").is_err());
assert!(p.parse("filter(point{[0]})").is_ok());
assert!(p.parse("filter(=(., [0]))").is_ok());
assert!(p.parse("filter(=(., [0]), point{[0]})").is_ok());
}
/* Not useful to test this rule
#[test]
fn predicates() {
let p = filters_parser();
}*/
#[test]
fn less() {
let p = filters_parser();
assert!(p
.parse(format!("filter({}, point{{[0]}})", "<(., [0])").as_str())
.is_ok());
assert!(p
.parse(format!("filter({}, point{{[0]}})", "<(, [0])").as_str())
.is_err());
assert!(p
.parse(format!("filter({}, point{{[0]}})", "<(.)").as_str())
.is_err());
assert!(p
.parse(format!("filter({}, point{{[0]}})", "<()").as_str())
.is_err());
}
#[test]
fn greater() {
let p = filters_parser();
assert!(p
.parse(format!("filter({}, point{{[0]}})", ">(., [0])").as_str())
.is_ok());
assert!(p
.parse(format!("filter({}, point{{[0]}})", ">(, [0])").as_str())
.is_err());
assert!(p
.parse(format!("filter({}, point{{[0]}})", ">(.)").as_str())
.is_err());
assert!(p
.parse(format!("filter({}, point{{[0]}})", ">()").as_str())
.is_err());
}
#[test]
fn equal() {
let p = filters_parser();
assert!(p
.parse(format!("filter({}, point{{[0]}})", "=(., [0])").as_str())
.is_ok());
assert!(p
.parse(format!("filter({}, point{{[0]}})", "=(, [0])").as_str())
.is_err());
assert!(p
.parse(format!("filter({}, point{{[0]}})", "=(.)").as_str())
.is_err());
assert!(p
.parse(format!("filter({}, point{{[0]}})", "=()").as_str())
.is_err());
}
#[test]
fn not() {
let p = filters_parser();
assert!(p
.parse(format!("filter({}, point{{[0]}})", "!(=(., [0]))").as_str())
.is_ok());
assert!(p
.parse(format!("filter({}, point{{[0]}})", "!()").as_str())
.is_err());
}
#[test]
fn and() {
let p = filters_parser();
assert!(p
.parse(format!("filter({}, point{{[0]}})", "&(=(., [0]), =(., [0]))").as_str())
.is_ok());
assert!(p
.parse(format!("filter({}, point{{[0]}})", "&(, =(., [0]))").as_str())
.is_err());
assert!(p
.parse(format!("filter({}, point{{[0]}})", "&(|(=(., [0])))").as_str())
.is_err());
assert!(p
.parse(format!("filter({}, point{{[0]}})", "&()").as_str())
.is_err());
}
#[test]
fn or() {
let p = filters_parser();
assert!(p
.parse(format!("filter({}, point{{[0]}})", "|(=(., [0]), =(., [0]))").as_str())
.is_ok());
assert!(p
.parse(format!("filter({}, point{{[0]}})", "|(, =(., [0]))").as_str())
.is_err());
assert!(p
.parse(format!("filter({}, point{{[0]}})", "|(|(=(., [0])))").as_str())
.is_err());
assert!(p
.parse(format!("filter({}, point{{[0]}})", "|()").as_str())
.is_err());
}
#[test]
fn bag() {
let p = filters_parser();
assert!(p.parse("bag{}").is_err());
assert!(p.parse("bag{point{[0]}}").is_ok());
assert!(p.parse("bag{point{[0]}, point{[0]}}").is_ok());
assert!(p.parse("bag{point{[0]}, point{[0]}, point{[0]}}").is_ok());
assert!(p
.parse("bag{point{[0]}, hypersphere{[0], 1}, hyperrectangle{[0], [1]}}")
.is_ok());
}
#[test]
fn outside() {
let p = filters_parser();
assert!(p.parse("outside()").is_err());
assert!(p.parse("outside(point{[0]})").is_ok());
}
#[test]
fn inside() {
let p = filters_parser();
assert!(p.parse("inside()").is_err());
assert!(p.parse("inside(point{[0]})").is_ok());
}
/* Not useful to test this rule
#[test]
fn shapes() {
let p = filters_parser();
assert!(p.parse("point{[0]}").is_ok());
assert!(p.parse("hyperrectangle{[0], [1]}").is_ok());
assert!(p.parse("hypersphere{[0], 1}").is_ok());
assert!(p.parse("nifti{\"\", uri(\"\")}").is_ok());
}*/
#[test]
fn hyperrectangle() {
let p = filters_parser();
// At least two positions when it is aligned with the axis, otherwise an even number
// of positions, as the number of vertices follows the rule 2**k, where k is the number
// of dimensions of the space containing the hyperrectangle.
assert!(p.parse("hyperrectangle{}").is_err());
assert!(p.parse("hyperrectangle{[]}").is_err());
assert!(p.parse("hyperrectangle{[0]}").is_err());
assert!(p.parse("hyperrectangle{[0], [1], [2]}").is_err());
assert!(p.parse("hyperrectangle{[0], [1], [2], [3], [4]}").is_err());
assert!(p.parse("hyperrectangle{[0], [1]}").is_ok());
assert!(p.parse("hyperrectangle{[0], [1], [2], [3]}").is_ok());
assert!(p
.parse("hyperrectangle{[0], [1], [2], [3], [4], [5]}")
.is_ok());
}
#[test]
fn hyperrsphere() {
let p = filters_parser();
assert!(p.parse("hypersphere{}").is_err());
assert!(p.parse("hypersphere{[]}").is_err());
assert!(p.parse("hypersphere{[0]}").is_err());
assert!(p.parse("hypersphere{[0], 23}").is_ok());
}
#[test]
fn point() {
let p = filters_parser();
assert!(p.parse("point{}").is_err());
assert!(p.parse("point{[]}").is_err());
assert!(p.parse("point{[0]}").is_ok());
}
#[test]
fn nifti() {
let p = filters_parser();
//FIXME: ADD STUFF
assert!(false);
}
#[test]
fn byte_provider() {
let p = filters_parser();
//FIXME: ADD STUFF
assert!(false);
}
/* Not useful to test this rule
#[test]
fn positions() {
let p = filters_parser();
assert!(p
.parse(
format!(
"filter(=({}, [1]), point{{[0]}})",
"str_cmp_ignore_case(.field, \"\")"
)
.as_str()
)
.is_ok());
assert!(p
.parse(format!("filter(=({}, [1]), point{{[0]}})", "str_cmp(.field, \"\")").as_str())
.is_ok());
assert!(p
.parse(format!("filter(=({}, [1]), point{{[0]}})", ".field").as_str())
.is_ok());
assert!(p
.parse(format!("filter(=({}, [1]), point{{[0]}})", "[0]").as_str())
.is_ok());
assert!(p
.parse(format!("filter(=({}, [1]), point{{[0]}})", "point{[0]}").as_str())
.is_err());
assert!(p
.parse(format!("filter(=({}, [1]), point{{[0]}})", "{0}").as_str())
.is_err());
assert!(p
.parse(format!("filter(=({}, [1]), point{{[0]}})", "").as_str())
.is_err());
}*/
#[test]
fn str_cmp() {
let p = filters_parser();
assert!(p
.parse(format!("filter(=({}, [1]), point{{[0]}})", "str_cmp(.field, \"\")").as_str())
.is_ok());
assert!(p
.parse(format!("filter(=({}, [1]), point{{[0]}})", "str_cmp(.field)").as_str())
.is_err());
assert!(p
.parse(format!("filter(=({}, [1]), point{{[0]}})", "str_cmp(\"\")").as_str())
.is_err());
}
#[test]
fn str_cmp_icase() {
let p = filters_parser();
assert!(p
.parse(
format!(
"filter(=({}, [1]), point{{[0]}})",
"str_cmp_ignore_case(.field, \"\")"
)
.as_str()
)
.is_ok());
assert!(p
.parse(
format!(
"filter(=({}, [1]), point{{[0]}})",
"str_cmp_ignore_case(.field)"
)
.as_str()
)
.is_err());
assert!(p
.parse(
format!(
"filter(=({}, [1]), point{{[0]}})",
"str_cmp_ignore_case(\"\")"
)
.as_str()
)
.is_err());
}
#[test]
fn selector() {
let p = filters_parser();
assert!(p
.parse(format!("filter(=({}, [1]), point{{[0]}})", ".").as_str())
.is_ok());
assert!(p
.parse(format!("filter(=({}, [1]), point{{[0]}})", ".field").as_str())
.is_ok());
assert!(p
.parse(format!("filter(=({}, [1]), point{{[0]}})", ".field.field").as_str())
.is_ok());
assert!(p
.parse(format!("filter(=({}, [1]), point{{[0]}})", ".field[1].field").as_str())
.is_ok());
assert!(p
.parse(format!("filter(=({}, [1]), point{{[0]}})", ".field.field[1]").as_str())
.is_ok());
}
#[test]
fn position() {
let p = filters_parser();
// Empty
assert!(p.parse(format!("point{{{}}}", "[]").as_str()).is_err());
// Non-numerical coordinate:
assert!(p.parse(format!("point{{{}}}", "[aa]").as_str()).is_err());
assert!(p
.parse(format!("point{{{}}}", "[\"aa\"]").as_str())
.is_err());
// One or more coordinates
assert!(p.parse(format!("point{{{}}}", "[0]").as_str()).is_ok());
assert!(p.parse(format!("point{{{}}}", "[0, 0]").as_str()).is_ok());
assert!(p
.parse(format!("point{{{}}}", "[0, 0, 0]").as_str())
.is_ok());
assert!(p
.parse(format!("point{{{}}}", "[0, 0, 0, 0]").as_str())
.is_ok());
assert!(p
.parse(format!("point{{{}}}", "[0,0,0,0]").as_str())
.is_ok());
}
#[test]
fn field() {
let p = filters_parser();
// Single dot
assert!(p
.parse(format!("filter(<({}, [1]), point{{[0]}})", ".").as_str())
.is_ok());
// Check first character is within allowed characters
assert!(p
.parse(format!("filter(<({}, [1]), point{{[0]}})", ".a").as_str())
.is_ok());
assert!(p
.parse(format!("filter(<({}, [1]), point{{[0]}})", "._").as_str())
.is_ok());
assert!(p
.parse(format!("filter(<({}, [1]), point{{[0]}})", ".2").as_str())
.is_err());
// Check second character is within allowed characters
assert!(p
.parse(format!("filter(<({}, [1]), point{{[0]}})", ".fa").as_str())
.is_ok());
assert!(p
.parse(format!("filter(<({}, [1]), point{{[0]}})", ".f2").as_str())
.is_ok());
assert!(p
.parse(format!("filter(<({}, [1]), point{{[0]}})", ".f_").as_str())
.is_ok());
assert!(p
.parse(format!("filter(<({}, [1]), point{{[0]}})", ".f2").as_str())
.is_ok());
// Check we can add subscript
assert!(p
.parse(format!("filter(<({}, [1]), point{{[0]}})", ".[23]").as_str())
.is_ok());
assert!(p
.parse(format!("filter(<({}, [1]), point{{[0]}})", ".f[0]").as_str())
.is_ok());
assert!(p
.parse(format!("filter(<({}, [1]), point{{[0]}})", ".f[2]").as_str())
.is_ok());
assert!(p
.parse(format!("filter(<({}, [1]), point{{[0]}})", ".f[23]").as_str())
.is_ok());
// Invalid index values
assert!(p
.parse(format!("filter(<({}, [1]), point{{[0]}})", ".f[2.3]").as_str())
.is_err());
assert!(p
.parse(format!("filter(<({}, [1]), point{{[0]}})", ".f[02]").as_str())
.is_err());
assert!(p
.parse(format!("filter(<({}, [1]), point{{[0]}})", ".f[-2]").as_str())
.is_err());
assert!(p
.parse(format!("filter(<({}, [1]), point{{[0]}})", ".f[2e2]").as_str())
.is_err());
assert!(p
.parse(format!("filter(<({}, [1]), point{{[0]}})", ".f[2E2]").as_str())
.is_err());
assert!(p
.parse(format!("filter(<({}, [1]), point{{[0]}})", ".f[+2]").as_str())
.is_err());
}
#[test]
fn string() {
fn test_str_ok(p: &queries::FiltersParser, string: &str) {
let n = format!(
"{}{}{}",
"nifti{", string, ", uri(\"http://a.nifti.file\") }"
);
let n = n.as_str();
assert!(p.parse(n).is_ok());
}
fn test_str_err(p: &queries::FiltersParser, string: &str) {
let n = format!(
"{}{}{}",
"nifti{", string, ", uri(\"http://a.nifti.file\") }"
);
let n = n.as_str();
assert!(p.parse(n).is_err());
}
let p = &filters_parser();
// Empty String
test_str_ok(p, r#""""#);
// Usual escapes
test_str_ok(p, r#""\"""#);
test_str_ok(p, r#""\\""#);
test_str_ok(p, r#""\/""#);
test_str_ok(p, r#""\b""#);
test_str_ok(p, r#""\f""#);
test_str_ok(p, r#""\n""#);
test_str_ok(p, r#""\r""#);
test_str_ok(p, r#""\t""#);
// Unicode Escape
test_str_ok(p, r#""\u0012""#);
test_str_ok(p, r#""\u001F""#);
test_str_ok(p, r#""\u001a""#);
// ASCI Letters & digit
test_str_ok(p, r#""abcdefghijklmnopqrstuvwxyz""#);
test_str_ok(p, r#""ABCDEFGHIJKLMNOPQRSTUVWXYZ""#);
test_str_ok(p, r#""0123456789""#);
// Space and some non-white characters
test_str_ok(p, r#"" ,.-;:!?'^&|§°+*ç%_""#);
// Invalid
test_str_err(p, "\"\u{0010}\""); // rust requires \u{..}, while JSON does not.
}
#[test]
fn positive_numbers() {
let p = filters_parser();
// Integers
assert!(p
.parse(format!("hypersphere{{[0],{}}}", "0").as_str())
.is_ok());
assert!(p
.parse(format!("hypersphere{{[0],{}}}", "+0").as_str())
.is_ok());
assert!(p
.parse(format!("hypersphere{{[0],{}}}", "-0").as_str())
.is_err());
assert!(p
.parse(format!("hypersphere{{[0],{}}}", "1").as_str())
.is_ok());
assert!(p
.parse(format!("hypersphere{{[0],{}}}", "+1").as_str())
.is_ok());
assert!(p
.parse(format!("hypersphere{{[0],{}}}", "-1").as_str())
.is_err());
// Floating point values
assert!(p
.parse(format!("hypersphere{{[0],{}}}", "0.0").as_str())
.is_ok());
assert!(p
.parse(format!("hypersphere{{[0],{}}}", "+0.0").as_str())
.is_ok());
assert!(p
.parse(format!("hypersphere{{[0],{}}}", "-0.0").as_str())
.is_err());
assert!(p
.parse(format!("hypersphere{{[0],{}}}", "0.1").as_str())
.is_ok());
assert!(p
.parse(format!("hypersphere{{[0],{}}}", "+0.01").as_str())
.is_ok());
assert!(p
.parse(format!("hypersphere{{[0],{}}}", "-0.01").as_str())
.is_err());
}
#[test]
fn numbers() {
let p = filters_parser();
// Integers
assert!(p.parse(format!("point{{[{}]}}", "0").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "+0").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "-0").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "1").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "+1").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "-1").as_str()).is_ok());
// Floating point values
assert!(p.parse(format!("point{{[{}]}}", "0.0").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "+0.0").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "-0.0").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "0.1").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "+0.01").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "-0.01").as_str()).is_ok());
}
#[test]
fn num() {
let p = filters_parser();
// Integers
assert!(p.parse(format!("point{{[{}]}}", "0").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "1").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "1e2").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "1e+2").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "1e-2").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "1E2").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "100").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "010").as_str()).is_err());
// Floating point values (normalized)
assert!(p.parse(format!("point{{[{}]}}", "0.0").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "0.1").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "0.1e0").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "0.1e2").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "0.1e+2").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "0.1e-2").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "0.1E2").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "0.1E23").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "0.01").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "0.").as_str()).is_err());
assert!(p
.parse(format!("point{{[{}]}}", "0.1E03").as_str())
.is_err());
assert!(p
.parse(format!("point{{[{}]}}", "0.1E0.3").as_str())
.is_err());
// Floating point values (denormalized)
assert!(p.parse(format!("point{{[{}]}}", "1.0").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "1.1").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "1.1e0").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "1.1e2").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "1.1e+2").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "1.1e-2").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "1.1E2").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "1.1E23").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "1.01").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "10.1").as_str()).is_ok());
assert!(p.parse(format!("point{{[{}]}}", "1.").as_str()).is_err());
assert!(p.parse(format!("point{{[{}]}}", "01.1").as_str()).is_err());
assert!(p
.parse(format!("point{{[{}]}}", "1.1E03").as_str())
.is_err());
assert!(p
.parse(format!("point{{[{}]}}", "1.1E0.3").as_str())
.is_err());
}
}